summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/assimp/CHANGES109
-rw-r--r--src/3rdparty/assimp/CREDITS14
-rw-r--r--src/3rdparty/assimp/LICENSE30
-rw-r--r--src/3rdparty/assimp/Readme.md119
-rw-r--r--src/3rdparty/assimp/assimp.pri247
-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
-rw-r--r--src/3rdparty/assimp/contrib/clipper/clipper.cpp2
-rw-r--r--src/3rdparty/assimp/contrib/clipper/clipper.hpp2
-rw-r--r--src/3rdparty/assimp/contrib/irrXML/irrXML.cpp1
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt64
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/CREDITS16
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/LICENSE22
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/README.md136
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp209
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp186
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp439
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp1008
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp440
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h164
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h247
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h104
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h187
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h254
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h269
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h2
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h60
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc18
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc2
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h261
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h2136
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h261
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h625
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h65
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h146
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h88
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h95
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h290
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h248
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h217
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h77
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/itoa.h304
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/meta.h181
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/pow10.h55
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h196
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h39
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h270
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h37
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h70
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h61
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h316
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h300
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h1313
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h207
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h654
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h1510
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h93
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h395
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/license.txt57
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/readme.md129
-rw-r--r--src/3rdparty/assimp/contrib/unzip/unzip.c2
-rw-r--r--src/3rdparty/assimp/contrib/zlib_note.txt11
-rw-r--r--src/3rdparty/assimp/include/assimp/Compiler/pstdint.h259
-rw-r--r--src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h4
-rw-r--r--src/3rdparty/assimp/include/assimp/DefaultLogger.hpp214
-rw-r--r--src/3rdparty/assimp/include/assimp/Exporter.hpp639
-rw-r--r--src/3rdparty/assimp/include/assimp/IOStream.hpp130
-rw-r--r--src/3rdparty/assimp/include/assimp/IOSystem.hpp323
-rw-r--r--src/3rdparty/assimp/include/assimp/Importer.hpp1130
-rw-r--r--src/3rdparty/assimp/include/assimp/LogStream.hpp78
-rw-r--r--src/3rdparty/assimp/include/assimp/Logger.hpp314
-rw-r--r--src/3rdparty/assimp/include/assimp/NullLogger.hpp92
-rw-r--r--src/3rdparty/assimp/include/assimp/ProgressHandler.hpp110
-rw-r--r--src/3rdparty/assimp/include/assimp/ai_assert.h50
-rw-r--r--src/3rdparty/assimp/include/assimp/anim.h556
-rw-r--r--src/3rdparty/assimp/include/assimp/camera.h250
-rw-r--r--src/3rdparty/assimp/include/assimp/cexport.h154
-rw-r--r--src/3rdparty/assimp/include/assimp/cfileio.h102
-rw-r--r--src/3rdparty/assimp/include/assimp/cimport.h348
-rw-r--r--src/3rdparty/assimp/include/assimp/color4.h70
-rw-r--r--src/3rdparty/assimp/include/assimp/color4.inl128
-rw-r--r--src/3rdparty/assimp/include/assimp/config.h410
-rw-r--r--src/3rdparty/assimp/include/assimp/defs.h357
-rw-r--r--src/3rdparty/assimp/include/assimp/importerdesc.h171
-rw-r--r--src/3rdparty/assimp/include/assimp/light.h327
-rw-r--r--src/3rdparty/assimp/include/assimp/material.h1442
-rw-r--r--src/3rdparty/assimp/include/assimp/material.inl342
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix3x3.h197
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix3x3.inl338
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix4x4.h329
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix4x4.inl555
-rw-r--r--src/3rdparty/assimp/include/assimp/mesh.h1055
-rw-r--r--src/3rdparty/assimp/include/assimp/metadata.h230
-rw-r--r--src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h92
-rw-r--r--src/3rdparty/assimp/include/assimp/postprocess.h1006
-rw-r--r--src/3rdparty/assimp/include/assimp/quaternion.h90
-rw-r--r--src/3rdparty/assimp/include/assimp/quaternion.inl271
-rw-r--r--src/3rdparty/assimp/include/assimp/scene.h536
-rw-r--r--src/3rdparty/assimp/include/assimp/texture.h206
-rw-r--r--src/3rdparty/assimp/include/assimp/types.h597
-rw-r--r--src/3rdparty/assimp/include/assimp/vector2.h70
-rw-r--r--src/3rdparty/assimp/include/assimp/vector2.inl94
-rw-r--r--src/3rdparty/assimp/include/assimp/vector3.h113
-rw-r--r--src/3rdparty/assimp/include/assimp/vector3.inl130
-rw-r--r--src/3rdparty/assimp/include/assimp/version.h30
-rw-r--r--src/3rdparty/assimp/qt_attribution.json3
-rw-r--r--src/3rdparty/assimp/revision.h2
-rw-r--r--src/3rdparty/patches/0001-Fix-ambiguous-if-else-in-assimp.patch31
-rw-r--r--src/3rdparty/patches/0001-assimp-Fix-type-warnings.patch48
-rw-r--r--src/3rdparty/patches/0002-assimp-Add-license-header.patch39
-rw-r--r--src/3rdparty/patches/0002-assimp-Fix-building-with-mingw-older-than-4.9.patch10174
-rw-r--r--src/3rdparty/patches/0003-assimp-Add-missing-case-option.patch11
-rw-r--r--src/3rdparty/patches/0003-assimp-Remove-usage-of-deprecated-keyword-register.patch382
-rw-r--r--src/3rdparty/patches/0004-assimp-Remove-register-keyword.patch12
-rw-r--r--src/3rdparty/patches/0004-assimp-Use-std-namespace-for-most-cmath-functions.patch1281
-rw-r--r--src/3rdparty/patches/0005-assimp-Avoid-unneeded-copy-ctor-calls-when-calling-getAiType.patch31
-rw-r--r--src/3rdparty/patches/0005-assimp-Fix-build-FBXConverter.patch35
-rw-r--r--src/animation/animation.pro3
-rw-r--r--src/animation/animationlogging.cpp8
-rw-r--r--src/animation/backend/additiveclipblend.cpp101
-rw-r--r--src/animation/backend/additiveclipblend_p.h110
-rw-r--r--src/animation/backend/animationclip.cpp159
-rw-r--r--src/animation/backend/animationclip_p.h48
-rw-r--r--src/animation/backend/animationutils.cpp431
-rw-r--r--src/animation/backend/animationutils_p.h193
-rw-r--r--src/animation/backend/backend.pri18
-rw-r--r--src/animation/backend/bezierevaluator.cpp2
-rw-r--r--src/animation/backend/blendedclipanimator.cpp6
-rw-r--r--src/animation/backend/blendedclipanimator_p.h10
-rw-r--r--src/animation/backend/buildblendtreesjob.cpp126
-rw-r--r--src/animation/backend/channelmapper_p.h1
-rw-r--r--src/animation/backend/channelmapping_p.h9
-rw-r--r--src/animation/backend/clipanimator.cpp5
-rw-r--r--src/animation/backend/clipanimator_p.h9
-rw-r--r--src/animation/backend/clipblendnode.cpp156
-rw-r--r--src/animation/backend/clipblendnode_p.h32
-rw-r--r--src/animation/backend/clipblendnodevisitor.cpp114
-rw-r--r--src/animation/backend/clipblendnodevisitor_p.h24
-rw-r--r--src/animation/backend/clipblendvalue.cpp116
-rw-r--r--src/animation/backend/clipblendvalue_p.h102
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob.cpp142
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob_p.h3
-rw-r--r--src/animation/backend/evaluateclipanimatorjob.cpp28
-rw-r--r--src/animation/backend/fcurve.cpp63
-rw-r--r--src/animation/backend/fcurve_p.h29
-rw-r--r--src/animation/backend/findrunningclipanimatorsjob.cpp6
-rw-r--r--src/animation/backend/handle_types_p.h2
-rw-r--r--src/animation/backend/handler.cpp7
-rw-r--r--src/animation/backend/handler_p.h17
-rw-r--r--src/animation/backend/keyframe_p.h10
-rw-r--r--src/animation/backend/lerpclipblend.cpp (renamed from src/animation/backend/lerpblend.cpp)48
-rw-r--r--src/animation/backend/lerpclipblend_p.h105
-rw-r--r--src/animation/backend/loadanimationclipjob.cpp4
-rw-r--r--src/animation/backend/managers_p.h16
-rw-r--r--src/animation/frontend/frontend.pri63
-rw-r--r--src/animation/frontend/qabstractanimation.cpp (renamed from src/extras/animations/qabstractanimation.cpp)85
-rw-r--r--src/animation/frontend/qabstractanimation.h (renamed from src/extras/animations/qabstractanimation.h)15
-rw-r--r--src/animation/frontend/qabstractanimation_p.h (renamed from src/extras/animations/qabstractanimation_p.h)14
-rw-r--r--src/animation/frontend/qabstractanimationclip.cpp171
-rw-r--r--src/animation/frontend/qabstractanimationclip.h (renamed from src/animation/frontend/qlerpblend.h)35
-rw-r--r--src/animation/frontend/qabstractanimationclip_p.h (renamed from src/animation/backend/lerpblend_p.h)29
-rw-r--r--src/animation/frontend/qabstractclipanimator.cpp241
-rw-r--r--src/animation/frontend/qabstractclipanimator.h96
-rw-r--r--src/animation/frontend/qabstractclipanimator_p.h (renamed from src/animation/frontend/qconductedclipanimator_p.h)24
-rw-r--r--src/animation/frontend/qabstractclipblendnode.cpp130
-rw-r--r--src/animation/frontend/qabstractclipblendnode.h8
-rw-r--r--src/animation/frontend/qabstractclipblendnode_p.h4
-rw-r--r--src/animation/frontend/qadditiveclipblend.cpp254
-rw-r--r--src/animation/frontend/qadditiveclipblend.h84
-rw-r--r--src/animation/frontend/qadditiveclipblend_p.h82
-rw-r--r--src/animation/frontend/qanimationaspect.cpp34
-rw-r--r--src/animation/frontend/qanimationclip.cpp78
-rw-r--r--src/animation/frontend/qanimationclip.h43
-rw-r--r--src/animation/frontend/qanimationclip_p.h43
-rw-r--r--src/animation/frontend/qanimationclipdata.cpp143
-rw-r--r--src/animation/frontend/qanimationclipdata.h101
-rw-r--r--src/animation/frontend/qanimationcliploader.cpp137
-rw-r--r--src/animation/frontend/qanimationcliploader.h (renamed from src/animation/backend/conductedclipanimator.cpp)76
-rw-r--r--src/animation/frontend/qanimationcliploader_p.h (renamed from src/animation/backend/conductedclipanimator_p.h)30
-rw-r--r--src/animation/frontend/qanimationcontroller.cpp (renamed from src/extras/animations/qanimationcontroller.cpp)170
-rw-r--r--src/animation/frontend/qanimationcontroller.h (renamed from src/extras/animations/qanimationcontroller.h)28
-rw-r--r--src/animation/frontend/qanimationcontroller_p.h (renamed from src/extras/animations/qanimationcontroller_p.h)14
-rw-r--r--src/animation/frontend/qanimationgroup.cpp212
-rw-r--r--src/animation/frontend/qanimationgroup.h (renamed from src/extras/animations/qanimationgroup.h)24
-rw-r--r--src/animation/frontend/qanimationgroup_p.h (renamed from src/extras/animations/qanimationgroup_p.h)14
-rw-r--r--src/animation/frontend/qblendedclipanimator.cpp279
-rw-r--r--src/animation/frontend/qblendedclipanimator.h19
-rw-r--r--src/animation/frontend/qblendedclipanimator_p.h13
-rw-r--r--src/animation/frontend/qchannel.cpp142
-rw-r--r--src/animation/frontend/qchannel.h98
-rw-r--r--src/animation/frontend/qchannelcomponent.cpp (renamed from src/quick3d/quick3danimation/items/quick3dabstractclipblendnode.cpp)106
-rw-r--r--src/animation/frontend/qchannelcomponent.h98
-rw-r--r--src/animation/frontend/qchannelmapper.h2
-rw-r--r--src/animation/frontend/qchannelmapping.h2
-rw-r--r--src/animation/frontend/qclipanimator.cpp130
-rw-r--r--src/animation/frontend/qclipanimator.h26
-rw-r--r--src/animation/frontend/qclipanimator_p.h17
-rw-r--r--src/animation/frontend/qclipblendnodecreatedchange.cpp17
-rw-r--r--src/animation/frontend/qclipblendnodecreatedchange.h3
-rw-r--r--src/animation/frontend/qclipblendnodecreatedchange_p.h3
-rw-r--r--src/animation/frontend/qclipblendvalue.cpp112
-rw-r--r--src/animation/frontend/qclipblendvalue.h83
-rw-r--r--src/animation/frontend/qclipblendvalue_p.h80
-rw-r--r--src/animation/frontend/qkeyframe.cpp (renamed from src/quick3d/imports/extras/defaults/qml/PerVertexColorMaterial.qml)20
-rw-r--r--src/animation/frontend/qkeyframe.h160
-rw-r--r--src/animation/frontend/qkeyframeanimation.cpp415
-rw-r--r--src/animation/frontend/qkeyframeanimation.h (renamed from src/extras/animations/qkeyframeanimation.h)28
-rw-r--r--src/animation/frontend/qkeyframeanimation_p.h (renamed from src/extras/animations/qkeyframeanimation_p.h)13
-rw-r--r--src/animation/frontend/qlerpclipblend.cpp (renamed from src/animation/frontend/qlerpblend.cpp)128
-rw-r--r--src/animation/frontend/qlerpclipblend.h86
-rw-r--r--src/animation/frontend/qlerpclipblend_p.h (renamed from src/animation/frontend/qlerpblend_p.h)16
-rw-r--r--src/animation/frontend/qmorphinganimation.cpp453
-rw-r--r--src/animation/frontend/qmorphinganimation.h (renamed from src/extras/animations/qmorphinganimation.h)34
-rw-r--r--src/animation/frontend/qmorphinganimation_p.h (renamed from src/extras/animations/qmorphinganimation_p.h)16
-rw-r--r--src/animation/frontend/qmorphtarget.cpp (renamed from src/extras/animations/qmorphtarget.cpp)80
-rw-r--r--src/animation/frontend/qmorphtarget.h (renamed from src/extras/animations/qmorphtarget.h)14
-rw-r--r--src/animation/frontend/qmorphtarget_p.h (renamed from src/extras/animations/qmorphtarget_p.h)12
-rw-r--r--src/animation/frontend/qvertexblendanimation.cpp (renamed from src/extras/animations/qvertexblendanimation.cpp)143
-rw-r--r--src/animation/frontend/qvertexblendanimation.h (renamed from src/extras/animations/qvertexblendanimation.h)26
-rw-r--r--src/animation/frontend/qvertexblendanimation_p.h (renamed from src/extras/animations/qvertexblendanimation_p.h)14
-rw-r--r--src/animation/job_common_p.h79
-rw-r--r--src/core/aspects/aspectcommanddebugger.cpp12
-rw-r--r--src/core/aspects/aspectcommanddebugger_p.h4
-rw-r--r--src/core/aspects/aspects.pri13
-rw-r--r--src/core/aspects/qabstractaspect.cpp39
-rw-r--r--src/core/aspects/qabstractaspect.h15
-rw-r--r--src/core/aspects/qabstractaspect_p.h20
-rw-r--r--src/core/aspects/qaspectengine.cpp41
-rw-r--r--src/core/aspects/qaspectengine.h5
-rw-r--r--src/core/aspects/qaspectengine_p.h6
-rw-r--r--src/core/aspects/qaspectfactory.cpp6
-rw-r--r--src/core/aspects/qaspectfactory_p.h4
-rw-r--r--src/core/aspects/qaspectmanager.cpp32
-rw-r--r--src/core/aspects/qaspectmanager_p.h11
-rw-r--r--src/core/aspects/qaspectthread.cpp5
-rw-r--r--src/core/aspects/qaspectthread_p.h4
-rw-r--r--src/core/changes/changes.pri7
-rw-r--r--src/core/changes/qcomponentaddedchange.cpp4
-rw-r--r--src/core/changes/qcomponentaddedchange_p.h5
-rw-r--r--src/core/changes/qcomponentremovedchange.cpp4
-rw-r--r--src/core/changes/qcomponentremovedchange_p.h5
-rw-r--r--src/core/changes/qdynamicpropertyupdatedchange_p.h3
-rw-r--r--src/core/changes/qnodecommand.cpp151
-rw-r--r--src/core/changes/qnodecommand.h85
-rw-r--r--src/core/changes/qnodecommand_p.h75
-rw-r--r--src/core/changes/qnodecreatedchange.cpp2
-rw-r--r--src/core/changes/qnodecreatedchange.h3
-rw-r--r--src/core/changes/qnodecreatedchange_p.h5
-rw-r--r--src/core/changes/qnodedestroyedchange.h2
-rw-r--r--src/core/changes/qnodedestroyedchange_p.h3
-rw-r--r--src/core/changes/qpropertynodeaddedchange.cpp1
-rw-r--r--src/core/changes/qpropertynodeaddedchange_p.h3
-rw-r--r--src/core/changes/qpropertynoderemovedchange.cpp1
-rw-r--r--src/core/changes/qpropertynoderemovedchange_p.h3
-rw-r--r--src/core/changes/qpropertyupdatedchange_p.h5
-rw-r--r--src/core/changes/qpropertyupdatedchangebase.cpp2
-rw-r--r--src/core/changes/qpropertyupdatedchangebase_p.h9
-rw-r--r--src/core/changes/qpropertyvalueaddedchange_p.h5
-rw-r--r--src/core/changes/qpropertyvalueaddedchangebase.cpp1
-rw-r--r--src/core/changes/qpropertyvalueaddedchangebase_p.h2
-rw-r--r--src/core/changes/qpropertyvalueremovedchange.cpp1
-rw-r--r--src/core/changes/qpropertyvalueremovedchange_p.h5
-rw-r--r--src/core/changes/qpropertyvalueremovedchangebase.cpp1
-rw-r--r--src/core/changes/qpropertyvalueremovedchangebase_p.h2
-rw-r--r--src/core/changes/qscenechange.cpp1
-rw-r--r--src/core/changes/qscenechange.h5
-rw-r--r--src/core/changes/qscenechange_p.h5
-rw-r--r--src/core/changes/qstaticpropertyupdatedchangebase.cpp1
-rw-r--r--src/core/changes/qstaticpropertyupdatedchangebase_p.h2
-rw-r--r--src/core/changes/qstaticpropertyvalueaddedchangebase.cpp1
-rw-r--r--src/core/changes/qstaticpropertyvalueaddedchangebase_p.h2
-rw-r--r--src/core/changes/qstaticpropertyvalueremovedchangebase_p.h2
-rw-r--r--src/core/configure.json26
-rw-r--r--src/core/corelogging.cpp8
-rw-r--r--src/core/corelogging_p.h2
-rw-r--r--src/core/jobs/dependencyhandler.cpp5
-rw-r--r--src/core/jobs/dependencyhandler_p.h9
-rw-r--r--src/core/jobs/qabstractaspectjobmanager_p.h3
-rw-r--r--src/core/jobs/qaspectjob.cpp3
-rw-r--r--src/core/jobs/qaspectjob.h4
-rw-r--r--src/core/jobs/qaspectjob_p.h4
-rw-r--r--src/core/jobs/qaspectjobmanager.cpp17
-rw-r--r--src/core/jobs/qaspectjobmanager_p.h7
-rw-r--r--src/core/jobs/qaspectjobproviderinterface_p.h4
-rw-r--r--src/core/jobs/qthreadpooler.cpp29
-rw-r--r--src/core/jobs/qthreadpooler_p.h15
-rw-r--r--src/core/jobs/task.cpp27
-rw-r--r--src/core/jobs/task_p.h9
-rw-r--r--src/core/nodes/propertychangehandler_p.h11
-rw-r--r--src/core/nodes/qabstractnodefactory_p.h3
-rw-r--r--src/core/nodes/qbackendnode.cpp30
-rw-r--r--src/core/nodes/qbackendnode.h8
-rw-r--r--src/core/nodes/qbackendnode_p.h6
-rw-r--r--src/core/nodes/qcomponent.cpp8
-rw-r--r--src/core/nodes/qcomponent_p.h4
-rw-r--r--src/core/nodes/qdestructionidandtypecollector_p.h2
-rw-r--r--src/core/nodes/qentity.cpp13
-rw-r--r--src/core/nodes/qentity.h3
-rw-r--r--src/core/nodes/qentity_p.h7
-rw-r--r--src/core/nodes/qnode.cpp181
-rw-r--r--src/core/nodes/qnode.h38
-rw-r--r--src/core/nodes/qnode_p.h16
-rw-r--r--src/core/nodes/qnodecreatedchangegenerator.cpp1
-rw-r--r--src/core/nodes/qnodecreatedchangegenerator_p.h5
-rw-r--r--src/core/nodes/qnodeid.cpp2
-rw-r--r--src/core/nodes/qnodeid.h2
-rw-r--r--src/core/nodes/qnodevisitor_p.h4
-rw-r--r--src/core/qbackendnodefactory_p.h3
-rw-r--r--src/core/qchangearbiter.cpp19
-rw-r--r--src/core/qchangearbiter_p.h17
-rw-r--r--src/core/qobservableinterface_p.h3
-rw-r--r--src/core/qpostman.cpp33
-rw-r--r--src/core/qscene.cpp25
-rw-r--r--src/core/qscene_p.h17
-rw-r--r--src/core/qsceneobserverinterface_p.h3
-rw-r--r--src/core/qscheduler.cpp10
-rw-r--r--src/core/qscheduler_p.h2
-rw-r--r--src/core/qtickclock.cpp3
-rw-r--r--src/core/qtickclock_p.h3
-rw-r--r--src/core/resources/qboundedcircularbuffer_p.h10
-rw-r--r--src/core/resources/qcircularbuffer_p.h12
-rw-r--r--src/core/resources/qframeallocator_p.h7
-rw-r--r--src/core/resources/qhandlemanager_p.h6
-rw-r--r--src/core/resources/qresourcemanager_p.h15
-rw-r--r--src/core/services/nullservices_p.h5
-rw-r--r--src/core/services/qabstractframeadvanceservice_p.h4
-rw-r--r--src/core/services/qabstractframeadvanceservice_p_p.h1
-rw-r--r--src/core/services/qabstractserviceprovider_p.h11
-rw-r--r--src/core/services/qdownloadhelperservice.cpp216
-rw-r--r--src/core/services/qdownloadhelperservice_p.h130
-rw-r--r--src/core/services/qdownloadhelperservice_p_p.h76
-rw-r--r--src/core/services/qdownloadnetworkworker.cpp148
-rw-r--r--src/core/services/qdownloadnetworkworker_p.h101
-rw-r--r--src/core/services/qeventfilterservice.cpp12
-rw-r--r--src/core/services/qeventfilterservice_p.h2
-rw-r--r--src/core/services/qopenglinformationservice.cpp2
-rw-r--r--src/core/services/qopenglinformationservice_p.h6
-rw-r--r--src/core/services/qopenglinformationservice_p_p.h1
-rw-r--r--src/core/services/qservicelocator.cpp33
-rw-r--r--src/core/services/qservicelocator_p.h14
-rw-r--r--src/core/services/qsysteminformationservice_p.h4
-rw-r--r--src/core/services/qsysteminformationservice_p_p.h1
-rw-r--r--src/core/services/qtickclockservice.cpp7
-rw-r--r--src/core/services/qtickclockservice_p.h3
-rw-r--r--src/core/services/services.pri8
-rw-r--r--src/core/transforms/qmath3d_p.h1
-rw-r--r--src/core/transforms/qtransform.cpp3
-rw-r--r--src/core/transforms/qtransform.h1
-rw-r--r--src/core/transforms/qtransform_p.h2
-rw-r--r--src/doc/qt3d.qdocconf27
-rw-r--r--src/doc/src/levelofdetailloader.qdoc2
-rw-r--r--src/doc/src/qt3d-index.qdoc5
-rw-r--r--src/doc/src/qt3d-module.qdoc15
-rw-r--r--src/doc/src/qt3danimation-module.qdoc228
-rw-r--r--src/doc/src/qt3dscene2d-module.qdoc94
-rw-r--r--src/extras/3dtext/3dtext.pri10
-rw-r--r--src/extras/3dtext/qextrudedtextgeometry.cpp (renamed from src/extras/3dtext/qtext3dgeometry.cpp)152
-rw-r--r--src/extras/3dtext/qextrudedtextgeometry.h (renamed from src/extras/3dtext/qtext3dgeometry.h)38
-rw-r--r--src/extras/3dtext/qextrudedtextgeometry_p.h (renamed from src/extras/3dtext/qtext3dgeometry_p.h)14
-rw-r--r--src/extras/3dtext/qextrudedtextmesh.cpp (renamed from src/extras/3dtext/qtext3dmesh.cpp)86
-rw-r--r--src/extras/3dtext/qextrudedtextmesh.h (renamed from src/extras/3dtext/qtext3dmesh.h)30
-rw-r--r--src/extras/animations/animations.pri26
-rw-r--r--src/extras/animations/qanimationgroup.cpp125
-rw-r--r--src/extras/animations/qkeyframeanimation.cpp262
-rw-r--r--src/extras/animations/qmorphinganimation.cpp280
-rw-r--r--src/extras/defaults/defaults.pri14
-rw-r--r--src/extras/defaults/qdiffusemapmaterial.cpp7
-rw-r--r--src/extras/defaults/qdiffusemapmaterial.h2
-rw-r--r--src/extras/defaults/qdiffusespecularmapmaterial.cpp7
-rw-r--r--src/extras/defaults/qdiffusespecularmapmaterial.h2
-rw-r--r--src/extras/defaults/qfirstpersoncameracontroller.cpp143
-rw-r--r--src/extras/defaults/qfirstpersoncameracontroller.h59
-rw-r--r--src/extras/defaults/qfirstpersoncameracontroller_p.h11
-rw-r--r--src/extras/defaults/qforwardrenderer.cpp61
-rw-r--r--src/extras/defaults/qforwardrenderer.h14
-rw-r--r--src/extras/defaults/qgoochmaterial.cpp2
-rw-r--r--src/extras/defaults/qgoochmaterial.h2
-rw-r--r--src/extras/defaults/qmetalroughmaterial.cpp240
-rw-r--r--src/extras/defaults/qmetalroughmaterial.h93
-rw-r--r--src/extras/defaults/qmetalroughmaterial_p.h106
-rw-r--r--src/extras/defaults/qnormaldiffusemapalphamaterial.cpp7
-rw-r--r--src/extras/defaults/qnormaldiffusemapalphamaterial_p.h2
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial.cpp8
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial.h2
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial_p.h2
-rw-r--r--src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp7
-rw-r--r--src/extras/defaults/qnormaldiffusespecularmapmaterial.h2
-rw-r--r--src/extras/defaults/qorbitcameracontroller.cpp20
-rw-r--r--src/extras/defaults/qorbitcameracontroller.h2
-rw-r--r--src/extras/defaults/qorbitcameracontroller_p.h7
-rw-r--r--src/extras/defaults/qpervertexcolormaterial.cpp7
-rw-r--r--src/extras/defaults/qpervertexcolormaterial.h2
-rw-r--r--src/extras/defaults/qphongalphamaterial.cpp7
-rw-r--r--src/extras/defaults/qphongalphamaterial.h6
-rw-r--r--src/extras/defaults/qphongmaterial.cpp8
-rw-r--r--src/extras/defaults/qphongmaterial.h2
-rw-r--r--src/extras/defaults/qskyboxentity.cpp56
-rw-r--r--src/extras/defaults/qskyboxentity.h13
-rw-r--r--src/extras/defaults/qskyboxentity_p.h6
-rw-r--r--src/extras/defaults/qt3dwindow.cpp90
-rw-r--r--src/extras/defaults/qt3dwindow.h28
-rw-r--r--src/extras/defaults/qt3dwindow_p.h92
-rw-r--r--src/extras/defaults/qtexturedmetalroughmaterial.cpp373
-rw-r--r--src/extras/defaults/qtexturedmetalroughmaterial.h96
-rw-r--r--src/extras/defaults/qtexturedmetalroughmaterial_p.h115
-rw-r--r--src/extras/defaults/qtexturematerial.cpp209
-rw-r--r--src/extras/defaults/qtexturematerial.h87
-rw-r--r--src/extras/defaults/qtexturematerial_p.h104
-rw-r--r--src/extras/extras.pro2
-rw-r--r--src/extras/extras.qrc7
-rw-r--r--src/extras/geometries/qconegeometry.cpp4
-rw-r--r--src/extras/geometries/qconemesh.cpp6
-rw-r--r--src/extras/geometries/qcuboidgeometry.cpp3
-rw-r--r--src/extras/geometries/qcuboidgeometry.h2
-rw-r--r--src/extras/geometries/qcuboidgeometry_p.h3
-rw-r--r--src/extras/geometries/qcuboidmesh.cpp3
-rw-r--r--src/extras/geometries/qcuboidmesh.h2
-rw-r--r--src/extras/geometries/qcylindergeometry.cpp5
-rw-r--r--src/extras/geometries/qcylindermesh.cpp6
-rw-r--r--src/extras/geometries/qplanegeometry.cpp49
-rw-r--r--src/extras/geometries/qplanegeometry.h6
-rw-r--r--src/extras/geometries/qplanegeometry_p.h4
-rw-r--r--src/extras/geometries/qplanemesh.cpp27
-rw-r--r--src/extras/geometries/qplanemesh.h6
-rw-r--r--src/extras/geometries/qspheregeometry.cpp4
-rw-r--r--src/extras/geometries/qspheremesh.cpp3
-rw-r--r--src/extras/geometries/qtorusgeometry.cpp6
-rw-r--r--src/extras/geometries/qtorusmesh.cpp3
-rw-r--r--src/extras/shaders/es2/distancefieldtext.frag36
-rw-r--r--src/extras/shaders/es2/distancefieldtext.vert17
-rw-r--r--src/extras/shaders/es2/light.inc.frag108
-rw-r--r--src/extras/shaders/gl3/distancefieldtext.frag38
-rw-r--r--src/extras/shaders/gl3/distancefieldtext.vert19
-rw-r--r--src/extras/shaders/gl3/light.inc.frag8
-rw-r--r--src/extras/shaders/gl3/metalrough.frag395
-rw-r--r--src/extras/shaders/gl3/metalrough.vert (renamed from src/quick3d/imports/extras/defaults/qml/LevelOfDetailLoader.qml)49
-rw-r--r--src/extras/shaders/gl3/metalroughuniform.frag371
-rw-r--r--src/extras/shaders/gl3/skybox.frag16
-rw-r--r--src/extras/text/areaallocator.cpp296
-rw-r--r--src/extras/text/areaallocator_p.h92
-rw-r--r--src/extras/text/distancefieldtextrenderer.cpp156
-rw-r--r--src/extras/text/distancefieldtextrenderer_p.h90
-rw-r--r--src/extras/text/distancefieldtextrenderer_p_p.h95
-rw-r--r--src/extras/text/qdistancefieldglyphcache.cpp370
-rw-r--r--src/extras/text/qdistancefieldglyphcache_p.h111
-rw-r--r--src/extras/text/qtext2dentity.cpp381
-rw-r--r--src/extras/text/qtext2dentity.h (renamed from src/animation/frontend/qconductedclipanimator.cpp)74
-rw-r--r--src/extras/text/qtext2dentity_p.h122
-rw-r--r--src/extras/text/qtext2dmaterial.cpp179
-rw-r--r--src/extras/text/qtext2dmaterial_p.h (renamed from src/animation/frontend/qconductedclipanimator.h)47
-rw-r--r--src/extras/text/qtext2dmaterial_p_p.h106
-rw-r--r--src/extras/text/qtextureatlas.cpp303
-rw-r--r--src/extras/text/qtextureatlas_p.h95
-rw-r--r--src/extras/text/qtextureatlas_p_p.h139
-rw-r--r--src/extras/text/text.pri21
-rw-r--r--src/input/backend/abstractaxisinput.cpp10
-rw-r--r--src/input/backend/action.cpp6
-rw-r--r--src/input/backend/actioninput.cpp4
-rw-r--r--src/input/backend/actioninput_p.h3
-rw-r--r--src/input/backend/analogaxisinput.cpp4
-rw-r--r--src/input/backend/assignkeyboardfocusjob.cpp11
-rw-r--r--src/input/backend/axis.cpp6
-rw-r--r--src/input/backend/axisaccumulator.cpp9
-rw-r--r--src/input/backend/axisaccumulator_p.h3
-rw-r--r--src/input/backend/axisaccumulatorjob.cpp1
-rw-r--r--src/input/backend/axisaccumulatorjob_p.h2
-rw-r--r--src/input/backend/axissetting.cpp4
-rw-r--r--src/input/backend/buttonaxisinput.cpp4
-rw-r--r--src/input/backend/eventsourcesetterhelper.cpp3
-rw-r--r--src/input/backend/eventsourcesetterhelper_p.h4
-rw-r--r--src/input/backend/genericdevicebackendnode.cpp7
-rw-r--r--src/input/backend/genericdevicebackendnode_p.h5
-rw-r--r--src/input/backend/inputchord.cpp6
-rw-r--r--src/input/backend/inputchord_p.h3
-rw-r--r--src/input/backend/inputhandler.cpp39
-rw-r--r--src/input/backend/inputhandler_p.h11
-rw-r--r--src/input/backend/inputmanagers_p.h5
-rw-r--r--src/input/backend/inputsequence.cpp12
-rw-r--r--src/input/backend/inputsequence_p.h3
-rw-r--r--src/input/backend/inputsettings.cpp4
-rw-r--r--src/input/backend/inputsettings_p.h2
-rw-r--r--src/input/backend/keyboarddevice.cpp8
-rw-r--r--src/input/backend/keyboarddevice_p.h5
-rw-r--r--src/input/backend/keyboardeventfilter.cpp8
-rw-r--r--src/input/backend/keyboardeventfilter_p.h2
-rw-r--r--src/input/backend/keyboardhandler.cpp15
-rw-r--r--src/input/backend/keyboardhandler_p.h2
-rw-r--r--src/input/backend/keyboardmousegenericdeviceintegration.cpp1
-rw-r--r--src/input/backend/keyeventdispatcherjob.cpp9
-rw-r--r--src/input/backend/keyeventdispatcherjob_p.h2
-rw-r--r--src/input/backend/loadproxydevicejob.cpp3
-rw-r--r--src/input/backend/logicaldevice.cpp12
-rw-r--r--src/input/backend/mousedevice.cpp13
-rw-r--r--src/input/backend/mousedevice_p.h5
-rw-r--r--src/input/backend/mouseeventdispatcherjob.cpp20
-rw-r--r--src/input/backend/mouseeventdispatcherjob_p.h11
-rw-r--r--src/input/backend/mouseeventfilter.cpp10
-rw-r--r--src/input/backend/mouseeventfilter_p.h2
-rw-r--r--src/input/backend/mousehandler.cpp14
-rw-r--r--src/input/backend/mousehandler_p.h4
-rw-r--r--src/input/backend/physicaldeviceproxy.cpp10
-rw-r--r--src/input/backend/qabstractphysicaldevicebackendnode.cpp16
-rw-r--r--src/input/backend/qabstractphysicaldevicebackendnode_p.h1
-rw-r--r--src/input/backend/qabstractphysicaldevicebackendnode_p_p.h7
-rw-r--r--src/input/backend/updateaxisactionjob.cpp1
-rw-r--r--src/input/backend/updateaxisactionjob_p.h1
-rw-r--r--src/input/frontend/qabstractactioninput.cpp1
-rw-r--r--src/input/frontend/qabstractactioninput_p.h3
-rw-r--r--src/input/frontend/qabstractaxisinput.cpp3
-rw-r--r--src/input/frontend/qabstractaxisinput.h2
-rw-r--r--src/input/frontend/qabstractaxisinput_p.h3
-rw-r--r--src/input/frontend/qabstractphysicaldevice.cpp4
-rw-r--r--src/input/frontend/qabstractphysicaldevice_p.h3
-rw-r--r--src/input/frontend/qabstractphysicaldeviceproxy.cpp2
-rw-r--r--src/input/frontend/qabstractphysicaldeviceproxy_p.h1
-rw-r--r--src/input/frontend/qaction.cpp6
-rw-r--r--src/input/frontend/qactioninput.cpp3
-rw-r--r--src/input/frontend/qactioninput.h2
-rw-r--r--src/input/frontend/qactioninput_p.h3
-rw-r--r--src/input/frontend/qanalogaxisinput.cpp1
-rw-r--r--src/input/frontend/qaxis.cpp1
-rw-r--r--src/input/frontend/qaxisaccumulator.cpp19
-rw-r--r--src/input/frontend/qaxisaccumulator_p.h3
-rw-r--r--src/input/frontend/qaxissetting.cpp1
-rw-r--r--src/input/frontend/qaxissetting.h3
-rw-r--r--src/input/frontend/qbuttonaxisinput.cpp1
-rw-r--r--src/input/frontend/qgamepadinput.cpp7
-rw-r--r--src/input/frontend/qgamepadinput_p.h1
-rw-r--r--src/input/frontend/qgenericinputdevice.cpp2
-rw-r--r--src/input/frontend/qgenericinputdevice_p.h1
-rw-r--r--src/input/frontend/qinputaspect.cpp74
-rw-r--r--src/input/frontend/qinputaspect_p.h2
-rw-r--r--src/input/frontend/qinputchord.cpp3
-rw-r--r--src/input/frontend/qinputchord.h2
-rw-r--r--src/input/frontend/qinputchord_p.h3
-rw-r--r--src/input/frontend/qinputdeviceintegration_p.h6
-rw-r--r--src/input/frontend/qinputdeviceintegration_p_p.h4
-rw-r--r--src/input/frontend/qinputdeviceintegrationfactory.cpp11
-rw-r--r--src/input/frontend/qinputdeviceplugin_p.h2
-rw-r--r--src/input/frontend/qinputsequence.cpp12
-rw-r--r--src/input/frontend/qinputsequence.h2
-rw-r--r--src/input/frontend/qinputsequence_p.h3
-rw-r--r--src/input/frontend/qinputsettings.cpp1
-rw-r--r--src/input/frontend/qinputsettings.h2
-rw-r--r--src/input/frontend/qinputsettings_p.h3
-rw-r--r--src/input/frontend/qkeyboarddevice.cpp6
-rw-r--r--src/input/frontend/qkeyboarddevice.h2
-rw-r--r--src/input/frontend/qkeyboarddevice_p.h3
-rw-r--r--src/input/frontend/qkeyboardhandler.cpp3
-rw-r--r--src/input/frontend/qkeyboardhandler_p.h2
-rw-r--r--src/input/frontend/qkeyevent.h6
-rw-r--r--src/input/frontend/qlogicaldevice.cpp7
-rw-r--r--src/input/frontend/qlogicaldevice_p.h3
-rw-r--r--src/input/frontend/qmousedevice.cpp3
-rw-r--r--src/input/frontend/qmousedevice.h2
-rw-r--r--src/input/frontend/qmousedevice_p.h2
-rw-r--r--src/input/frontend/qmouseevent.cpp2
-rw-r--r--src/input/frontend/qmouseevent.h17
-rw-r--r--src/input/frontend/qmousehandler.cpp11
-rw-r--r--src/input/frontend/qmousehandler.h2
-rw-r--r--src/input/frontend/qmousehandler_p.h3
-rw-r--r--src/input/frontend/qphysicaldevicecreatedchange.cpp2
-rw-r--r--src/logic/callbackjob.cpp5
-rw-r--r--src/logic/executor.cpp6
-rw-r--r--src/logic/handler.cpp6
-rw-r--r--src/logic/manager.cpp11
-rw-r--r--src/logic/manager_p.h3
-rw-r--r--src/logic/managers_p.h5
-rw-r--r--src/logic/qframeaction.cpp1
-rw-r--r--src/logic/qframeaction_p.h2
-rw-r--r--src/logic/qlogicaspect.cpp17
-rw-r--r--src/logic/qlogicaspect_p.h3
-rw-r--r--src/plugins/geometryloaders/default/basegeometryloader.cpp2
-rw-r--r--src/plugins/geometryloaders/default/basegeometryloader_p.h20
-rw-r--r--src/plugins/geometryloaders/default/objgeometryloader.cpp12
-rw-r--r--src/plugins/geometryloaders/default/plygeometryloader.cpp2
-rw-r--r--src/plugins/geometryloaders/default/stlgeometryloader.cpp2
-rw-r--r--src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp2
-rw-r--r--src/plugins/geometryloaders/geometryloaders.pro2
-rw-r--r--src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp2
-rw-r--r--src/plugins/renderplugins/renderplugins.pro2
-rw-r--r--src/plugins/renderplugins/scene2d/main.cpp (renamed from src/quick3d/imports/extras/defaults/qml/TextureMaterial.qml)45
-rw-r--r--src/plugins/renderplugins/scene2d/scene2d.pro19
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.cpp111
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.h92
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.json3
-rw-r--r--src/plugins/sceneparsers/assimp/assimp.pro2
-rw-r--r--src/plugins/sceneparsers/assimp/assimphelpers.cpp10
-rw-r--r--src/plugins/sceneparsers/assimp/assimphelpers.h5
-rw-r--r--src/plugins/sceneparsers/assimp/assimpimporter.cpp180
-rw-r--r--src/plugins/sceneparsers/assimp/assimpimporter.h25
-rw-r--r--src/plugins/sceneparsers/gltf/gltfimporter.cpp47
-rw-r--r--src/plugins/sceneparsers/gltf/gltfimporter.h11
-rw-r--r--src/plugins/sceneparsers/gltf/gltfio.cpp1588
-rw-r--r--src/plugins/sceneparsers/gltfexport/gltfexporter.cpp49
-rw-r--r--src/plugins/sceneparsers/sceneparsers.pro10
-rw-r--r--src/quick3d/imports/animation/plugins.qmltypes670
-rw-r--r--src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp54
-rw-r--r--src/quick3d/imports/core/plugins.qmltypes82
-rw-r--r--src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp19
-rw-r--r--src/quick3d/imports/core/qt3dquick3dcoreplugin.h1
-rw-r--r--src/quick3d/imports/extras/defaults/defaults.pri26
-rw-r--r--src/quick3d/imports/extras/defaults/qml/DefaultAlphaEffect.qml148
-rw-r--r--src/quick3d/imports/extras/defaults/qml/DefaultEffect.qml104
-rw-r--r--src/quick3d/imports/extras/defaults/qml/DiffuseMapMaterial.qml81
-rw-r--r--src/quick3d/imports/extras/defaults/qml/DiffuseSpecularMapMaterial.qml93
-rw-r--r--src/quick3d/imports/extras/defaults/qml/FirstPersonCameraController.qml191
-rw-r--r--src/quick3d/imports/extras/defaults/qml/ForwardRenderer.qml77
-rw-r--r--src/quick3d/imports/extras/defaults/qml/GoochMaterial.qml71
-rw-r--r--src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaEffect.qml115
-rw-r--r--src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaMaterial.qml92
-rw-r--r--src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapMaterial.qml97
-rw-r--r--src/quick3d/imports/extras/defaults/qml/NormalDiffuseSpecularMapMaterial.qml110
-rw-r--r--src/quick3d/imports/extras/defaults/qml/OrbitCameraController.qml236
-rw-r--r--src/quick3d/imports/extras/defaults/qml/PhongAlphaMaterial.qml68
-rw-r--r--src/quick3d/imports/extras/defaults/qml/SkyboxEntity.qml151
-rw-r--r--src/quick3d/imports/extras/importsextras.pro30
-rw-r--r--src/quick3d/imports/extras/plugins.qmltypes1181
-rw-r--r--src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp127
-rw-r--r--src/quick3d/imports/extras/qt3dquick3dextrasplugin.h1
-rw-r--r--src/quick3d/imports/input/plugins.qmltypes86
-rw-r--r--src/quick3d/imports/input/qt3dquick3dinputplugin.cpp34
-rw-r--r--src/quick3d/imports/logic/plugins.qmltypes27
-rw-r--r--src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp5
-rw-r--r--src/quick3d/imports/render/importsrender.pro2
-rw-r--r--src/quick3d/imports/render/plugins.qmltypes438
-rw-r--r--src/quick3d/imports/render/qt3dquick3drenderplugin.cpp155
-rw-r--r--src/quick3d/imports/scene2d/importsscene2d.pro19
-rw-r--r--src/quick3d/imports/scene2d/plugins.qmltypes121
-rw-r--r--src/quick3d/imports/scene2d/qmldir3
-rw-r--r--src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp58
-rw-r--r--src/quick3d/imports/scene2d/qtquickscene2dplugin.h62
-rw-r--r--src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp6
-rw-r--r--src/quick3d/imports/scene3d/scene3dcleaner.cpp6
-rw-r--r--src/quick3d/imports/scene3d/scene3dcleaner_p.h2
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp45
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem_p.h7
-rw-r--r--src/quick3d/imports/scene3d/scene3dlogging.cpp2
-rw-r--r--src/quick3d/imports/scene3d/scene3dlogging_p.h2
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp70
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h7
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial_p.h4
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp10
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h1
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode.cpp3
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode_p.h2
-rw-r--r--src/quick3d/quick3d/items/items.pri6
-rw-r--r--src/quick3d/quick3d/items/quick3dentity.cpp7
-rw-r--r--src/quick3d/quick3d/items/quick3dentity_p.h5
-rw-r--r--src/quick3d/quick3d/items/quick3dentityloader.cpp97
-rw-r--r--src/quick3d/quick3d/items/quick3dentityloader_p.h17
-rw-r--r--src/quick3d/quick3d/items/quick3dentityloader_p_p.h7
-rw-r--r--src/quick3d/quick3d/items/quick3dnode.cpp3
-rw-r--r--src/quick3d/quick3d/items/quick3dnode_p.h3
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp10
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h3
-rw-r--r--src/quick3d/quick3d/items/quick3dnodev9.cpp203
-rw-r--r--src/quick3d/quick3d/items/quick3dnodev9_p.h109
-rw-r--r--src/quick3d/quick3d/qqmlaspectengine.cpp7
-rw-r--r--src/quick3d/quick3d/qqmlaspectengine.h2
-rw-r--r--src/quick3d/quick3d/qqmlaspectengine_p.h5
-rw-r--r--src/quick3d/quick3d/qquaternionanimation.cpp1
-rw-r--r--src/quick3d/quick3d/qquaternionanimation_p.h3
-rw-r--r--src/quick3d/quick3d/qt3dquick_global.cpp21
-rw-r--r--src/quick3d/quick3d/qt3dquick_global_p.h1
-rw-r--r--src/quick3d/quick3d/qt3dquicknodefactory.cpp1
-rw-r--r--src/quick3d/quick3d/qt3dquicknodefactory_p.h3
-rw-r--r--src/quick3d/quick3d/qt3dquickvaluetypes_p.h10
-rw-r--r--src/quick3d/quick3danimation/items/items.pri14
-rw-r--r--src/quick3d/quick3danimation/items/quick3danimationcontroller.cpp (renamed from src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp)4
-rw-r--r--src/quick3d/quick3danimation/items/quick3danimationcontroller_p.h (renamed from src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h)32
-rw-r--r--src/quick3d/quick3danimation/items/quick3danimationgroup.cpp (renamed from src/quick3d/quick3dextras/items/quick3danimationgroup.cpp)24
-rw-r--r--src/quick3d/quick3danimation/items/quick3danimationgroup_p.h (renamed from src/quick3d/quick3dextras/items/quick3danimationgroup_p.h)32
-rw-r--r--src/quick3d/quick3danimation/items/quick3dchannelmapper_p.h2
-rw-r--r--src/quick3d/quick3danimation/items/quick3dkeyframeanimation.cpp (renamed from src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp)4
-rw-r--r--src/quick3d/quick3danimation/items/quick3dkeyframeanimation_p.h (renamed from src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h)16
-rw-r--r--src/quick3d/quick3danimation/items/quick3dmorphinganimation.cpp (renamed from src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp)22
-rw-r--r--src/quick3d/quick3danimation/items/quick3dmorphinganimation_p.h (renamed from src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h)30
-rw-r--r--src/quick3d/quick3danimation/items/quick3dmorphtarget.cpp (renamed from src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp)4
-rw-r--r--src/quick3d/quick3danimation/items/quick3dmorphtarget_p.h (renamed from src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h)16
-rw-r--r--src/quick3d/quick3danimation/items/quick3dvertexblendanimation.cpp104
-rw-r--r--src/quick3d/quick3danimation/items/quick3dvertexblendanimation_p.h93
-rw-r--r--src/quick3d/quick3dextras/items/items.pri13
-rw-r--r--src/quick3d/quick3dextras/items/quick3dlevelofdetailloader.cpp194
-rw-r--r--src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p.h121
-rw-r--r--src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p_p.h87
-rw-r--r--src/quick3d/quick3dextras/qt3dquickextras_global_p.h (renamed from src/render/frontend/qboundingsphere_p.h)27
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow.cpp106
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow.h18
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow_p.h86
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindowlogging.cpp50
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindowlogging_p.h66
-rw-r--r--src/quick3d/quick3dextras/quick3dextras.pro12
-rw-r--r--src/quick3d/quick3dinput/items/quick3daction.cpp2
-rw-r--r--src/quick3d/quick3dinput/items/quick3daction_p.h5
-rw-r--r--src/quick3d/quick3dinput/items/quick3daxis.cpp2
-rw-r--r--src/quick3d/quick3dinput/items/quick3daxis_p.h7
-rw-r--r--src/quick3d/quick3dinput/items/quick3dinputchord.cpp2
-rw-r--r--src/quick3d/quick3dinput/items/quick3dinputchord_p.h5
-rw-r--r--src/quick3d/quick3dinput/items/quick3dinputsequence.cpp2
-rw-r--r--src/quick3d/quick3dinput/items/quick3dinputsequence_p.h5
-rw-r--r--src/quick3d/quick3dinput/items/quick3dlogicaldevice.cpp2
-rw-r--r--src/quick3d/quick3dinput/items/quick3dlogicaldevice_p.h5
-rw-r--r--src/quick3d/quick3dinput/items/quick3dphysicaldevice.cpp2
-rw-r--r--src/quick3d/quick3dinput/items/quick3dphysicaldevice_p.h7
-rw-r--r--src/quick3d/quick3dinput/qt3dquickinput_global.cpp4
-rw-r--r--src/quick3d/quick3dinput/qt3dquickinputnodefactory.cpp2
-rw-r--r--src/quick3d/quick3dinput/qt3dquickinputnodefactory_p.h3
-rw-r--r--src/quick3d/quick3drender/items/quick3dbuffer.cpp6
-rw-r--r--src/quick3d/quick3drender/items/quick3dbuffer_p.h3
-rw-r--r--src/quick3d/quick3drender/items/quick3deffect.cpp3
-rw-r--r--src/quick3d/quick3drender/items/quick3deffect_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dgeometry.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3dgeometry_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dlayerfilter.cpp3
-rw-r--r--src/quick3d/quick3drender/items/quick3dlayerfilter_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dmaterial.cpp3
-rw-r--r--src/quick3d/quick3drender/items/quick3dmaterial_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dmemorybarrier.cpp10
-rw-r--r--src/quick3d/quick3drender/items/quick3dmemorybarrier_p.h6
-rw-r--r--src/quick3d/quick3drender/items/quick3dparameter.cpp6
-rw-r--r--src/quick3d/quick3drender/items/quick3dparameter_p.h3
-rw-r--r--src/quick3d/quick3drender/items/quick3dparameter_p_p.h4
-rw-r--r--src/quick3d/quick3drender/items/quick3drenderpass.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3drenderpass_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3drenderpassfilter.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3drenderpassfilter_p.h7
-rw-r--r--src/quick3d/quick3drender/items/quick3drendertargetoutput.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3drendertargetoutput_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3drendertargetselector.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3drendertargetselector_p.h7
-rw-r--r--src/quick3d/quick3drender/items/quick3dscene.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3dscene_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dshaderdata.cpp18
-rw-r--r--src/quick3d/quick3drender/items/quick3dshaderdata_p.h8
-rw-r--r--src/quick3d/quick3drender/items/quick3dshaderdataarray.cpp4
-rw-r--r--src/quick3d/quick3drender/items/quick3dshaderdataarray_p.h3
-rw-r--r--src/quick3d/quick3drender/items/quick3dstateset.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3dstateset_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dtechnique.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3dtechnique_p.h5
-rw-r--r--src/quick3d/quick3drender/items/quick3dtechniquefilter.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3dtechniquefilter_p.h7
-rw-r--r--src/quick3d/quick3drender/items/quick3dtexture.cpp5
-rw-r--r--src/quick3d/quick3drender/items/quick3dtexture_p.h6
-rw-r--r--src/quick3d/quick3drender/items/quick3dviewport.cpp2
-rw-r--r--src/quick3d/quick3drender/items/quick3dviewport_p.h3
-rw-r--r--src/quick3d/quick3drender/qt3dquickrender_global.cpp4
-rw-r--r--src/quick3d/quick3drender/qt3dquickrendernodefactory.cpp2
-rw-r--r--src/quick3d/quick3drender/qt3dquickrendernodefactory_p.h3
-rw-r--r--src/quick3d/quick3dscene2d/items/items.pri17
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.cpp365
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.h112
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d_p.h99
-rw-r--r--src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp100
-rw-r--r--src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h93
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.cpp516
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.pri10
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d_p.h134
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2devent_p.h84
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dmanager.cpp248
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dmanager_p.h112
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp162
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h130
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2d_global.cpp58
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2d_global.h56
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2d_global_p.h88
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2d_logging.cpp49
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2d_logging_p.h65
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory.cpp89
-rw-r--r--src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory_p.h89
-rw-r--r--src/quick3d/quick3dscene2d/quick3dscene2d.pro31
-rw-r--r--src/render/backend/abstractrenderer_p.h4
-rw-r--r--src/render/backend/attachmentpack.cpp2
-rw-r--r--src/render/backend/backendnode.cpp16
-rw-r--r--src/render/backend/backendnode_p.h8
-rw-r--r--src/render/backend/bufferutils_p.h115
-rw-r--r--src/render/backend/buffervisitor_p.h212
-rw-r--r--src/render/backend/cameralens.cpp126
-rw-r--r--src/render/backend/cameralens_p.h28
-rw-r--r--src/render/backend/commandexecuter.cpp5
-rw-r--r--src/render/backend/commandexecuter_p.h4
-rw-r--r--src/render/backend/commandthread.cpp129
-rw-r--r--src/render/backend/commandthread_p.h (renamed from src/quick3d/quick3danimation/items/quick3dabstractclipblendnode_p.h)62
-rw-r--r--src/render/backend/entity.cpp32
-rw-r--r--src/render/backend/entity_p.h18
-rw-r--r--src/render/backend/frameprofiler_p.h14
-rw-r--r--src/render/backend/handle_types_p.h2
-rw-r--r--src/render/backend/levelofdetail.cpp29
-rw-r--r--src/render/backend/levelofdetail_p.h8
-rw-r--r--src/render/backend/managers_p.h15
-rw-r--r--src/render/backend/nodemanagers.cpp15
-rw-r--r--src/render/backend/nodemanagers_p.h13
-rw-r--r--src/render/backend/openglvertexarrayobject.cpp63
-rw-r--r--src/render/backend/openglvertexarrayobject_p.h18
-rw-r--r--src/render/backend/platformsurfacefilter.cpp4
-rw-r--r--src/render/backend/platformsurfacefilter_p.h4
-rw-r--r--src/render/backend/render-backend.pri22
-rw-r--r--src/render/backend/renderer.cpp290
-rw-r--r--src/render/backend/renderer_p.h23
-rw-r--r--src/render/backend/renderqueue.cpp6
-rw-r--r--src/render/backend/renderqueue_p.h4
-rw-r--r--src/render/backend/rendertargetoutput.cpp9
-rw-r--r--src/render/backend/rendertargetoutput_p.h3
-rw-r--r--src/render/backend/renderthread_p.h8
-rw-r--r--src/render/backend/renderview.cpp52
-rw-r--r--src/render/backend/renderview_p.h20
-rw-r--r--src/render/backend/renderviewbuilder.cpp29
-rw-r--r--src/render/backend/resourceaccessor.cpp123
-rw-r--r--src/render/backend/resourceaccessor_p.h102
-rw-r--r--src/render/backend/shadervariables_p.h1
-rw-r--r--src/render/backend/triangleboundingvolume.cpp17
-rw-r--r--src/render/backend/triangleboundingvolume_p.h2
-rw-r--r--src/render/backend/trianglesvisitor.cpp129
-rw-r--r--src/render/backend/trianglesvisitor_p.h27
-rw-r--r--src/render/framegraph/buffercapture.cpp (renamed from src/quick3d/imports/extras/defaults/qml/PhongMaterial.qml)34
-rw-r--r--src/render/framegraph/buffercapture_p.h75
-rw-r--r--src/render/framegraph/framegraph.pri5
-rw-r--r--src/render/framegraph/framegraphnode_p.h1
-rw-r--r--src/render/framegraph/framegraphvisitor.cpp26
-rw-r--r--src/render/framegraph/framegraphvisitor_p.h14
-rw-r--r--src/render/framegraph/memorybarrier.cpp12
-rw-r--r--src/render/framegraph/memorybarrier_p.h4
-rw-r--r--src/render/framegraph/qbuffercapture.cpp73
-rw-r--r--src/render/framegraph/qbuffercapture.h69
-rw-r--r--src/render/framegraph/qbuffercapture_p.h74
-rw-r--r--src/render/framegraph/qmemorybarrier.cpp49
-rw-r--r--src/render/framegraph/qmemorybarrier.h45
-rw-r--r--src/render/framegraph/qmemorybarrier_p.h4
-rw-r--r--src/render/framegraph/qrendercapture.cpp81
-rw-r--r--src/render/framegraph/qrendercapture.h17
-rw-r--r--src/render/framegraph/qsortpolicy.cpp4
-rw-r--r--src/render/framegraph/qviewport.cpp34
-rw-r--r--src/render/framegraph/qviewport.h4
-rw-r--r--src/render/framegraph/qviewport_p.h2
-rw-r--r--src/render/framegraph/rendercapture.cpp2
-rw-r--r--src/render/framegraph/viewportnode.cpp16
-rw-r--r--src/render/framegraph/viewportnode_p.h4
-rw-r--r--src/render/frontend/qabstractfunctor.h1
-rw-r--r--src/render/frontend/qcamera.cpp103
-rw-r--r--src/render/frontend/qcamera.h8
-rw-r--r--src/render/frontend/qcameralens.cpp79
-rw-r--r--src/render/frontend/qcameralens.h10
-rw-r--r--src/render/frontend/qcameralens_p.h9
-rw-r--r--src/render/frontend/qlevelofdetail.cpp107
-rw-r--r--src/render/frontend/qlevelofdetail.h24
-rw-r--r--src/render/frontend/qlevelofdetail_p.h6
-rw-r--r--src/render/frontend/qlevelofdetailboundingsphere.cpp (renamed from src/render/frontend/qboundingsphere.cpp)105
-rw-r--r--src/render/frontend/qlevelofdetailboundingsphere.h (renamed from src/render/frontend/qboundingsphere.h)35
-rw-r--r--src/render/frontend/qlevelofdetailswitch.cpp14
-rw-r--r--src/render/frontend/qpickingsettings.cpp60
-rw-r--r--src/render/frontend/qrenderaspect.cpp87
-rw-r--r--src/render/frontend/qrenderaspect.h2
-rw-r--r--src/render/frontend/qrenderaspect_p.h15
-rw-r--r--src/render/frontend/qrenderplugin_p.h89
-rw-r--r--src/render/frontend/qrenderpluginfactory.cpp99
-rw-r--r--src/render/frontend/qrenderpluginfactory_p.h75
-rw-r--r--src/render/frontend/qrenderpluginfactoryif.cpp65
-rw-r--r--src/render/frontend/qrenderpluginfactoryif_p.h82
-rw-r--r--src/render/frontend/qrendersettings.cpp7
-rw-r--r--src/render/frontend/render-frontend.pri14
-rw-r--r--src/render/frontend/sphere.cpp3
-rw-r--r--src/render/frontend/sphere_p.h2
-rw-r--r--src/render/geometry/attribute.cpp2
-rw-r--r--src/render/geometry/buffer.cpp44
-rw-r--r--src/render/geometry/buffer_p.h6
-rw-r--r--src/render/geometry/geometryrenderer.cpp2
-rw-r--r--src/render/geometry/qbuffer.cpp40
-rw-r--r--src/render/geometry/qbuffer.h12
-rw-r--r--src/render/geometry/qbuffer_p.h2
-rw-r--r--src/render/geometry/qgeometry.cpp16
-rw-r--r--src/render/geometry/qmesh.cpp190
-rw-r--r--src/render/geometry/qmesh_p.h26
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp163
-rw-r--r--src/render/graphicshelpers/graphicscontext_p.h10
-rw-r--r--src/render/graphicshelpers/graphicshelperes2.cpp41
-rw-r--r--src/render/graphicshelpers/graphicshelperes2_p.h8
-rw-r--r--src/render/graphicshelpers/graphicshelpergl2.cpp26
-rw-r--r--src/render/graphicshelpers/graphicshelpergl2_p.h4
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_2.cpp44
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_2_p.h4
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_3.cpp12
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_3_p.h4
-rw-r--r--src/render/graphicshelpers/graphicshelpergl4.cpp44
-rw-r--r--src/render/graphicshelpers/graphicshelpergl4_p.h4
-rw-r--r--src/render/graphicshelpers/graphicshelperinterface_p.h7
-rw-r--r--src/render/io/glbuffer.cpp12
-rw-r--r--src/render/io/glbuffer_p.h2
-rw-r--r--src/render/io/qgeometryloaderfactory_p.h1
-rw-r--r--src/render/io/qsceneimporter_p.h3
-rw-r--r--src/render/io/qsceneloader.cpp28
-rw-r--r--src/render/io/qsceneloader.h8
-rw-r--r--src/render/io/qsceneloader_p.h2
-rw-r--r--src/render/io/scene.cpp14
-rw-r--r--src/render/io/scenemanager.cpp65
-rw-r--r--src/render/io/scenemanager_p.h28
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp188
-rw-r--r--src/render/jobs/computefilteredboundingvolumejob.cpp130
-rw-r--r--src/render/jobs/computefilteredboundingvolumejob_p.h91
-rw-r--r--src/render/jobs/job_common_p.h2
-rw-r--r--src/render/jobs/jobs.pri9
-rw-r--r--src/render/jobs/lightgatherer.cpp9
-rw-r--r--src/render/jobs/lightgatherer_p.h8
-rw-r--r--src/render/jobs/loadscenejob.cpp68
-rw-r--r--src/render/jobs/loadscenejob_p.h2
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp75
-rw-r--r--src/render/jobs/pickboundingvolumejob_p.h10
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp57
-rw-r--r--src/render/jobs/pickboundingvolumeutils_p.h17
-rw-r--r--src/render/jobs/renderviewjobutils.cpp33
-rw-r--r--src/render/jobs/renderviewjobutils_p.h2
-rw-r--r--src/render/jobs/sendbuffercapturejob.cpp (renamed from src/render/framegraph/qsortcriterion.h)64
-rw-r--r--src/render/jobs/sendbuffercapturejob_p.h99
-rw-r--r--src/render/jobs/updatelevelofdetailjob.cpp8
-rw-r--r--src/render/lights/environmentlight.cpp (renamed from src/render/framegraph/qsortcriterion.cpp)44
-rw-r--r--src/render/lights/environmentlight_p.h81
-rw-r--r--src/render/lights/lights.pri5
-rw-r--r--src/render/lights/qenvironmentlight.cpp189
-rw-r--r--src/render/lights/qenvironmentlight.h86
-rw-r--r--src/render/lights/qenvironmentlight_p.h85
-rw-r--r--src/render/materialsystem/qeffect.cpp60
-rw-r--r--src/render/materialsystem/qmaterial.cpp102
-rw-r--r--src/render/materialsystem/qparameter.cpp127
-rw-r--r--src/render/materialsystem/qrenderpass.cpp91
-rw-r--r--src/render/materialsystem/qshaderdata_p.h7
-rw-r--r--src/render/materialsystem/qshaderprogram.cpp79
-rw-r--r--src/render/materialsystem/qshaderprogram.h15
-rw-r--r--src/render/materialsystem/qshaderprogram_p.h8
-rw-r--r--src/render/materialsystem/qtechnique.cpp128
-rw-r--r--src/render/materialsystem/shader.cpp63
-rw-r--r--src/render/materialsystem/shader_p.h18
-rw-r--r--src/render/materialsystem/shadercache.cpp5
-rw-r--r--src/render/materialsystem/shadercache_p.h1
-rw-r--r--src/render/picking/objectpicker.cpp13
-rw-r--r--src/render/picking/pickeventfilter.cpp21
-rw-r--r--src/render/picking/pickeventfilter_p.h7
-rw-r--r--src/render/picking/qobjectpicker.cpp44
-rw-r--r--src/render/picking/qpickevent.cpp32
-rw-r--r--src/render/picking/qpickevent_p.h11
-rw-r--r--src/render/picking/qpicktriangleevent.cpp52
-rw-r--r--src/render/picking/qpicktriangleevent.h5
-rw-r--r--src/render/raycasting/qabstractcollisionqueryservice.cpp6
-rw-r--r--src/render/raycasting/qabstractcollisionqueryservice_p.h4
-rw-r--r--src/render/raycasting/qboundingvolume_p.h3
-rw-r--r--src/render/raycasting/qcollisionqueryresult.cpp5
-rw-r--r--src/render/raycasting/qcollisionqueryresult_p.h21
-rw-r--r--src/render/raycasting/qraycastingservice.cpp8
-rw-r--r--src/render/render.pro3
-rw-r--r--src/render/renderlogging.cpp22
-rw-r--r--src/render/texture/apitexturemanager_p.h17
-rw-r--r--src/render/texture/gltexture.cpp59
-rw-r--r--src/render/texture/gltexture_p.h15
-rw-r--r--src/render/texture/qabstracttexture.cpp5
-rw-r--r--src/render/texture/qabstracttexture_p.h4
-rw-r--r--src/render/texture/qpaintedtextureimage.cpp44
-rw-r--r--src/render/texture/qtexture.cpp202
-rw-r--r--src/render/texture/qtexture_p.h28
-rw-r--r--src/render/texture/texture.cpp28
-rw-r--r--src/render/texture/texture_p.h7
-rw-r--r--src/render/texture/textureimage.cpp2
-rw-r--r--src/src.pro146
1329 files changed, 163153 insertions, 120661 deletions
diff --git a/src/3rdparty/assimp/CHANGES b/src/3rdparty/assimp/CHANGES
index 7fa999a95..1d98700f8 100644
--- a/src/3rdparty/assimp/CHANGES
+++ b/src/3rdparty/assimp/CHANGES
@@ -2,11 +2,100 @@
CHANGELOG
----------------------------------------------------------------------
+3.3.1 (2016-07-08)
+
+FIXES/HOUSEKEEPING:
+ - Setup of default precision for 17 exporters
+ - Fix xcode project files
+ - Fix BlenderTesselator: offsetof operator
+ - Invalid version in cmake file
+ - Update pstdint.h to latest greatest
+
+
+3.3.0 (2016-07-05)
+
+FEATURES:
+ - C++11 support enabled
+ - New regression-test-UI
+ - Experimental glTF-importer support
+ - OpenGEX: add support for cameras and lights
+ - C4D: update to latest Melange-SDK
+ - Add a gitter channel
+ - Coverity check enabled
+ - Switch to <...> include brackets for public headers
+ - Enable export by pyAssimp
+ - CI: check windows build
+ - Add functionality to perform a singlepost-processing step
+ - many more, just check the history
+
+FIXES/HOUSEKEEPING:
+ - Fix of many resource leaks in unittests and main lib
+ - Fix iOS-buildfor X64
+ - Choosing zlib manually for cmake
+ - many more, just check the history
+
+
+3.2.1 (2016-010-10)
+
+FEATURES:
+ - Updated glTF exporter to meet 1.0 specification.
+
+FIXES/HOUSEKEEPING:
+ - Fixed glTF Validator errors for exported glTF format.
+
+ISSUES:
+ - Hard coded sampler setting for
+ - magFilter
+ - minFilter
+ - void* in ExportData for accessor max and min.
+
+
+3.2.0 (2015-11-03)
+
+FEATURES:
+ - OpenDDL-Parser is part of contrib-source.
+ - Experimental OpenGEX-support
+ - CI-check for linux and windows
+ - Coverity check added
+ - New regression testsuite.
+
+FIXES/HOUSEKEEPING:
+ - Hundreds of bugfixes in all parts of the library
+ - Unified line endings
+
+
+API COMPATIBILITY:
+ - Removed precompiled header to increase build speed for linux
+
+
+3.1.1 (2014-06-15)
+
+FEATURES:
+ - Support for FBX 2013 and newer, binary and ASCII (this is partly
+ work from Google Summer of Code 2012)
+ - Support for OGRE binary mesh and skeleton format
+ - Updated BLEND support for newer Blender versions
+ - Support for arbitrary meta data, used to hold FBX and DAE metadata
+ - OBJ Export now produces smaller files
+ - Meshes can now have names, this is supported by the major importers
+ - Improved IFC geometry generation
+ - M3 support has been removed
+
+FIXES/HOUSEKEEPING:
+ - Hundreds of bugfixes in all parts of the library
+ - CMake is now the primary build system
+
+API COMPATIBILITY:
+ - 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
+ and aiMesh::mName
+ - Export interface has been cleaned up and unified
+ - Other than that no relevant changes
+
3.0 (2012-07-07)
FEATURES:
- - new export interface similar to the import API.
+ - new export interface similar to the import API.
- Supported export formats: Collada, OBJ, PLY and STL
- added new import formats: XGL/ZGL, M3 (experimental)
- new postprocessing steps: Debone
@@ -23,11 +112,11 @@ FIXES/HOUSEKEEPING:
- improved CMake build system
- templatized math library
- reduce dependency on boost.thread, only remaining spot
- is synchronization for the C logging API
+ is synchronization for the C logging API
API COMPATIBILITY:
- renamed headers, export interface, C API properties and meta data
- prevent compatibility with code written for 2.0, but in
+ prevent compatibility with code written for 2.0, but in
most cases these can be easily resolved
- Note: 3.0 is not binary compatible with 2.0
@@ -45,9 +134,9 @@ FEATURES:
spatial structure) in some expensive postprocessing steps
- AssimpView now uses a reworked layout which leaves more space
to the scene hierarchy window
-
+
- Add C# bindings ('Assimp.NET')
- - Keep BSD-licensed and otherwise free test files in separate
+ - Keep BSD-licensed and otherwise free test files in separate
folders (./test/models and ./test/models-nonbsd).
FIXES:
@@ -57,20 +146,20 @@ FIXES:
- OpenGL-sample now works with MinGW
- Fix Importer::FindLoader failing on uppercase file extensions
- Fix flawed path handling when locating external files
- - Limit the maximum number of vertices, faces, face indices and
+ - Limit the maximum number of vertices, faces, face indices and
weights that Assimp is able to handle. This is to avoid
crashes due to overflowing counters.
-
+
- Updated XCode project files
- Further CMAKE build improvements
-
+
API CHANGES:
- Add data structures for vertex-based animations (These are not
currently used, however ...)
- Some Assimp::Importer methods are const now.
-
-
+
+
diff --git a/src/3rdparty/assimp/CREDITS b/src/3rdparty/assimp/CREDITS
index 070a15431..16096cd1d 100644
--- a/src/3rdparty/assimp/CREDITS
+++ b/src/3rdparty/assimp/CREDITS
@@ -30,7 +30,7 @@ Ogre Loader, VC2010 fixes and CMake fixes.
- Sebastian Hempel,
PyAssimp (first version)
-Compile-Bugfixes for mingw, add enviroment for static library support in make.
+Compile-Bugfixes for mingw, add environment for static library support in make.
- Jonathan Pokrass
Supplied a bugfix concerning the scaling in the md3 loader.
@@ -114,7 +114,7 @@ Contributes a fix for the configure script environment.
Contributed AssimpDelphi (/port/AssimpDelphi).
- rdb
-Contributes a bundle of fixes and improvments for the bsp-importer.
+Contributes a bundle of fixes and improvements for the bsp-importer.
- Mick P
For contributing the De-bone postprocessing step and filing various bug reports.
@@ -148,3 +148,13 @@ Bugfixes for uv-tanget calculation.
- Jonne Nauha
Ogre Binary format support
+
+- Filip Wasil, Tieto Poland Sp. z o.o.
+Android JNI asset extraction support
+
+- Richard Steffen
+Contributed ExportProperties interface
+Contributed X File exporter
+Contributed Step (stp) exporter
+
+
diff --git a/src/3rdparty/assimp/LICENSE b/src/3rdparty/assimp/LICENSE
index 44f91785f..262606aff 100644
--- a/src/3rdparty/assimp/LICENSE
+++ b/src/3rdparty/assimp/LICENSE
@@ -1,10 +1,10 @@
Open Asset Import Library (assimp)
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, assimp 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
@@ -21,16 +21,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,9 +41,9 @@ AN EXCEPTION applies to all files in the ./test/models-nonbsd folder.
These are 3d models for testing purposes, from various free sources
on the internet. They are - unless otherwise stated - copyright of
their respective creators, which may impose additional requirements
-on the use of their work. For any of these models, see
+on the use of their work. For any of these models, see
<model-name>.source.txt for more legal information. Contact us if you
-are a copyright holder and believe that we credited you inproperly or
+are a copyright holder and believe that we credited you inproperly or
if you don't want your files to appear in the repository.
@@ -76,9 +76,3 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
-
-
-
diff --git a/src/3rdparty/assimp/Readme.md b/src/3rdparty/assimp/Readme.md
index 214417798..e4fe07b02 100644
--- a/src/3rdparty/assimp/Readme.md
+++ b/src/3rdparty/assimp/Readme.md
@@ -1,39 +1,54 @@
-Open Asset Import Library (assimp)
-========
+Open Asset Import Library (assimp)
+==================================
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
+APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
-This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
+Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
+
+This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories.
+The current build status is:
+
+Linux [![Linux Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
+Windows [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
+Coverity<a href="https://scan.coverity.com/projects/5607">
+ <img alt="Coverity Scan Build Status"
+ src="https://scan.coverity.com/projects/5607/badge.svg"/>
+</a>
+Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+<br>
+__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
#### Supported file formats ####
-The library provides importers for a lot of file formats, including:
+A full list [is here](http://assimp.sourceforge.net/main_features_formats.html).
+__Importers__:
- 3DS
-- BLEND (Blender 3D)
+- BLEND (Blender)
- DAE/Collada
- FBX
-- IFC-STEP
+- IFC-STEP
- ASE
- DXF
- HMP
- MD2
-- MD3
+- MD3
- MD5
- MDC
- MDL
- NFF
- PLY
- STL
-- X
-- OBJ
+- X
+- OBJ
+- OpenGEX
- SMD
-- LWO
-- LXO
+- LWO
+- LXO
- LWS
-- TER
-- AC3D
-- MS3D
+- TER
+- AC3D
+- MS3D
- COB
- Q3BSP
- XGL
@@ -44,77 +59,81 @@ The library provides importers for a lot of file formats, including:
- Ogre Binary
- Ogre XML
- Q3D
-
-Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
+- ASSBIN (Assimp custom format)
+- glTF (partial)
+- 3MF
+
+Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
- C4D (https://github.com/acgessler/assimp-cinema4d)
-Exporters include:
+__Exporters__:
- DAE (Collada)
- STL
- OBJ
- PLY
+- X
+- 3DS
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
-
-See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
+- ASSBIN
+- STEP
+- glTF (partial)
+### Building ###
+Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
+### Ports ###
+* [Android](port/AndroidJNI/README.md)
+* [Python](port/PyAssimp/README.md)
+* [.NET](port/AssimpNET/Readme.md)
+* [Pascal](port/AssimpPascal/Readme.md)
#### Repository structure ####
+Open Asset Import Library is implemented in C++. The directory structure is:
-
-Open Asset Import Library is implemented in C++ (but provides both a C and a
-C++ish interface). The directory structure is:
-
- /bin Folder for binaries, only used on Windows
/code Source code
/contrib Third-party libraries
/doc Documentation (doxysource and pre-compiled docs)
/include Public header C and C++ header files
- /lib Static library location for Windows
- /obj Object file location for Windows
/scripts Scripts used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those.
/test Unit- and regression tests, test suite of models
- /tools Tools (viewer, command line `assimp`)
- /samples A small number of samples to illustrate possible
+ /tools Tools (old assimp viewer, command line `assimp`)
+ /samples A small number of samples to illustrate possible
use cases for Assimp
- /workspaces Build enviroments for vc,xcode,... (deprecated,
+ /workspaces Build environments for vc,xcode,... (deprecated,
CMake has superseeded all legacy build options!)
-
-### Building ###
-
-
-Take a look into the `INSTALL` file. Our build system is CMake, if you already used CMake before there is a good chance you know what to do.
-
-
### Where to get help ###
-
-
For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
(CHMs for Windows are included in some release packages and should be located right here in the root folder).
-If the documentation doesn't solve your problems,
-[try our forums at SF.net](http://sourceforge.net/p/assimp/discussion/817654) or ask on
-[StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
+If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
-For development discussions, there is also a mailing list, _assimp-discussions_
- [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
+For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
+ [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
-### Contributing ###
+Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
+
+And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type
+> /join #assetimporterlib
-Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
+### Contributing ###
+Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
a pull request with your changes against the main repository's `master` branch.
+### Donate ###
+If you like assimp, consider buying us a beer (or two):
+[Donate](http://sourceforge.net/donate/index.php?group_id=226462)
### License ###
+Our license is based on the modified, __3-clause BSD__-License.
-Our license is based on the modified, __3-clause BSD__-License, which is very liberal.
-
-An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
+An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
-For the legal details, see the `LICENSE` file.
+For the legal details, see the `LICENSE` file.
+### Why this name ###
+Sorry, we're germans :-), no english native speakers ...
diff --git a/src/3rdparty/assimp/assimp.pri b/src/3rdparty/assimp/assimp.pri
index 802a645fe..4c0eb40c9 100644
--- a/src/3rdparty/assimp/assimp.pri
+++ b/src/3rdparty/assimp/assimp.pri
@@ -15,7 +15,13 @@ qtConfig(system-zlib):!if(cross_compile:host_build): \
else: \
QT_PRIVATE += zlib-private
-DEFINES += ASSIMP_BUILD_NO_OWN_ZLIB ASSIMP_BUILD_NO_COMPRESSED_IFC ASSIMP_BUILD_NO_Q3BSP_IMPORTER
+DEFINES += \
+ ASSIMP_BUILD_NO_OWN_ZLIB \
+ ASSIMP_BUILD_NO_COMPRESSED_IFC \
+ ASSIMP_BUILD_NO_Q3BSP_IMPORTER \
+ ASSIMP_BUILD_NO_C4D_IMPORTER \
+ ASSIMP_BUILD_NO_3MF_IMPORTER \
+ OPENDDL_STATIC_LIBARY
intel_icc: {
# warning #310: old-style parameter list (anachronism)
@@ -30,15 +36,17 @@ intel_icc: {
QMAKE_CXXFLAGS_WARN_ON += $$QMAKE_CFLAGS_WARN_ON
} else:gcc|clang: {
# Stop compiler complaining about ignored qualifiers on return types
- QMAKE_CFLAGS_WARN_ON += -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-function -Wno-reorder
- QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
+ QMAKE_CFLAGS_WARN_ON += -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-function
+ QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -Wno-reorder
} else:msvc {
# Disabled Warnings:
# 4100: 'identifier' : unreferenced formal parameter
# 4189: 'identifier' : local variable is initialized but not referenced
# 4267: coversion from 'size_t' to 'int', possible loss of data
# 4996: Function call with parameters that may be unsafe
- QMAKE_CFLAGS_WARN_ON += -wd"4100" -wd"4189" -wd"4267" -wd"4996"
+ # 4828: The file contains a character starting at offset 0x167b that
+ # is illegal in the current source character set (codepage 65001)
+ QMAKE_CFLAGS_WARN_ON += -wd"4100" -wd"4189" -wd"4267" -wd"4996" -wd"4828"
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
}
@@ -56,35 +64,40 @@ VPATH += \
$$PWD/contrib/clipper \
$$PWD/contrib/ConvertUTF \
$$PWD/contrib/irrXML \
- $$PWD/contrib/unzip \
+ $$PWD/contrib/unzip
INCLUDEPATH += \
$$PWD \
$$PWD/code \
- $$PWD/code/BoostWorkaround \
$$PWD/include \
$$PWD/include/assimp/Compiler \
+ $$PWD/contrib/clipper \
$$PWD/contrib/ConvertUTF \
$$PWD/contrib/irrXML \
+ $$PWD/contrib/openddlparser/include \
$$PWD/contrib/poly2tri/poly2tri \
- $$PWD/contrib/clipper \
+ $$PWD/contrib/rapidjson/include \
$$PWD/contrib/unzip
# Input
HEADERS += revision.h \
+ code/3DSExporter.h \
code/3DSHelper.h \
code/3DSLoader.h \
code/ACLoader.h \
code/ASELoader.h \
code/ASEParser.h \
code/assbin_chunks.h \
- code/AssimpPCH.h \
+ code/AssbinExporter.h \
+ code/AssbinLoader.h \
+ code/AssxmlExporter.h \
code/B3DImporter.h \
code/BaseImporter.h \
+ code/BaseProcess.h \
code/Bitmap.h \
code/BlenderBMesh.h \
- code/BaseProcess.h \
code/BlenderDNA.h \
+ code/BlenderDNA.inl \
code/BlenderIntermediate.h \
code/BlenderLoader.h \
code/BlenderModifier.h \
@@ -93,7 +106,8 @@ HEADERS += revision.h \
code/BlenderTessellator.h \
code/BlobIOSystem.h \
code/BVHLoader.h \
- code/ByteSwap.h \
+ code/ByteSwapper.h \
+ code/C4DImporter.h \
code/CalcTangentsProcess.h \
code/CInterfaceIOWrapper.h \
code/COBLoader.h \
@@ -104,15 +118,30 @@ HEADERS += revision.h \
code/ColladaParser.h \
code/ComputeUVMappingProcess.h \
code/ConvertToLHProcess.h \
+ code/CreateAnimMesh.h \
code/CSMLoader.h \
+ code/D3MFImporter.h \
+ code/D3MFOpcPackage.h \
code/DeboneProcess.h \
code/DefaultIOStream.h \
code/DefaultIOSystem.h \
code/DefaultProgressHandler.h \
+ code/Defines.h \
code/DXFHelper.h \
code/DXFLoader.h \
code/Exceptional.h \
code/fast_atof.h \
+ code/FBXCompileConfig.h \
+ code/FBXConverter.h \
+ code/FBXDocument.h \
+ code/FBXDocumentUtil.h \
+ code/FBXImporter.h \
+ code/FBXImportSettings.h \
+ code/FBXMeshGeometry.h \
+ code/FBXParser.h \
+ code/FBXProperties.h \
+ code/FBXTokenizer.h \
+ code/FBXUtil.h \
code/FileLogStream.h \
code/FileSystemFilter.h \
code/FindDegenerates.h \
@@ -122,6 +151,12 @@ HEADERS += revision.h \
code/GenericProperty.h \
code/GenFaceNormalsProcess.h \
code/GenVertexNormalsProcess.h \
+ code/glTFAsset.h \
+ code/glTFAsset.inl \
+ code/glTFAssetWriter.h \
+ code/glTFAssetWriter.inl \
+ code/glTFExporter.h \
+ code/glTFImporter.h \
code/HalfLifeFileData.h \
code/Hash.h \
code/HMPFileData.h \
@@ -144,8 +179,10 @@ HEADERS += revision.h \
code/LWOFileData.h \
code/LWOLoader.h \
code/LWSLoader.h \
+ code/Macros.h \
code/MakeVerboseFormat.h \
code/MaterialSystem.h \
+ code/MathFunctions.h \
code/MD2FileData.h \
code/MD2Loader.h \
code/MD2NormalTable.h \
@@ -171,6 +208,14 @@ HEADERS += revision.h \
code/ObjFileParser.h \
code/ObjTools.h \
code/OFFLoader.h \
+ code/OgreBinarySerializer.h \
+ code/OgreImporter.h \
+ code/OgreParsingUtils.h \
+ code/OgreStructs.h \
+ code/OgreXmlSerializer.h \
+ code/OpenGEXExporter.h \
+ code/OpenGEXImporter.h \
+ code/OpenGEXStructs.h \
code/OptimizeGraph.h \
code/OptimizeMeshes.h \
code/ParsingUtils.h \
@@ -195,21 +240,27 @@ HEADERS += revision.h \
code/ScenePreprocessor.h \
code/ScenePrivate.h \
code/SGSpatialSort.h \
+ code/SIBImporter.h \
code/SkeletonMeshBuilder.h \
code/SMDLoader.h \
code/SmoothingGroups.h \
+ code/SmoothingGroups.inl \
code/SortByPTypeProcess.h \
code/SpatialSort.h \
code/SplitByBoneCountProcess.h \
code/SplitLargeMeshes.h \
code/StandardShapes.h \
code/StdOStreamLogStream.h \
+ code/StepExporter.h \
code/STEPFile.h \
+ code/STEPFileEncoding.h \
code/STEPFileReader.h \
code/STLExporter.h \
code/STLLoader.h \
code/StreamReader.h \
+ code/StreamWriter.h \
code/StringComparison.h \
+ code/StringUtils.h \
code/Subdivision.h \
code/TargetAnimation.h \
code/TerragenLoader.h \
@@ -221,10 +272,12 @@ HEADERS += revision.h \
code/Vertex.h \
code/VertexTriangleAdjacency.h \
code/Win32DebugLogStream.h \
+ code/XFileExporter.h \
code/XFileHelper.h \
code/XFileImporter.h \
code/XFileParser.h \
code/XGLLoader.h \
+ code/XMLTools.h \
code/res/resource.h \
contrib/clipper/clipper.hpp \
contrib/ConvertUTF/ConvertUTF.h \
@@ -234,6 +287,48 @@ HEADERS += revision.h \
contrib/irrXML/irrString.h \
contrib/irrXML/irrTypes.h \
contrib/irrXML/irrXML.h \
+ contrib/openddlparser/include/openddlparser/DDLNode.h \
+ contrib/openddlparser/include/openddlparser/OpenDDLCommon.h \
+ contrib/openddlparser/include/openddlparser/OpenDDLExport.h \
+ contrib/openddlparser/include/openddlparser/OpenDDLParser.h \
+ contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h \
+ contrib/openddlparser/include/openddlparser/Value.h \
+ contrib/poly2tri/poly2tri/poly2tri.h \
+ contrib/poly2tri/poly2tri/common/shapes.h \
+ contrib/poly2tri/poly2tri/common/utils.h \
+ contrib/poly2tri/poly2tri/sweep/advancing_front.h \
+ contrib/poly2tri/poly2tri/sweep/cdt.h \
+ contrib/poly2tri/poly2tri/sweep/sweep.h \
+ contrib/poly2tri/poly2tri/sweep/sweep_context.h \
+ contrib/rapidjson/include/rapidjson/allocators.h \
+ contrib/rapidjson/include/rapidjson/document.h \
+ contrib/rapidjson/include/rapidjson/encodedstream.h \
+ contrib/rapidjson/include/rapidjson/encodings.h \
+ contrib/rapidjson/include/rapidjson/error/en.h \
+ contrib/rapidjson/include/rapidjson/error/error.h \
+ contrib/rapidjson/include/rapidjson/filereadstream.h \
+ contrib/rapidjson/include/rapidjson/filewritestream.h \
+ contrib/rapidjson/include/rapidjson/internal/biginteger.h \
+ contrib/rapidjson/include/rapidjson/internal/diyfp.h \
+ contrib/rapidjson/include/rapidjson/internal/dtoa.h \
+ contrib/rapidjson/include/rapidjson/internal/ieee754.h \
+ contrib/rapidjson/include/rapidjson/internal/itoa.h \
+ contrib/rapidjson/include/rapidjson/internal/meta.h \
+ contrib/rapidjson/include/rapidjson/internal/pow10.h \
+ contrib/rapidjson/include/rapidjson/internal/stack.h \
+ contrib/rapidjson/include/rapidjson/internal/strfunc.h \
+ contrib/rapidjson/include/rapidjson/internal/strtod.h \
+ contrib/rapidjson/include/rapidjson/internal/swap.h \
+ contrib/rapidjson/include/rapidjson/memorybuffer.h \
+ contrib/rapidjson/include/rapidjson/memorystream.h \
+ contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h \
+ contrib/rapidjson/include/rapidjson/msinttypes/stdint.h \
+ contrib/rapidjson/include/rapidjson/pointer.h \
+ contrib/rapidjson/include/rapidjson/prettywriter.h \
+ contrib/rapidjson/include/rapidjson/rapidjson.h \
+ contrib/rapidjson/include/rapidjson/reader.h \
+ contrib/rapidjson/include/rapidjson/stringbuffer.h \
+ contrib/rapidjson/include/rapidjson/writer.h \
contrib/unzip/crypt.h \
contrib/unzip/ioapi.h \
contrib/unzip/unzip.h \
@@ -244,6 +339,7 @@ HEADERS += revision.h \
include/assimp/cfileio.h \
include/assimp/cimport.h \
include/assimp/color4.h \
+ include/assimp/color4.inl \
include/assimp/config.h \
include/assimp/DefaultLogger.hpp \
include/assimp/defs.h \
@@ -256,90 +352,53 @@ HEADERS += revision.h \
include/assimp/Logger.hpp \
include/assimp/LogStream.hpp \
include/assimp/material.h \
+ include/assimp/material.inl \
include/assimp/matrix3x3.h \
+ include/assimp/matrix3x3.inl \
include/assimp/matrix4x4.h \
+ include/assimp/matrix4x4.inl \
include/assimp/mesh.h \
+ include/assimp/metadata.h \
include/assimp/NullLogger.hpp \
include/assimp/postprocess.h \
include/assimp/ProgressHandler.hpp \
include/assimp/quaternion.h \
+ include/assimp/quaternion.inl \
include/assimp/scene.h \
include/assimp/texture.h \
include/assimp/types.h \
include/assimp/vector2.h \
- include/assimp/vector3.h \
- include/assimp/version.h \
include/assimp/vector2.inl \
+ include/assimp/vector3.h \
include/assimp/vector3.inl \
- include/assimp/color4.inl \
- include/assimp/quaternion.inl \
- include/assimp/matrix3x3.inl \
- include/assimp/matrix4x4.inl \
- include/assimp/material.inl \
- include/assimp/metadata.h \
+ include/assimp/version.h \
include/assimp/Compiler/poppack1.h \
include/assimp/Compiler/pushpack1.h \
- include/assimp/Compiler/pstdint.h \
- code/BoostWorkaround/boost/foreach.hpp \
- code/BoostWorkaround/boost/format.hpp \
- code/BoostWorkaround/boost/lexical_cast.hpp \
- code/BoostWorkaround/boost/make_shared.hpp \
- code/BoostWorkaround/boost/noncopyable.hpp \
- code/BoostWorkaround/boost/pointer_cast.hpp \
- code/BoostWorkaround/boost/scoped_array.hpp \
- code/BoostWorkaround/boost/scoped_ptr.hpp \
- code/BoostWorkaround/boost/shared_array.hpp \
- code/BoostWorkaround/boost/shared_ptr.hpp \
- code/BoostWorkaround/boost/static_assert.hpp \
- code/BoostWorkaround/boost/timer.hpp \
- contrib/poly2tri/poly2tri/poly2tri.h \
- code/BoostWorkaround/boost/math/common_factor_rt.hpp \
- code/BoostWorkaround/boost/tuple/tuple.hpp \
- contrib/poly2tri/poly2tri/common/shapes.h \
- contrib/poly2tri/poly2tri/common/utils.h \
- contrib/poly2tri/poly2tri/sweep/advancing_front.h \
- contrib/poly2tri/poly2tri/sweep/cdt.h \
- contrib/poly2tri/poly2tri/sweep/sweep.h \
- contrib/poly2tri/poly2tri/sweep/sweep_context.h \
- code/SmoothingGroups.inl \
- code/BlenderDNA.inl \
- code/FBXConverter.h \
- code/FBXDocument.h \
- code/FBXDocumentUtil.h \
- code/FBXImporter.h \
- code/FBXImportSettings.h \
- code/FBXParser.h \
- code/FBXProperties.h \
- code/FBXTokenizer.h \
- code/FBXUtil.h \
- code/OgreImporter.h \
- code/OgreParsingUtils.h \
- code/FBXCompileConfig.h \
- code/STEPFileEncoding.h \
- code/OgreBinarySerializer.h \
- code/OgreStructs.h \
- code/OgreXmlSerializer.h \
- code/CreateAnimMesh.h
+ include/assimp/Compiler/pstdint.h
SOURCES += code/3DSConverter.cpp \
+ code/3DSExporter.cpp \
code/3DSLoader.cpp \
code/ACLoader.cpp \
code/ASELoader.cpp \
code/ASEParser.cpp \
+ code/AssbinExporter.cpp \
+ code/AssbinLoader.cpp \
code/Assimp.cpp \
code/AssimpCExport.cpp \
- code/AssimpPCH.cpp \
+ code/AssxmlExporter.cpp \
code/B3DImporter.cpp \
code/BaseImporter.cpp \
+ code/BaseProcess.cpp \
code/Bitmap.cpp \
code/BlenderBMesh.cpp \
- code/BaseProcess.cpp \
code/BlenderDNA.cpp \
code/BlenderLoader.cpp \
code/BlenderModifier.cpp \
code/BlenderScene.cpp \
code/BlenderTessellator.cpp \
code/BVHLoader.cpp \
+ code/C4DImporter.cpp \
code/CalcTangentsProcess.cpp \
code/COBLoader.cpp \
code/ColladaExporter.cpp \
@@ -347,24 +406,46 @@ SOURCES += code/3DSConverter.cpp \
code/ColladaParser.cpp \
code/ComputeUVMappingProcess.cpp \
code/ConvertToLHProcess.cpp \
+ code/CreateAnimMesh.cpp \
code/CSMLoader.cpp \
+ code/D3MFImporter.cpp \
+ code/D3MFOpcPackage.cpp \
code/DeboneProcess.cpp \
code/DefaultIOStream.cpp \
code/DefaultIOSystem.cpp \
code/DefaultLogger.cpp \
code/DXFLoader.cpp \
code/Exporter.cpp \
+ code/FBXAnimation.cpp \
+ code/FBXBinaryTokenizer.cpp \
+ code/FBXConverter.cpp \
+ code/FBXDeformer.cpp \
+ code/FBXDocument.cpp \
+ code/FBXDocumentUtil.cpp \
+ code/FBXImporter.cpp \
+ code/FBXMaterial.cpp \
+ code/FBXMeshGeometry.cpp \
+ code/FBXModel.cpp \
+ code/FBXNodeAttribute.cpp \
+ code/FBXParser.cpp \
+ code/FBXProperties.cpp \
+ code/FBXTokenizer.cpp \
+ code/FBXUtil.cpp \
code/FindDegenerates.cpp \
code/FindInstancesProcess.cpp \
code/FindInvalidDataProcess.cpp \
code/FixNormalsStep.cpp \
code/GenFaceNormalsProcess.cpp \
code/GenVertexNormalsProcess.cpp \
+ code/glTFExporter.cpp \
+ code/glTFImporter.cpp \
code/HMPLoader.cpp \
+ code/IFCBoolean.cpp \
code/IFCCurve.cpp \
code/IFCGeometry.cpp \
code/IFCLoader.cpp \
code/IFCMaterial.cpp \
+ code/IFCOpenings.cpp \
code/IFCProfile.cpp \
code/IFCReaderGen1.cpp \
code/IFCReaderGen2.cpp \
@@ -399,8 +480,13 @@ SOURCES += code/3DSConverter.cpp \
code/ObjFileMtlImporter.cpp \
code/ObjFileParser.cpp \
code/OFFLoader.cpp \
+ code/OgreBinarySerializer.cpp \
code/OgreImporter.cpp \
code/OgreMaterial.cpp \
+ code/OgreStructs.cpp \
+ code/OgreXmlSerializer.cpp \
+ code/OpenGEXExporter.cpp \
+ code/OpenGEXImporter.cpp \
code/OptimizeGraph.cpp \
code/OptimizeMeshes.cpp \
code/PlyExporter.cpp \
@@ -420,6 +506,7 @@ SOURCES += code/3DSConverter.cpp \
code/SceneCombiner.cpp \
code/ScenePreprocessor.cpp \
code/SGSpatialSort.cpp \
+ code/SIBImporter.cpp \
code/SkeletonMeshBuilder.cpp \
code/SMDLoader.cpp \
code/SortByPTypeProcess.cpp \
@@ -427,6 +514,8 @@ SOURCES += code/3DSConverter.cpp \
code/SplitByBoneCountProcess.cpp \
code/SplitLargeMeshes.cpp \
code/StandardShapes.cpp \
+ code/StepExporter.cpp \
+ code/STEPFileEncoding.cpp \
code/STEPFileReader.cpp \
code/STLExporter.cpp \
code/STLLoader.cpp \
@@ -437,42 +526,24 @@ SOURCES += code/3DSConverter.cpp \
code/TriangulateProcess.cpp \
code/UnrealLoader.cpp \
code/ValidateDataStructure.cpp \
+ code/Version.cpp \
code/VertexTriangleAdjacency.cpp \
+ code/XFileExporter.cpp \
code/XFileImporter.cpp \
code/XFileParser.cpp \
code/XGLLoader.cpp \
contrib/clipper/clipper.cpp \
contrib/ConvertUTF/ConvertUTF.c \
contrib/irrXML/irrXML.cpp \
- contrib/unzip/ioapi.c \
- contrib/unzip/unzip.c \
+ contrib/openddlparser/code/DDLNode.cpp \
+ contrib/openddlparser/code/OpenDDLCommon.cpp \
+ contrib/openddlparser/code/OpenDDLExport.cpp \
+ contrib/openddlparser/code/OpenDDLParser.cpp \
+ contrib/openddlparser/code/Value.cpp \
contrib/poly2tri/poly2tri/common/shapes.cc \
contrib/poly2tri/poly2tri/sweep/advancing_front.cc \
contrib/poly2tri/poly2tri/sweep/cdt.cc \
contrib/poly2tri/poly2tri/sweep/sweep.cc \
contrib/poly2tri/poly2tri/sweep/sweep_context.cc \
- code/FBXAnimation.cpp \
- code/FBXBinaryTokenizer.cpp \
- code/FBXDeformer.cpp \
- code/FBXDocument.cpp \
- code/FBXDocumentUtil.cpp \
- code/FBXImporter.cpp \
- code/FBXMaterial.cpp \
- code/FBXMeshGeometry.cpp \
- code/FBXModel.cpp \
- code/FBXNodeAttribute.cpp \
- code/FBXParser.cpp \
- code/FBXProperties.cpp \
- code/FBXTokenizer.cpp \
- code/FBXUtil.cpp \
- code/IFCBoolean.cpp \
- code/IFCOpenings.cpp \
- code/FBXConverter.cpp \
- code/STEPFileEncoding.cpp \
- code/OgreBinarySerializer.cpp \
- code/OgreStructs.cpp \
- code/OgreXmlSerializer.cpp \
- code/CreateAnimMesh.cpp
-
-
-
+ contrib/unzip/ioapi.c \
+ contrib/unzip/unzip.c
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
diff --git a/src/3rdparty/assimp/contrib/clipper/clipper.cpp b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
index b2316ccd5..c8c62bc2a 100644
--- a/src/3rdparty/assimp/contrib/clipper/clipper.cpp
+++ b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
@@ -26,7 +26,7 @@
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
-* September 24–28, 2005 , Long Beach, California, USA *
+* September 24–28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
diff --git a/src/3rdparty/assimp/contrib/clipper/clipper.hpp b/src/3rdparty/assimp/contrib/clipper/clipper.hpp
index f6f196d0d..3d6510dff 100644
--- a/src/3rdparty/assimp/contrib/clipper/clipper.hpp
+++ b/src/3rdparty/assimp/contrib/clipper/clipper.hpp
@@ -26,7 +26,7 @@
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
-* September 24–28, 2005 , Long Beach, California, USA *
+* September 24–28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
diff --git a/src/3rdparty/assimp/contrib/irrXML/irrXML.cpp b/src/3rdparty/assimp/contrib/irrXML/irrXML.cpp
index 2705ea7b8..42509b5f3 100644
--- a/src/3rdparty/assimp/contrib/irrXML/irrXML.cpp
+++ b/src/3rdparty/assimp/contrib/irrXML/irrXML.cpp
@@ -5,7 +5,6 @@
// Need to include Assimp, too. We're using Assimp's version of fast_atof
// so we need stdint.h. But no PCH.
-#include "./../../code/AssimpPCH.h"
#include "irrXML.h"
#include "irrString.h"
diff --git a/src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt b/src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt
new file mode 100644
index 000000000..a39d0219f
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt
@@ -0,0 +1,64 @@
+CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
+PROJECT( OpenDDL-Parser )
+SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
+SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
+SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
+SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
+SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
+
+if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+ find_package(Threads)
+else()
+ add_definitions( -D_CRT_SECURE_NO_WARNINGS )
+endif()
+
+add_definitions( -DOPENDDLPARSER_BUILD )
+add_definitions( -DOPENDDL_NO_USE_CPP11 )
+add_definitions( -D_VARIADIC_MAX=10 )
+
+INCLUDE_DIRECTORIES(
+ ./
+ include/
+ contrib/gtest-1.7.0/include
+ contrib/gtest-1.7.0/
+)
+
+link_directories(
+ ./
+)
+
+SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
+SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
+
+if( WIN32 AND NOT CYGWIN )
+ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" ) # Force to always compile with W4
+ if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
+ string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
+ else()
+ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" )
+ endif()
+elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+ # Update if necessary
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x")
+elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+endif()
+
+SET ( openddl_parser_src
+ code/OpenDDLParser.cpp
+ code/DDLNode.cpp
+ code/Value.cpp
+ include/openddlparser/OpenDDLParser.h
+ include/openddlparser/OpenDDLParserUtils.h
+ include/openddlparser/OpenDDLCommon.h
+ include/openddlparser/DDLNode.h
+ include/openddlparser/Value.h
+ README.md
+)
+
+SOURCE_GROUP( code FILES ${openddl_parser_src} )
+
+ADD_LIBRARY( openddl_parser SHARED
+ ${openddl_parser_src}
+)
diff --git a/src/3rdparty/assimp/contrib/openddlparser/CREDITS b/src/3rdparty/assimp/contrib/openddlparser/CREDITS
new file mode 100644
index 000000000..a2b01eb13
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/CREDITS
@@ -0,0 +1,16 @@
+===============================================================
+OpenDDL-Parser
+Developers and Contributors
+===============================================================
+
+- Kim Kulling ( kimmi ):
+Founder
+
+- Fredrik Hansson ( FredrikHson ):
+Improvements value interface, serveral bugfixes.
+
+- Henry Read ( henrya2 ):
+Static build option, Interface improvements
+
+- Paul Holland ( pkholland ):
+Bugfixes.
diff --git a/src/3rdparty/assimp/contrib/openddlparser/LICENSE b/src/3rdparty/assimp/contrib/openddlparser/LICENSE
new file mode 100644
index 000000000..4c1476bc4
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/src/3rdparty/assimp/contrib/openddlparser/README.md b/src/3rdparty/assimp/contrib/openddlparser/README.md
new file mode 100644
index 000000000..619747d23
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/README.md
@@ -0,0 +1,136 @@
+The OpenDDL-Parser
+==================
+
+The OpenDDL-Parser is a small and easy to use library for OpenDDL-file-format-parsing. OpenDDL is the shortcut for Open Data Description Language, a data-declaration language introduced by Eric Lengyel. Please check http://openddl.org/ if you want to learn more about it.
+
+Build status
+============
+Linux build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser)
+Current coverity check status:
+<a href="https://scan.coverity.com/projects/5606">
+ <img alt="Coverity Scan Build Status"
+ src="https://scan.coverity.com/projects/5606/badge.svg"/>
+</a>
+
+Get the source code
+===================
+You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command:
+
+> git clone https://github.com/kimkulling/openddl-parser.git
+
+Building the source from the GitHub-Repo
+========================================
+To build the library you need to install cmake first ( see http://www.cmake.org/ for more information ). Make also sure that a compiler tool-chain is installed on your machine.
+After installing it you can open a console and enter:
+
+> cmake CMakeLists.txt
+
+This command will generate a build environment for your installed build enrironment ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ).
+When using an IDE open the IDE and run the build. When using GNU-make type in your console:
+
+> make
+
+and that's all.
+
+When using Visual Studio CMake will generate you a solution for ythe library. Just build it there.
+
+Use the library
+===============
+To use the OpenDDL-parser you need to build the lib first. Now add the
+> <Repo-folder>/include
+
+to your include-path and the
+
+> <Repo-folder>/lib
+
+to your lib-folder. Link the openddl.lib to your application.
+
+Here is a small example how to use the lib:
+
+```cpp
+
+#include <iostream>
+#include <cassert>
+#include <openddlparser/OpenDDLParser.h>
+
+USE_ODDLPARSER_NS;
+
+int main( int argc, char *argv[] ) {
+ if( argc < 3 ) {
+ return 1;
+ }
+
+ char *filename( nullptr );
+ if( 0 == strncmp( FileOption, argv[ 1 ], strlen( FileOption ) ) ) {
+ filename = argv[ 2 ];
+ }
+ std::cout << "file to import: " << filename << std::endl;
+ if( nullptr == filename ) {
+ std::cerr << "Invalid filename." << std::endl;
+ return Error;
+ }
+
+ FILE *fileStream = fopen( filename, "r+" );
+ if( NULL == filename ) {
+ std::cerr << "Cannot open file " << filename << std::endl;
+ return 1;
+ }
+
+ // obtain file size:
+ fseek( fileStream, 0, SEEK_END );
+ const size_t size( ftell( fileStream ) );
+ rewind( fileStream );
+ if( size > 0 ) {
+ char *buffer = new char[ size ];
+ const size_t readSize( fread( buffer, sizeof( char ), size, fileStream ) );
+ assert( readSize == size );
+ OpenDDLParser theParser;
+ theParser.setBuffer( buffer, size );
+ const bool result( theParser.parse() );
+ if( !result ) {
+ std::cerr << "Error while parsing file " << filename << "." << std::endl;
+ }
+ }
+ return 0;
+}
+
+```
+
+How to access the imported data
+===============================
+The data is organized as a tree. You can get the root-node of the tree with the following code:
+
+```cpp
+OpenDDLParser theParser;
+theParser.setBuffer( buffer, size );
+const bool result( theParser.parse() );
+if ( result ) {
+ DDLNode *root = theParser.getRoot();
+ DDLNode::DllNodeList childs = root->getChildNodeList();
+ for ( size_t i=0; i<childs.size(); i++ ) {
+ DDLNode *child = childs[ i ];
+ Property *prop = child->getProperty(); // to get properties
+ std::string type = child->getType(); // to get the node type
+ Value *values = child->getValue(); // to get the data;
+
+ // to loop through all values
+ while ( values != ddl_nullptr ) {
+ int current = values->getInt32();
+ values = value->getNext();
+ }
+ }
+}
+
+```
+
+The node instance called root contains the data.
+
+All data lists are organized as linked lists.
+
+Reference documentation
+=======================
+Please check http://kimkulling.github.io/openddl-parser/doxygen_html/index.html.
+
+Projects using OpenDDL-Parser
+=============================
+- Asset Importer Lib: https://github.com/assimp/assimp .
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp
new file mode 100644
index 000000000..0cc95bdfc
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp
@@ -0,0 +1,209 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParser.h>
+
+#include <algorithm>
+
+BEGIN_ODDLPARSER_NS
+
+DDLNode::DllNodeList DDLNode::s_allocatedNodes;
+
+template<class T>
+inline
+static void releaseDataType( T *ptr ) {
+ if( ddl_nullptr == ptr ) {
+ return;
+ }
+
+ T *current( ddl_nullptr );
+ while( ptr ) {
+ current = ptr;
+ ptr = ptr->m_next;
+ delete current;
+ }
+}
+
+static void releaseReferencedNames( Reference *ref ) {
+ if( ddl_nullptr == ref ) {
+ return;
+ }
+
+ delete ref;
+}
+
+DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent )
+: m_type( type )
+, m_name( name )
+, m_parent( parent )
+, m_children()
+, m_properties( ddl_nullptr )
+, m_value( ddl_nullptr )
+, m_dtArrayList( ddl_nullptr )
+, m_references( ddl_nullptr )
+, m_idx( idx ) {
+ if( m_parent ) {
+ m_parent->m_children.push_back( this );
+ }
+}
+
+DDLNode::~DDLNode() {
+ releaseDataType<Property>( m_properties );
+ releaseDataType<Value>( m_value );
+ releaseReferencedNames( m_references );
+
+ delete m_dtArrayList;
+ m_dtArrayList = ddl_nullptr;
+ if( s_allocatedNodes[ m_idx ] == this ) {
+ s_allocatedNodes[ m_idx ] = ddl_nullptr;
+ }
+}
+
+void DDLNode::attachParent( DDLNode *parent ) {
+ if( m_parent == parent ) {
+ return;
+ }
+
+ m_parent = parent;
+ if( ddl_nullptr != m_parent ) {
+ m_parent->m_children.push_back( this );
+ }
+}
+
+void DDLNode::detachParent() {
+ if( m_parent ) {
+ std::vector<DDLNode*>::iterator it;
+ it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
+ if( m_parent->m_children.end() != it ) {
+ m_parent->m_children.erase( it );
+ }
+ m_parent = ddl_nullptr;
+ }
+}
+
+DDLNode *DDLNode::getParent() const {
+ return m_parent;
+}
+
+const DDLNode::DllNodeList &DDLNode::getChildNodeList() const {
+ return m_children;
+}
+
+void DDLNode::setType( const std::string &type ) {
+ m_type = type;
+}
+
+const std::string &DDLNode::getType() const {
+ return m_type;
+}
+
+void DDLNode::setName( const std::string &name ) {
+ m_name = name;
+}
+
+const std::string &DDLNode::getName() const {
+ return m_name;
+}
+
+void DDLNode::setProperties( Property *prop ) {
+ m_properties = prop;
+}
+
+Property *DDLNode::getProperties() const {
+ return m_properties;
+}
+
+bool DDLNode::hasProperty( const std::string &name ) {
+ const Property *prop( findPropertyByName( name ) );
+ return ( ddl_nullptr != prop );
+}
+
+bool DDLNode::hasProperties() const {
+ return( ddl_nullptr != m_properties );
+}
+
+Property *DDLNode::findPropertyByName( const std::string &name ) {
+ if( name.empty() ) {
+ return ddl_nullptr;
+ }
+
+ if( ddl_nullptr == m_properties ) {
+ return ddl_nullptr;
+ }
+
+ Property *current( m_properties );
+ while( ddl_nullptr != current ) {
+ int res = strncmp( current->m_key->m_buffer, name.c_str(), name.size() );
+ if( 0 == res ) {
+ return current;
+ }
+ current = current->m_next;
+ }
+
+ return ddl_nullptr;
+}
+
+void DDLNode::setValue( Value *val ) {
+ m_value = val;
+}
+
+Value *DDLNode::getValue() const {
+ return m_value;
+}
+
+void DDLNode::setDataArrayList( DataArrayList *dtArrayList ) {
+ m_dtArrayList = dtArrayList;
+}
+
+DataArrayList *DDLNode::getDataArrayList() const {
+ return m_dtArrayList;
+}
+
+void DDLNode::setReferences( Reference *refs ) {
+ m_references = refs;
+}
+
+Reference *DDLNode::getReferences() const {
+ return m_references;
+}
+
+DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
+ const size_t idx( s_allocatedNodes.size() );
+ DDLNode *node = new DDLNode( type, name, idx, parent );
+ s_allocatedNodes.push_back( node );
+
+ return node;
+}
+
+void DDLNode::releaseNodes() {
+ if( s_allocatedNodes.size() > 0 ) {
+ for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+ if( *it ) {
+ delete *it;
+ }
+ }
+ s_allocatedNodes.clear();
+ }
+}
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
new file mode 100644
index 000000000..13a96f7a8
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
@@ -0,0 +1,186 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/DDLNode.h>
+
+BEGIN_ODDLPARSER_NS
+
+Text::Text( const char *buffer, size_t numChars )
+: m_capacity( 0 )
+, m_len( 0 )
+, m_buffer( ddl_nullptr ) {
+ set( buffer, numChars );
+}
+
+Text::~Text() {
+ clear();
+}
+
+void Text::clear() {
+ delete[] m_buffer;
+ m_buffer = ddl_nullptr;
+ m_capacity = 0;
+ m_len = 0;
+}
+
+void Text::set( const char *buffer, size_t numChars ) {
+ clear();
+ if( numChars > 0 ) {
+ m_len = numChars;
+ m_capacity = m_len + 1;
+ m_buffer = new char[ m_capacity ];
+ strncpy( m_buffer, buffer, numChars );
+ m_buffer[ numChars ] = '\0';
+ }
+}
+
+bool Text::operator == ( const std::string &name ) const {
+ if( m_len != name.size() ) {
+ return false;
+ }
+ const int res( strncmp( m_buffer, name.c_str(), name.size() ) );
+
+ return ( 0 == res );
+}
+
+bool Text::operator == ( const Text &rhs ) const {
+ if( m_len != rhs.m_len ) {
+ return false;
+ }
+
+ const int res( strncmp( m_buffer, rhs.m_buffer, m_len ) );
+
+ return ( 0 == res );
+}
+
+Name::Name( NameType type, Text *id )
+: m_type( type )
+, m_id( id ) {
+ // empty
+}
+
+Name::~Name() {
+ delete m_id;
+ m_id = ddl_nullptr;
+}
+
+Reference::Reference()
+: m_numRefs( 0 )
+, m_referencedName( ddl_nullptr ) {
+ // empty
+}
+
+Reference::Reference( size_t numrefs, Name **names )
+: m_numRefs( numrefs )
+, m_referencedName( ddl_nullptr ) {
+ if ( numrefs > 0 ) {
+ m_referencedName = new Name *[ numrefs ];
+ for ( size_t i = 0; i < numrefs; i++ ) {
+ Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id );
+ m_referencedName[ i ] = name;
+ }
+ }
+}
+
+Reference::~Reference() {
+ for( size_t i = 0; i < m_numRefs; i++ ) {
+ delete m_referencedName[ i ];
+ }
+ m_numRefs = 0;
+ m_referencedName = ddl_nullptr;
+}
+
+size_t Reference::sizeInBytes() {
+ if ( 0 == m_numRefs ) {
+ return 0;
+ }
+
+ size_t size( 0 );
+ for ( size_t i = 0; i < m_numRefs; i++ ) {
+ Name *name( m_referencedName[ i ] );
+ if ( ddl_nullptr != name ) {
+ size += name->m_id->m_len;
+ }
+ }
+
+ return size;
+}
+
+Property::Property( Text *id )
+: m_key( id )
+, m_value( ddl_nullptr )
+, m_ref( ddl_nullptr )
+, m_next( ddl_nullptr ) {
+ // empty
+}
+
+Property::~Property() {
+ m_key = ddl_nullptr;
+ m_value = ddl_nullptr;
+ m_ref = ddl_nullptr;;
+ m_next = ddl_nullptr;;
+}
+
+DataArrayList::DataArrayList()
+: m_numItems( 0 )
+, m_dataList( ddl_nullptr )
+, m_next( ddl_nullptr ) {
+ // empty
+}
+
+DataArrayList::~DataArrayList() {
+ // empty
+}
+
+size_t DataArrayList::size() {
+ size_t result( 0 );
+ if ( ddl_nullptr == m_next ) {
+ if ( m_dataList != ddl_nullptr ) {
+ result = 1;
+ }
+ return result;
+ }
+
+ DataArrayList *n( m_next );
+ while( ddl_nullptr != n ) {
+ result++;
+ n = n->m_next;
+ }
+ return result;
+}
+
+Context::Context()
+: m_root( ddl_nullptr ) {
+ // empty
+}
+
+Context::~Context() {
+ clear();
+}
+
+void Context::clear() {
+ delete m_root;
+ m_root = ddl_nullptr;
+}
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
new file mode 100644
index 000000000..2e73ea470
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
@@ -0,0 +1,439 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLExport.h>
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/Value.h>
+#include <openddlparser/OpenDDLParser.h>
+
+#include <sstream>
+
+BEGIN_ODDLPARSER_NS
+
+StreamFormatterBase::StreamFormatterBase() {
+
+}
+
+StreamFormatterBase::~StreamFormatterBase() {
+
+}
+
+std::string StreamFormatterBase::format( const std::string &statement ) {
+ std::string tmp( statement );
+ return tmp;
+}
+
+IOStreamBase::IOStreamBase( StreamFormatterBase *formatter )
+: m_formatter( formatter )
+, m_file( ddl_nullptr ) {
+ if (ddl_nullptr == m_formatter) {
+ m_formatter = new StreamFormatterBase;
+ }
+}
+
+IOStreamBase::~IOStreamBase() {
+ delete m_formatter;
+ m_formatter = ddl_nullptr;
+}
+
+bool IOStreamBase::open( const std::string &name ) {
+ m_file = ::fopen( name.c_str(), "a" );
+ if (m_file == ddl_nullptr) {
+ return false;
+ }
+
+ return true;
+}
+
+bool IOStreamBase::close() {
+ if (ddl_nullptr == m_file) {
+ return false;
+ }
+
+ ::fclose( m_file );
+ m_file = ddl_nullptr;
+
+ return true;
+}
+
+size_t IOStreamBase::write( const std::string &statement ) {
+ if (ddl_nullptr == m_file) {
+ return 0;
+ }
+ std::string formatStatement = m_formatter->format( statement );
+ return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file );
+}
+
+struct DDLNodeIterator {
+ const DDLNode::DllNodeList &m_childs;
+ size_t m_idx;
+
+ DDLNodeIterator( const DDLNode::DllNodeList &childs )
+ : m_childs( childs )
+ , m_idx( 0 ) {
+ // empty
+ }
+
+ ~DDLNodeIterator() {
+ // empty
+ }
+
+ bool getNext( DDLNode **node ) {
+ if( m_childs.size() > (m_idx+1) ) {
+ m_idx++;
+ *node = m_childs[ m_idx ];
+ return true;
+ }
+
+ return false;
+ }
+
+private:
+ DDLNodeIterator() ddl_no_copy;
+ DDLNodeIterator &operator = ( const DDLNodeIterator & ) ddl_no_copy;
+};
+
+static void writeLineEnd( std::string &statement ) {
+ statement += "\n";
+}
+
+OpenDDLExport::OpenDDLExport( IOStreamBase *stream )
+: m_stream( stream ) {
+ if (ddl_nullptr == m_stream) {
+ m_stream = new IOStreamBase();
+ }
+}
+
+OpenDDLExport::~OpenDDLExport() {
+ if (ddl_nullptr != m_stream) {
+ m_stream->close();
+ }
+ delete m_stream;
+}
+
+bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) {
+ if( ddl_nullptr == ctx ) {
+ return false;
+ }
+
+ DDLNode *root( ctx->m_root );
+ if ( ddl_nullptr == root ) {
+ return true;
+ }
+
+ if (!filename.empty()) {
+ if (!m_stream->open( filename )) {
+ return false;
+ }
+ }
+
+ const bool retValue( handleNode( root ) );
+
+ return retValue;
+}
+
+bool OpenDDLExport::handleNode( DDLNode *node ) {
+ if( ddl_nullptr == node ) {
+ return true;
+ }
+
+ const DDLNode::DllNodeList &childs = node->getChildNodeList();
+ if( childs.empty() ) {
+ return true;
+ }
+ DDLNode *current( ddl_nullptr );
+ DDLNodeIterator it( childs );
+ std::string statement;
+ bool success( true );
+ while( it.getNext( &current ) ) {
+ if( ddl_nullptr != current ) {
+ success |= writeNode( current, statement );
+ if( !handleNode( current ) ) {
+ success = false;
+ }
+ }
+ }
+
+ return success;
+}
+
+bool OpenDDLExport::writeToStream( const std::string &statement ) {
+ if (ddl_nullptr == m_stream ) {
+ return false;
+ }
+
+ if ( !statement.empty()) {
+ m_stream->write( statement );
+ }
+
+ return true;
+}
+
+bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
+ bool success( true );
+ writeNodeHeader( node, statement );
+ if (node->hasProperties()) {
+ success |= writeProperties( node, statement );
+ }
+ writeLineEnd( statement );
+
+ statement = "}";
+ DataArrayList *al( node->getDataArrayList() );
+ if ( ddl_nullptr != al ) {
+ writeValueType( al->m_dataList->m_type, al->m_numItems, statement );
+ writeValueArray( al, statement );
+ }
+ Value *v( node->getValue() );
+ if (ddl_nullptr != v ) {
+ writeValueType( v->m_type, 1, statement );
+ statement = "{";
+ writeLineEnd( statement );
+ writeValue( v, statement );
+ statement = "}";
+ writeLineEnd( statement );
+ }
+ statement = "}";
+ writeLineEnd( statement );
+
+ writeToStream( statement );
+
+ return true;
+}
+
+bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) {
+ if (ddl_nullptr == node) {
+ return false;
+ }
+
+ statement += node->getType();
+ const std::string &name( node->getName() );
+ if ( !name.empty() ) {
+ statement += " ";
+ statement += "$";
+ statement += name;
+ }
+
+ return true;
+}
+
+bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) {
+ if ( ddl_nullptr == node ) {
+ return false;
+ }
+
+ Property *prop( node->getProperties() );
+ // if no properties are there, return
+ if ( ddl_nullptr == prop ) {
+ return true;
+ }
+
+ if ( ddl_nullptr != prop ) {
+ // for instance (attrib = "position", bla=2)
+ statement += "(";
+ bool first( true );
+ while ( ddl_nullptr != prop ) {
+ if (!first) {
+ statement += ", ";
+ } else {
+ first = false;
+ }
+ statement += std::string( prop->m_key->m_buffer );
+ statement += " = ";
+ writeValue( prop->m_value, statement );
+ prop = prop->m_next;
+ }
+
+ statement += ")";
+ }
+
+ return true;
+}
+
+bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std::string &statement ) {
+ if ( Value::ddl_types_max == type) {
+ return false;
+ }
+
+ const std::string typeStr( getTypeToken( type ) );
+ statement += typeStr;
+ // if we have an array to write
+ if ( numItems > 1 ) {
+ statement += "[";
+ char buffer[ 256 ];
+ ::memset( buffer, '\0', 256 * sizeof( char ) );
+ sprintf( buffer, "%d", int(numItems) );
+ statement += buffer;
+ statement += "]";
+ }
+
+ return true;
+}
+
+bool OpenDDLExport::writeValue( Value *val, std::string &statement ) {
+ if (ddl_nullptr == val) {
+ return false;
+ }
+
+ switch ( val->m_type ) {
+ case Value::ddl_bool:
+ if ( true == val->getBool() ) {
+ statement += "true";
+ } else {
+ statement += "false";
+ }
+ break;
+ case Value::ddl_int8:
+ {
+ std::stringstream stream;
+ const int i = static_cast<int>( val->getInt8() );
+ stream << i;
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_int16:
+ {
+ std::stringstream stream;
+ char buffer[ 256 ];
+ ::memset( buffer, '\0', 256 * sizeof( char ) );
+ sprintf( buffer, "%d", val->getInt16() );
+ statement += buffer;
+ }
+ break;
+ case Value::ddl_int32:
+ {
+ std::stringstream stream;
+ char buffer[ 256 ];
+ ::memset( buffer, '\0', 256 * sizeof( char ) );
+ const int i = static_cast< int >( val->getInt32() );
+ sprintf( buffer, "%d", i );
+ statement += buffer;
+ }
+ break;
+ case Value::ddl_int64:
+ {
+ std::stringstream stream;
+ const int i = static_cast< int >( val->getInt64() );
+ stream << i;
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_unsigned_int8:
+ {
+ std::stringstream stream;
+ const int i = static_cast< unsigned int >( val->getUnsignedInt8() );
+ stream << i;
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_unsigned_int16:
+ {
+ std::stringstream stream;
+ const int i = static_cast< unsigned int >( val->getUnsignedInt16() );
+ stream << i;
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_unsigned_int32:
+ {
+ std::stringstream stream;
+ const int i = static_cast< unsigned int >( val->getUnsignedInt32() );
+ stream << i;
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_unsigned_int64:
+ {
+ std::stringstream stream;
+ const int i = static_cast< unsigned int >( val->getUnsignedInt64() );
+ stream << i;
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_half:
+ break;
+ case Value::ddl_float:
+ {
+ std::stringstream stream;
+ stream << val->getFloat();
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_double:
+ {
+ std::stringstream stream;
+ stream << val->getDouble();
+ statement += stream.str();
+ }
+ break;
+ case Value::ddl_string:
+ {
+ std::stringstream stream;
+ stream << val->getString();
+ statement += "\"";
+ statement += stream.str();
+ statement += "\"";
+ }
+ break;
+ case Value::ddl_ref:
+ break;
+ case Value::ddl_none:
+ case Value::ddl_types_max:
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) {
+ if (ddl_nullptr == al) {
+ return false;
+ }
+
+ if (0 == al->m_numItems) {
+ return true;
+ }
+
+ DataArrayList *nextDataArrayList = al ;
+ Value *nextValue( nextDataArrayList->m_dataList );
+ while (ddl_nullptr != nextDataArrayList) {
+ if (ddl_nullptr != nextDataArrayList) {
+ statement += "{ ";
+ nextValue = nextDataArrayList->m_dataList;
+ size_t idx( 0 );
+ while (ddl_nullptr != nextValue) {
+ if (idx > 0) {
+ statement += ", ";
+ }
+ writeValue( nextValue, statement );
+ nextValue = nextValue->m_next;
+ idx++;
+ }
+ statement += " }";
+ }
+ nextDataArrayList = nextDataArrayList->m_next;
+ }
+
+ return true;
+}
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
new file mode 100644
index 000000000..6f471be36
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
@@ -0,0 +1,1008 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLParser.h>
+#include <openddlparser/OpenDDLExport.h>
+
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <math.h>
+
+#ifdef _WIN32
+# include <windows.h>
+#endif // _WIN32
+
+
+BEGIN_ODDLPARSER_NS
+
+static const char *Version = "0.3.0";
+
+namespace Grammar {
+ static const char *OpenBracketToken = "{";
+ static const char *CloseBracketToken = "}";
+ static const char *OpenPropertyToken = "(";
+ static const char *ClosePropertyToken = ")";
+ static const char *OpenArrayToken = "[";
+ static const char *CloseArrayToken = "]";
+ static const char *BoolTrue = "true";
+ static const char *BoolFalse = "false";
+ static const char *CommaSeparator = ",";
+
+ static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+ "bool",
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "unsigned_int8",
+ "unsigned_int16",
+ "unsigned_int32",
+ "unsigned_int64",
+ "half",
+ "float",
+ "double",
+ "string",
+ "ref"
+ };
+} // Namespace Grammar
+
+const char *getTypeToken( Value::ValueType type ) {
+ return Grammar::PrimitiveTypeToken[ type ];
+}
+
+static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
+ std::stringstream stream;
+ stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl;
+ std::string full(in);
+ std::string part(full.substr(0,50));
+ stream << part;
+ callback( ddl_error_msg, stream.str() );
+}
+
+static bool isIntegerType( Value::ValueType integerType ) {
+ if( integerType != Value::ddl_int8 && integerType != Value::ddl_int16 &&
+ integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
+ return false;
+ }
+ return true;
+}
+
+static bool isUnsignedIntegerType( Value::ValueType integerType ) {
+ if( integerType != Value::ddl_unsigned_int8 && integerType != Value::ddl_unsigned_int16 &&
+ integerType != Value::ddl_unsigned_int32 && integerType != Value::ddl_unsigned_int64 ) {
+ return false;
+ }
+
+ return true;
+}
+
+static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) {
+ if( ddl_nullptr == id || ddl_nullptr == parser ) {
+ return ddl_nullptr;
+ }
+
+ const std::string type( id->m_buffer );
+ DDLNode *parent( parser->top() );
+ DDLNode *node = DDLNode::create( type, "", parent );
+
+ return node;
+}
+
+static void logMessage( LogSeverity severity, const std::string &msg ) {
+ std::string log;
+ if( ddl_debug_msg == severity ) {
+ log += "Debug:";
+ } else if( ddl_info_msg == severity ) {
+ log += "Info :";
+ } else if( ddl_warn_msg == severity ) {
+ log += "Warn :";
+ } else if( ddl_error_msg == severity ) {
+ log += "Error:";
+ } else {
+ log += "None :";
+ }
+
+ log += msg;
+ std::cout << log;
+}
+
+OpenDDLParser::OpenDDLParser()
+: m_logCallback( logMessage )
+, m_buffer()
+, m_stack()
+, m_context( ddl_nullptr ) {
+ // empty
+}
+
+OpenDDLParser::OpenDDLParser( const char *buffer, size_t len )
+: m_logCallback( &logMessage )
+, m_buffer()
+, m_context( ddl_nullptr ) {
+ if( 0 != len ) {
+ setBuffer( buffer, len );
+ }
+}
+
+OpenDDLParser::~OpenDDLParser() {
+ clear();
+}
+
+void OpenDDLParser::setLogCallback( logCallback callback ) {
+ if( ddl_nullptr != callback ) {
+ // install user-specific log callback
+ m_logCallback = callback;
+ } else {
+ // install default log callback
+ m_logCallback = &logMessage;
+ }
+}
+
+OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {
+ return m_logCallback;
+}
+
+void OpenDDLParser::setBuffer( const char *buffer, size_t len ) {
+ clear();
+ if( 0 == len ) {
+ return;
+ }
+
+ m_buffer.resize( len );
+ ::memcpy(&m_buffer[ 0 ], buffer, len );
+}
+
+void OpenDDLParser::setBuffer( const std::vector<char> &buffer ) {
+ clear();
+ m_buffer.resize( buffer.size() );
+ std::copy( buffer.begin(), buffer.end(), m_buffer.begin() );
+}
+
+const char *OpenDDLParser::getBuffer() const {
+ if( m_buffer.empty() ) {
+ return ddl_nullptr;
+ }
+
+ return &m_buffer[ 0 ];
+}
+
+size_t OpenDDLParser::getBufferSize() const {
+ return m_buffer.size();
+}
+
+void OpenDDLParser::clear() {
+ m_buffer.resize( 0 );
+ if( ddl_nullptr != m_context ) {
+ m_context->m_root = ddl_nullptr;
+ }
+
+ DDLNode::releaseNodes();
+}
+
+bool OpenDDLParser::parse() {
+ if( m_buffer.empty() ) {
+ return false;
+ }
+
+ normalizeBuffer( m_buffer );
+
+ m_context = new Context;
+ m_context->m_root = DDLNode::create( "root", "", ddl_nullptr );
+ pushNode( m_context->m_root );
+
+ // do the main parsing
+ char *current( &m_buffer[ 0 ] );
+ char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 );
+ size_t pos( current - &m_buffer[ 0 ] );
+ while( pos < m_buffer.size() ) {
+ current = parseNextNode( current, end );
+ if(current==ddl_nullptr) {
+ return false;
+ }
+ pos = current - &m_buffer[ 0 ];
+ }
+ return true;
+}
+
+bool OpenDDLParser::exportContext( Context *ctx, const std::string &filename ) {
+ if( ddl_nullptr == ctx ) {
+ return false;
+ }
+
+ OpenDDLExport myExporter;
+ return myExporter.exportContext( ctx, filename );
+}
+
+char *OpenDDLParser::parseNextNode( char *in, char *end ) {
+ in = parseHeader( in, end );
+ in = parseStructure( in, end );
+
+ return in;
+}
+
+#ifdef DEBUG_HEADER_NAME
+static void dumpId( Identifier *id ) {
+ if( ddl_nullptr != id ) {
+ if ( ddl_nullptr != id->m_text.m_buffer ) {
+ std::cout << id->m_text.m_buffer << std::endl;
+ }
+ }
+}
+#endif
+
+char *OpenDDLParser::parseHeader( char *in, char *end ) {
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ Text *id( ddl_nullptr );
+ in = OpenDDLParser::parseIdentifier( in, end, &id );
+
+#ifdef DEBUG_HEADER_NAME
+ dumpId( id );
+#endif // DEBUG_HEADER_NAME
+
+ in = lookForNextToken( in, end );
+ if( ddl_nullptr != id ) {
+ // store the node
+ DDLNode *node( createDDLNode( id, this ) );
+ if( ddl_nullptr != node ) {
+ pushNode( node );
+ } else {
+ std::cerr << "nullptr returned by creating DDLNode." << std::endl;
+ }
+
+ Name *name(ddl_nullptr);
+ in = OpenDDLParser::parseName(in, end, &name);
+ if( ddl_nullptr != name && ddl_nullptr != node ) {
+ const std::string nodeName( name->m_id->m_buffer );
+ node->setName( nodeName );
+ }
+
+ Property *first(ddl_nullptr);
+ in = lookForNextToken(in, end);
+ if (*in == Grammar::OpenPropertyToken[0]) {
+ in++;
+ Property *prop(ddl_nullptr), *prev(ddl_nullptr);
+ while (*in != Grammar::ClosePropertyToken[0] && in != end) {
+ in = OpenDDLParser::parseProperty(in, end, &prop);
+ in = lookForNextToken(in, end);
+
+ if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) {
+ logInvalidTokenError(in, Grammar::ClosePropertyToken, m_logCallback);
+ return ddl_nullptr;
+ }
+
+ if (ddl_nullptr != prop && *in != Grammar::CommaSeparator[0]) {
+ if (ddl_nullptr == first) {
+ first = prop;
+ }
+ if (ddl_nullptr != prev) {
+ prev->m_next = prop;
+ }
+ prev = prop;
+ }
+ }
+ in++;
+ }
+
+ // set the properties
+ if (ddl_nullptr != first && ddl_nullptr != node) {
+ node->setProperties(first);
+ }
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseStructure( char *in, char *end ) {
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ bool error( false );
+ in = lookForNextToken( in, end );
+ if( *in == '{' ) {
+ // loop over all children ( data and nodes )
+ do {
+ in = parseStructureBody( in, end, error );
+ if(in == ddl_nullptr){
+ return ddl_nullptr;
+ }
+ } while ( *in != '}' );
+ in++;
+ } else {
+ in++;
+ logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
+ error = true;
+ return ddl_nullptr;
+ }
+ in = lookForNextToken( in, end );
+
+ // pop node from stack after successful parsing
+ if( !error ) {
+ popNode();
+ }
+
+ return in;
+}
+
+static void setNodeValues( DDLNode *currentNode, Value *values ) {
+ if( ddl_nullptr != values ){
+ if( ddl_nullptr != currentNode ) {
+ currentNode->setValue( values );
+ }
+ }
+}
+
+static void setNodeReferences( DDLNode *currentNode, Reference *refs ) {
+ if( ddl_nullptr != refs ) {
+ if( ddl_nullptr != currentNode ) {
+ currentNode->setReferences( refs );
+ }
+ }
+}
+
+static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayList ) {
+ if( ddl_nullptr != dtArrayList ) {
+ if( ddl_nullptr != currentNode ) {
+ currentNode->setDataArrayList( dtArrayList );
+ }
+ }
+}
+
+char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
+ if( !isNumeric( *in ) && !isCharacter( *in ) ) {
+ in++;
+ }
+
+ in = lookForNextToken( in, end );
+ Value::ValueType type( Value::ddl_none );
+ size_t arrayLen( 0 );
+ in = OpenDDLParser::parsePrimitiveDataType( in, end, type, arrayLen );
+ if( Value::ddl_none != type ) {
+ // parse a primitive data type
+ in = lookForNextToken( in, end );
+ if( *in == Grammar::OpenBracketToken[ 0 ] ) {
+ Reference *refs( ddl_nullptr );
+ DataArrayList *dtArrayList( ddl_nullptr );
+ Value *values( ddl_nullptr );
+ if( 1 == arrayLen ) {
+ size_t numRefs( 0 ), numValues( 0 );
+ in = parseDataList( in, end, type, &values, numValues, &refs, numRefs );
+ setNodeValues( top(), values );
+ setNodeReferences( top(), refs );
+ } else if( arrayLen > 1 ) {
+ in = parseDataArrayList( in, end, type, &dtArrayList );
+ setNodeDataArrayList( top(), dtArrayList );
+ } else {
+ std::cerr << "0 for array is invalid." << std::endl;
+ error = true;
+ }
+ }
+
+ in = lookForNextToken( in, end );
+ if( *in != '}' ) {
+ logInvalidTokenError( in, std::string( Grammar::CloseBracketToken ), m_logCallback );
+ return ddl_nullptr;
+ } else {
+ //in++;
+ }
+ } else {
+ // parse a complex data type
+ in = parseNextNode( in, end );
+ }
+
+ return in;
+}
+
+void OpenDDLParser::pushNode( DDLNode *node ) {
+ if( ddl_nullptr == node ) {
+ return;
+ }
+
+ m_stack.push_back( node );
+}
+
+DDLNode *OpenDDLParser::popNode() {
+ if( m_stack.empty() ) {
+ return ddl_nullptr;
+ }
+
+ DDLNode *topNode( top() );
+ m_stack.pop_back();
+
+ return topNode;
+}
+
+DDLNode *OpenDDLParser::top() {
+ if( m_stack.empty() ) {
+ return ddl_nullptr;
+ }
+
+ DDLNode *top( m_stack.back() );
+ return top;
+}
+
+DDLNode *OpenDDLParser::getRoot() const {
+ if( ddl_nullptr == m_context ) {
+ return ddl_nullptr;
+ }
+
+ return m_context->m_root;
+}
+
+Context *OpenDDLParser::getContext() const {
+ return m_context;
+}
+
+void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
+ if( buffer.empty() ) {
+ return;
+ }
+
+ std::vector<char> newBuffer;
+ const size_t len( buffer.size() );
+ char *end( &buffer[ len-1 ] + 1 );
+ for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
+ char *c( &buffer[readIdx] );
+ // check for a comment
+ if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
+ newBuffer.push_back( buffer[ readIdx ] );
+ } else {
+ if( isComment<char>( c, end ) ) {
+ ++readIdx;
+ // skip the comment and the rest of the line
+ while( !isEndofLine( buffer[ readIdx ] ) ) {
+ ++readIdx;
+ }
+ }
+ }
+ }
+ buffer = newBuffer;
+}
+
+char *OpenDDLParser::parseName( char *in, char *end, Name **name ) {
+ *name = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ // ignore blanks
+ in = lookForNextToken( in, end );
+ if( *in != '$' && *in != '%' ) {
+ return in;
+ }
+
+ NameType ntype( GlobalName );
+ if( *in == '%' ) {
+ ntype = LocalName;
+ }
+ in++;
+ Name *currentName( ddl_nullptr );
+ Text *id( ddl_nullptr );
+ in = parseIdentifier( in, end, &id );
+ if( id ) {
+ currentName = new Name( ntype, id );
+ if( currentName ) {
+ *name = currentName;
+ }
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) {
+ *id = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ // ignore blanks
+ in = lookForNextToken( in, end );
+
+ // staring with a number is forbidden
+ if( isNumeric<const char>( *in ) ) {
+ return in;
+ }
+
+ // get size of id
+ size_t idLen( 0 );
+ char *start( in );
+ while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] && *in != '$' ) {
+ ++in;
+ ++idLen;
+ }
+
+ const size_t len( idLen );
+ Text *newId = new Text( start, len );
+ *id = newId;
+
+ return in;
+}
+
+char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len ) {
+ type = Value::ddl_none;
+ len = 0;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ size_t prim_len( 0 );
+ for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
+ prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
+ if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
+ type = ( Value::ValueType ) i;
+ break;
+ }
+ }
+
+ if( Value::ddl_none == type ) {
+ in = lookForNextToken( in, end );
+ return in;
+ } else {
+ in += prim_len;
+ }
+
+ bool ok( true );
+ if( *in == Grammar::OpenArrayToken[ 0 ] ) {
+ ok = false;
+ in++;
+ char *start( in );
+ while ( in != end ) {
+ in++;
+ if( *in == Grammar::CloseArrayToken[ 0 ] ) {
+ len = ::atoi( start );
+ ok = true;
+ in++;
+ break;
+ }
+ }
+ } else {
+ len = 1;
+ }
+ if( !ok ) {
+ type = Value::ddl_none;
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &names ) {
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ Name *nextName( ddl_nullptr );
+ in = parseName( in, end, &nextName );
+ if( nextName ) {
+ names.push_back( nextName );
+ }
+ while( Grammar::CommaSeparator[ 0 ] == *in ) {
+ in = getNextSeparator( in, end );
+ if( Grammar::CommaSeparator[ 0 ] == *in ) {
+ in = parseName( in, end, &nextName );
+ if( nextName ) {
+ names.push_back( nextName );
+ }
+ } else {
+ break;
+ }
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean ) {
+ *boolean = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ char *start( in );
+ size_t len( 0 );
+ while( !isSeparator( *in ) && in != end ) {
+ in++;
+ len++;
+ }
+ len++;
+ int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
+ if( 0 != res ) {
+ res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
+ if( 0 != res ) {
+ *boolean = ddl_nullptr;
+ return in;
+ }
+ *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+ (*boolean)->setBool( false );
+ } else {
+ *boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
+ (*boolean)->setBool( true );
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType ) {
+ *integer = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ if( !(isIntegerType( integerType ) || isUnsignedIntegerType(integerType)) ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ char *start( in );
+ while( !isSeparator( *in ) && in != end ) {
+ in++;
+ }
+
+ if( isNumeric( *start ) ) {
+#ifdef OPENDDL_NO_USE_CPP11
+ const int64 value( atol( start ) ); // maybe not really 64bit as atoll is but exists without c++11
+ const uint64 uvalue( strtoul( start,ddl_nullptr,10 ) );
+#else
+ const int64 value( atoll( start ) );
+ const uint64 uvalue( strtoull( start,ddl_nullptr,10 ) );
+#endif
+ *integer = ValueAllocator::allocPrimData( integerType );
+ switch( integerType ) {
+ case Value::ddl_int8:
+ ( *integer )->setInt8( (int8) value );
+ break;
+ case Value::ddl_int16:
+ ( *integer )->setInt16( ( int16 ) value );
+ break;
+ case Value::ddl_int32:
+ ( *integer )->setInt32( ( int32 ) value );
+ break;
+ case Value::ddl_int64:
+ ( *integer )->setInt64( ( int64 ) value );
+ break;
+ case Value::ddl_unsigned_int8:
+ ( *integer )->setUnsignedInt8( (uint8) uvalue );
+ break;
+ case Value::ddl_unsigned_int16:
+ ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
+ break;
+ case Value::ddl_unsigned_int32:
+ ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
+ break;
+ case Value::ddl_unsigned_int64:
+ ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
+ break;
+ default:
+ break;
+ }
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating, Value::ValueType floatType) {
+ *floating = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ char *start( in );
+ while( !isSeparator( *in ) && in != end ) {
+ in++;
+ }
+
+ // parse the float value
+ bool ok( false );
+ if ( isHexLiteral( start, end ) ) {
+ parseHexaLiteral( start, end, floating );
+ return in;
+ }
+
+ if( isNumeric( *start ) ) {
+ ok = true;
+ } else {
+ if( *start == '-' ) {
+ if( isNumeric( *(start+1) ) ) {
+ ok = true;
+ }
+ }
+ }
+
+ if( ok ) {
+ if(floatType == Value::ddl_double)
+ {
+ const double value( atof( start ) );
+ *floating = ValueAllocator::allocPrimData( Value::ddl_double );
+ ( *floating )->setDouble( value );
+ } else {
+ const float value( ( float ) atof( start ) );
+ *floating = ValueAllocator::allocPrimData( Value::ddl_float );
+ ( *floating )->setFloat( value );
+ }
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData ) {
+ *stringData = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ size_t len( 0 );
+ char *start( in );
+ if( *start == '\"' ) {
+ start++;
+ in++;
+ while( *in != '\"' && in != end ) {
+ in++;
+ len++;
+ }
+
+ *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
+ ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
+ ( *stringData )->m_data[len] = '\0';
+ in++;
+ }
+
+ return in;
+}
+
+static void createPropertyWithData( Text *id, Value *primData, Property **prop ) {
+ if( ddl_nullptr != primData ) {
+ ( *prop ) = new Property( id );
+ ( *prop )->m_value = primData;
+ }
+}
+
+char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
+ *data = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ if( *in != '0' ) {
+ return in;
+ }
+
+ in++;
+ if( *in != 'x' && *in != 'X' ) {
+ return in;
+ }
+
+ in++;
+ bool ok( true );
+ char *start( in );
+ int pos( 0 );
+ while( !isSeparator( *in ) && in != end ) {
+ if( ( *in < '0' && *in > '9' ) || ( *in < 'a' && *in > 'f' ) || ( *in < 'A' && *in > 'F' ) ) {
+ ok = false;
+ break;
+ }
+ pos++;
+ in++;
+ }
+
+ if( !ok ) {
+ return in;
+ }
+
+ int value( 0 );
+ while( pos > 0 ) {
+ int v = hex2Decimal( *start );
+ pos--;
+ value = ( value << 4 ) | v;
+ start++;
+ }
+
+ *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
+ if( ddl_nullptr != *data ) {
+ ( *data )->setUnsignedInt64( value );
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
+ *prop = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ Text *id( ddl_nullptr );
+ in = parseIdentifier( in, end, &id );
+ if( ddl_nullptr != id ) {
+ in = lookForNextToken( in, end );
+ if( *in == '=' ) {
+ in++;
+ in = getNextToken( in, end );
+ Value *primData( ddl_nullptr );
+ if( isInteger( in, end ) ) {
+ in = parseIntegerLiteral( in, end, &primData );
+ createPropertyWithData( id, primData, prop );
+ } else if( isFloat( in, end ) ) {
+ in = parseFloatingLiteral( in, end, &primData );
+ createPropertyWithData( id, primData, prop );
+ } else if( isStringLiteral( *in ) ) { // string data
+ in = parseStringLiteral( in, end, &primData );
+ createPropertyWithData( id, primData, prop );
+ } else { // reference data
+ std::vector<Name*> names;
+ in = parseReference( in, end, names );
+ if( !names.empty() ) {
+ Reference *ref = new Reference( names.size(), &names[ 0 ] );
+ ( *prop ) = new Property( id );
+ ( *prop )->m_ref = ref;
+ }
+ }
+ }
+ }
+
+ return in;
+}
+
+char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type, Value **data,
+ size_t &numValues, Reference **refs, size_t &numRefs ) {
+ *data = ddl_nullptr;
+ numValues = numRefs = 0;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ if( *in == '{' ) {
+ in++;
+ Value *current( ddl_nullptr ), *prev( ddl_nullptr );
+ while( '}' != *in ) {
+ current = ddl_nullptr;
+ in = lookForNextToken( in, end );
+ if ( Value::ddl_ref == type ) {
+ std::vector<Name*> names;
+ in = parseReference( in, end, names );
+ if ( !names.empty() ) {
+ Reference *ref = new Reference( names.size(), &names[ 0 ] );
+ *refs = ref;
+ numRefs = names.size();
+ }
+ } else if ( Value::ddl_none == type ) {
+ if (isInteger( in, end )) {
+ in = parseIntegerLiteral( in, end, &current );
+ } else if (isFloat( in, end )) {
+ in = parseFloatingLiteral( in, end, &current );
+ } else if (isStringLiteral( *in )) {
+ in = parseStringLiteral( in, end, &current );
+ } else if (isHexLiteral( in, end )) {
+ in = parseHexaLiteral( in, end, &current );
+ }
+ } else {
+ switch(type){
+ case Value::ddl_int8:
+ case Value::ddl_int16:
+ case Value::ddl_int32:
+ case Value::ddl_int64:
+ case Value::ddl_unsigned_int8:
+ case Value::ddl_unsigned_int16:
+ case Value::ddl_unsigned_int32:
+ case Value::ddl_unsigned_int64:
+ in = parseIntegerLiteral( in, end, &current, type);
+ break;
+ case Value::ddl_half:
+ case Value::ddl_float:
+ case Value::ddl_double:
+ in = parseFloatingLiteral( in, end, &current, type);
+ break;
+ case Value::ddl_string:
+ in = parseStringLiteral( in, end, &current );
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( ddl_nullptr != current ) {
+ if( ddl_nullptr == *data ) {
+ *data = current;
+ prev = current;
+ } else {
+ prev->setNext( current );
+ prev = current;
+ }
+ numValues++;
+ }
+
+ in = getNextSeparator( in, end );
+ if( ',' != *in && Grammar::CloseBracketToken[ 0 ] != *in && !isSpace( *in ) ) {
+ break;
+ }
+ }
+ in++;
+ }
+
+ return in;
+}
+
+static DataArrayList *createDataArrayList( Value *currentValue, size_t numValues,
+ Reference *refs, size_t numRefs ) {
+ DataArrayList *dataList( new DataArrayList );
+ dataList->m_dataList = currentValue;
+ dataList->m_numItems = numValues;
+ dataList->m_refs = refs;
+ dataList->m_numRefs = numRefs;
+
+ return dataList;
+}
+
+char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType type,
+ DataArrayList **dataArrayList ) {
+ if ( ddl_nullptr == dataArrayList ) {
+ return in;
+ }
+
+ *dataArrayList = ddl_nullptr;
+ if( ddl_nullptr == in || in == end ) {
+ return in;
+ }
+
+ in = lookForNextToken( in, end );
+ if( *in == Grammar::OpenBracketToken[ 0 ] ) {
+ in++;
+ Value *currentValue( ddl_nullptr );
+ Reference *refs( ddl_nullptr );
+ DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
+ do {
+ size_t numRefs( 0 ), numValues( 0 );
+ currentValue = ddl_nullptr;
+
+ in = parseDataList( in, end, type, &currentValue, numValues, &refs, numRefs );
+ if( ddl_nullptr != currentValue || 0 != numRefs ) {
+ if( ddl_nullptr == prev ) {
+ *dataArrayList = createDataArrayList( currentValue, numValues, refs, numRefs );
+ prev = *dataArrayList;
+ } else {
+ currentDataList = createDataArrayList( currentValue, numValues, refs, numRefs );
+ if( ddl_nullptr != prev ) {
+ prev->m_next = currentDataList;
+ prev = currentDataList;
+ }
+ }
+ }
+ } while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
+ in = lookForNextToken( in, end );
+ in++;
+ }
+
+ return in;
+}
+
+const char *OpenDDLParser::getVersion() {
+ return Version;
+}
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp
new file mode 100644
index 000000000..3e251c508
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp
@@ -0,0 +1,440 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/Value.h>
+
+#include <iostream>
+#include <cassert>
+
+BEGIN_ODDLPARSER_NS
+
+static Value::Iterator end( ddl_nullptr );
+
+Value::Iterator::Iterator()
+: m_start( ddl_nullptr )
+, m_current( ddl_nullptr ) {
+ // empty
+}
+
+Value::Iterator::Iterator( Value *start )
+: m_start( start )
+, m_current( start ) {
+ // empty
+}
+
+Value::Iterator::Iterator( const Iterator &rhs )
+: m_start( rhs.m_start )
+, m_current( rhs.m_current ) {
+ // empty
+}
+
+Value::Iterator::~Iterator() {
+ // empty
+}
+
+bool Value::Iterator::hasNext() const {
+ if( ddl_nullptr == m_current ) {
+ return false;
+ }
+ return ( ddl_nullptr != m_current->getNext() );
+}
+
+Value *Value::Iterator::getNext() {
+ if( !hasNext() ) {
+ return ddl_nullptr;
+ }
+
+ Value *v( m_current->getNext() );
+ m_current = v;
+
+ return v;
+}
+
+const Value::Iterator Value::Iterator::operator++( int ) {
+ if( ddl_nullptr == m_current ) {
+ return end;
+ }
+
+ m_current = m_current->getNext();
+ Iterator inst( m_current );
+
+ return inst;
+}
+
+Value::Iterator &Value::Iterator::operator++( ) {
+ if( ddl_nullptr == m_current ) {
+ return end;
+ }
+
+ m_current = m_current->getNext();
+
+ return *this;
+}
+
+bool Value::Iterator::operator == ( const Iterator &rhs ) const {
+ return ( m_current == rhs.m_current );
+}
+
+Value *Value::Iterator::operator->( ) const {
+ if(ddl_nullptr == m_current ) {
+ return ddl_nullptr;
+ }
+ return m_current;
+}
+
+Value::Value( ValueType type )
+: m_type( type )
+, m_size( 0 )
+, m_data( ddl_nullptr )
+, m_next( ddl_nullptr ) {
+ // empty
+}
+
+Value::~Value() {
+ // empty
+}
+
+void Value::setBool( bool value ) {
+ assert( ddl_bool == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+bool Value::getBool() {
+ assert( ddl_bool == m_type );
+ return ( *m_data == 1 );
+}
+
+void Value::setInt8( int8 value ) {
+ assert( ddl_int8 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+int8 Value::getInt8() {
+ assert( ddl_int8 == m_type );
+ return ( int8 ) ( *m_data );
+}
+
+void Value::setInt16( int16 value ) {
+ assert( ddl_int16 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+int16 Value::getInt16() {
+ assert( ddl_int16 == m_type );
+ int16 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setInt32( int32 value ) {
+ assert( ddl_int32 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+int32 Value::getInt32() {
+ assert( ddl_int32 == m_type );
+ int32 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setInt64( int64 value ) {
+ assert( ddl_int64 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+int64 Value::getInt64() {
+ assert( ddl_int64 == m_type );
+ int64 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setUnsignedInt8( uint8 value ) {
+ assert( ddl_unsigned_int8 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+uint8 Value::getUnsignedInt8() const {
+ assert( ddl_unsigned_int8 == m_type );
+ uint8 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setUnsignedInt16( uint16 value ) {
+ assert( ddl_unsigned_int16 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+uint16 Value::getUnsignedInt16() const {
+ assert( ddl_unsigned_int16 == m_type );
+ uint16 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setUnsignedInt32( uint32 value ) {
+ assert( ddl_unsigned_int32 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+uint32 Value::getUnsignedInt32() const {
+ assert( ddl_unsigned_int32 == m_type );
+ uint32 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setUnsignedInt64( uint64 value ) {
+ assert( ddl_unsigned_int64 == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+uint64 Value::getUnsignedInt64() const {
+ assert( ddl_unsigned_int64 == m_type );
+ uint64 i;
+ ::memcpy( &i, m_data, m_size );
+ return i;
+}
+
+void Value::setFloat( float value ) {
+ assert( ddl_float == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+float Value::getFloat() const {
+ if( m_type == ddl_float ) {
+ float v;
+ ::memcpy( &v, m_data, m_size );
+ return ( float ) v;
+ } else {
+ float tmp;
+ ::memcpy( &tmp, m_data, 4 );
+ return ( float ) tmp;
+ }
+}
+
+void Value::setDouble( double value ) {
+ assert( ddl_double == m_type );
+ ::memcpy( m_data, &value, m_size );
+}
+
+double Value::getDouble() const {
+ if ( m_type == ddl_double ) {
+ double v;
+ ::memcpy( &v, m_data, m_size );
+ return ( float ) v;
+ }
+ else {
+ double tmp;
+ ::memcpy( &tmp, m_data, 4 );
+ return ( double ) tmp;
+ }
+}
+
+void Value::setString( const std::string &str ) {
+ assert( ddl_string == m_type );
+ ::memcpy( m_data, str.c_str(), str.size() );
+ m_data[ str.size() ] = '\0';
+}
+
+const char *Value::getString() const {
+ assert( ddl_string == m_type );
+ return (const char*) m_data;
+}
+
+void Value::setRef( Reference *ref ) {
+ assert( ddl_ref == m_type );
+
+ if ( ddl_nullptr != ref ) {
+ const size_t sizeInBytes( ref->sizeInBytes() );
+ if ( sizeInBytes > 0 ) {
+ if ( ddl_nullptr != m_data ) {
+ delete [] m_data;
+ }
+
+ m_data = new unsigned char[ sizeof( Reference ) ];
+ Reference *myRef = ( Reference * ) m_data;
+ myRef->m_numRefs = ref->m_numRefs;
+ myRef->m_referencedName = new Name *[ myRef->m_numRefs ];
+ for ( size_t i = 0; i < myRef->m_numRefs; i++ ) {
+ myRef->m_referencedName[ i ] = new Name( ref->m_referencedName[ i ]->m_type, ref->m_referencedName[ i ]->m_id );
+ }
+ }
+ }
+}
+
+Reference *Value::getRef() const {
+ assert( ddl_ref == m_type );
+
+ return (Reference*) m_data;
+}
+
+void Value::dump() {
+ switch( m_type ) {
+ case ddl_none:
+ std::cout << "None" << std::endl;
+ break;
+ case ddl_bool:
+ std::cout << getBool() << std::endl;
+ break;
+ case ddl_int8:
+ std::cout << getInt8() << std::endl;
+ break;
+ case ddl_int16:
+ std::cout << getInt16() << std::endl;
+ break;
+ case ddl_int32:
+ std::cout << getInt32() << std::endl;
+ break;
+ case ddl_int64:
+ std::cout << getInt64() << std::endl;
+ break;
+ case ddl_unsigned_int8:
+ std::cout << "Not supported" << std::endl;
+ break;
+ case ddl_unsigned_int16:
+ std::cout << "Not supported" << std::endl;
+ break;
+ case ddl_unsigned_int32:
+ std::cout << "Not supported" << std::endl;
+ break;
+ case ddl_unsigned_int64:
+ std::cout << "Not supported" << std::endl;
+ break;
+ case ddl_half:
+ std::cout << "Not supported" << std::endl;
+ break;
+ case ddl_float:
+ std::cout << getFloat() << std::endl;
+ break;
+ case ddl_double:
+ std::cout << getDouble() << std::endl;
+ break;
+ case ddl_string:
+ std::cout << getString() << std::endl;
+ break;
+ case ddl_ref:
+ std::cout << "Not supported" << std::endl;
+ break;
+ default:
+ break;
+ }
+}
+
+void Value::setNext( Value *next ) {
+ m_next = next;
+}
+
+Value *Value::getNext() const {
+ return m_next;
+}
+
+size_t Value::size(){
+ size_t result=1;
+ Value *n=m_next;
+ while( n!=ddl_nullptr) {
+ result++;
+ n=n->m_next;
+ }
+ return result;
+}
+
+Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
+ if( type == Value::ddl_none || Value::ddl_types_max == type ) {
+ return ddl_nullptr;
+ }
+
+ Value *data = new Value( type );
+ data->m_type = type;
+ switch( type ) {
+ case Value::ddl_bool:
+ data->m_size = sizeof( bool );
+ break;
+ case Value::ddl_int8:
+ data->m_size = sizeof( int8 );
+ break;
+ case Value::ddl_int16:
+ data->m_size = sizeof( int16 );
+ break;
+ case Value::ddl_int32:
+ data->m_size = sizeof( int32 );
+ break;
+ case Value::ddl_int64:
+ data->m_size = sizeof( int64 );
+ break;
+ case Value::ddl_unsigned_int8:
+ data->m_size = sizeof( uint8 );
+ break;
+ case Value::ddl_unsigned_int16:
+ data->m_size = sizeof( uint16 );
+ break;
+ case Value::ddl_unsigned_int32:
+ data->m_size = sizeof( uint32 );
+ break;
+ case Value::ddl_unsigned_int64:
+ data->m_size = sizeof( uint64 );
+ break;
+ case Value::ddl_half:
+ data->m_size = sizeof( short );
+ break;
+ case Value::ddl_float:
+ data->m_size = sizeof( float );
+ break;
+ case Value::ddl_double:
+ data->m_size = sizeof( double );
+ break;
+ case Value::ddl_string:
+ data->m_size = sizeof( char );
+ break;
+ case Value::ddl_ref:
+ data->m_size = sizeof( char );
+ break;
+ case Value::ddl_none:
+ case Value::ddl_types_max:
+ default:
+ break;
+ }
+
+ if( data->m_size ) {
+ size_t len1( len );
+ if( Value::ddl_string == type ) {
+ len1++;
+ }
+ data->m_size *= len1;
+ data->m_data = new unsigned char[ data->m_size ];
+ }
+
+ return data;
+}
+
+void ValueAllocator::releasePrimData( Value **data ) {
+ if( !data ) {
+ return;
+ }
+
+ delete *data;
+ *data = ddl_nullptr;
+}
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
new file mode 100644
index 000000000..137135604
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
@@ -0,0 +1,164 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class Value;
+class OpenDDLParser;
+
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+///
+/// @ingroup OpenDDLParser
+/// @brief This class represents one single instance in the object tree of the parsed OpenDDL-file.
+///
+/// A DDLNode represents one leaf in the OpenDDL-node tree. It can have one parent node and multiple children.
+/// You can assign special properties to a single DDLNode instance.
+/// A node instance can store values via a linked list. You can get the first value from the DDLNode.
+/// A node can store data-array-lists and references as well.
+///
+class DLL_ODDLPARSER_EXPORT DDLNode {
+public:
+ friend class OpenDDLParser;
+
+ /// @brief The child-node-list type.
+ typedef std::vector<DDLNode*> DllNodeList;
+
+public:
+ /// @brief The class destructor.
+ ~DDLNode();
+
+ /// @brief Will attach a parent node instance, an older one will be released.
+ /// @param parent [in] The parent node instance.
+ void attachParent( DDLNode *parent );
+
+ /// @brief Will try to detach a parent node instance, if there is any.
+ void detachParent();
+
+ /// @brief Returns the assigned parent node instance, will return ddl_nullptr id no parent is assigned.
+ /// @return The parent node instance.
+ DDLNode *getParent() const;
+
+ /// @brief Returns the child node list.
+ /// @return The list of child nodes.
+ const DllNodeList &getChildNodeList() const;
+
+ /// Set the type of the DDLNode instance.
+ /// @param type [in] The type.
+ void setType( const std::string &type );
+
+ /// @brief Returns the type of the DDLNode instance.
+ /// @return The type of the DDLNode instance.
+ const std::string &getType() const;
+
+ /// Set the name of the DDLNode instance.
+ /// @param type [in] The name.
+ void setName( const std::string &name );
+
+ /// @brief Returns the name of the DDLNode instance.
+ /// @return The name of the DDLNode instance.
+ const std::string &getName() const;
+
+ /// @brief Set a new property set.
+ /// @param prop [in] The first element of the property set.
+ void setProperties( Property *prop );
+
+ /// @brief Returns the first element of the assigned property set.
+ /// @return The first property of the assigned property set.
+ Property *getProperties() const;
+
+ /// @brief Looks for a given property.
+ /// @param name [in] The name for the property to look for.
+ /// @return true, if a corresponding property is assigned to the node, false if not.
+ bool hasProperty( const std::string &name );
+
+ /// @brief Will return true, if any properties are assigned to the node instance.
+ /// @return True, if properties are assigned.
+ bool hasProperties() const;
+
+ /// @brief Search for a given property and returns it. Will return ddl_nullptr if no property was found.
+ /// @param name [in] The name for the property to look for.
+ /// @return The property or ddl_nullptr if no property was found.
+ Property *findPropertyByName( const std::string &name );
+
+ /// @brief Set a new value set.
+ /// @param val [in] The first value instance of the value set.
+ void setValue( Value *val );
+
+ /// @brief Returns the first element of the assigned value set.
+ /// @return The first property of the assigned value set.
+ Value *getValue() const;
+
+ /// @brief Set a new DataArrayList.
+ /// @param val [in] The DataArrayList instance.
+ void setDataArrayList( DataArrayList *dtArrayList );
+
+ /// @brief Returns the DataArrayList.
+ /// @return The DataArrayList.
+ DataArrayList *getDataArrayList() const;
+
+ /// @brief Set a new Reference set.
+ /// @param val [in] The first value instance of the Reference set.
+ void setReferences( Reference *refs );
+
+ /// @brief Returns the first element of the assigned Reference set.
+ /// @return The first property of the assigned Reference set.
+ Reference *getReferences() const;
+
+ /// @brief The creation method.
+ /// @param type [in] The DDLNode type.
+ /// @param name [in] The name for the new DDLNode instance.
+ /// @param parent [in] The parent node instance or ddl_nullptr if no parent node is there.
+ /// @return The new created node instance.
+ static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
+
+private:
+ DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent = ddl_nullptr );
+ DDLNode();
+ DDLNode( const DDLNode & ) ddl_no_copy;
+ DDLNode &operator = ( const DDLNode & ) ddl_no_copy;
+ static void releaseNodes();
+
+private:
+ std::string m_type;
+ std::string m_name;
+ DDLNode *m_parent;
+ std::vector<DDLNode*> m_children;
+ Property *m_properties;
+ Value *m_value;
+ DataArrayList *m_dtArrayList;
+ Reference *m_references;
+ size_t m_idx;
+ static DllNodeList s_allocatedNodes;
+};
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
new file mode 100644
index 000000000..d3e0fb458
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
@@ -0,0 +1,247 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <cstddef>
+#include <vector>
+#include <string>
+
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32
+# include <inttypes.h>
+#endif
+
+#if defined(_MSC_VER) && !defined( OPENDDL_STATIC_LIBARY )
+
+# define TAG_DLL_EXPORT __declspec(dllexport)
+# define TAG_DLL_IMPORT __declspec(dllimport )
+# ifdef OPENDDLPARSER_BUILD
+# define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
+# else
+# define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
+# endif // OPENDDLPARSER_BUILD
+# pragma warning( disable : 4251 )
+#else
+# define DLL_ODDLPARSER_EXPORT
+#endif // _WIN32
+
+// Namespace declarations, override this to avoid any conflicts
+#define BEGIN_ODDLPARSER_NS namespace ODDLParser {
+#define END_ODDLPARSER_NS } // namespace ODDLParser
+#define USE_ODDLPARSER_NS using namespace ODDLParser;
+
+BEGIN_ODDLPARSER_NS
+
+// We will use C++11 optional
+#ifndef OPENDDL_NO_USE_CPP11
+ // All C++11 constructs
+# define ddl_nullptr nullptr
+# define ddl_override override
+# define ddl_final final
+# define ddl_no_copy = delete
+#else
+ // Fall-back for older compilers
+# define ddl_nullptr NULL
+# define ddl_override
+# define ddl_final
+# define ddl_no_copy
+#endif // OPENDDL_NO_USE_CPP11
+
+// Forward declarations
+class DDLNode;
+class Value;
+
+struct Name;
+struct Identifier;
+struct Reference;
+struct Property;
+struct DataArrayList;
+
+// Platform-specific typedefs
+#ifdef _WIN32
+typedef signed __int64 int64_impl;
+typedef unsigned __int64 uint64_impl;
+#else
+typedef int64_t int64_impl;
+typedef uint64_t uint64_impl;
+#endif
+
+// OpenDDL-specific data typedefs
+typedef signed char int8; ///< Signed integer, 1 byte
+typedef signed short int16; ///< Signed integer, 2 byte
+typedef signed int int32; ///< Signed integer, 4 byte
+typedef int64_impl int64; ///< Signed integer, 8 byte
+typedef unsigned char uint8; ///< Unsigned integer, 1 byte
+typedef unsigned short uint16; ///< Unsigned integer, 2 byte
+typedef unsigned int uint32; ///< Unsigned integer, 4 byte
+typedef uint64_impl uint64; ///< Unsigned integer, 8 byte
+
+/// @brief Stores a text.
+///
+/// A text is stored in a simple character buffer. Texts buffer can be
+/// greater than the number of stored characters in them.
+struct DLL_ODDLPARSER_EXPORT Text {
+ size_t m_capacity; ///< The capacity of the text.
+ size_t m_len; ///< The length of the text.
+ char *m_buffer; ///< The buffer with the text.
+
+ /// @brief The constructor with a given text buffer.
+ /// @param buffer [in] The buffer.
+ /// @param numChars [in] The number of characters in the buffer.
+ Text( const char *buffer, size_t numChars );
+
+ /// @brief The destructor.
+ ~Text();
+
+ /// @brief Clears the text.
+ void clear();
+
+ /// @brief Set a new text.
+ /// @param buffer [in] The buffer.
+ /// @param numChars [in] The number of characters in the buffer.
+ void set( const char *buffer, size_t numChars );
+
+ /// @brief The compare operator for std::strings.
+ bool operator == ( const std::string &name ) const;
+
+ /// @brief The compare operator for Texts.
+ bool operator == ( const Text &rhs ) const;
+
+private:
+ Text( const Text & ) ddl_no_copy;
+ Text &operator = ( const Text & ) ddl_no_copy;
+};
+
+/// @brief Description of the type of a name.
+enum NameType {
+ GlobalName, ///< Name is global.
+ LocalName ///< Name is local.
+};
+
+/// @brief Stores an OpenDDL-specific name
+struct DLL_ODDLPARSER_EXPORT Name {
+ NameType m_type; ///< The type of the name ( @see NameType ).
+ Text *m_id; ///< The id.
+
+ /// @brief The constructor with the type and the id.
+ /// @param type [in] The name type.
+ /// @param id [in] The id.
+ Name( NameType type, Text *id );
+
+ /// @brief The destructor.
+ ~Name();
+
+private:
+ Name( const Name & ) ddl_no_copy;
+ Name &operator = ( const Name& ) ddl_no_copy;
+};
+
+/// @brief Stores a bundle of references.
+struct DLL_ODDLPARSER_EXPORT Reference {
+ size_t m_numRefs; ///< The number of stored references.
+ Name **m_referencedName; ///< The reference names.
+
+ /// @brief The default constructor.
+ Reference();
+
+ /// @brief The constructor with an array of ref names.
+ /// @param numrefs [in] The number of ref names.
+ /// @param names [in] The ref names.
+ Reference( size_t numrefs, Name **names );
+
+ /// @brief The destructor.
+ ~Reference();
+
+ /// @brief Returns the size in bytes to store one deep reference copy.
+ /// @return The size on bytes.
+ size_t sizeInBytes();
+
+private:
+ Reference( const Reference & ) ddl_no_copy;
+ Reference &operator = ( const Reference & ) ddl_no_copy;
+};
+
+/// @brief Stores a property list.
+struct DLL_ODDLPARSER_EXPORT Property {
+ Text *m_key; ///< The identifier / key of the property.
+ Value *m_value; ///< The value assigned to its key / id ( ddl_nullptr if none ).
+ Reference *m_ref; ///< References assigned to its key / id ( ddl_nullptr if none ).
+ Property *m_next; ///< The next property ( ddl_nullptr if none ).
+
+ /// @brief The default constructor.
+ Property();
+
+ /// @brief The constructor for initialization.
+ /// @param id [in] The identifier
+ Property( Text *id );
+
+ /// @brief The destructor.
+ ~Property();
+
+private:
+ Property( const Property & ) ddl_no_copy;
+ Property &operator = ( const Property & ) ddl_no_copy;
+};
+
+/// @brief Stores a data array list.
+struct DLL_ODDLPARSER_EXPORT DataArrayList {
+ size_t m_numItems; ///< The number of items in the list.
+ Value *m_dataList; ///< The data list ( a Value ).
+ DataArrayList *m_next; ///< The next data array list ( ddl_nullptr if last ).
+ Reference *m_refs;
+ size_t m_numRefs;
+
+ /// @brief The default constructor for initialization.
+ DataArrayList();
+
+ /// @brief The destructor.
+ ~DataArrayList();
+
+ /// @brief Gets the length of the array
+ size_t size();
+
+private:
+ DataArrayList( const DataArrayList & ) ddl_no_copy;
+ DataArrayList &operator = ( const DataArrayList & ) ddl_no_copy;
+};
+
+/// @brief Stores the context of a parsed OpenDDL declaration.
+struct DLL_ODDLPARSER_EXPORT Context {
+ DDLNode *m_root; ///< The root node of the OpenDDL node tree.
+
+ /// @brief Constructor for initialization.
+ Context();
+
+ /// @brief Destructor.
+ ~Context();
+
+ /// @brief Clears the whole node tree.
+ void clear();
+
+private:
+ Context( const Context & ) ddl_no_copy;
+ Context &operator = ( const Context & ) ddl_no_copy;
+};
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
new file mode 100644
index 000000000..8ede537d9
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
@@ -0,0 +1,104 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/Value.h>
+
+BEGIN_ODDLPARSER_NS
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup IOStreamBase
+/// @brief This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
+public:
+ StreamFormatterBase();
+ virtual ~StreamFormatterBase();
+ virtual std::string format( const std::string &statement );
+};
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup IOStreamBase
+/// @brief This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT IOStreamBase {
+public:
+ IOStreamBase( StreamFormatterBase *formatter = ddl_nullptr );
+ virtual ~IOStreamBase();
+ virtual bool open( const std::string &anme );
+ virtual bool close();
+ virtual size_t write( const std::string &statement );
+
+private:
+ StreamFormatterBase *m_formatter;
+ FILE *m_file;
+};
+
+//-------------------------------------------------------------------------------------------------
+///
+/// @ingroup OpenDDLParser
+/// @brief This class represents the OpenDDLExporter.
+///
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT OpenDDLExport {
+public:
+ /// @brief The class constructor
+ OpenDDLExport( IOStreamBase *stream = ddl_nullptr );
+
+ /// @brief The class destructor.
+ ~OpenDDLExport();
+
+ /// @brief Export the data of a parser context.
+ /// @param ctx [in] Pointer to the context.
+ /// @param filename [in] The filename for the export.
+ /// @return True in case of success, false in case of an error.
+ bool exportContext( Context *ctx, const std::string &filename );
+
+ /// @brief Handles a node export.
+ /// @param node [in] The node to handle with.
+ /// @return True in case of success, false in case of an error.
+ bool handleNode( DDLNode *node );
+
+ /// @brief Writes the statement to the stream.
+ /// @param statement [in] The content to write.
+ /// @return True in case of success, false in case of an error.
+ bool writeToStream( const std::string &statement );
+
+protected:
+ bool writeNode( DDLNode *node, std::string &statement );
+ bool writeNodeHeader( DDLNode *node, std::string &statement );
+ bool writeProperties( DDLNode *node, std::string &statement );
+ bool writeValueType( Value::ValueType type, size_t numItems, std::string &statement );
+ bool writeValue( Value *val, std::string &statement );
+ bool writeValueArray( DataArrayList *al, std::string &statement );
+
+private:
+ OpenDDLExport( const OpenDDLExport & ) ddl_no_copy;
+ OpenDDLExport &operator = ( const OpenDDLExport & ) ddl_no_copy;
+
+private:
+ IOStreamBase *m_stream;
+};
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
new file mode 100644
index 000000000..efeab6026
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
@@ -0,0 +1,187 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/DDLNode.h>
+#include <openddlparser/OpenDDLParserUtils.h>
+#include <openddlparser/Value.h>
+
+#include <vector>
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+class DDLNode;
+class Value;
+
+struct Identifier;
+struct Reference;
+struct Property;
+
+/// @brief Utility function to search for the next token or the end of the buffer.
+/// @param in [in] The start position in the buffer.
+/// @param end [in] The end position in the buffer.
+/// @return Pointer showing to the next token or the end of the buffer.
+/// @detail Will not increase buffer when already a valid buffer was found.
+template<class T>
+inline
+T *lookForNextToken( T *in, T *end ) {
+ while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+ in++;
+ }
+ return in;
+}
+
+/// @brief Utility function to go for the next token or the end of the buffer.
+/// @param in [in] The start position in the buffer.
+/// @param end [in] The end position in the buffer.
+/// @return Pointer showing to the next token or the end of the buffer.
+/// @detail Will increase buffer by a minimum of one.
+template<class T>
+inline
+T *getNextToken( T *in, T *end ) {
+ T *tmp( in );
+ in = lookForNextToken( in, end );
+ if( tmp == in ) {
+ in++;
+ }
+ return in;
+}
+
+/// @brief Defines the log severity.
+enum LogSeverity {
+ ddl_debug_msg = 0, ///< Debug message, for debugging
+ ddl_info_msg, ///< Info messages, normal mode
+ ddl_warn_msg, ///< Parser warnings
+ ddl_error_msg ///< Parser errors
+};
+
+DLL_ODDLPARSER_EXPORT const char *getTypeToken( Value::ValueType type );
+
+//-------------------------------------------------------------------------------------------------
+/// @class OpenDDLParser
+/// @ingroup OpenDDLParser
+
+///
+/// @brief This is the main API for the OpenDDL-parser.
+///
+/// Use instances of this class to manage the parsing and handling of your parser contexts.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT OpenDDLParser {
+public:
+ /// @brief The log callback function pointer.
+ typedef void( *logCallback )( LogSeverity severity, const std::string &msg );
+
+public:
+ /// @brief The default class constructor.
+ OpenDDLParser();
+
+ /// @brief The class constructor.
+ /// @param buffer [in] The buffer
+ /// @param len [in] Size of the buffer
+ OpenDDLParser( const char *buffer, size_t len );
+
+ /// @brief The class destructor.
+ ~OpenDDLParser();
+
+ /// @brief Setter for an own log callback function.
+ /// @param callback [in] The own callback.
+ void setLogCallback( logCallback callback );
+
+ /// @brief Getter for the log callback.
+ /// @return The current log callback.
+ logCallback getLogCallback() const;
+
+ /// @brief Assigns a new buffer to parse.
+ /// @param buffer [in] The buffer
+ /// @param len [in] Size of the buffer
+ void setBuffer( const char *buffer, size_t len );
+
+ /// @brief Assigns a new buffer to parse.
+ /// @param buffer [in] The buffer as a std::vector.
+ void setBuffer( const std::vector<char> &buffer );
+
+ /// @brief Returns the buffer pointer.
+ /// @return The buffer pointer.
+ const char *getBuffer() const;
+
+ /// @brief Returns the size of the buffer.
+ /// @return The buffer size.
+ size_t getBufferSize() const;
+
+ /// @brief Clears all parser data, including buffer and active context.
+ void clear();
+
+ /// @brief Starts the parsing of the OpenDDL-file.
+ /// @return True in case of success, false in case of an error.
+ /// @remark In case of errors check log.
+ bool parse();
+
+ bool exportContext( Context *ctx, const std::string &filename );
+
+ /// @brief Returns the root node.
+ /// @return The root node.
+ DDLNode *getRoot() const;
+
+ /// @brief Returns the parser context, only available in case of a succeeded parsing.
+ /// @return Pointer to the active context or ddl_nullptr.
+ Context *getContext() const;
+
+public: // parser helpers
+ char *parseNextNode( char *current, char *end );
+ char *parseHeader( char *in, char *end );
+ char *parseStructure( char *in, char *end );
+ char *parseStructureBody( char *in, char *end, bool &error );
+ void pushNode( DDLNode *node );
+ DDLNode *popNode();
+ DDLNode *top();
+ static void normalizeBuffer( std::vector<char> &buffer );
+ static char *parseName( char *in, char *end, Name **name );
+ static char *parseIdentifier( char *in, char *end, Text **id );
+ static char *parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len );
+ static char *parseReference( char *in, char *end, std::vector<Name*> &names );
+ static char *parseBooleanLiteral( char *in, char *end, Value **boolean );
+ static char *parseIntegerLiteral( char *in, char *end, Value **integer, Value::ValueType integerType = Value::ddl_int32 );
+ static char *parseFloatingLiteral( char *in, char *end, Value **floating, Value::ValueType floatType= Value::ddl_float );
+ static char *parseStringLiteral( char *in, char *end, Value **stringData );
+ static char *parseHexaLiteral( char *in, char *end, Value **data );
+ static char *parseProperty( char *in, char *end, Property **prop );
+ static char *parseDataList( char *in, char *end, Value::ValueType type, Value **data, size_t &numValues, Reference **refs, size_t &numRefs );
+ static char *parseDataArrayList( char *in, char *end, Value::ValueType type, DataArrayList **dataList );
+ static const char *getVersion();
+
+private:
+ OpenDDLParser( const OpenDDLParser & ) ddl_no_copy;
+ OpenDDLParser &operator = ( const OpenDDLParser & ) ddl_no_copy;
+
+private:
+ logCallback m_logCallback;
+ std::vector<char> m_buffer;
+
+ typedef std::vector<DDLNode*> DDLNodeStack;
+ DDLNodeStack m_stack;
+ Context *m_context;
+};
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
new file mode 100644
index 000000000..778a1b46e
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
@@ -0,0 +1,254 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+template<class T>
+inline
+bool isUpperCase( T in ) {
+ return ( in >= 'A' && in <= 'Z' );
+}
+
+template<class T>
+inline
+bool isLowerCase( T in ) {
+ return ( in >= 'a' && in <= 'z' );
+}
+
+template<class T>
+inline
+bool isSpace( const T in ) {
+ return ( ' ' == in || '\t' == in );
+}
+
+template<class T>
+inline
+bool isNewLine( const T in ) {
+ return ( '\n' == in || ( '\r' == in ) );
+}
+
+template<class T>
+inline
+bool isSeparator( T in ) {
+ if( isSpace( in ) || ',' == in || '{' == in || '}' == in || '[' == in || '(' == in || ')' == in ) {
+ return true;
+ }
+ return false;
+}
+
+static const unsigned char chartype_table[ 256 ] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127
+ 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, 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, 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,
+};
+
+template<class T>
+inline
+bool isNumeric( const T in ) {
+ return ( chartype_table[ static_cast<int>( in ) ] == 1 );
+}
+
+template<class T>
+inline
+bool isNotEndOfToken( T *in, T *end ) {
+ return ( '}' != *in && ',' != *in && !isSpace( *in ) && ')' != *in && in != end );
+}
+
+template<class T>
+inline
+bool isInteger( T *in, T *end ) {
+ if( in != end ) {
+ if( *in == '-' ) {
+ in++;
+ }
+ }
+
+ bool result( false );
+ while( isNotEndOfToken( in, end ) ) {
+ result = isNumeric( *in );
+ if( !result ) {
+ break;
+ }
+ in++;
+ }
+
+ return result;
+}
+
+template<class T>
+inline
+bool isFloat( T *in, T *end ) {
+ if( in != end ) {
+ if( *in == '-' ) {
+ in++;
+ }
+ }
+
+ // check for <1>.0f
+ bool result( false );
+ while( isNotEndOfToken( in, end ) ) {
+ if( *in == '.' ) {
+ result = true;
+ break;
+ }
+ result = isNumeric( *in );
+ if( !result ) {
+ return false;
+ }
+ in++;
+ }
+
+ // check for 1<.>0f
+ if( *in == '.' ) {
+ in++;
+ } else {
+ return false;
+ }
+
+ // check for 1.<0>f
+ while( isNotEndOfToken( in, end ) ) {
+ result = isNumeric( *in );
+ if( !result ) {
+ return false;
+ }
+ in++;
+ }
+
+ return result;
+}
+
+template<class T>
+inline
+bool isCharacter( const T in ) {
+ return ( ( in >= 'a' && in <= 'z' ) || ( in >= 'A' && in <= 'Z' ) );
+}
+
+template<class T>
+inline
+bool isStringLiteral( const T in ) {
+ return ( in == '\"' );
+}
+
+template<class T>
+inline
+bool isHexLiteral( T *in, T *end ) {
+ if( *in == '0' ) {
+ if( in + 1 != end ) {
+ if( *( in + 1 ) == 'x' || *( in + 1 ) == 'X' ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+template<class T>
+inline
+bool isReference( T *in, T *end ) {
+ if( *in == 'r' ) {
+ if( *(in+1) == 'e' ) {
+ if( *(in+2) == 'f' ) {
+ if( ( in + 2 ) != end ) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+template<class T>
+inline
+bool isEndofLine( const T in ) {
+ return ( '\n' == in );
+}
+
+template<class T>
+inline
+static T *getNextSeparator( T *in, T *end ) {
+ while( !isSeparator( *in ) || in == end ) {
+ in++;
+ }
+ return in;
+}
+
+static const int ErrorHex2Decimal = 9999999;
+
+inline
+int hex2Decimal( char in ) {
+ if( isNumeric( in ) ) {
+ return ( in - 48 );
+ }
+
+ char hexCodeLower( 'a' ), hexCodeUpper( 'A' );
+ for( int i = 0; i<16; i++ ) {
+ if( in == hexCodeLower + i || in == hexCodeUpper + i ) {
+ return ( i+10 );
+ }
+ }
+
+ return ErrorHex2Decimal;
+}
+
+template<class T>
+inline
+bool isComment( T *in, T *end ) {
+ if ( *in=='/' ) {
+ if ( in+1!=end ) {
+ if ( *( in+1 )=='/' ) {
+ char *drive( ( in+2 ) );
+ if ( (isUpperCase<T>( *drive )||isLowerCase<T>( *drive ))&&*( drive+1 )=='/' ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+END_ODDLPARSER_NS
+
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h
new file mode 100644
index 000000000..242ec8781
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h
@@ -0,0 +1,269 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+#include <string>
+
+BEGIN_ODDLPARSER_NS
+
+struct ValueAllocator;
+
+///------------------------------------------------------------------------------------------------
+/// @brief This class implements a value.
+///
+/// Values are used to store data types like boolean, integer, floats, double and many mode. To get
+/// an overview please check the enum VylueType ( @see Value::ValueType ).
+/// Values can be single items or lists of items. They are implemented as linked lists.
+///------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT Value {
+ friend struct ValueAllocator;
+
+public:
+ /// @brief This class implements an iterator through a Value list.
+ ///
+ /// When getting a new value you need to know how to iterate through it. The Value::Iterator
+ /// will help you here:
+ /// @code
+ /// Value *val = node->getValue();
+ /// Value::Iterator it( val );
+ /// while( it.hasNext() ) {
+ /// Value v( it.getNext );
+ /// }
+ /// @endcode
+ class DLL_ODDLPARSER_EXPORT Iterator {
+ public:
+ /// @brief The default class constructor.
+ Iterator();
+
+ /// @brief The class constructor with the start value.
+ /// @param start [in] The first value for iteration,
+ Iterator( Value *start );
+
+ Iterator( const Iterator &rhs );
+
+ /// @brief The class destructor.
+ ~Iterator();
+
+ /// @brief Will return true, if another value is in the list.
+ /// @return true if another value is there.
+ bool hasNext() const;
+
+ /// @brief Returns the next item and moves the iterator to it.
+ /// @return The next value, is ddl_nullptr in case of being the last item.
+ Value *getNext();
+
+ /// @brief The post-increment operator.
+ const Iterator operator++( int );
+
+ /// @brief The pre-increment operator.
+ Iterator &operator++( );
+
+ /// @brief The compare operator.
+ /// @param rhs [in] The instance to compare.
+ /// @return true if equal.
+ bool operator == ( const Iterator &rhs ) const;
+
+ /// @brief The * operator.
+ /// @return The instance or ddl_nullptr if end of list is reached.
+ Value *operator->( ) const;
+
+ private:
+ Value *m_start;
+ Value *m_current;
+
+ private:
+ Iterator &operator = ( const Iterator & );
+ };
+
+ /// @brief This enum describes the data type stored in the value.
+ enum ValueType {
+ ddl_none = -1, ///< Nothing specified
+ ddl_bool = 0, ///< A boolean type
+ ddl_int8, ///< Integer type, 8 bytes
+ ddl_int16, ///< Integer type, 16 bytes
+ ddl_int32, ///< Integer type, 32 bytes
+ ddl_int64, ///< Integer type, 64 bytes
+ ddl_unsigned_int8, ///< Unsigned integer type, 8 bytes
+ ddl_unsigned_int16, ///< Unsigned integer type, 16 bytes
+ ddl_unsigned_int32, ///< Unsigned integer type, 32 bytes
+ ddl_unsigned_int64, ///< Unsigned integer type, 64 bytes
+ ddl_half, ///< Half data type.
+ ddl_float, ///< float data type
+ ddl_double, ///< Double data type.
+ ddl_string, ///< String data type.
+ ddl_ref, ///< Reference, used to define references to other data definitions.
+ ddl_types_max ///< Upper limit.
+ };
+
+ /// @brief The class constructor.
+ /// @param type [in] The value type.
+ Value( ValueType type );
+
+ /// @brief The class destructor.
+ ~Value();
+
+ /// @brief Assigns a boolean to the value.
+ /// @param value [in9 The value.
+ void setBool( bool value );
+
+ /// @brief Returns the boolean value.
+ /// @return The boolean value.
+ bool getBool();
+
+ /// @brief Assigns a int8 to the value.
+ /// @param value [in] The value.
+ void setInt8( int8 value );
+
+ /// @brief Returns the int8 value.
+ /// @return The int8 value.
+ int8 getInt8();
+
+ /// @brief Assigns a int16 to the value.
+ /// @param value [in] The value.
+ void setInt16( int16 value );
+
+ /// @brief Returns the int16 value.
+ /// @return The int16 value.
+ int16 getInt16();
+
+ /// @brief Assigns a int32 to the value.
+ /// @param value [in] The value.
+ void setInt32( int32 value );
+
+ /// @brief Returns the int16 value.
+ /// @return The int32 value.
+ int32 getInt32();
+
+ /// @brief Assigns a int64 to the value.
+ /// @param value [in] The value.
+ void setInt64( int64 value );
+
+ /// @brief Returns the int16 value.
+ /// @return The int64 value.
+ int64 getInt64();
+
+ /// @brief Assigns a unsigned int8 to the value.
+ /// @param value [in] The value.
+ void setUnsignedInt8( uint8 value );
+
+ /// @brief Returns the unsigned int8 value.
+ /// @return The unsigned int8 value.
+ uint8 getUnsignedInt8() const;
+
+ /// @brief Assigns a unsigned int16 to the value.
+ /// @param value [in] The value.
+ void setUnsignedInt16( uint16 value );
+
+ /// @brief Returns the unsigned int16 value.
+ /// @return The unsigned int16 value.
+ uint16 getUnsignedInt16() const;
+
+ /// @brief Assigns a unsigned int32 to the value.
+ /// @param value [in] The value.
+ void setUnsignedInt32( uint32 value );
+
+ /// @brief Returns the unsigned int8 value.
+ /// @return The unsigned int32 value.
+ uint32 getUnsignedInt32() const;
+
+ /// @brief Assigns a unsigned int64 to the value.
+ /// @param value [in] The value.
+ void setUnsignedInt64( uint64 value );
+
+ /// @brief Returns the unsigned int64 value.
+ /// @return The unsigned int64 value.
+ uint64 getUnsignedInt64() const;
+
+ /// @brief Assigns a float to the value.
+ /// @param value [in] The value.
+ void setFloat( float value );
+
+ /// @brief Returns the float value.
+ /// @return The float value.
+ float getFloat() const;
+
+ /// @brief Assigns a double to the value.
+ /// @param value [in] The value.
+ void setDouble( double value );
+
+ /// @brief Returns the double value.
+ /// @return The double value.
+ double getDouble() const;
+
+ /// @brief Assigns a std::string to the value.
+ /// @param value [in] The value.
+ void setString( const std::string &str );
+
+ /// @brief Returns the std::string value.
+ /// @return The std::string value.
+ const char *getString() const;
+
+ /// @brief Set the reference.
+ /// @param ref [in] Pointer showing to the reference.
+ void setRef( Reference *ref );
+
+ /// @brief Returns the pointer showing to the reference.
+ /// @return Pointer showing to the reference.
+ Reference *getRef() const;
+
+ /// @brief Dumps the value.
+ void dump();
+
+ /// @brief Assigns the next value.
+ /// @param next [n] The next value.
+ void setNext( Value *next );
+
+ /// @brief Returns the next value.
+ /// @return The next value.s
+ Value *getNext() const;
+
+ /// @brief Gets the length of the array.
+ /// @return The number of items in the array.
+ size_t size();
+
+ ValueType m_type;
+ size_t m_size;
+ unsigned char *m_data;
+ Value *m_next;
+
+private:
+ Value &operator =( const Value & ) ddl_no_copy;
+ Value( const Value & ) ddl_no_copy;
+};
+
+///------------------------------------------------------------------------------------------------
+/// @brief This class implements the value allocator.
+///------------------------------------------------------------------------------------------------
+struct DLL_ODDLPARSER_EXPORT ValueAllocator {
+ static Value *allocPrimData( Value::ValueType type, size_t len = 1 );
+ static void releasePrimData( Value **data );
+
+private:
+ ValueAllocator() ddl_no_copy;
+ ValueAllocator( const ValueAllocator & ) ddl_no_copy;
+ ValueAllocator &operator = ( const ValueAllocator & ) ddl_no_copy;
+};
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
index f3b3c65a1..4f691838f 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
@@ -107,7 +107,7 @@ struct Point {
/// Get the length of this point (the norm).
double Length() const
{
- return std::sqrt(x * x + y * y);
+ return sqrt(x * x + y * y);
}
/// Convert this point into a unit point. Returns the Length.
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h
index 30bef66f8..f123fedaf 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h
@@ -32,67 +32,13 @@
#ifndef UTILS_H
#define UTILS_H
-// Otherwise #defines like M_PI are undeclared under Visual Studio
-#define _USE_MATH_DEFINES
-
#include <exception>
-#include <math.h>
-
-#ifndef M_E
-#define M_E (2.7182818284590452354)
-#endif
-
-#ifndef M_LOG2E
-#define M_LOG2E (1.4426950408889634074)
-#endif
-
-#ifndef M_LOG10E
-#define M_LOG10E (0.43429448190325182765)
-#endif
-
-#ifndef M_LN2
-#define M_LN2 (0.69314718055994530942)
-#endif
-
-#ifndef M_LN10
-#define M_LN10 (2.30258509299404568402)
-#endif
-
-#ifndef M_PI
-#define M_PI (3.14159265358979323846)
-#endif
-
-#ifndef M_PI_2
-#define M_PI_2 (1.57079632679489661923)
-#endif
-
-#ifndef M_PI_4
-#define M_PI_4 (0.78539816339744830962)
-#endif
-
-#ifndef M_1_PI
-#define M_1_PI (0.31830988618379067154)
-#endif
-
-#ifndef M_2_PI
-#define M_2_PI (0.63661977236758134308)
-#endif
-
-#ifndef M_2_SQRTPI
-#define M_2_SQRTPI (1.12837916709551257390)
-#endif
-
-#ifndef M_SQRT2
-#define M_SQRT2 (1.41421356237309504880)
-#endif
-
-#ifndef M_SQRT1_2
-#define M_SQRT1_2 (0.70710678118654752440)
-#endif
namespace p2t {
-const double PI_3div4 = 3 * M_PI / 4;
+const double PI = 3.1415926535897932384626433832795029;
+const double PI_2 = 2 * PI;
+const double PI_3div4 = 3 * PI / 4;
const double EPSILON = 1e-15;
enum Orientation { CW, CCW, COLLINEAR };
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc
index e02226bd1..ed7c49ac4 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc
@@ -231,7 +231,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
while (node->next) {
double angle = HoleAngle(*node);
- if (angle > M_PI_2 || angle < -M_PI_2) break;
+ if (angle > PI_2 || angle < -PI_2) break;
Fill(tcx, *node);
node = node->next;
}
@@ -241,7 +241,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
while (node->prev) {
double angle = HoleAngle(*node);
- if (angle > M_PI_2 || angle < -M_PI_2) break;
+ if (angle > PI_2 || angle < -PI_2) break;
Fill(tcx, *node);
node = node->prev;
}
@@ -652,13 +652,6 @@ void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t,
Triangle& ot = t->NeighborAcross(p);
Point& op = *ot.OppositePoint(*t, p);
- if (&ot == NULL) {
- // If we want to integrate the fillEdgeEvent do it here
- // With current implementation we should never get here
- //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
- assert(0);
- }
-
if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
// Lets rotate shared edge one vertex CW
RotateTrianglePair(*t, p, ot, op);
@@ -728,13 +721,6 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
Triangle& ot = t.NeighborAcross(p);
Point& op = *ot.OppositePoint(t, p);
- if (&t.NeighborAcross(p) == NULL) {
- // If we want to integrate the fillEdgeEvent do it here
- // With current implementation we should never get here
- //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
- assert(0);
- }
-
if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {
// flip with new edge op->eq
FlipEdgeEvent(tcx, eq, op, &ot, op);
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc
index c9dd5a8c4..235e1eb05 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc
@@ -164,7 +164,7 @@ void SweepContext::RemoveFromMap(Triangle* triangle)
void SweepContext::MeshClean(Triangle& triangle)
{
- if (&triangle != NULL && !triangle.IsInterior()) {
+ if (!triangle.IsInterior()) {
triangle.IsInterior(true);
triangles_.push_back(&triangle);
for (int i = 0; i < 3; i++) {
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h
new file mode 100644
index 000000000..24e6044b3
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h
@@ -0,0 +1,261 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ALLOCATORS_H_
+#define RAPIDJSON_ALLOCATORS_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+ \brief Concept for allocating, resizing and freeing memory block.
+
+ Note that Malloc() and Realloc() are non-static but Free() is static.
+
+ So if an allocator need to support Free(), it needs to put its pointer in
+ the header of memory block.
+
+\code
+concept Allocator {
+ static const bool kNeedFree; //!< Whether this allocator needs to call Free().
+
+ // Allocate a memory block.
+ // \param size of the memory block in bytes.
+ // \returns pointer to the memory block.
+ void* Malloc(size_t size);
+
+ // Resize a memory block.
+ // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+ // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+ // \param newSize the new size in bytes.
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+ // Free a memory block.
+ // \param pointer to the memory block. Null pointer is permitted.
+ static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+ \note implements Allocator concept
+*/
+class CrtAllocator {
+public:
+ static const bool kNeedFree = true;
+ void* Malloc(size_t size) {
+ if (size) // behavior of malloc(0) is implementation defined.
+ return std::malloc(size);
+ else
+ return NULL; // standardize to returning NULL.
+ }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ (void)originalSize;
+ if (newSize == 0) {
+ std::free(originalPtr);
+ return NULL;
+ }
+ return std::realloc(originalPtr, newSize);
+ }
+ static void Free(void *ptr) { std::free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks.
+
+ It does not free memory blocks. And Realloc() only allocate new memory.
+
+ The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+ User may also supply a buffer as the first chunk.
+
+ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+ The user-buffer is not deallocated by this allocator.
+
+ \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+ \note implements Allocator concept
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+ static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+ //! Constructor with chunkSize.
+ /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ }
+
+ //! Constructor with user-supplied buffer.
+ /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+ The user buffer will not be deallocated when this allocator is destructed.
+
+ \param buffer User supplied buffer.
+ \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+ \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ RAPIDJSON_ASSERT(buffer != 0);
+ RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+ chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
+ chunkHead_->capacity = size - sizeof(ChunkHeader);
+ chunkHead_->size = 0;
+ chunkHead_->next = 0;
+ }
+
+ //! Destructor.
+ /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+ */
+ ~MemoryPoolAllocator() {
+ Clear();
+ RAPIDJSON_DELETE(ownBaseAllocator_);
+ }
+
+ //! Deallocates all memory chunks, excluding the user-supplied buffer.
+ void Clear() {
+ while (chunkHead_ && chunkHead_ != userBuffer_) {
+ ChunkHeader* next = chunkHead_->next;
+ baseAllocator_->Free(chunkHead_);
+ chunkHead_ = next;
+ }
+ if (chunkHead_ && chunkHead_ == userBuffer_)
+ chunkHead_->size = 0; // Clear user buffer
+ }
+
+ //! Computes the total capacity of allocated memory chunks.
+ /*! \return total capacity in bytes.
+ */
+ size_t Capacity() const {
+ size_t capacity = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ capacity += c->capacity;
+ return capacity;
+ }
+
+ //! Computes the memory blocks allocated.
+ /*! \return total used bytes.
+ */
+ size_t Size() const {
+ size_t size = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ size += c->size;
+ return size;
+ }
+
+ //! Allocates a memory block. (concept Allocator)
+ void* Malloc(size_t size) {
+ if (!size)
+ return NULL;
+
+ size = RAPIDJSON_ALIGN(size);
+ if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+ AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+
+ void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
+ chunkHead_->size += size;
+ return buffer;
+ }
+
+ //! Resizes a memory block (concept Allocator)
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ if (originalPtr == 0)
+ return Malloc(newSize);
+
+ if (newSize == 0)
+ return NULL;
+
+ // Do not shrink if new size is smaller than original
+ if (originalSize >= newSize)
+ return originalPtr;
+
+ // Simply expand it if it is the last allocation and there is sufficient space
+ if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
+ size_t increment = static_cast<size_t>(newSize - originalSize);
+ increment = RAPIDJSON_ALIGN(increment);
+ if (chunkHead_->size + increment <= chunkHead_->capacity) {
+ chunkHead_->size += increment;
+ return originalPtr;
+ }
+ }
+
+ // Realloc process: allocate and copy memory, do not free original buffer.
+ void* newBuffer = Malloc(newSize);
+ RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
+ if (originalSize)
+ std::memcpy(newBuffer, originalPtr, originalSize);
+ return newBuffer;
+ }
+
+ //! Frees a memory block (concept Allocator)
+ static void Free(void *ptr) { (void)ptr; } // Do nothing
+
+private:
+ //! Copy constructor is not permitted.
+ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
+ //! Copy assignment operator is not permitted.
+ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
+
+ //! Creates a new chunk.
+ /*! \param capacity Capacity of the chunk in bytes.
+ */
+ void AddChunk(size_t capacity) {
+ if (!baseAllocator_)
+ ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
+ ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
+ chunk->capacity = capacity;
+ chunk->size = 0;
+ chunk->next = chunkHead_;
+ chunkHead_ = chunk;
+ }
+
+ static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+ //! Chunk header for perpending to each chunk.
+ /*! Chunks are stored as a singly linked list.
+ */
+ struct ChunkHeader {
+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
+ size_t size; //!< Current size of allocated memory in bytes.
+ ChunkHeader *next; //!< Next chunk in the linked list.
+ };
+
+ ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+ size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
+ void *userBuffer_; //!< User supplied buffer.
+ BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
+ BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h
new file mode 100644
index 000000000..98053cbd5
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h
@@ -0,0 +1,2136 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+/*! \file document.h */
+
+#include "reader.h"
+#include "internal/meta.h"
+#include "internal/strfunc.h"
+#include <new> // placement new
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_HAS_STDSTRING
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
+#else
+#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
+#endif
+/*! \def RAPIDJSON_HAS_STDSTRING
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable RapidJSON support for \c std::string
+
+ By defining this preprocessor symbol to \c 1, several convenience functions for using
+ \ref rapidjson::GenericValue with \c std::string are enabled, especially
+ for construction and comparison.
+
+ \hideinitializer
+*/
+#endif // !defined(RAPIDJSON_HAS_STDSTRING)
+
+#if RAPIDJSON_HAS_STDSTRING
+#include <string>
+#endif // RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include <iterator> // std::iterator, std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// Forward declaration.
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+template <typename Encoding, typename Allocator, typename StackAllocator>
+class GenericDocument;
+
+//! Name-value pair in a JSON object value.
+/*!
+ This class was internal to GenericValue. It used to be a inner struct.
+ But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
+ https://code.google.com/p/rapidjson/issues/detail?id=64
+*/
+template <typename Encoding, typename Allocator>
+struct GenericMember {
+ GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
+ GenericValue<Encoding, Allocator> value; //!< value of member.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericMemberIterator
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+
+//! (Constant) member iterator for a JSON object value
+/*!
+ \tparam Const Is this a constant iterator?
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+
+ This class implements a Random Access Iterator for GenericMember elements
+ of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
+
+ \note This iterator implementation is mainly intended to avoid implicit
+ conversions from iterator values to \c NULL,
+ e.g. from GenericValue::FindMember.
+
+ \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
+ pointer-based implementation, if your platform doesn't provide
+ the C++ <iterator> header.
+
+ \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
+ */
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator
+ : public std::iterator<std::random_access_iterator_tag
+ , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
+
+ friend class GenericValue<Encoding,Allocator>;
+ template <bool, typename, typename> friend class GenericMemberIterator;
+
+ typedef GenericMember<Encoding,Allocator> PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
+
+public:
+ //! Iterator type itself
+ typedef GenericMemberIterator Iterator;
+ //! Constant iterator type
+ typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
+ //! Non-constant iterator type
+ typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
+
+ //! Pointer to (const) GenericMember
+ typedef typename BaseType::pointer Pointer;
+ //! Reference to (const) GenericMember
+ typedef typename BaseType::reference Reference;
+ //! Signed integer type (e.g. \c ptrdiff_t)
+ typedef typename BaseType::difference_type DifferenceType;
+
+ //! Default constructor (singular value)
+ /*! Creates an iterator pointing to no element.
+ \note All operations, except for comparisons, are undefined on such values.
+ */
+ GenericMemberIterator() : ptr_() {}
+
+ //! Iterator conversions to more const
+ /*!
+ \param it (Non-const) iterator to copy from
+
+ Allows the creation of an iterator from another GenericMemberIterator
+ that is "less const". Especially, creating a non-constant iterator
+ from a constant iterator are disabled:
+ \li const -> non-const (not ok)
+ \li const -> const (ok)
+ \li non-const -> const (ok)
+ \li non-const -> non-const (ok)
+
+ \note If the \c Const template parameter is already \c false, this
+ constructor effectively defines a regular copy-constructor.
+ Otherwise, the copy constructor is implicitly defined.
+ */
+ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+
+ //! @name stepping
+ //@{
+ Iterator& operator++(){ ++ptr_; return *this; }
+ Iterator& operator--(){ --ptr_; return *this; }
+ Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
+ Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
+ //@}
+
+ //! @name increment/decrement
+ //@{
+ Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
+ Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
+
+ Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
+ Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
+ //@}
+
+ //! @name relations
+ //@{
+ bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
+ bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
+ bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
+ bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
+ bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
+ bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
+ //@}
+
+ //! @name dereference
+ //@{
+ Reference operator*() const { return *ptr_; }
+ Pointer operator->() const { return ptr_; }
+ Reference operator[](DifferenceType n) const { return ptr_[n]; }
+ //@}
+
+ //! Distance
+ DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
+
+private:
+ //! Internal constructor from plain pointer
+ explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
+
+ Pointer ptr_; //!< raw pointer
+};
+
+#else // RAPIDJSON_NOMEMBERITERATORCLASS
+
+// class-based member iterator implementation disabled, use plain pointers
+
+template <bool Const, typename Encoding, typename Allocator>
+struct GenericMemberIterator;
+
+//! non-const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<false,Encoding,Allocator> {
+ //! use plain pointer as iterator type
+ typedef GenericMember<Encoding,Allocator>* Iterator;
+};
+//! const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<true,Encoding,Allocator> {
+ //! use plain const pointer as iterator type
+ typedef const GenericMember<Encoding,Allocator>* Iterator;
+};
+
+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericStringRef
+
+//! Reference to a constant string (not taking a copy)
+/*!
+ \tparam CharType character type of the string
+
+ This helper class is used to automatically infer constant string
+ references for string literals, especially from \c const \b (!)
+ character arrays.
+
+ The main use is for creating JSON string values without copying the
+ source string via an \ref Allocator. This requires that the referenced
+ string pointers have a sufficient lifetime, which exceeds the lifetime
+ of the associated GenericValue.
+
+ \b Example
+ \code
+ Value v("foo"); // ok, no need to copy & calculate length
+ const char foo[] = "foo";
+ v.SetString(foo); // ok
+
+ const char* bar = foo;
+ // Value x(bar); // not ok, can't rely on bar's lifetime
+ Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
+ Value y(StringRef(bar, 3)); // ok, explicitly pass length
+ \endcode
+
+ \see StringRef, GenericValue::SetString
+*/
+template<typename CharType>
+struct GenericStringRef {
+ typedef CharType Ch; //!< character type of the string
+
+ //! Create string reference from \c const character array
+ /*!
+ This constructor implicitly creates a constant string reference from
+ a \c const character array. It has better performance than
+ \ref StringRef(const CharType*) by inferring the string \ref length
+ from the array length, and also supports strings containing null
+ characters.
+
+ \tparam N length of the string, automatically inferred
+
+ \param str Constant character array, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note Constant complexity.
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+ template<SizeType N>
+ GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
+ : s(str), length(N-1) {}
+
+ //! Explicitly create string reference from \c const character pointer
+ /*!
+ This constructor can be used to \b explicitly create a reference to
+ a constant string pointer.
+
+ \see StringRef(const CharType*)
+
+ \param str Constant character pointer, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+ explicit GenericStringRef(const CharType* str)
+ : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
+
+ //! Create constant string reference from pointer and length
+ /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param len length of the string, excluding the trailing NULL terminator
+
+ \post \ref s == str && \ref length == len
+ \note Constant complexity.
+ */
+ GenericStringRef(const CharType* str, SizeType len)
+ : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
+
+ //! implicit conversion to plain CharType pointer
+ operator const Ch *() const { return s; }
+
+ const Ch* const s; //!< plain CharType pointer
+ const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
+
+private:
+ //! Disallow copy-assignment
+ GenericStringRef operator=(const GenericStringRef&);
+ //! Disallow construction from non-const array
+ template<SizeType N>
+ GenericStringRef(CharType (&str)[N]) /* = delete */;
+};
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+ \tparam CharType Character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+
+ \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str) {
+ return GenericStringRef<CharType>(str, internal::StrLen(str));
+}
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ This version has better performance with supplied length, and also
+ supports string containing null characters.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param length The length of source string.
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
+ return GenericStringRef<CharType>(str, SizeType(length));
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+//! Mark a string object as constant string
+/*! Mark a string object (e.g. \c std::string) as a "string literal".
+ This function can be used to avoid copying a string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
+ return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue type traits
+namespace internal {
+
+template <typename T, typename Encoding = void, typename Allocator = void>
+struct IsGenericValueImpl : FalseType {};
+
+// select candidates according to nested encoding and allocator types
+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
+ : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
+
+// helper to match arbitrary GenericValue instantiations, including derived classes
+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+ A JSON value can be one of 7 types. This class is a variant type supporting
+ these types.
+
+ Use the Value if UTF8 and default allocator
+
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericValue {
+public:
+ //! Name-value pair in an object.
+ typedef GenericMember<Encoding, Allocator> Member;
+ typedef Encoding EncodingType; //!< Encoding type from template parameter.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
+ typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
+ typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
+ typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
+ typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor creates a null value.
+ GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
+ rhs.flags_ = kNullFlag; // give up contents
+ }
+#endif
+
+private:
+ //! Copy constructor is not permitted.
+ GenericValue(const GenericValue& rhs);
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Moving from a GenericDocument is not permitted.
+ template <typename StackAllocator>
+ GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
+
+ //! Move assignment from a GenericDocument is not permitted.
+ template <typename StackAllocator>
+ GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
+#endif
+
+public:
+
+ //! Constructor with JSON value type.
+ /*! This creates a Value of specified type with default content.
+ \param type Type of the value.
+ \note Default content for number is zero.
+ */
+ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
+ static const unsigned defaultFlags[7] = {
+ kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
+ kNumberAnyFlag
+ };
+ RAPIDJSON_ASSERT(type <= kNumberType);
+ flags_ = defaultFlags[type];
+
+ // Use ShortString to store empty string.
+ if (type == kStringType)
+ data_.ss.SetLength(0);
+ }
+
+ //! Explicit copy constructor (with allocator)
+ /*! Creates a copy of a Value by using the given Allocator
+ \tparam SourceAllocator allocator of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
+ \see CopyFrom()
+ */
+ template< typename SourceAllocator >
+ GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+
+ //! Constructor for boolean value.
+ /*! \param b Boolean value
+ \note This constructor is limited to \em real boolean values and rejects
+ implicitly converted types like arbitrary pointers. Use an explicit cast
+ to \c bool, if you want to construct a boolean JSON value in such cases.
+ */
+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
+ template <typename T>
+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
+#else
+ explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
+#endif
+ : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
+ // safe-guard against failing SFINAE
+ RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+ }
+
+ //! Constructor for int value.
+ explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
+ data_.n.i64 = i;
+ if (i >= 0)
+ flags_ |= kUintFlag | kUint64Flag;
+ }
+
+ //! Constructor for unsigned value.
+ explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
+ data_.n.u64 = u;
+ if (!(u & 0x80000000))
+ flags_ |= kIntFlag | kInt64Flag;
+ }
+
+ //! Constructor for int64_t value.
+ explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
+ data_.n.i64 = i64;
+ if (i64 >= 0) {
+ flags_ |= kNumberUint64Flag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ flags_ |= kUintFlag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+ else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+
+ //! Constructor for uint64_t value.
+ explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
+ data_.n.u64 = u64;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+ flags_ |= kInt64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ flags_ |= kUintFlag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+
+#if defined(__APPLE__)
+ //! Constructor for unsigned long value.
+ explicit GenericValue(unsigned long u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
+ data_.n.u64 = u64;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+ flags_ |= kInt64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ flags_ |= kUintFlag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+
+#if !defined(__x86_64__) && !defined(__arm64__)
+ //! Constructor for size_t value.
+ explicit GenericValue( size_t u ) RAPIDJSON_NOEXCEPT : data_(), flags_( kNumberUintFlag ) {
+ data_.n.u64 = u;
+ if ( !( u&0x80000000 ) )
+ flags_ |= kIntFlag|kInt64Flag;
+ }
+#endif
+#endif
+
+ //! Constructor for double value.
+ explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor for copy-string from a string object (i.e. do make a copy of string)
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+#endif
+
+ //! Destructor.
+ /*! Need to destruct elements of array, members of object, or copy-string.
+ */
+ ~GenericValue() {
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+ switch(flags_) {
+ case kArrayFlag:
+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+ v->~GenericValue();
+ Allocator::Free(data_.a.elements);
+ break;
+
+ case kObjectFlag:
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ Allocator::Free(data_.o.members);
+ break;
+
+ case kCopyStringFlag:
+ Allocator::Free(const_cast<Ch*>(data_.s.str));
+ break;
+
+ default:
+ break; // Do nothing for other types.
+ }
+ }
+ }
+
+ //@}
+
+ //!@name Assignment operators
+ //@{
+
+ //! Assignment with move semantics.
+ /*! \param rhs Source of the assignment. It will become a null value after assignment.
+ */
+ GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_ASSERT(this != &rhs);
+ this->~GenericValue();
+ RawAssign(rhs);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+ return *this = rhs.Move();
+ }
+#endif
+
+ //! Assignment of constant string reference (no copy)
+ /*! \param str Constant string reference to be assigned
+ \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
+ \see GenericStringRef, operator=(T)
+ */
+ GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
+ GenericValue s(str);
+ return *this = s;
+ }
+
+ //! Assignment with primitive types.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value The value to be assigned.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref SetString(const Ch*, Allocator&) (for copying) or
+ \ref StringRef() (to explicitly mark the pointer as constant) instead.
+ All other pointer types would implicitly convert to \c bool,
+ use \ref SetBool() instead.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
+ operator=(T value) {
+ GenericValue v(value);
+ return *this = v;
+ }
+
+ //! Deep-copy assignment from Value
+ /*! Assigns a \b copy of the Value to the current Value object
+ \tparam SourceAllocator Allocator type of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator to use for copying
+ */
+ template <typename SourceAllocator>
+ GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
+ RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
+ this->~GenericValue();
+ new (this) GenericValue(rhs, allocator);
+ return *this;
+ }
+
+ //! Exchange the contents of this value with those of other.
+ /*!
+ \param other Another value.
+ \note Constant complexity.
+ */
+ GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
+ GenericValue temp;
+ temp.RawAssign(*this);
+ RawAssign(other);
+ other.RawAssign(temp);
+ return *this;
+ }
+
+ //! free-standing swap function helper
+ /*!
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
+ \code
+ void swap(MyClass& a, MyClass& b) {
+ using std::swap;
+ swap(a.value, b.value);
+ // ...
+ }
+ \endcode
+ \see Swap()
+ */
+ friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+
+ //! Prepare Value for move semantics
+ /*! \return *this */
+ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
+ //@}
+
+ //!@name Equal-to and not-equal-to operators
+ //@{
+ //! Equal-to operator
+ /*!
+ \note If an object contains duplicated named member, comparing equality with any object is always \c false.
+ \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
+ */
+ template <typename SourceAllocator>
+ bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ typedef GenericValue<Encoding, SourceAllocator> RhsType;
+ if (GetType() != rhs.GetType())
+ return false;
+
+ switch (GetType()) {
+ case kObjectType: // Warning: O(n^2) inner-loop
+ if (data_.o.size != rhs.data_.o.size)
+ return false;
+ for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
+ typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
+ if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
+ return false;
+ }
+ return true;
+
+ case kArrayType:
+ if (data_.a.size != rhs.data_.a.size)
+ return false;
+ for (SizeType i = 0; i < data_.a.size; i++)
+ if ((*this)[i] != rhs[i])
+ return false;
+ return true;
+
+ case kStringType:
+ return StringEqual(rhs);
+
+ case kNumberType:
+ if (IsDouble() || rhs.IsDouble()) {
+ double a = GetDouble(); // May convert from integer to double.
+ double b = rhs.GetDouble(); // Ditto
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
+ else
+ return data_.n.u64 == rhs.data_.n.u64;
+
+ default: // kTrueType, kFalseType, kNullType
+ return true;
+ }
+ }
+
+ //! Equal-to operator with const C-string pointer
+ bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Equal-to operator with string object
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
+#endif
+
+ //! Equal-to operator with primitive types
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
+
+ //! Not-equal-to operator
+ /*! \return !(*this == rhs)
+ */
+ template <typename SourceAllocator>
+ bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with const C-string pointer
+ bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with arbitrary types
+ /*! \return !(*this == rhs)
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
+
+ //! Equal-to operator with arbitrary types (symmetric version)
+ /*! \return (rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
+
+ //! Not-Equal-to operator with arbitrary types (symmetric version)
+ /*! \return !(rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
+ //@}
+
+ //!@name Type
+ //@{
+
+ Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
+ bool IsNull() const { return flags_ == kNullFlag; }
+ bool IsFalse() const { return flags_ == kFalseFlag; }
+ bool IsTrue() const { return flags_ == kTrueFlag; }
+ bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
+ bool IsObject() const { return flags_ == kObjectFlag; }
+ bool IsArray() const { return flags_ == kArrayFlag; }
+ bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
+ bool IsInt() const { return (flags_ & kIntFlag) != 0; }
+ bool IsUint() const { return (flags_ & kUintFlag) != 0; }
+ bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
+ bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
+ bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
+ bool IsString() const { return (flags_ & kStringFlag) != 0; }
+
+ //@}
+
+ //!@name Null
+ //@{
+
+ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+ //@}
+
+ //!@name Bool
+ //@{
+
+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
+ //!< Set boolean value
+ /*! \post IsBool() == true */
+ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+ //@}
+
+ //!@name Object
+ //@{
+
+ //! Set this value as an empty object.
+ /*! \post IsObject() == true */
+ GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+ //! Get the number of members in the object.
+ SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
+
+ //! Check whether the object is empty.
+ bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
+ \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
+ Since 0.2, if the name is not correct, it will assert.
+ If user is unsure whether a member exists, user should use HasMember() first.
+ A better approach is to use FindMember().
+ \note Linear time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
+ GenericValue n(StringRef(name));
+ return (*this)[n];
+ }
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam SourceAllocator Allocator of the \c name value
+
+ \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
+ And it can also handle strings with embedded null characters.
+
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator member = FindMember(name);
+ if (member != MemberEnd())
+ return member->value;
+ else {
+ RAPIDJSON_ASSERT(false); // see above note
+ static GenericValue NullValue;
+ return NullValue;
+ }
+ }
+ template <typename SourceAllocator>
+ const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Get a value from an object associated with name (string object).
+ GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
+ const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
+#endif
+
+ //! Const member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
+ //! Const \em past-the-end member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
+ //! Member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
+ //! \em Past-the-end member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
+
+ //! Check whether a member exists in the object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Check whether a member exists in the object with string object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
+#endif
+
+ //! Check whether a member exists in the object with GenericValue name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
+
+ //! Find member by name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ MemberIterator FindMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return FindMember(n);
+ }
+
+ ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+ //! Find member by name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+ MemberIterator member = MemberBegin();
+ for ( ; member != MemberEnd(); ++member)
+ if (name.StringEqual(member->name))
+ break;
+ return member;
+ }
+ template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Find member by string object name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+ */
+ MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
+ ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
+#endif
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c name and \c value will be transferred to this object on success.
+ \pre IsObject() && name.IsString()
+ \post name.IsNull() && value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+
+ Object& o = data_.o;
+ if (o.size >= o.capacity) {
+ if (o.capacity == 0) {
+ o.capacity = kDefaultObjectCapacity;
+ o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
+ }
+ else {
+ SizeType oldCapacity = o.capacity;
+ o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
+ o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
+ }
+ }
+ o.members[o.size].name.RawAssign(name);
+ o.members[o.size].value.RawAssign(value);
+ o.size++;
+ return *this;
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Add a string object as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
+ GenericValue v(value, allocator);
+ return AddMember(name, v, allocator);
+ }
+#endif
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A string value as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(GenericValue& name, T value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this object on success.
+ \pre IsObject()
+ \post value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A constant string reference as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(StringRefType name, T value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Remove all members in the object.
+ /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void RemoveAllMembers() {
+ RAPIDJSON_ASSERT(IsObject());
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ data_.o.size = 0;
+ }
+
+ //! Remove a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Linear time complexity.
+ */
+ bool RemoveMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return RemoveMember(n);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
+#endif
+
+ template <typename SourceAllocator>
+ bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ RemoveMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Remove a member in object by iterator.
+ /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
+ \return the new iterator after removal.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Constant time complexity.
+ */
+ MemberIterator RemoveMember(MemberIterator m) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(data_.o.members != 0);
+ RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
+
+ MemberIterator last(data_.o.members + (data_.o.size - 1));
+ if (data_.o.size > 1 && m != last) {
+ // Move the last one to this place
+ *m = *last;
+ }
+ else {
+ // Only one left, just destroy
+ m->~Member();
+ }
+ --data_.o.size;
+ return m;
+ }
+
+ //! Remove a member from an object by iterator.
+ /*! \param pos iterator to the member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
+ \return Iterator following the removed element.
+ If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
+ \note This function preserves the relative order of the remaining object
+ members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator pos) {
+ return EraseMember(pos, pos +1);
+ }
+
+ //! Remove members in the range [first, last) from an object.
+ /*! \param first iterator to the first member to remove
+ \param last iterator following the last member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
+ \return Iterator following the last removed element.
+ \note This function preserves the relative order of the remaining object
+ members.
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(data_.o.members != 0);
+ RAPIDJSON_ASSERT(first >= MemberBegin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= MemberEnd());
+
+ MemberIterator pos = MemberBegin() + (first - MemberBegin());
+ for (MemberIterator itr = pos; itr != last; ++itr)
+ itr->~Member();
+ std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
+ data_.o.size -= (last - first);
+ return pos;
+ }
+
+ //! Erase a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note Linear time complexity.
+ */
+ bool EraseMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return EraseMember(n);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
+#endif
+
+ template <typename SourceAllocator>
+ bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ EraseMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Set this value as an empty array.
+ /*! \post IsArray == true */
+ GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+ //! Get the number of elements in array.
+ SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+ //! Get the capacity of array.
+ SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+ //! Check whether the array is empty.
+ bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+ //! Remove all elements in the array.
+ /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void Clear() {
+ RAPIDJSON_ASSERT(IsArray());
+ for (SizeType i = 0; i < data_.a.size; ++i)
+ data_.a.elements[i].~GenericValue();
+ data_.a.size = 0;
+ }
+
+ //! Get an element from array by index.
+ /*! \pre IsArray() == true
+ \param index Zero-based index of element.
+ \see operator[](T*)
+ */
+ GenericValue& operator[](SizeType index) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(index < data_.a.size);
+ return data_.a.elements[index];
+ }
+ const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+ //! Element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
+ //! \em Past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
+ //! Constant element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+ //! Constant \em past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+ //! Request the array to have enough capacity to store elements.
+ /*! \param newCapacity The capacity that the array at least need to have.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note Linear time complexity.
+ */
+ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (newCapacity > data_.a.capacity) {
+ data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
+ data_.a.capacity = newCapacity;
+ }
+ return *this;
+ }
+
+ //! Append a GenericValue at the end of the array.
+ /*! \param value Value to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \post value.IsNull() == true
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this array on success.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ */
+ GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (data_.a.size >= data_.a.capacity)
+ Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
+ data_.a.elements[data_.a.size++].RawAssign(value);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
+ return PushBack(value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+ //! Append a constant string reference at the end of the array.
+ /*! \param value Constant string reference to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ \see GenericStringRef
+ */
+ GenericValue& PushBack(StringRefType value, Allocator& allocator) {
+ return (*this).template PushBack<StringRefType>(value, allocator);
+ }
+
+ //! Append a primitive value at the end of the array.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value Value of primitive type T to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref PushBack(GenericValue&, Allocator&) or \ref
+ PushBack(StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ PushBack(T value, Allocator& allocator) {
+ GenericValue v(value);
+ return PushBack(v, allocator);
+ }
+
+ //! Remove the last element in the array.
+ /*!
+ \note Constant time complexity.
+ */
+ GenericValue& PopBack() {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(!Empty());
+ data_.a.elements[--data_.a.size].~GenericValue();
+ return *this;
+ }
+
+ //! Remove an element of array by iterator.
+ /*!
+ \param pos iterator to the element to remove
+ \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
+ \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator pos) {
+ return Erase(pos, pos + 1);
+ }
+
+ //! Remove elements in the range [first, last) of the array.
+ /*!
+ \param first iterator to the first element to remove
+ \param last iterator following the last element to remove
+ \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
+ \return Iterator following the last removed element.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(data_.a.size > 0);
+ RAPIDJSON_ASSERT(data_.a.elements != 0);
+ RAPIDJSON_ASSERT(first >= Begin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= End());
+ ValueIterator pos = Begin() + (first - Begin());
+ for (ValueIterator itr = pos; itr != last; ++itr)
+ itr->~GenericValue();
+ std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
+ data_.a.size -= (last - first);
+ return pos;
+ }
+
+ //@}
+
+ //!@name Number
+ //@{
+
+ int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
+ unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
+ int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
+
+ double GetDouble() const {
+ RAPIDJSON_ASSERT(IsNumber());
+ if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
+ if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
+ if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
+ if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
+ RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
+ }
+
+ GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
+ GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
+ GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
+ GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
+ GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
+
+ //@}
+
+ //!@name String
+ //@{
+
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
+
+ //! Get the length of string.
+ /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+ */
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
+
+ //! Set this value as a string without copying source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string pointer.
+ \param length The length of source string, excluding the trailing null terminator.
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == length
+ \see SetString(StringRefType)
+ */
+ GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
+
+ //! Set this value as a string without copying source string.
+ /*! \param s source string reference
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == s.length
+ */
+ GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string.
+ \param length The length of source string, excluding the trailing null terminator.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
+#endif
+
+ //@}
+
+ //! Generate events of this value to a Handler.
+ /*! This function adopts the GoF visitor pattern.
+ Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+ It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+ \tparam Handler type of handler.
+ \param handler An object implementing concept Handler.
+ */
+ template <typename Handler>
+ bool Accept(Handler& handler) const {
+ switch(GetType()) {
+ case kNullType: return handler.Null();
+ case kFalseType: return handler.Bool(false);
+ case kTrueType: return handler.Bool(true);
+
+ case kObjectType:
+ if (!handler.StartObject())
+ return false;
+ for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
+ RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
+ if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
+ return false;
+ if (!m->value.Accept(handler))
+ return false;
+ }
+ return handler.EndObject(data_.o.size);
+
+ case kArrayType:
+ if (!handler.StartArray())
+ return false;
+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+ if (!v->Accept(handler))
+ return false;
+ return handler.EndArray(data_.a.size);
+
+ case kStringType:
+ return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
+
+ default:
+ RAPIDJSON_ASSERT(GetType() == kNumberType);
+ if (IsInt()) return handler.Int(data_.n.i.i);
+ else if (IsUint()) return handler.Uint(data_.n.u.u);
+ else if (IsInt64()) return handler.Int64(data_.n.i64);
+ else if (IsUint64()) return handler.Uint64(data_.n.u64);
+ else return handler.Double(data_.n.d);
+ }
+ }
+
+private:
+ template <typename, typename> friend class GenericValue;
+ template <typename, typename, typename> friend class GenericDocument;
+
+ enum {
+ kBoolFlag = 0x100,
+ kNumberFlag = 0x200,
+ kIntFlag = 0x400,
+ kUintFlag = 0x800,
+ kInt64Flag = 0x1000,
+ kUint64Flag = 0x2000,
+ kDoubleFlag = 0x4000,
+ kStringFlag = 0x100000,
+ kCopyFlag = 0x200000,
+ kInlineStrFlag = 0x400000,
+
+ // Initial flags of different types.
+ kNullFlag = kNullType,
+ kTrueFlag = kTrueType | kBoolFlag,
+ kFalseFlag = kFalseType | kBoolFlag,
+ kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+ kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+ kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+ kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+ kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+ kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
+ kConstStringFlag = kStringType | kStringFlag,
+ kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+ kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
+ kObjectFlag = kObjectType,
+ kArrayFlag = kArrayType,
+
+ kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
+ };
+
+ static const SizeType kDefaultArrayCapacity = 16;
+ static const SizeType kDefaultObjectCapacity = 16;
+
+ struct String {
+ const Ch* str;
+ SizeType length;
+ unsigned hashcode; //!< reserved
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
+ // (excluding the terminating zero) and store a value to determine the length of the contained
+ // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
+ // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
+ // the string terminator as well. For getting the string length back from that value just use
+ // "MaxSize - str[LenPos]".
+ // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
+ // inline (for `UTF8`-encoded strings).
+ struct ShortString {
+ enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+ Ch str[MaxChars];
+
+ inline static bool Usable(SizeType len) { return (MaxSize >= len); }
+ inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); }
+ inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
+ }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // By using proper binary layout, retrieval of different integer types do not need conversions.
+ union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+ struct I {
+ int i;
+ char padding[4];
+ }i;
+ struct U {
+ unsigned u;
+ char padding2[4];
+ }u;
+#else
+ struct I {
+ char padding[4];
+ int i;
+ }i;
+ struct U {
+ char padding2[4];
+ unsigned u;
+ }u;
+#endif
+ int64_t i64;
+ uint64_t u64;
+ double d;
+ }; // 8 bytes
+
+ struct Object {
+ Member* members;
+ SizeType size;
+ SizeType capacity;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ struct Array {
+ GenericValue* elements;
+ SizeType size;
+ SizeType capacity;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ union Data {
+ String s;
+ ShortString ss;
+ Number n;
+ Object o;
+ Array a;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // Initialize this value as array with initial data, without calling destructor.
+ void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
+ flags_ = kArrayFlag;
+ if (count) {
+ data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
+ std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
+ }
+ else
+ data_.a.elements = NULL;
+ data_.a.size = data_.a.capacity = count;
+ }
+
+ //! Initialize this value as object with initial data, without calling destructor.
+ void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
+ flags_ = kObjectFlag;
+ if (count) {
+ data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
+ std::memcpy(data_.o.members, members, count * sizeof(Member));
+ }
+ else
+ data_.o.members = NULL;
+ data_.o.size = data_.o.capacity = count;
+ }
+
+ //! Initialize this value as constant string, without calling destructor.
+ void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
+ flags_ = kConstStringFlag;
+ data_.s.str = s;
+ data_.s.length = s.length;
+ }
+
+ //! Initialize this value as copy string with initial data, without calling destructor.
+ void SetStringRaw(StringRefType s, Allocator& allocator) {
+ Ch* str = NULL;
+ if(ShortString::Usable(s.length)) {
+ flags_ = kShortStringFlag;
+ data_.ss.SetLength(s.length);
+ str = data_.ss.str;
+ } else {
+ flags_ = kCopyStringFlag;
+ data_.s.length = s.length;
+ str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
+ data_.s.str = str;
+ }
+ std::memcpy(str, s, s.length * sizeof(Ch));
+ str[s.length] = '\0';
+ }
+
+ //! Assignment without calling destructor
+ void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ data_ = rhs.data_;
+ flags_ = rhs.flags_;
+ rhs.flags_ = kNullFlag;
+ }
+
+ template <typename SourceAllocator>
+ bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ RAPIDJSON_ASSERT(IsString());
+ RAPIDJSON_ASSERT(rhs.IsString());
+
+ const SizeType len1 = GetStringLength();
+ const SizeType len2 = rhs.GetStringLength();
+ if(len1 != len2) { return false; }
+
+ const Ch* const str1 = GetString();
+ const Ch* const str2 = rhs.GetString();
+ if(str1 == str2) { return true; } // fast path for constant string
+
+ return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
+ }
+
+ Data data_;
+ unsigned flags_;
+};
+
+//! GenericValue with UTF8 encoding
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument
+
+//! A document for parsing JSON text as DOM.
+/*!
+ \note implements Handler concept
+ \tparam Encoding Encoding for both parsing and string storage.
+ \tparam Allocator Allocator for allocating memory for the DOM
+ \tparam StackAllocator Allocator for allocating memory for stack during parsing.
+ \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+
+ //! Constructor
+ /*! Creates an empty document of specified type.
+ \param type Mandatory type of object to create.
+ \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+ //! Constructor
+ /*! Creates an empty document which type is Null.
+ \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(std::move(rhs.stack_)),
+ parseResult_(rhs.parseResult_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+ }
+#endif
+
+ ~GenericDocument() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ {
+ // The cast to ValueType is necessary here, because otherwise it would
+ // attempt to call GenericValue's templated assignment operator.
+ ValueType::operator=(std::forward<ValueType>(rhs));
+
+ // Calling the destructor here would prematurely call stack_'s destructor
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = std::move(rhs.stack_);
+ parseResult_ = rhs.parseResult_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+
+ return *this;
+ }
+#endif
+
+ //! Exchange the contents of this document with those of another.
+ /*!
+ \param other Another document.
+ \note Constant complexity.
+ \see GenericValue::Swap
+ */
+ GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
+ ValueType::Swap(rhs);
+ stack_.Swap(rhs.stack_);
+ internal::Swap(allocator_, rhs.allocator_);
+ internal::Swap(ownAllocator_, rhs.ownAllocator_);
+ internal::Swap(parseResult_, rhs.parseResult_);
+ return *this;
+ }
+
+ //! free-standing swap function helper
+ /*!
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
+ \code
+ void swap(MyClass& a, MyClass& b) {
+ using std::swap;
+ swap(a.doc, b.doc);
+ // ...
+ }
+ \endcode
+ \see Swap()
+ */
+ friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+
+ //!@name Parse from stream
+ //!@{
+
+ //! Parse JSON text from an input stream (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam SourceEncoding Encoding of input stream
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
+ stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
+ ClearStackOnExit scope(*this);
+ parseResult_ = reader.template Parse<parseFlags>(is, *this);
+ if (parseResult_) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
+ }
+ return *this;
+ }
+
+ //! Parse JSON text from an input stream
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<parseFlags, Encoding, InputStream>(is);
+ }
+
+ //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
+ }
+ //!@}
+
+ //!@name Parse in-place from mutable string
+ //!@{
+
+ //! Parse JSON text from a mutable string
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& ParseInsitu(Ch* str) {
+ GenericInsituStringStream<Encoding> s(str);
+ return ParseStream<parseFlags | kParseInsituFlag>(s);
+ }
+
+ //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
+ /*! \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ GenericDocument& ParseInsitu(Ch* str) {
+ return ParseInsitu<kParseDefaultFlags>(str);
+ }
+ //!@}
+
+ //!@name Parse from read-only string
+ //!@{
+
+ //! Parse JSON text from a read-only string (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \tparam SourceEncoding Transcoding from input Encoding
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const Ch* str) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ GenericStringStream<SourceEncoding> s(str);
+ return ParseStream<parseFlags, SourceEncoding>(s);
+ }
+
+ //! Parse JSON text from a read-only string
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<parseFlags, Encoding>(str);
+ }
+
+ //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
+ /*! \param str Read-only zero-terminated string to be parsed.
+ */
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+ //!@}
+
+ //!@name Handling parse errors
+ //!@{
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseError() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+ //!@}
+
+ //! Get the allocator of this document.
+ Allocator& GetAllocator() {
+ RAPIDJSON_ASSERT(allocator_);
+ return *allocator_;
+ }
+
+ //! Get the capacity of stack in bytes.
+ size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
+ ~ClearStackOnExit() { d_.ClearStack(); }
+ private:
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ GenericDocument& d_;
+ };
+
+ // callers of the following private Handler functions
+ template <typename,typename,typename> friend class GenericReader; // for parsing
+ template <typename, typename> friend class GenericValue; // for deep copying
+
+ // Implementation of Handler
+ bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
+ bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
+ bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
+
+ bool String(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ return true;
+ }
+
+ bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
+
+ bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount) {
+ typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+ stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
+ return true;
+ }
+
+ bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
+
+ bool EndArray(SizeType elementCount) {
+ ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+ stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+ return true;
+ }
+
+private:
+ //! Prohibit copying
+ GenericDocument(const GenericDocument&);
+ //! Prohibit assignment
+ GenericDocument& operator=(const GenericDocument&);
+
+ void ClearStack() {
+ if (Allocator::kNeedFree)
+ while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+ (stack_.template Pop<ValueType>(1))->~ValueType();
+ else
+ stack_.Clear();
+ stack_.ShrinkToFit();
+ }
+
+ void Destroy() {
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ static const size_t kDefaultStackCapacity = 1024;
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ internal::Stack<StackAllocator> stack_;
+ ParseResult parseResult_;
+};
+
+//! GenericDocument with UTF8 encoding
+typedef GenericDocument<UTF8<> > Document;
+
+// defined here due to the dependency on GenericDocument
+template <typename Encoding, typename Allocator>
+template <typename SourceAllocator>
+inline
+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
+{
+ switch (rhs.GetType()) {
+ case kObjectType:
+ case kArrayType: { // perform deep copy via SAX Handler
+ GenericDocument<Encoding,Allocator> d(&allocator);
+ rhs.Accept(d);
+ RawAssign(*d.stack_.template Pop<GenericValue>(1));
+ }
+ break;
+ case kStringType:
+ if (rhs.flags_ == kConstStringFlag) {
+ flags_ = rhs.flags_;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ } else {
+ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+ }
+ break;
+ default: // kNumberType, kTrueType, kFalseType, kNullType
+ flags_ = rhs.flags_;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ break;
+ }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(_MSC_VER) || defined(__GNUC__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_DOCUMENT_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h
new file mode 100644
index 000000000..fd3bfaf13
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h
@@ -0,0 +1,261 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
+#define RAPIDJSON_ENCODEDSTREAM_H_
+
+#include "rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Input byte stream wrapper with a statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
+*/
+template <typename Encoding, typename InputByteStream>
+class EncodedInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedInputStream(InputByteStream& is) : is_(is) {
+ current_ = Encoding::TakeBOM(is_);
+ }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
+ size_t Tell() const { return is_.Tell(); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+
+ InputByteStream& is_;
+ Ch current_;
+};
+
+//! Output byte stream wrapper with statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
+*/
+template <typename Encoding, typename OutputByteStream>
+class EncodedOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
+ if (putBOM)
+ Encoding::PutBOM(os_);
+ }
+
+ void Put(Ch c) { Encoding::Put(os_, c); }
+ void Flush() { os_.Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
+ Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ EncodedOutputStream(const EncodedOutputStream&);
+ EncodedOutputStream& operator=(const EncodedOutputStream&);
+
+ OutputByteStream& os_;
+};
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for reading.
+ \tparam InputByteStream type of input byte stream to be wrapped.
+*/
+template <typename CharType, typename InputByteStream>
+class AutoUTFInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param is input stream to be wrapped.
+ \param type UTF encoding type if it is not detected from the stream.
+ */
+ AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+ DetectType();
+ static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
+ takeFunc_ = f[type_];
+ current_ = takeFunc_(*is_);
+ }
+
+ UTFType GetType() const { return type_; }
+ bool HasBOM() const { return hasBOM_; }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
+ size_t Tell() const { return is_->Tell(); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ AutoUTFInputStream(const AutoUTFInputStream&);
+ AutoUTFInputStream& operator=(const AutoUTFInputStream&);
+
+ // Detect encoding type with BOM or RFC 4627
+ void DetectType() {
+ // BOM (Byte Order Mark):
+ // 00 00 FE FF UTF-32BE
+ // FF FE 00 00 UTF-32LE
+ // FE FF UTF-16BE
+ // FF FE UTF-16LE
+ // EF BB BF UTF-8
+
+ const unsigned char* c = (const unsigned char *)is_->Peek4();
+ if (!c)
+ return;
+
+ unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
+ hasBOM_ = false;
+ if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
+
+ // RFC 4627: Section 3
+ // "Since the first two characters of a JSON text will always be ASCII
+ // characters [RFC0020], it is possible to determine whether an octet
+ // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
+ // at the pattern of nulls in the first four octets."
+ // 00 00 00 xx UTF-32BE
+ // 00 xx 00 xx UTF-16BE
+ // xx 00 00 00 UTF-32LE
+ // xx 00 xx 00 UTF-16LE
+ // xx xx xx xx UTF-8
+
+ if (!hasBOM_) {
+ unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
+ switch (pattern) {
+ case 0x08: type_ = kUTF32BE; break;
+ case 0x0A: type_ = kUTF16BE; break;
+ case 0x01: type_ = kUTF32LE; break;
+ case 0x05: type_ = kUTF16LE; break;
+ case 0x0F: type_ = kUTF8; break;
+ default: break; // Use type defined by user.
+ }
+ }
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+ }
+
+ typedef Ch (*TakeFunc)(InputByteStream& is);
+ InputByteStream* is_;
+ UTFType type_;
+ Ch current_;
+ TakeFunc takeFunc_;
+ bool hasBOM_;
+};
+
+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for writing.
+ \tparam InputByteStream type of output byte stream to be wrapped.
+*/
+template <typename CharType, typename OutputByteStream>
+class AutoUTFOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param os output stream to be wrapped.
+ \param type UTF encoding type.
+ \param putBOM Whether to write BOM at the beginning of the stream.
+ */
+ AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+
+ static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
+ putFunc_ = f[type_];
+
+ if (putBOM)
+ PutBOM();
+ }
+
+ UTFType GetType() const { return type_; }
+
+ void Put(Ch c) { putFunc_(*os_, c); }
+ void Flush() { os_->Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
+ Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ AutoUTFOutputStream(const AutoUTFOutputStream&);
+ AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
+
+ void PutBOM() {
+ typedef void (*PutBOMFunc)(OutputByteStream&);
+ static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
+ f[type_](*os_);
+ }
+
+ typedef void (*PutFunc)(OutputByteStream&, Ch);
+
+ OutputByteStream* os_;
+ UTFType type_;
+ PutFunc putFunc_;
+};
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h
new file mode 100644
index 000000000..90b46ed32
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h
@@ -0,0 +1,625 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODINGS_H_
+#define RAPIDJSON_ENCODINGS_H_
+
+#include "rapidjson.h"
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(overflow)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+ \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+ typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
+
+ enum { supportUnicode = 1 }; // or 0 if not supporting unicode
+
+ //! \brief Encode a Unicode codepoint to an output stream.
+ //! \param os Output stream.
+ //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint);
+
+ //! \brief Decode a Unicode codepoint from an input stream.
+ //! \param is Input stream.
+ //! \param codepoint Output of the unicode codepoint.
+ //! \return true if a valid codepoint can be decoded from the stream.
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint);
+
+ //! \brief Validate one Unicode codepoint from an encoded stream.
+ //! \param is Input stream to obtain codepoint.
+ //! \param os Output for copying one codepoint.
+ //! \return true if it is valid.
+ //! \note This function just validating and copying the codepoint without actually decode it.
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os);
+
+ // The following functions are deal with byte streams.
+
+ //! Take a character from input byte stream, skip BOM if exist.
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is);
+
+ //! Take a character from input byte stream.
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is);
+
+ //! Put BOM to output byte stream.
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os);
+
+ //! Put a character to output byte stream.
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+ http://tools.ietf.org/html/rfc3629
+ \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct UTF8 {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ Ch c = is.Take();
+ if (!(c & 0x80)) {
+ *codepoint = (unsigned char)c;
+ return true;
+ }
+
+ unsigned char type = GetRange((unsigned char)c);
+ *codepoint = (0xFF >> type) & (unsigned char)c;
+ bool result = true;
+ switch (type) {
+ case 2: TAIL(); return result;
+ case 3: TAIL(); TAIL(); return result;
+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+ case 6: TAIL(); TAIL(); TAIL(); return result;
+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+#define COPY() os.Put(c = is.Take())
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ Ch c;
+ COPY();
+ if (!(c & 0x80))
+ return true;
+
+ bool result = true;
+ switch (GetRange((unsigned char)c)) {
+ case 2: TAIL(); return result;
+ case 3: TAIL(); TAIL(); return result;
+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+ case 6: TAIL(); TAIL(); TAIL(); return result;
+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ static unsigned char GetRange(unsigned char c) {
+ // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+ // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
+ static const unsigned char type[] = {
+ 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,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,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,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+ };
+ return type[c];
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ Ch c = Take(is);
+ if ((unsigned char)c != 0xEFu) return c;
+ c = is.Take();
+ if ((unsigned char)c != 0xBBu) return c;
+ c = is.Take();
+ if ((unsigned char)c != 0xBFu) return c;
+ c = is.Take();
+ return c;
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return is.Take();
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+ http://tools.ietf.org/html/rfc2781
+ \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF16LE and UTF16BE, which handle endianness.
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ os.Put(static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ os.Put((v & 0x3FF) | 0xDC00);
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ Ch c = is.Take();
+ if (c < 0xD800 || c > 0xDFFF) {
+ *codepoint = c;
+ return true;
+ }
+ else if (c <= 0xDBFF) {
+ *codepoint = (c & 0x3FF) << 10;
+ c = is.Take();
+ *codepoint |= (c & 0x3FF);
+ *codepoint += 0x10000;
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ Ch c;
+ os.Put(c = is.Take());
+ if (c < 0xD800 || c > 0xDFFF)
+ return true;
+ else if (c <= 0xDBFF) {
+ os.Put(c = is.Take());
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+};
+
+//! UTF-16 little endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16LE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take();
+ c |= (unsigned char)is.Take() << 8;
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xFFu); os.Put(0xFEu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(c & 0xFFu);
+ os.Put((c >> 8) & 0xFFu);
+ }
+};
+
+//! UTF-16 big endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16BE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take() << 8;
+ c |= (unsigned char)is.Take();
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xFEu); os.Put(0xFFu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put((c >> 8) & 0xFFu);
+ os.Put(c & 0xFFu);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-32
+ \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF32LE and UTF32BE, which handle endianness.
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(codepoint);
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c = is.Take();
+ *codepoint = c;
+ return c <= 0x10FFFF;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c;
+ os.Put(c = is.Take());
+ return c <= 0x10FFFF;
+ }
+};
+
+//! UTF-32 little endian enocoding.
+template<typename CharType = unsigned>
+struct UTF32LE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take();
+ c |= (unsigned char)is.Take() << 8;
+ c |= (unsigned char)is.Take() << 16;
+ c |= (unsigned char)is.Take() << 24;
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(c & 0xFFu);
+ os.Put((c >> 8) & 0xFFu);
+ os.Put((c >> 16) & 0xFFu);
+ os.Put((c >> 24) & 0xFFu);
+ }
+};
+
+//! UTF-32 big endian encoding.
+template<typename CharType = unsigned>
+struct UTF32BE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take() << 24;
+ c |= (unsigned char)is.Take() << 16;
+ c |= (unsigned char)is.Take() << 8;
+ c |= (unsigned char)is.Take();
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put((c >> 24) & 0xFFu);
+ os.Put((c >> 16) & 0xFFu);
+ os.Put((c >> 8) & 0xFFu);
+ os.Put(c & 0xFFu);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ASCII
+
+//! ASCII encoding.
+/*! http://en.wikipedia.org/wiki/ASCII
+ \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct ASCII {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 0 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ unsigned char c = static_cast<unsigned char>(is.Take());
+ *codepoint = c;
+ return c <= 0X7F;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ unsigned char c = is.Take();
+ os.Put(c);
+ return c <= 0x7F;
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ Ch c = Take(is);
+ return c;
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return is.Take();
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ (void)os;
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoUTF
+
+//! Runtime-specified UTF encoding type of a stream.
+enum UTFType {
+ kUTF8 = 0, //!< UTF-8.
+ kUTF16LE = 1, //!< UTF-16 little endian.
+ kUTF16BE = 2, //!< UTF-16 big endian.
+ kUTF32LE = 3, //!< UTF-32 little endian.
+ kUTF32BE = 4 //!< UTF-32 big endian.
+};
+
+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
+*/
+template<typename CharType>
+struct AutoUTF {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+ template<typename OutputStream>
+ RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
+ template <typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+ typedef bool (*DecodeFunc)(InputStream&, unsigned*);
+ static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
+ return (*f[is.GetType()])(is, codepoint);
+ }
+
+ template <typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
+ static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
+ return (*f[is.GetType()])(is, os);
+ }
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Transcoder
+
+//! Encoding conversion.
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder {
+ //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::Encode(os, codepoint);
+ return true;
+ }
+
+ //! Validate one Unicode codepoint from an encoded stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Transcode(is, os); // Since source/target encoding is different, must transcode.
+ }
+};
+
+//! Specialization of Transcoder with same source and target encoding.
+template<typename Encoding>
+struct Transcoder<Encoding, Encoding> {
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Encoding::Validate(is, os); // source/target encoding are the same
+ }
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__GNUC__) || defined(_MSV_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h
new file mode 100644
index 000000000..d5f9caab8
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h
@@ -0,0 +1,65 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ERROR_EN_H__
+#define RAPIDJSON_ERROR_EN_H__
+
+#include "error.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Maps error code of parsing into error message.
+/*!
+ \ingroup RAPIDJSON_ERRORS
+ \param parseErrorCode Error code obtained in parsing.
+ \return the error message.
+ \note User can make a copy of this function for localization.
+ Using switch-case is safer for future modification of error codes.
+*/
+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
+ switch (parseErrorCode) {
+ case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
+
+ case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
+ case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values.");
+
+ case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
+
+ case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
+ case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
+ case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
+
+ case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
+
+ case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
+ case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
+ case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
+ case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
+ case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
+
+ case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
+ case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
+ case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
+
+ case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
+ case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
+
+ default:
+ return RAPIDJSON_ERROR_STRING("Unknown error.");
+ }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ERROR_EN_H__
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h
new file mode 100644
index 000000000..f9094fb95
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h
@@ -0,0 +1,146 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ERROR_ERROR_H__
+#define RAPIDJSON_ERROR_ERROR_H__
+
+#include "../rapidjson.h"
+
+/*! \file error.h */
+
+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_CHARTYPE
+
+//! Character type of error messages.
+/*! \ingroup RAPIDJSON_ERRORS
+ The default character type is \c char.
+ On Windows, user can define this macro as \c TCHAR for supporting both
+ unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_CHARTYPE
+#define RAPIDJSON_ERROR_CHARTYPE char
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_STRING
+
+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
+/*! \ingroup RAPIDJSON_ERRORS
+ By default this conversion macro does nothing.
+ On Windows, user can define this macro as \c _T(x) for supporting both
+ unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_STRING
+#define RAPIDJSON_ERROR_STRING(x) x
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseErrorCode
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+ \see GenericReader::Parse, GenericReader::GetParseErrorCode
+*/
+enum ParseErrorCode {
+ kParseErrorNone = 0, //!< No error.
+
+ kParseErrorDocumentEmpty, //!< The document is empty.
+ kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
+
+ kParseErrorValueInvalid, //!< Invalid value.
+
+ kParseErrorObjectMissName, //!< Missing a name for object member.
+ kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
+ kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
+
+ kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
+
+ kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
+ kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
+ kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
+ kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
+ kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
+
+ kParseErrorNumberTooBig, //!< Number too big to be stored in double.
+ kParseErrorNumberMissFraction, //!< Miss fraction part in number.
+ kParseErrorNumberMissExponent, //!< Miss exponent in number.
+
+ kParseErrorTermination, //!< Parsing was terminated.
+ kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
+};
+
+//! Result of parsing (wraps ParseErrorCode)
+/*!
+ \ingroup RAPIDJSON_ERRORS
+ \code
+ Document doc;
+ ParseResult ok = doc.Parse("[42]");
+ if (!ok) {
+ fprintf(stderr, "JSON parse error: %s (%u)",
+ GetParseError_En(ok.Code()), ok.Offset());
+ exit(EXIT_FAILURE);
+ }
+ \endcode
+ \see GenericReader::Parse, GenericDocument::Parse
+*/
+struct ParseResult {
+
+ //! Default constructor, no error.
+ ParseResult() : code_(kParseErrorNone), offset_(0) {}
+ //! Constructor to set an error.
+ ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
+
+ //! Get the error code.
+ ParseErrorCode Code() const { return code_; }
+ //! Get the error offset, if \ref IsError(), 0 otherwise.
+ size_t Offset() const { return offset_; }
+
+ //! Conversion to \c bool, returns \c true, iff !\ref IsError().
+ operator bool() const { return !IsError(); }
+ //! Whether the result is an error.
+ bool IsError() const { return code_ != kParseErrorNone; }
+
+ bool operator==(const ParseResult& that) const { return code_ == that.code_; }
+ bool operator==(ParseErrorCode code) const { return code_ == code; }
+ friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
+
+ //! Reset error code.
+ void Clear() { Set(kParseErrorNone); }
+ //! Update error code and offset.
+ void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
+
+private:
+ ParseErrorCode code_;
+ size_t offset_;
+};
+
+//! Function pointer type of GetParseError().
+/*! \ingroup RAPIDJSON_ERRORS
+
+ This is the prototype for \c GetParseError_X(), where \c X is a locale.
+ User can dynamically change locale in runtime, e.g.:
+\code
+ GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
+ const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
+\endcode
+*/
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ERROR_ERROR_H__
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h
new file mode 100644
index 000000000..3913eb74b
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h
@@ -0,0 +1,88 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEREADSTREAM_H_
+#define RAPIDJSON_FILEREADSTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! File byte stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileReadStream {
+public:
+ typedef char Ch; //!< Character type (byte).
+
+ //! Constructor.
+ /*!
+ \param fp File pointer opened for read.
+ \param buffer user-supplied buffer.
+ \param bufferSize size of buffer in bytes. Must >=4 bytes.
+ */
+ FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ RAPIDJSON_ASSERT(bufferSize >= 4);
+ Read();
+ }
+
+ Ch Peek() const { return *current_; }
+ Ch Take() { Ch c = *current_; Read(); return c; }
+ size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ return (current_ + 4 <= bufferLast_) ? current_ : 0;
+ }
+
+private:
+ void Read() {
+ if (current_ < bufferLast_)
+ ++current_;
+ else if (!eof_) {
+ count_ += readCount_;
+ readCount_ = fread(buffer_, 1, bufferSize_, fp_);
+ bufferLast_ = buffer_ + readCount_ - 1;
+ current_ = buffer_;
+
+ if (readCount_ < bufferSize_) {
+ buffer_[readCount_] = '\0';
+ ++bufferLast_;
+ eof_ = true;
+ }
+ }
+ }
+
+ std::FILE* fp_;
+ Ch *buffer_;
+ size_t bufferSize_;
+ Ch *bufferLast_;
+ Ch *current_;
+ size_t readCount_;
+ size_t count_; //!< Number of characters read
+ bool eof_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h
new file mode 100644
index 000000000..afd7e19b8
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h
@@ -0,0 +1,95 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
+#define RAPIDJSON_FILEWRITESTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of C file stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileWriteStream {
+public:
+ typedef char Ch; //!< Character type. Only support char.
+
+ FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ }
+
+ void Put(char c) {
+ if (current_ >= bufferEnd_)
+ Flush();
+
+ *current_++ = c;
+ }
+
+ void PutN(char c, size_t n) {
+ size_t avail = static_cast<size_t>(bufferEnd_ - current_);
+ while (n > avail) {
+ std::memset(current_, c, avail);
+ current_ += avail;
+ Flush();
+ n -= avail;
+ avail = static_cast<size_t>(bufferEnd_ - current_);
+ }
+
+ if (n > 0) {
+ std::memset(current_, c, n);
+ current_ += n;
+ }
+ }
+
+ void Flush() {
+ if (current_ != buffer_) {
+ size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
+ if (result < static_cast<size_t>(current_ - buffer_)) {
+ // failure deliberately ignored at this time
+ // added to avoid warn_unused_result build errors
+ }
+ current_ = buffer_;
+ }
+ }
+
+ // Not implemented
+ char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+ char Take() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ FileWriteStream(const FileWriteStream&);
+ FileWriteStream& operator=(const FileWriteStream&);
+
+ std::FILE* fp_;
+ char *buffer_;
+ char *bufferEnd_;
+ char *current_;
+};
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(FileWriteStream& stream, char c, size_t n) {
+ stream.PutN(c, n);
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h
new file mode 100644
index 000000000..4477cf5d1
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h
@@ -0,0 +1,290 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_BIGINTEGER_H_
+#define RAPIDJSON_BIGINTEGER_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h> // for _umul128
+#pragma intrinsic(_umul128)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class BigInteger {
+public:
+ typedef uint64_t Type;
+
+ BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+ }
+
+ explicit BigInteger(uint64_t u) : count_(1) {
+ digits_[0] = u;
+ }
+
+ BigInteger(const char* decimals, size_t length) : count_(1) {
+ RAPIDJSON_ASSERT(length > 0);
+ digits_[0] = 0;
+ size_t i = 0;
+ const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
+ while (length >= kMaxDigitPerIteration) {
+ AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
+ length -= kMaxDigitPerIteration;
+ i += kMaxDigitPerIteration;
+ }
+
+ if (length > 0)
+ AppendDecimal64(decimals + i, decimals + i + length);
+ }
+
+ BigInteger& operator=(const BigInteger &rhs)
+ {
+ if (this != &rhs) {
+ count_ = rhs.count_;
+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+ }
+ return *this;
+ }
+
+ BigInteger& operator=(uint64_t u) {
+ digits_[0] = u;
+ count_ = 1;
+ return *this;
+ }
+
+ BigInteger& operator+=(uint64_t u) {
+ Type backup = digits_[0];
+ digits_[0] += u;
+ for (size_t i = 0; i < count_ - 1; i++) {
+ if (digits_[i] >= backup)
+ return *this; // no carry
+ backup = digits_[i + 1];
+ digits_[i + 1] += 1;
+ }
+
+ // Last carry
+ if (digits_[count_ - 1] < backup)
+ PushBack(1);
+
+ return *this;
+ }
+
+ BigInteger& operator*=(uint64_t u) {
+ if (u == 0) return *this = 0;
+ if (u == 1) return *this;
+ if (*this == 1) return *this = u;
+
+ uint64_t k = 0;
+ for (size_t i = 0; i < count_; i++) {
+ uint64_t hi;
+ digits_[i] = MulAdd64(digits_[i], u, k, &hi);
+ k = hi;
+ }
+
+ if (k > 0)
+ PushBack(k);
+
+ return *this;
+ }
+
+ BigInteger& operator*=(uint32_t u) {
+ if (u == 0) return *this = 0;
+ if (u == 1) return *this;
+ if (*this == 1) return *this = u;
+
+ uint64_t k = 0;
+ for (size_t i = 0; i < count_; i++) {
+ const uint64_t c = digits_[i] >> 32;
+ const uint64_t d = digits_[i] & 0xFFFFFFFF;
+ const uint64_t uc = u * c;
+ const uint64_t ud = u * d;
+ const uint64_t p0 = ud + k;
+ const uint64_t p1 = uc + (p0 >> 32);
+ digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
+ k = p1 >> 32;
+ }
+
+ if (k > 0)
+ PushBack(k);
+
+ return *this;
+ }
+
+ BigInteger& operator<<=(size_t shift) {
+ if (IsZero() || shift == 0) return *this;
+
+ size_t offset = shift / kTypeBit;
+ size_t interShift = shift % kTypeBit;
+ RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
+
+ if (interShift == 0) {
+ std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
+ count_ += offset;
+ }
+ else {
+ digits_[count_] = 0;
+ for (size_t i = count_; i > 0; i--)
+ digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
+ digits_[offset] = digits_[0] << interShift;
+ count_ += offset;
+ if (digits_[count_])
+ count_++;
+ }
+
+ std::memset(digits_, 0, offset * sizeof(Type));
+
+ return *this;
+ }
+
+ bool operator==(const BigInteger& rhs) const {
+ return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
+ }
+
+ bool operator==(const Type rhs) const {
+ return count_ == 1 && digits_[0] == rhs;
+ }
+
+ BigInteger& MultiplyPow5(unsigned exp) {
+ static const uint32_t kPow5[12] = {
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+ if (exp == 0) return *this;
+ for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
+ for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
+ if (exp > 0) *this *= kPow5[exp - 1];
+ return *this;
+ }
+
+ // Compute absolute difference of this and rhs.
+ // Assume this != rhs
+ bool Difference(const BigInteger& rhs, BigInteger* out) const {
+ int cmp = Compare(rhs);
+ RAPIDJSON_ASSERT(cmp != 0);
+ const BigInteger *a, *b; // Makes a > b
+ bool ret;
+ if (cmp < 0) { a = &rhs; b = this; ret = true; }
+ else { a = this; b = &rhs; ret = false; }
+
+ Type borrow = 0;
+ for (size_t i = 0; i < a->count_; i++) {
+ Type d = a->digits_[i] - borrow;
+ if (i < b->count_)
+ d -= b->digits_[i];
+ borrow = (d > a->digits_[i]) ? 1 : 0;
+ out->digits_[i] = d;
+ if (d != 0)
+ out->count_ = i + 1;
+ }
+
+ return ret;
+ }
+
+ int Compare(const BigInteger& rhs) const {
+ if (count_ != rhs.count_)
+ return count_ < rhs.count_ ? -1 : 1;
+
+ for (size_t i = count_; i-- > 0;)
+ if (digits_[i] != rhs.digits_[i])
+ return digits_[i] < rhs.digits_[i] ? -1 : 1;
+
+ return 0;
+ }
+
+ size_t GetCount() const { return count_; }
+ Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
+ bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
+
+private:
+ void AppendDecimal64(const char* begin, const char* end) {
+ uint64_t u = ParseUint64(begin, end);
+ if (IsZero())
+ *this = u;
+ else {
+ unsigned exp = static_cast<unsigned>(end - begin);
+ (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
+ }
+ }
+
+ void PushBack(Type digit) {
+ RAPIDJSON_ASSERT(count_ < kCapacity);
+ digits_[count_++] = digit;
+ }
+
+ static uint64_t ParseUint64(const char* begin, const char* end) {
+ uint64_t r = 0;
+ for (const char* p = begin; p != end; ++p) {
+ RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
+ r = r * 10u + (unsigned)(*p - '0');
+ }
+ return r;
+ }
+
+ // Assume a * b + k < 2^128
+ static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ uint64_t low = _umul128(a, b, outHigh) + k;
+ if (low < k)
+ (*outHigh)++;
+ return low;
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+ __extension__ typedef unsigned __int128 uint128;
+ uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
+ p += k;
+ *outHigh = static_cast<uint64_t>(p >> 64);
+ return static_cast<uint64_t>(p);
+#else
+ const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
+ uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
+ x1 += (x0 >> 32); // can't give carry
+ x1 += x2;
+ if (x1 < x2)
+ x3 += (static_cast<uint64_t>(1) << 32);
+ uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
+ uint64_t hi = x3 + (x1 >> 32);
+
+ lo += k;
+ if (lo < k)
+ hi++;
+ *outHigh = hi;
+ return lo;
+#endif
+ }
+
+ static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
+ static const size_t kCapacity = kBitCount / sizeof(Type);
+ static const size_t kTypeBit = sizeof(Type) * 8;
+
+ Type digits_[kCapacity];
+ size_t count_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_BIGINTEGER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h
new file mode 100644
index 000000000..7a55ee31c
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h
@@ -0,0 +1,248 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DIYFP_H_
+#define RAPIDJSON_DIYFP_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse64)
+#pragma intrinsic(_umul128)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+struct DiyFp {
+ DiyFp() {}
+
+ DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
+
+ explicit DiyFp(double d) {
+ union {
+ double d;
+ uint64_t u64;
+ } u = { d };
+
+ int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
+ uint64_t significand = (u.u64 & kDpSignificandMask);
+ if (biased_e != 0) {
+ f = significand + kDpHiddenBit;
+ e = biased_e - kDpExponentBias;
+ }
+ else {
+ f = significand;
+ e = kDpMinExponent + 1;
+ }
+ }
+
+ DiyFp operator-(const DiyFp& rhs) const {
+ return DiyFp(f - rhs.f, e);
+ }
+
+ DiyFp operator*(const DiyFp& rhs) const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ uint64_t h;
+ uint64_t l = _umul128(f, rhs.f, &h);
+ if (l & (uint64_t(1) << 63)) // rounding
+ h++;
+ return DiyFp(h, e + rhs.e + 64);
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+ __extension__ typedef unsigned __int128 uint128;
+ uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
+ uint64_t h = static_cast<uint64_t>(p >> 64);
+ uint64_t l = static_cast<uint64_t>(p);
+ if (l & (uint64_t(1) << 63)) // rounding
+ h++;
+ return DiyFp(h, e + rhs.e + 64);
+#else
+ const uint64_t M32 = 0xFFFFFFFF;
+ const uint64_t a = f >> 32;
+ const uint64_t b = f & M32;
+ const uint64_t c = rhs.f >> 32;
+ const uint64_t d = rhs.f & M32;
+ const uint64_t ac = a * c;
+ const uint64_t bc = b * c;
+ const uint64_t ad = a * d;
+ const uint64_t bd = b * d;
+ uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
+ tmp += 1U << 31; /// mult_round
+ return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
+#endif
+ }
+
+ DiyFp Normalize() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ unsigned long index;
+ _BitScanReverse64(&index, f);
+ return DiyFp(f << (63 - index), e - (63 - index));
+#elif defined(__GNUC__) && __GNUC__ >= 4
+ int s = __builtin_clzll(f);
+ return DiyFp(f << s, e - s);
+#else
+ DiyFp res = *this;
+ while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ return res;
+#endif
+ }
+
+ DiyFp NormalizeBoundary() const {
+ DiyFp res = *this;
+ while (!(res.f & (kDpHiddenBit << 1))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+ res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+ return res;
+ }
+
+ void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+ DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+ DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+ mi.f <<= mi.e - pl.e;
+ mi.e = pl.e;
+ *plus = pl;
+ *minus = mi;
+ }
+
+ double ToDouble() const {
+ union {
+ double d;
+ uint64_t u64;
+ }u;
+ const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
+ static_cast<uint64_t>(e + kDpExponentBias);
+ u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
+ return u.d;
+ }
+
+ static const int kDiySignificandSize = 64;
+ static const int kDpSignificandSize = 52;
+ static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
+ static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
+ static const int kDpMinExponent = -kDpExponentBias;
+ static const int kDpDenormalExponent = -kDpExponentBias + 1;
+ static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+ static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+ static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+ uint64_t f;
+ int e;
+};
+
+inline DiyFp GetCachedPowerByIndex(size_t index) {
+ // 10^-348, 10^-340, ..., 10^340
+ static const uint64_t kCachedPowers_F[] = {
+ RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
+ RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
+ RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
+ RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
+ RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
+ RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
+ RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
+ RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
+ RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
+ RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
+ RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
+ RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
+ RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
+ RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
+ RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
+ RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
+ RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
+ RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
+ RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
+ RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
+ RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
+ RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
+ RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
+ RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
+ RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
+ RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
+ RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
+ RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
+ RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
+ RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
+ RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
+ RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
+ RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
+ RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
+ RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
+ RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
+ RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
+ RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
+ RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
+ RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
+ RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
+ RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
+ RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
+ RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
+ };
+ static const int16_t kCachedPowers_E[] = {
+ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
+ -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
+ -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
+ -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
+ -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
+ 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
+ 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
+ 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
+ 907, 933, 960, 986, 1013, 1039, 1066
+ };
+ return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
+}
+
+inline DiyFp GetCachedPower(int e, int* K) {
+
+ //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+ double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
+ int k = static_cast<int>(dk);
+ if (dk - k > 0.0)
+ k++;
+
+ unsigned index = static_cast<unsigned>((k >> 3) + 1);
+ *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
+
+ return GetCachedPowerByIndex(index);
+}
+
+inline DiyFp GetCachedPower10(int exp, int *outExp) {
+ unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
+ *outExp = -348 + static_cast<int>(index) * 8;
+ return GetCachedPowerByIndex(index);
+ }
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DIYFP_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h
new file mode 100644
index 000000000..d04ae21cc
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h
@@ -0,0 +1,217 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DTOA_
+#define RAPIDJSON_DTOA_
+
+#include "itoa.h" // GetDigitsLut()
+#include "diyfp.h"
+#include "ieee754.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+ while (rest < wp_w && delta - rest >= ten_kappa &&
+ (rest + ten_kappa < wp_w || /// closer
+ wp_w - rest > rest + ten_kappa - wp_w)) {
+ buffer[len - 1]--;
+ rest += ten_kappa;
+ }
+}
+
+inline unsigned CountDecimalDigit32(uint32_t n) {
+ // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+ if (n < 10) return 1;
+ if (n < 100) return 2;
+ if (n < 1000) return 3;
+ if (n < 10000) return 4;
+ if (n < 100000) return 5;
+ if (n < 1000000) return 6;
+ if (n < 10000000) return 7;
+ if (n < 100000000) return 8;
+ // Will not reach 10 digits in DigitGen()
+ //if (n < 1000000000) return 9;
+ //return 10;
+ return 9;
+}
+
+inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+ static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+ const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+ const DiyFp wp_w = Mp - W;
+ uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+ uint64_t p2 = Mp.f & (one.f - 1);
+ unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
+ *len = 0;
+
+ while (kappa > 0) {
+ uint32_t d = 0;
+ switch (kappa) {
+ case 9: d = p1 / 100000000; p1 %= 100000000; break;
+ case 8: d = p1 / 10000000; p1 %= 10000000; break;
+ case 7: d = p1 / 1000000; p1 %= 1000000; break;
+ case 6: d = p1 / 100000; p1 %= 100000; break;
+ case 5: d = p1 / 10000; p1 %= 10000; break;
+ case 4: d = p1 / 1000; p1 %= 1000; break;
+ case 3: d = p1 / 100; p1 %= 100; break;
+ case 2: d = p1 / 10; p1 %= 10; break;
+ case 1: d = p1; p1 = 0; break;
+ default:;
+ }
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
+ kappa--;
+ uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+ if (tmp <= delta) {
+ *K += kappa;
+ GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+ return;
+ }
+ }
+
+ // kappa = 0
+ for (;;) {
+ p2 *= 10;
+ delta *= 10;
+ char d = static_cast<char>(p2 >> -one.e);
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + d);
+ p2 &= one.f - 1;
+ kappa--;
+ if (p2 < delta) {
+ *K += kappa;
+ GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast<int>(kappa)]);
+ return;
+ }
+ }
+}
+
+inline void Grisu2(double value, char* buffer, int* length, int* K) {
+ const DiyFp v(value);
+ DiyFp w_m, w_p;
+ v.NormalizedBoundaries(&w_m, &w_p);
+
+ const DiyFp c_mk = GetCachedPower(w_p.e, K);
+ const DiyFp W = v.Normalize() * c_mk;
+ DiyFp Wp = w_p * c_mk;
+ DiyFp Wm = w_m * c_mk;
+ Wm.f++;
+ Wp.f--;
+ DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+
+inline char* WriteExponent(int K, char* buffer) {
+ if (K < 0) {
+ *buffer++ = '-';
+ K = -K;
+ }
+
+ if (K >= 100) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
+ K %= 100;
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else if (K >= 10) {
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K));
+
+ return buffer;
+}
+
+inline char* Prettify(char* buffer, int length, int k) {
+ const int kk = length + k; // 10^(kk-1) <= v < 10^kk
+
+ if (length <= kk && kk <= 21) {
+ // 1234e7 -> 12340000000
+ for (int i = length; i < kk; i++)
+ buffer[i] = '0';
+ buffer[kk] = '.';
+ buffer[kk + 1] = '0';
+ return &buffer[kk + 2];
+ }
+ else if (0 < kk && kk <= 21) {
+ // 1234e-2 -> 12.34
+ std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
+ buffer[kk] = '.';
+ return &buffer[length + 1];
+ }
+ else if (-6 < kk && kk <= 0) {
+ // 1234e-6 -> 0.001234
+ const int offset = 2 - kk;
+ std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
+ buffer[0] = '0';
+ buffer[1] = '.';
+ for (int i = 2; i < offset; i++)
+ buffer[i] = '0';
+ return &buffer[length + offset];
+ }
+ else if (length == 1) {
+ // 1e30
+ buffer[1] = 'e';
+ return WriteExponent(kk - 1, &buffer[2]);
+ }
+ else {
+ // 1234e30 -> 1.234e33
+ std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
+ buffer[1] = '.';
+ buffer[length + 1] = 'e';
+ return WriteExponent(kk - 1, &buffer[0 + length + 2]);
+ }
+}
+
+inline char* dtoa(double value, char* buffer) {
+ Double d(value);
+ if (d.IsZero()) {
+ if (d.Sign())
+ *buffer++ = '-'; // -0.0, Issue #289
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ else {
+ if (value < 0) {
+ *buffer++ = '-';
+ value = -value;
+ }
+ int length, K;
+ Grisu2(value, buffer, &length, &K);
+ return Prettify(buffer, length, K);
+ }
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DTOA_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h
new file mode 100644
index 000000000..2fdaf54b3
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h
@@ -0,0 +1,77 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_IEEE754_
+#define RAPIDJSON_IEEE754_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class Double {
+public:
+ Double() {}
+ Double(double d) : d_(d) {}
+ Double(uint64_t u) : u_(u) {}
+
+ double Value() const { return d_; }
+ uint64_t Uint64Value() const { return u_; }
+
+ double NextPositiveDouble() const {
+ RAPIDJSON_ASSERT(!Sign());
+ return Double(u_ + 1).Value();
+ }
+
+ bool Sign() const { return (u_ & kSignMask) != 0; }
+ uint64_t Significand() const { return u_ & kSignificandMask; }
+ int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
+
+ bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
+ bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
+ bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
+ bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
+
+ uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
+ int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
+ uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
+
+ static unsigned EffectiveSignificandSize(int order) {
+ if (order >= -1021)
+ return 53;
+ else if (order <= -1074)
+ return 0;
+ else
+ return (unsigned)order + 1074;
+ }
+
+private:
+ static const int kSignificandSize = 52;
+ static const int kExponentBias = 0x3FF;
+ static const int kDenormalExponent = 1 - kExponentBias;
+ static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
+ static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+ static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+ static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+ union {
+ double d_;
+ uint64_t u_;
+ };
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_IEEE754_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/itoa.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/itoa.h
new file mode 100644
index 000000000..01a4e7e72
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/itoa.h
@@ -0,0 +1,304 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ITOA_
+#define RAPIDJSON_ITOA_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline const char* GetDigitsLut() {
+ static const char cDigitsLut[200] = {
+ '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+ '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+ '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+ '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+ '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+ '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+ '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+ '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+ '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+ '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+ };
+ return cDigitsLut;
+}
+
+inline char* u32toa(uint32_t value, char* buffer) {
+ const char* cDigitsLut = GetDigitsLut();
+
+ if (value < 10000) {
+ const uint32_t d1 = (value / 100) << 1;
+ const uint32_t d2 = (value % 100) << 1;
+
+ if (value >= 1000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 100)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 10)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ }
+ else if (value < 100000000) {
+ // value = bbbbcccc
+ const uint32_t b = value / 10000;
+ const uint32_t c = value % 10000;
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ if (value >= 10000000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 1000000)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 100000)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ else {
+ // value = aabbbbcccc in decimal
+
+ const uint32_t a = value / 100000000; // 1 to 42
+ value %= 100000000;
+
+ if (a >= 10) {
+ const unsigned i = a << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+
+ const uint32_t b = value / 10000; // 0 to 9999
+ const uint32_t c = value % 10000; // 0 to 9999
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ *buffer++ = cDigitsLut[d1];
+ *buffer++ = cDigitsLut[d1 + 1];
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ return buffer;
+}
+
+inline char* i32toa(int32_t value, char* buffer) {
+ uint32_t u = static_cast<uint32_t>(value);
+ if (value < 0) {
+ *buffer++ = '-';
+ u = ~u + 1;
+ }
+
+ return u32toa(u, buffer);
+}
+
+inline char* u64toa(uint64_t value, char* buffer) {
+ const char* cDigitsLut = GetDigitsLut();
+ const uint64_t kTen8 = 100000000;
+ const uint64_t kTen9 = kTen8 * 10;
+ const uint64_t kTen10 = kTen8 * 100;
+ const uint64_t kTen11 = kTen8 * 1000;
+ const uint64_t kTen12 = kTen8 * 10000;
+ const uint64_t kTen13 = kTen8 * 100000;
+ const uint64_t kTen14 = kTen8 * 1000000;
+ const uint64_t kTen15 = kTen8 * 10000000;
+ const uint64_t kTen16 = kTen8 * kTen8;
+
+ if (value < kTen8) {
+ uint32_t v = static_cast<uint32_t>(value);
+ if (v < 10000) {
+ const uint32_t d1 = (v / 100) << 1;
+ const uint32_t d2 = (v % 100) << 1;
+
+ if (v >= 1000)
+ *buffer++ = cDigitsLut[d1];
+ if (v >= 100)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (v >= 10)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ }
+ else {
+ // value = bbbbcccc
+ const uint32_t b = v / 10000;
+ const uint32_t c = v % 10000;
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ if (value >= 10000000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 1000000)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 100000)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ }
+ else if (value < kTen16) {
+ const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+ const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+
+ const uint32_t b0 = v0 / 10000;
+ const uint32_t c0 = v0 % 10000;
+
+ const uint32_t d1 = (b0 / 100) << 1;
+ const uint32_t d2 = (b0 % 100) << 1;
+
+ const uint32_t d3 = (c0 / 100) << 1;
+ const uint32_t d4 = (c0 % 100) << 1;
+
+ const uint32_t b1 = v1 / 10000;
+ const uint32_t c1 = v1 % 10000;
+
+ const uint32_t d5 = (b1 / 100) << 1;
+ const uint32_t d6 = (b1 % 100) << 1;
+
+ const uint32_t d7 = (c1 / 100) << 1;
+ const uint32_t d8 = (c1 % 100) << 1;
+
+ if (value >= kTen15)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= kTen14)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= kTen13)
+ *buffer++ = cDigitsLut[d2];
+ if (value >= kTen12)
+ *buffer++ = cDigitsLut[d2 + 1];
+ if (value >= kTen11)
+ *buffer++ = cDigitsLut[d3];
+ if (value >= kTen10)
+ *buffer++ = cDigitsLut[d3 + 1];
+ if (value >= kTen9)
+ *buffer++ = cDigitsLut[d4];
+ if (value >= kTen8)
+ *buffer++ = cDigitsLut[d4 + 1];
+
+ *buffer++ = cDigitsLut[d5];
+ *buffer++ = cDigitsLut[d5 + 1];
+ *buffer++ = cDigitsLut[d6];
+ *buffer++ = cDigitsLut[d6 + 1];
+ *buffer++ = cDigitsLut[d7];
+ *buffer++ = cDigitsLut[d7 + 1];
+ *buffer++ = cDigitsLut[d8];
+ *buffer++ = cDigitsLut[d8 + 1];
+ }
+ else {
+ const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
+ value %= kTen16;
+
+ if (a < 10)
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+ else if (a < 100) {
+ const uint32_t i = a << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else if (a < 1000) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
+
+ const uint32_t i = (a % 100) << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else {
+ const uint32_t i = (a / 100) << 1;
+ const uint32_t j = (a % 100) << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ *buffer++ = cDigitsLut[j];
+ *buffer++ = cDigitsLut[j + 1];
+ }
+
+ const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+ const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+
+ const uint32_t b0 = v0 / 10000;
+ const uint32_t c0 = v0 % 10000;
+
+ const uint32_t d1 = (b0 / 100) << 1;
+ const uint32_t d2 = (b0 % 100) << 1;
+
+ const uint32_t d3 = (c0 / 100) << 1;
+ const uint32_t d4 = (c0 % 100) << 1;
+
+ const uint32_t b1 = v1 / 10000;
+ const uint32_t c1 = v1 % 10000;
+
+ const uint32_t d5 = (b1 / 100) << 1;
+ const uint32_t d6 = (b1 % 100) << 1;
+
+ const uint32_t d7 = (c1 / 100) << 1;
+ const uint32_t d8 = (c1 % 100) << 1;
+
+ *buffer++ = cDigitsLut[d1];
+ *buffer++ = cDigitsLut[d1 + 1];
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ *buffer++ = cDigitsLut[d5];
+ *buffer++ = cDigitsLut[d5 + 1];
+ *buffer++ = cDigitsLut[d6];
+ *buffer++ = cDigitsLut[d6 + 1];
+ *buffer++ = cDigitsLut[d7];
+ *buffer++ = cDigitsLut[d7 + 1];
+ *buffer++ = cDigitsLut[d8];
+ *buffer++ = cDigitsLut[d8 + 1];
+ }
+
+ return buffer;
+}
+
+inline char* i64toa(int64_t value, char* buffer) {
+ uint64_t u = static_cast<uint64_t>(value);
+ if (value < 0) {
+ *buffer++ = '-';
+ u = ~u + 1;
+ }
+
+ return u64toa(u, buffer);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ITOA_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/meta.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/meta.h
new file mode 100644
index 000000000..5a9aaa428
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/meta.h
@@ -0,0 +1,181 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_META_H_
+#define RAPIDJSON_INTERNAL_META_H_
+
+#include "../rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+#if defined(_MSC_VER)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(6334)
+#endif
+
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+#include <type_traits>
+#endif
+
+//@cond RAPIDJSON_INTERNAL
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
+template <typename T> struct Void { typedef void Type; };
+
+///////////////////////////////////////////////////////////////////////////////
+// BoolType, TrueType, FalseType
+//
+template <bool Cond> struct BoolType {
+ static const bool Value = Cond;
+ typedef BoolType Type;
+};
+typedef BoolType<true> TrueType;
+typedef BoolType<false> FalseType;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
+//
+
+template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
+template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
+template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
+template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
+
+template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
+template <> struct AndExprCond<true, true> : TrueType {};
+template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
+template <> struct OrExprCond<false, false> : FalseType {};
+
+template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
+template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
+template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
+template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AddConst, MaybeAddConst, RemoveConst
+template <typename T> struct AddConst { typedef const T Type; };
+template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
+template <typename T> struct RemoveConst { typedef T Type; };
+template <typename T> struct RemoveConst<const T> { typedef T Type; };
+
+
+///////////////////////////////////////////////////////////////////////////////
+// IsSame, IsConst, IsMoreConst, IsPointer
+//
+template <typename T, typename U> struct IsSame : FalseType {};
+template <typename T> struct IsSame<T, T> : TrueType {};
+
+template <typename T> struct IsConst : FalseType {};
+template <typename T> struct IsConst<const T> : TrueType {};
+
+template <typename CT, typename T>
+struct IsMoreConst
+ : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
+ BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
+
+template <typename T> struct IsPointer : FalseType {};
+template <typename T> struct IsPointer<T*> : TrueType {};
+
+///////////////////////////////////////////////////////////////////////////////
+// IsBaseOf
+//
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+template <typename B, typename D> struct IsBaseOf
+ : BoolType< ::std::is_base_of<B,D>::value> {};
+
+#else // simplified version adopted from Boost
+
+template<typename B, typename D> struct IsBaseOfImpl {
+ RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
+ RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
+
+ typedef char (&Yes)[1];
+ typedef char (&No) [2];
+
+ template <typename T>
+ static Yes Check(const D*, T);
+ static No Check(const B*, int);
+
+ struct Host {
+ operator const B*() const;
+ operator const D*();
+ };
+
+ enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
+};
+
+template <typename B, typename D> struct IsBaseOf
+ : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
+
+#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+
+//////////////////////////////////////////////////////////////////////////
+// EnableIf / DisableIf
+//
+template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
+template <typename T> struct EnableIfCond<false, T> { /* empty */ };
+
+template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
+template <typename T> struct DisableIfCond<true, T> { /* empty */ };
+
+template <typename Condition, typename T = void>
+struct EnableIf : EnableIfCond<Condition::Value, T> {};
+
+template <typename Condition, typename T = void>
+struct DisableIf : DisableIfCond<Condition::Value, T> {};
+
+// SFINAE helpers
+struct SfinaeTag {};
+template <typename T> struct RemoveSfinaeTag;
+template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
+
+#define RAPIDJSON_REMOVEFPTR_(type) \
+ typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
+ < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
+
+#define RAPIDJSON_ENABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_DISABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+//@endcond
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_META_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/pow10.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/pow10.h
new file mode 100644
index 000000000..02f475d70
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/pow10.h
@@ -0,0 +1,55 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+ \param n non-negative exponent. Must <= 308.
+ \return 10.0^n
+*/
+inline double Pow10(int n) {
+ static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
+ 1e+0,
+ 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
+ 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+ 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+ 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+ 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+ 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+ 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+ 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+ 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+ 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+ 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+ 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+ 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+ 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+ 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
+ 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
+ };
+ RAPIDJSON_ASSERT(n >= 0 && n <= 308);
+ return e[n];
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POW10_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h
new file mode 100644
index 000000000..344785dcd
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h
@@ -0,0 +1,196 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+#include "../rapidjson.h"
+#include "swap.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+ // Optimization note: Do not allocate memory for stack_ in constructor.
+ // Do it lazily when first Push() -> Expand() -> Resize().
+ Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
+ RAPIDJSON_ASSERT(stackCapacity > 0);
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack(Stack&& rhs)
+ : allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(rhs.stack_),
+ stackTop_(rhs.stackTop_),
+ stackEnd_(rhs.stackEnd_),
+ initialCapacity_(rhs.initialCapacity_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+#endif
+
+ ~Stack() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack& operator=(Stack&& rhs) {
+ if (&rhs != this)
+ {
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = rhs.stack_;
+ stackTop_ = rhs.stackTop_;
+ stackEnd_ = rhs.stackEnd_;
+ initialCapacity_ = rhs.initialCapacity_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+ return *this;
+ }
+#endif
+
+ void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
+ internal::Swap(allocator_, rhs.allocator_);
+ internal::Swap(ownAllocator_, rhs.ownAllocator_);
+ internal::Swap(stack_, rhs.stack_);
+ internal::Swap(stackTop_, rhs.stackTop_);
+ internal::Swap(stackEnd_, rhs.stackEnd_);
+ internal::Swap(initialCapacity_, rhs.initialCapacity_);
+ }
+
+ void Clear() { stackTop_ = stack_; }
+
+ void ShrinkToFit() {
+ if (Empty()) {
+ // If the stack is empty, completely deallocate the memory.
+ Allocator::Free(stack_);
+ stack_ = 0;
+ stackTop_ = 0;
+ stackEnd_ = 0;
+ }
+ else
+ Resize(GetSize());
+ }
+
+ // Optimization note: try to minimize the size of this function for force inline.
+ // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+ // Expand the stack if needed
+ if (stackTop_ + sizeof(T) * count >= stackEnd_)
+ Expand<T>(count);
+
+ T* ret = reinterpret_cast<T*>(stackTop_);
+ stackTop_ += sizeof(T) * count;
+ return ret;
+ }
+
+ template<typename T>
+ T* Pop(size_t count) {
+ RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+ stackTop_ -= count * sizeof(T);
+ return reinterpret_cast<T*>(stackTop_);
+ }
+
+ template<typename T>
+ T* Top() {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ T* Bottom() { return (T*)stack_; }
+
+ bool HasAllocator() const {
+ return allocator_ != 0;
+ }
+
+ Allocator& GetAllocator() {
+ RAPIDJSON_ASSERT(allocator_);
+ return *allocator_;
+ }
+ bool Empty() const { return stackTop_ == stack_; }
+ size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
+ size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
+
+private:
+ template<typename T>
+ void Expand(size_t count) {
+ // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
+ size_t newCapacity;
+ if (stack_ == 0) {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ newCapacity = initialCapacity_;
+ } else {
+ newCapacity = GetCapacity();
+ newCapacity += (newCapacity + 1) / 2;
+ }
+ size_t newSize = GetSize() + sizeof(T) * count;
+ if (newCapacity < newSize)
+ newCapacity = newSize;
+
+ Resize(newCapacity);
+ }
+
+ void Resize(size_t newCapacity) {
+ const size_t size = GetSize(); // Backup the current size
+ stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
+ stackTop_ = stack_ + size;
+ stackEnd_ = stack_ + newCapacity;
+ }
+
+ void Destroy() {
+ Allocator::Free(stack_);
+ RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
+ }
+
+ // Prohibit copy constructor & assignment operator.
+ Stack(const Stack&);
+ Stack& operator=(const Stack&);
+
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ char *stack_;
+ char *stackTop_;
+ char *stackEnd_;
+ size_t initialCapacity_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STACK_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h
new file mode 100644
index 000000000..84405065a
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h
@@ -0,0 +1,39 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+ \param s Null-terminated input string.
+ \return Number of characters in the string.
+ \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+ const Ch* p = s;
+ while (*p) ++p;
+ return SizeType(p - s);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h
new file mode 100644
index 000000000..a1b821197
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h
@@ -0,0 +1,270 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRTOD_
+#define RAPIDJSON_STRTOD_
+
+#include "../rapidjson.h"
+#include "ieee754.h"
+#include "biginteger.h"
+#include "diyfp.h"
+#include "pow10.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline double FastPath(double significand, int exp) {
+ if (exp < -308)
+ return 0.0;
+ else if (exp >= 0)
+ return significand * internal::Pow10(exp);
+ else
+ return significand / internal::Pow10(-exp);
+}
+
+inline double StrtodNormalPrecision(double d, int p) {
+ if (p < -308) {
+ // Prevent expSum < -308, making Pow10(p) = 0
+ d = FastPath(d, -308);
+ d = FastPath(d, p + 308);
+ }
+ else
+ d = FastPath(d, p);
+ return d;
+}
+
+template <typename T>
+inline T Min3(T a, T b, T c) {
+ T m = a;
+ if (m > b) m = b;
+ if (m > c) m = c;
+ return m;
+}
+
+inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
+ const Double db(b);
+ const uint64_t bInt = db.IntegerSignificand();
+ const int bExp = db.IntegerExponent();
+ const int hExp = bExp - 1;
+
+ int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
+
+ // Adjust for decimal exponent
+ if (dExp >= 0) {
+ dS_Exp2 += dExp;
+ dS_Exp5 += dExp;
+ }
+ else {
+ bS_Exp2 -= dExp;
+ bS_Exp5 -= dExp;
+ hS_Exp2 -= dExp;
+ hS_Exp5 -= dExp;
+ }
+
+ // Adjust for binary exponent
+ if (bExp >= 0)
+ bS_Exp2 += bExp;
+ else {
+ dS_Exp2 -= bExp;
+ hS_Exp2 -= bExp;
+ }
+
+ // Adjust for half ulp exponent
+ if (hExp >= 0)
+ hS_Exp2 += hExp;
+ else {
+ dS_Exp2 -= hExp;
+ bS_Exp2 -= hExp;
+ }
+
+ // Remove common power of two factor from all three scaled values
+ int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
+ dS_Exp2 -= common_Exp2;
+ bS_Exp2 -= common_Exp2;
+ hS_Exp2 -= common_Exp2;
+
+ BigInteger dS = d;
+ dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
+
+ BigInteger bS(bInt);
+ bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
+
+ BigInteger hS(1);
+ hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
+
+ BigInteger delta(0);
+ dS.Difference(bS, &delta);
+
+ return delta.Compare(hS);
+}
+
+inline bool StrtodFast(double d, int p, double* result) {
+ // Use fast path for string-to-double conversion if possible
+ // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
+ if (p > 22 && p < 22 + 16) {
+ // Fast Path Cases In Disguise
+ d *= internal::Pow10(p - 22);
+ p = 22;
+ }
+
+ if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
+ *result = FastPath(d, p);
+ return true;
+ }
+ else
+ return false;
+}
+
+// Compute an approximation and see if it is within 1/2 ULP
+inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
+ uint64_t significand = 0;
+ size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
+ for (; i < length; i++) {
+ if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
+ (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
+ break;
+ significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
+ }
+
+ if (i < length && decimals[i] >= '5') // Rounding
+ significand++;
+
+ size_t remaining = length - i;
+ const unsigned kUlpShift = 3;
+ const unsigned kUlp = 1 << kUlpShift;
+ int error = (remaining == 0) ? 0 : kUlp / 2;
+
+ DiyFp v(significand, 0);
+ v = v.Normalize();
+ error <<= -v.e;
+
+ const int dExp = (int)decimalPosition - (int)i + exp;
+
+ int actualExp;
+ DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
+ if (actualExp != dExp) {
+ static const DiyFp kPow10[] = {
+ DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
+ DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
+ DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
+ DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
+ DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
+ DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
+ DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
+ };
+ int adjustment = dExp - actualExp - 1;
+ RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
+ v = v * kPow10[adjustment];
+ if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
+ error += kUlp / 2;
+ }
+
+ v = v * cachedPower;
+
+ error += kUlp + (error == 0 ? 0 : 1);
+
+ const int oldExp = v.e;
+ v = v.Normalize();
+ error <<= oldExp - v.e;
+
+ const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
+ unsigned precisionSize = 64 - effectiveSignificandSize;
+ if (precisionSize + kUlpShift >= 64) {
+ unsigned scaleExp = (precisionSize + kUlpShift) - 63;
+ v.f >>= scaleExp;
+ v.e += scaleExp;
+ error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
+ precisionSize -= scaleExp;
+ }
+
+ DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
+ const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
+ const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
+ if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
+ rounded.f++;
+ if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
+ rounded.f >>= 1;
+ rounded.e++;
+ }
+ }
+
+ *result = rounded.ToDouble();
+
+ return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
+}
+
+inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+ const BigInteger dInt(decimals, length);
+ const int dExp = (int)decimalPosition - (int)length + exp;
+ Double a(approx);
+ int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
+ if (cmp < 0)
+ return a.Value(); // within half ULP
+ else if (cmp == 0) {
+ // Round towards even
+ if (a.Significand() & 1)
+ return a.NextPositiveDouble();
+ else
+ return a.Value();
+ }
+ else // adjustment
+ return a.NextPositiveDouble();
+}
+
+inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+ RAPIDJSON_ASSERT(d >= 0.0);
+ RAPIDJSON_ASSERT(length >= 1);
+
+ double result;
+ if (StrtodFast(d, p, &result))
+ return result;
+
+ // Trim leading zeros
+ while (*decimals == '0' && length > 1) {
+ length--;
+ decimals++;
+ decimalPosition--;
+ }
+
+ // Trim trailing zeros
+ while (decimals[length - 1] == '0' && length > 1) {
+ length--;
+ decimalPosition--;
+ exp++;
+ }
+
+ // Trim right-most digits
+ const int kMaxDecimalDigit = 780;
+ if ((int)length > kMaxDecimalDigit) {
+ int delta = (int(length) - kMaxDecimalDigit);
+ exp += delta;
+ decimalPosition -= static_cast<unsigned>(delta);
+ length = kMaxDecimalDigit;
+ }
+
+ // If too small, underflow to zero
+ if (int(length) + exp < -324)
+ return 0.0;
+
+ if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
+ return result;
+
+ // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
+ return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRTOD_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h
new file mode 100644
index 000000000..0590921f1
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h
@@ -0,0 +1,37 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_SWAP_H_
+#define RAPIDJSON_INTERNAL_SWAP_H_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom swap() to avoid dependency on C++ <algorithm> header
+/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
+ \note This has the same semantics as std::swap().
+*/
+template <typename T>
+inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_SWAP_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h
new file mode 100644
index 000000000..2484b2185
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h
@@ -0,0 +1,70 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_MEMORYBUFFER_H_
+#define RAPIDJSON_MEMORYBUFFER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output byte stream.
+/*!
+ This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
+
+ It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
+
+ Differences between MemoryBuffer and StringBuffer:
+ 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer.
+ 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
+
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Allocator = CrtAllocator>
+struct GenericMemoryBuffer {
+ typedef char Ch; // byte
+
+ GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() { stack_.ShrinkToFit(); }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetBuffer() const {
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+};
+
+typedef GenericMemoryBuffer<> MemoryBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
+ std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h
new file mode 100644
index 000000000..99feae5d7
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h
@@ -0,0 +1,61 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_MEMORYSTREAM_H_
+#define RAPIDJSON_MEMORYSTREAM_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory input byte stream.
+/*!
+ This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
+
+ It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
+
+ Differences between MemoryStream and StringStream:
+ 1. StringStream has encoding but MemoryStream is a byte stream.
+ 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
+ 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
+ \note implements Stream concept
+*/
+struct MemoryStream {
+ typedef char Ch; // byte
+
+ MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
+
+ Ch Peek() const { return (src_ == end_) ? '\0' : *src_; }
+ Ch Take() { return (src_ == end_) ? '\0' : *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ return Tell() + 4 <= size_ ? src_ : 0;
+ }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* begin_; //!< Original head of the string.
+ const Ch* end_; //!< End of stream.
+ size_t size_; //!< Size of the stream.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h
new file mode 100644
index 000000000..18111286b
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/inttypes.h
@@ -0,0 +1,316 @@
+// ISO C9x compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2013 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the product nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// The above software in this distribution may have been modified by
+// THL A29 Limited ("Tencent Modifications").
+// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// miloyip: VC supports inttypes.h since VC2013
+#if _MSC_VER >= 1800
+#include <inttypes.h>
+#else
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+ intmax_t quot;
+ intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8 "d"
+#define PRIi8 "i"
+#define PRIdLEAST8 "d"
+#define PRIiLEAST8 "i"
+#define PRIdFAST8 "d"
+#define PRIiFAST8 "i"
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIdLEAST16 "hd"
+#define PRIiLEAST16 "hi"
+#define PRIdFAST16 "hd"
+#define PRIiFAST16 "hi"
+
+#define PRId32 "I32d"
+#define PRIi32 "I32i"
+#define PRIdLEAST32 "I32d"
+#define PRIiLEAST32 "I32i"
+#define PRIdFAST32 "I32d"
+#define PRIiFAST32 "I32i"
+
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIdLEAST64 "I64d"
+#define PRIiLEAST64 "I64i"
+#define PRIdFAST64 "I64d"
+#define PRIiFAST64 "I64i"
+
+#define PRIdMAX "I64d"
+#define PRIiMAX "I64i"
+
+#define PRIdPTR "Id"
+#define PRIiPTR "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8 "o"
+#define PRIu8 "u"
+#define PRIx8 "x"
+#define PRIX8 "X"
+#define PRIoLEAST8 "o"
+#define PRIuLEAST8 "u"
+#define PRIxLEAST8 "x"
+#define PRIXLEAST8 "X"
+#define PRIoFAST8 "o"
+#define PRIuFAST8 "u"
+#define PRIxFAST8 "x"
+#define PRIXFAST8 "X"
+
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+#define PRIoLEAST16 "ho"
+#define PRIuLEAST16 "hu"
+#define PRIxLEAST16 "hx"
+#define PRIXLEAST16 "hX"
+#define PRIoFAST16 "ho"
+#define PRIuFAST16 "hu"
+#define PRIxFAST16 "hx"
+#define PRIXFAST16 "hX"
+
+#define PRIo32 "I32o"
+#define PRIu32 "I32u"
+#define PRIx32 "I32x"
+#define PRIX32 "I32X"
+#define PRIoLEAST32 "I32o"
+#define PRIuLEAST32 "I32u"
+#define PRIxLEAST32 "I32x"
+#define PRIXLEAST32 "I32X"
+#define PRIoFAST32 "I32o"
+#define PRIuFAST32 "I32u"
+#define PRIxFAST32 "I32x"
+#define PRIXFAST32 "I32X"
+
+#define PRIo64 "I64o"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#define PRIX64 "I64X"
+#define PRIoLEAST64 "I64o"
+#define PRIuLEAST64 "I64u"
+#define PRIxLEAST64 "I64x"
+#define PRIXLEAST64 "I64X"
+#define PRIoFAST64 "I64o"
+#define PRIuFAST64 "I64u"
+#define PRIxFAST64 "I64x"
+#define PRIXFAST64 "I64X"
+
+#define PRIoMAX "I64o"
+#define PRIuMAX "I64u"
+#define PRIxMAX "I64x"
+#define PRIXMAX "I64X"
+
+#define PRIoPTR "Io"
+#define PRIuPTR "Iu"
+#define PRIxPTR "Ix"
+#define PRIXPTR "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8 "d"
+#define SCNi8 "i"
+#define SCNdLEAST8 "d"
+#define SCNiLEAST8 "i"
+#define SCNdFAST8 "d"
+#define SCNiFAST8 "i"
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNdLEAST16 "hd"
+#define SCNiLEAST16 "hi"
+#define SCNdFAST16 "hd"
+#define SCNiFAST16 "hi"
+
+#define SCNd32 "ld"
+#define SCNi32 "li"
+#define SCNdLEAST32 "ld"
+#define SCNiLEAST32 "li"
+#define SCNdFAST32 "ld"
+#define SCNiFAST32 "li"
+
+#define SCNd64 "I64d"
+#define SCNi64 "I64i"
+#define SCNdLEAST64 "I64d"
+#define SCNiLEAST64 "I64i"
+#define SCNdFAST64 "I64d"
+#define SCNiFAST64 "I64i"
+
+#define SCNdMAX "I64d"
+#define SCNiMAX "I64i"
+
+#ifdef _WIN64 // [
+# define SCNdPTR "I64d"
+# define SCNiPTR "I64i"
+#else // _WIN64 ][
+# define SCNdPTR "ld"
+# define SCNiPTR "li"
+#endif // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8 "o"
+#define SCNu8 "u"
+#define SCNx8 "x"
+#define SCNX8 "X"
+#define SCNoLEAST8 "o"
+#define SCNuLEAST8 "u"
+#define SCNxLEAST8 "x"
+#define SCNXLEAST8 "X"
+#define SCNoFAST8 "o"
+#define SCNuFAST8 "u"
+#define SCNxFAST8 "x"
+#define SCNXFAST8 "X"
+
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+#define SCNX16 "hX"
+#define SCNoLEAST16 "ho"
+#define SCNuLEAST16 "hu"
+#define SCNxLEAST16 "hx"
+#define SCNXLEAST16 "hX"
+#define SCNoFAST16 "ho"
+#define SCNuFAST16 "hu"
+#define SCNxFAST16 "hx"
+#define SCNXFAST16 "hX"
+
+#define SCNo32 "lo"
+#define SCNu32 "lu"
+#define SCNx32 "lx"
+#define SCNX32 "lX"
+#define SCNoLEAST32 "lo"
+#define SCNuLEAST32 "lu"
+#define SCNxLEAST32 "lx"
+#define SCNXLEAST32 "lX"
+#define SCNoFAST32 "lo"
+#define SCNuFAST32 "lu"
+#define SCNxFAST32 "lx"
+#define SCNXFAST32 "lX"
+
+#define SCNo64 "I64o"
+#define SCNu64 "I64u"
+#define SCNx64 "I64x"
+#define SCNX64 "I64X"
+#define SCNoLEAST64 "I64o"
+#define SCNuLEAST64 "I64u"
+#define SCNxLEAST64 "I64x"
+#define SCNXLEAST64 "I64X"
+#define SCNoFAST64 "I64o"
+#define SCNuFAST64 "I64u"
+#define SCNxFAST64 "I64x"
+#define SCNXFAST64 "I64X"
+
+#define SCNoMAX "I64o"
+#define SCNuMAX "I64u"
+#define SCNxMAX "I64x"
+#define SCNXMAX "I64X"
+
+#ifdef _WIN64 // [
+# define SCNoPTR "I64o"
+# define SCNuPTR "I64u"
+# define SCNxPTR "I64x"
+# define SCNXPTR "I64X"
+#else // _WIN64 ][
+# define SCNoPTR "lo"
+# define SCNuPTR "lu"
+# define SCNxPTR "lx"
+# define SCNXPTR "lX"
+#endif // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ // did division wrong; must fix up
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#endif // _MSC_VER >= 1800
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h
new file mode 100644
index 000000000..a26fff4bf
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h
@@ -0,0 +1,300 @@
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2013 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the product nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// The above software in this distribution may have been modified by
+// THL A29 Limited ("Tencent Modifications").
+// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
+#if _MSC_VER >= 1600 // [
+#include <stdint.h>
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+#undef INT8_C
+#undef INT16_C
+#undef INT32_C
+#undef INT64_C
+#undef UINT8_C
+#undef UINT16_C
+#undef UINT32_C
+#undef UINT64_C
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C // [
+# define INTMAX_C INT64_C
+#endif // INTMAX_C ]
+#ifndef UINTMAX_C // [
+# define UINTMAX_C UINT64_C
+#endif // UINTMAX_C ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#else // ] _MSC_VER >= 1700 [
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+# include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+#else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+#endif
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef signed __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef _W64 signed int intptr_t;
+ typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C // [
+# define INTMAX_C INT64_C
+#endif // INTMAX_C ]
+#ifndef UINTMAX_C // [
+# define UINTMAX_C UINT64_C
+#endif // UINTMAX_C ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_VER >= 1600 ]
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h
new file mode 100644
index 000000000..5d2aa8d63
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h
@@ -0,0 +1,1313 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POINTER_H_
+#define RAPIDJSON_POINTER_H_
+
+#include "document.h"
+#include "internal/itoa.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+ \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
+*/
+enum PointerParseErrorCode {
+ kPointerParseErrorNone = 0, //!< The parse is successful
+
+ kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
+ kPointerParseErrorInvalidEscape, //!< Invalid escape
+ kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
+ kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericPointer
+
+//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
+/*!
+ This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
+ (https://tools.ietf.org/html/rfc6901).
+
+ A JSON pointer is for identifying a specific value in a JSON document
+ (GenericDocument). It can simplify coding of DOM tree manipulation, because it
+ can access multiple-level depth of DOM tree with single API call.
+
+ After it parses a string representation (e.g. "/foo/0" or URI fragment
+ representation (e.g. "#/foo/0") into its internal representation (tokens),
+ it can be used to resolve a specific value in multiple documents, or sub-tree
+ of documents.
+
+ Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
+ Apart from assignment, a Pointer cannot be modified after construction.
+
+ Although Pointer is very convenient, please aware that constructing Pointer
+ involves parsing and dynamic memory allocation. A special constructor with user-
+ supplied tokens eliminates these.
+
+ GenericPointer depends on GenericDocument and GenericValue.
+
+ \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
+ \tparam Allocator The allocator type for allocating memory for internal representation.
+
+ \note GenericPointer uses same encoding of ValueType.
+ However, Allocator of GenericPointer is independent of Allocator of Value.
+*/
+template <typename ValueType, typename Allocator = CrtAllocator>
+class GenericPointer {
+public:
+ typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
+ typedef typename EncodingType::Ch Ch; //!< Character type from Value
+
+ //! A token is the basic units of internal representation.
+ /*!
+ A JSON pointer string representation "/foo/123" is parsed to two tokens:
+ "foo" and 123. 123 will be represented in both numeric form and string form.
+ They are resolved according to the actual value type (object or array).
+
+ For token that are not numbers, or the numeric value is out of bound
+ (greater than limits of SizeType), they are only treated as string form
+ (i.e. the token's index will be equal to kPointerInvalidIndex).
+
+ This struct is public so that user can create a Pointer without parsing and
+ allocation, using a special constructor.
+ */
+ struct Token {
+ const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
+ SizeType length; //!< Length of the name.
+ SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
+ };
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor.
+ GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+
+ //! Constructor that parses a string or URI fragment representation.
+ /*!
+ \param source A null-terminated, string or URI fragment representation of JSON pointer.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ */
+ explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source, internal::StrLen(source));
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor that parses a string or URI fragment representation.
+ /*!
+ \param source A string or URI fragment representation of JSON pointer.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source.c_str(), source.size());
+ }
+#endif
+
+ //! Constructor that parses a string or URI fragment representation, with length of the source string.
+ /*!
+ \param source A string or URI fragment representation of JSON pointer.
+ \param length Length of source.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ \note Slightly faster than the overload without length.
+ */
+ GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source, length);
+ }
+
+ //! Constructor with user-supplied tokens.
+ /*!
+ This constructor let user supplies const array of tokens.
+ This prevents the parsing process and eliminates allocation.
+ This is preferred for memory constrained environments.
+
+ \param tokens An constant array of tokens representing the JSON pointer.
+ \param tokenCount Number of tokens.
+
+ \b Example
+ \code
+ #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
+ #define INDEX(i) { #i, sizeof(#i) - 1, i }
+
+ static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
+ static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
+ // Equivalent to static const Pointer p("/foo/123");
+
+ #undef NAME
+ #undef INDEX
+ \endcode
+ */
+ GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+
+ //! Copy constructor.
+ GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ *this = rhs;
+ }
+
+ //! Destructor.
+ ~GenericPointer() {
+ if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
+ Allocator::Free(tokens_);
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ //! Assignment operator.
+ GenericPointer& operator=(const GenericPointer& rhs) {
+ if (this != &rhs) {
+ // Do not delete ownAllcator
+ if (nameBuffer_)
+ Allocator::Free(tokens_);
+
+ tokenCount_ = rhs.tokenCount_;
+ parseErrorOffset_ = rhs.parseErrorOffset_;
+ parseErrorCode_ = rhs.parseErrorCode_;
+
+ if (rhs.nameBuffer_)
+ CopyFromRaw(rhs); // Normally parsed tokens.
+ else {
+ tokens_ = rhs.tokens_; // User supplied const tokens.
+ nameBuffer_ = 0;
+ }
+ }
+ return *this;
+ }
+
+ //@}
+
+ //!@name Append token
+ //@{
+
+ //! Append a token and return a new Pointer
+ /*!
+ \param token Token to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
+ GenericPointer r;
+ r.allocator_ = allocator;
+ Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
+ std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
+ r.tokens_[tokenCount_].name = p;
+ r.tokens_[tokenCount_].length = token.length;
+ r.tokens_[tokenCount_].index = token.index;
+ return r;
+ }
+
+ //! Append a name token with length, and return a new Pointer
+ /*!
+ \param name Name to be appended.
+ \param length Length of name.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
+ Token token = { name, length, kPointerInvalidIndex };
+ return Append(token, allocator);
+ }
+
+ //! Append a name token without length, and return a new Pointer
+ /*!
+ \param name Name (const Ch*) to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
+ Append(T* name, Allocator* allocator = 0) const {
+ return Append(name, StrLen(name), allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Append a name token, and return a new Pointer
+ /*!
+ \param name Name to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
+ return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
+ }
+#endif
+
+ //! Append a index token, and return a new Pointer
+ /*!
+ \param index Index to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
+ char buffer[21];
+ SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer;
+ buffer[length] = '\0';
+
+ if (sizeof(Ch) == 1) {
+ Token token = { (Ch*)buffer, length, index };
+ return Append(token, allocator);
+ }
+ else {
+ Ch name[21];
+ for (size_t i = 0; i <= length; i++)
+ name[i] = buffer[i];
+ Token token = { name, length, index };
+ return Append(token, allocator);
+ }
+ }
+
+ //! Append a token by value, and return a new Pointer
+ /*!
+ \param value Value (either Uint or String) to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
+ if (token.IsString())
+ return Append(token.GetString(), token.GetStringLength(), allocator);
+ else {
+ RAPIDJSON_ASSERT(token.IsUint64());
+ RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
+ return Append(static_cast<SizeType>(token.GetUint64()), allocator);
+ }
+ }
+
+ //!@name Handling Parse Error
+ //@{
+
+ //! Check whether this is a valid pointer.
+ bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
+
+ //! Get the parsing error offset in code unit.
+ size_t GetParseErrorOffset() const { return parseErrorOffset_; }
+
+ //! Get the parsing error code.
+ PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
+
+ //@}
+
+ //!@name Tokens
+ //@{
+
+ //! Get the token array (const version only).
+ const Token* GetTokens() const { return tokens_; }
+
+ //! Get the number of tokens.
+ size_t GetTokenCount() const { return tokenCount_; }
+
+ //@}
+
+ //!@name Equality/inequality operators
+ //@{
+
+ //! Equality operator.
+ /*!
+ \note When any pointers are invalid, always returns false.
+ */
+ bool operator==(const GenericPointer& rhs) const {
+ if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
+ return false;
+
+ for (size_t i = 0; i < tokenCount_; i++) {
+ if (tokens_[i].index != rhs.tokens_[i].index ||
+ tokens_[i].length != rhs.tokens_[i].length ||
+ (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //! Inequality operator.
+ /*!
+ \note When any pointers are invalid, always returns true.
+ */
+ bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
+
+ //@}
+
+ //!@name Stringify
+ //@{
+
+ //! Stringify the pointer into string representation.
+ /*!
+ \tparam OutputStream Type of output stream.
+ \param os The output stream.
+ */
+ template<typename OutputStream>
+ bool Stringify(OutputStream& os) const {
+ return Stringify<false, OutputStream>(os);
+ }
+
+ //! Stringify the pointer into URI fragment representation.
+ /*!
+ \tparam OutputStream Type of output stream.
+ \param os The output stream.
+ */
+ template<typename OutputStream>
+ bool StringifyUriFragment(OutputStream& os) const {
+ return Stringify<true, OutputStream>(os);
+ }
+
+ //@}
+
+ //!@name Create value
+ //@{
+
+ //! Create a value in a subtree.
+ /*!
+ If the value is not exist, it creates all parent values and a JSON Null value.
+ So it always succeed and return the newly created or existing value.
+
+ Remind that it may change types of parents according to tokens, so it
+ potentially removes previously stored values. For example, if a document
+ was an array, and "/foo" is used to create a value, then the document
+ will be changed to an object, and all existing array elements are lost.
+
+ \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
+ \return The resolved newly created (a JSON Null value), or already exists value.
+ */
+ ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
+ RAPIDJSON_ASSERT(IsValid());
+ ValueType* v = &root;
+ bool exist = true;
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
+ v->PushBack(Value().Move(), allocator);
+ v = &((*v)[v->Size() - 1]);
+ exist = false;
+ }
+ else {
+ if (t->index == kPointerInvalidIndex) { // must be object name
+ if (!v->IsObject())
+ v->SetObject(); // Change to Object
+ }
+ else { // object name or array index
+ if (!v->IsArray() && !v->IsObject())
+ v->SetArray(); // Change to Array
+ }
+
+ if (v->IsArray()) {
+ if (t->index >= v->Size()) {
+ v->Reserve(t->index + 1, allocator);
+ while (t->index >= v->Size())
+ v->PushBack(Value().Move(), allocator);
+ exist = false;
+ }
+ v = &((*v)[t->index]);
+ }
+ else {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd()) {
+ v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator);
+ v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
+ exist = false;
+ }
+ else
+ v = &m->value;
+ }
+ }
+ }
+
+ if (alreadyExist)
+ *alreadyExist = exist;
+
+ return *v;
+ }
+
+ //! Creates a value in a document.
+ /*!
+ \param document A document to be resolved.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
+ \return The resolved newly created, or already exists value.
+ */
+ template <typename stackAllocator>
+ ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
+ return Create(document, document.GetAllocator(), alreadyExist);
+ }
+
+ //@}
+
+ //!@name Query value
+ //@{
+
+ //! Query a value in a subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Pointer to the value if it can be resolved. Otherwise null.
+ */
+ ValueType* Get(ValueType& root) const {
+ RAPIDJSON_ASSERT(IsValid());
+ ValueType* v = &root;
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ switch (v->GetType()) {
+ case kObjectType:
+ {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd())
+ return 0;
+ v = &m->value;
+ }
+ break;
+ case kArrayType:
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
+ return 0;
+ v = &((*v)[t->index]);
+ break;
+ default:
+ return 0;
+ }
+ }
+ return v;
+ }
+
+ //! Query a const value in a const subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Pointer to the value if it can be resolved. Otherwise null.
+ */
+ const ValueType* Get(const ValueType& root) const { return Get(const_cast<ValueType&>(root)); }
+
+ //@}
+
+ //!@name Query a value with default
+ //@{
+
+ //! Query a value in a subtree with default value.
+ /*!
+ Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
+ So that this function always succeed.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param defaultValue Default value to be cloned if the value was not exists.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
+ }
+
+ //! Query a value in a subtree with default null-terminated string.
+ ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Query a value in a subtree with default std::basic_string.
+ ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
+ }
+#endif
+
+ //! Query a value in a subtree with default primitive value.
+ /*!
+ \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
+ return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
+ }
+
+ //! Query a value in a document with default value.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+ //! Query a value in a document with default null-terminated string.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Query a value in a document with default std::basic_string.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+#endif
+
+ //! Query a value in a document with default primitive value.
+ /*!
+ \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T, typename stackAllocator>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+ //@}
+
+ //!@name Set a value
+ //@{
+
+ //! Set a value in a subtree, with move semantics.
+ /*!
+ It creates all parents if they are not exist or types are different to the tokens.
+ So this function always succeeds but potentially remove existing values.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param value Value to be set.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = value;
+ }
+
+ //! Set a value in a subtree, with copy semantics.
+ ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator).CopyFrom(value, allocator);
+ }
+
+ //! Set a null-terminated string in a subtree.
+ ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value, allocator).Move();
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set a std::basic_string in a subtree.
+ ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value, allocator).Move();
+ }
+#endif
+
+ //! Set a primitive value in a subtree.
+ /*!
+ \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value).Move();
+ }
+
+ //! Set a value in a document, with move semantics.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
+ return Create(document) = value;
+ }
+
+ //! Set a value in a document, with copy semantics.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
+ return Create(document).CopyFrom(value, document.GetAllocator());
+ }
+
+ //! Set a null-terminated string in a document.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Sets a std::basic_string in a document.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
+ }
+#endif
+
+ //! Set a primitive value in a document.
+ /*!
+ \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T, typename stackAllocator>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
+ return Create(document) = value;
+ }
+
+ //@}
+
+ //!@name Swap a value
+ //@{
+
+ //! Swap a value with a value in a subtree.
+ /*!
+ It creates all parents if they are not exist or types are different to the tokens.
+ So this function always succeeds but potentially remove existing values.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param value Value to be swapped.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator).Swap(value);
+ }
+
+ //! Swap a value with a value in a document.
+ template <typename stackAllocator>
+ ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
+ return Create(document).Swap(value);
+ }
+
+ //@}
+
+ //! Erase a value in a subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Whether the resolved value is found and erased.
+
+ \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
+ */
+ bool Erase(ValueType& root) const {
+ RAPIDJSON_ASSERT(IsValid());
+ if (tokenCount_ == 0) // Cannot erase the root
+ return false;
+
+ ValueType* v = &root;
+ const Token* last = tokens_ + (tokenCount_ - 1);
+ for (const Token *t = tokens_; t != last; ++t) {
+ switch (v->GetType()) {
+ case kObjectType:
+ {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd())
+ return false;
+ v = &m->value;
+ }
+ break;
+ case kArrayType:
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
+ return false;
+ v = &((*v)[t->index]);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ switch (v->GetType()) {
+ case kObjectType:
+ return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
+ case kArrayType:
+ if (last->index == kPointerInvalidIndex || last->index >= v->Size())
+ return false;
+ v->Erase(v->Begin() + last->index);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+private:
+ //! Clone the content from rhs to this.
+ /*!
+ \param rhs Source pointer.
+ \param extraToken Extra tokens to be allocated.
+ \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
+ \return Start of non-occupied name buffer, for storing extra names.
+ */
+ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
+ if (!allocator_) // allocator is independently owned.
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
+ for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
+ nameBufferSize += t->length;
+
+ tokenCount_ = rhs.tokenCount_ + extraToken;
+ tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
+ nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
+ std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
+ std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
+
+ // Adjust pointers to name buffer
+ std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
+ for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
+ t->name += diff;
+
+ return nameBuffer_ + nameBufferSize;
+ }
+
+ //! Check whether a character should be percent-encoded.
+ /*!
+ According to RFC 3986 2.3 Unreserved Characters.
+ \param c The character (code unit) to be tested.
+ */
+ bool NeedPercentEncode(Ch c) const {
+ return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
+ }
+
+ //! Parse a JSON String or its URI fragment representation into tokens.
+ /*!
+ \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
+ \param length Length of the source string.
+ \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
+ */
+ void Parse(const Ch* source, size_t length) {
+ RAPIDJSON_ASSERT(source != NULL);
+ RAPIDJSON_ASSERT(nameBuffer_ == 0);
+ RAPIDJSON_ASSERT(tokens_ == 0);
+
+ // Create own allocator if user did not supply.
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ // Count number of '/' as tokenCount
+ tokenCount_ = 0;
+ for (const Ch* s = source; s != source + length; s++)
+ if (*s == '/')
+ tokenCount_++;
+
+ Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
+ Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
+ size_t i = 0;
+
+ // Detect if it is a URI fragment
+ bool uriFragment = false;
+ if (source[i] == '#') {
+ uriFragment = true;
+ i++;
+ }
+
+ if (i != length && source[i] != '/') {
+ parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
+ goto error;
+ }
+
+ while (i < length) {
+ RAPIDJSON_ASSERT(source[i] == '/');
+ i++; // consumes '/'
+
+ token->name = name;
+ bool isNumber = true;
+
+ while (i < length && source[i] != '/') {
+ Ch c = source[i];
+ if (uriFragment) {
+ // Decoding percent-encoding for URI fragment
+ if (c == '%') {
+ PercentDecodeStream is(&source[i], source + length);
+ GenericInsituStringStream<EncodingType> os(name);
+ Ch* begin = os.PutBegin();
+ if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
+ parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
+ goto error;
+ }
+ size_t len = os.PutEnd(begin);
+ i += is.Tell() - 1;
+ if (len == 1)
+ c = *name;
+ else {
+ name += len;
+ isNumber = false;
+ i++;
+ continue;
+ }
+ }
+ else if (NeedPercentEncode(c)) {
+ parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
+ goto error;
+ }
+ }
+
+ i++;
+
+ // Escaping "~0" -> '~', "~1" -> '/'
+ if (c == '~') {
+ if (i < length) {
+ c = source[i];
+ if (c == '0') c = '~';
+ else if (c == '1') c = '/';
+ else {
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
+ goto error;
+ }
+ i++;
+ }
+ else {
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
+ goto error;
+ }
+ }
+
+ // First check for index: all of characters are digit
+ if (c < '0' || c > '9')
+ isNumber = false;
+
+ *name++ = c;
+ }
+ token->length = name - token->name;
+ if (token->length == 0)
+ isNumber = false;
+ *name++ = '\0'; // Null terminator
+
+ // Second check for index: more than one digit cannot have leading zero
+ if (isNumber && token->length > 1 && token->name[0] == '0')
+ isNumber = false;
+
+ // String to SizeType conversion
+ SizeType n = 0;
+ if (isNumber) {
+ for (size_t j = 0; j < token->length; j++) {
+ SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
+ if (m < n) { // overflow detection
+ isNumber = false;
+ break;
+ }
+ n = m;
+ }
+ }
+
+ token->index = isNumber ? n : kPointerInvalidIndex;
+ token++;
+ }
+
+ RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
+ parseErrorCode_ = kPointerParseErrorNone;
+ return;
+
+ error:
+ Allocator::Free(tokens_);
+ nameBuffer_ = 0;
+ tokens_ = 0;
+ tokenCount_ = 0;
+ parseErrorOffset_ = i;
+ return;
+ }
+
+ //! Stringify to string or URI fragment representation.
+ /*!
+ \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
+ \tparam OutputStream type of output stream.
+ \param os The output stream.
+ */
+ template<bool uriFragment, typename OutputStream>
+ bool Stringify(OutputStream& os) const {
+ RAPIDJSON_ASSERT(IsValid());
+
+ if (uriFragment)
+ os.Put('#');
+
+ for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ os.Put('/');
+ for (size_t j = 0; j < t->length; j++) {
+ Ch c = t->name[j];
+ if (c == '~') {
+ os.Put('~');
+ os.Put('0');
+ }
+ else if (c == '/') {
+ os.Put('~');
+ os.Put('1');
+ }
+ else if (uriFragment && NeedPercentEncode(c)) {
+ // Transcode to UTF8 sequence
+ GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
+ PercentEncodeStream<OutputStream> target(os);
+ if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
+ return false;
+ j += source.Tell() - 1;
+ }
+ else
+ os.Put(c);
+ }
+ }
+ return true;
+ }
+
+ //! A helper stream for decoding a percent-encoded sequence into code unit.
+ /*!
+ This stream decodes %XY triplet into code unit (0-255).
+ If it encounters invalid characters, it sets output code unit as 0 and
+ mark invalid, and to be checked by IsValid().
+ */
+ class PercentDecodeStream {
+ public:
+ //! Constructor
+ /*!
+ \param source Start of the stream
+ \param end Past-the-end of the stream.
+ */
+ PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
+
+ Ch Take() {
+ if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
+ valid_ = false;
+ return 0;
+ }
+ src_++;
+ Ch c = 0;
+ for (int j = 0; j < 2; j++) {
+ c <<= 4;
+ Ch h = *src_;
+ if (h >= '0' && h <= '9') c += h - '0';
+ else if (h >= 'A' && h <= 'F') c += h - 'A' + 10;
+ else if (h >= 'a' && h <= 'f') c += h - 'a' + 10;
+ else {
+ valid_ = false;
+ return 0;
+ }
+ src_++;
+ }
+ return c;
+ }
+
+ size_t Tell() const { return src_ - head_; }
+ bool IsValid() const { return valid_; }
+
+ private:
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+ const Ch* end_; //!< Past-the-end position.
+ bool valid_; //!< Whether the parsing is valid.
+ };
+
+ //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
+ template <typename OutputStream>
+ class PercentEncodeStream {
+ public:
+ PercentEncodeStream(OutputStream& os) : os_(os) {}
+ void Put(char c) { // UTF-8 must be byte
+ unsigned char u = static_cast<unsigned char>(c);
+ static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ os_.Put('%');
+ os_.Put(hexDigits[u >> 4]);
+ os_.Put(hexDigits[u & 15]);
+ }
+ private:
+ OutputStream& os_;
+ };
+
+ Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
+ Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
+ Ch* nameBuffer_; //!< A buffer containing all names in tokens.
+ Token* tokens_; //!< A list of tokens.
+ size_t tokenCount_; //!< Number of tokens in tokens_.
+ size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
+ PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
+};
+
+//! GenericPointer for Value (UTF-8, default allocator).
+typedef GenericPointer<Value> Pointer;
+
+//!@name Helper functions for GenericPointer
+//@{
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
+ return pointer.Create(root, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
+ return pointer.Create(document);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
+ return pointer.Get(root);
+}
+
+template <typename T>
+const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer) {
+ return pointer.Get(root);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root);
+}
+
+template <typename T, typename CharType, size_t N>
+const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+#endif
+
+template <typename T, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+#endif
+
+template <typename T, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+#endif
+
+template <typename DocumentType, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+#endif
+
+template <typename DocumentType, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+#endif
+
+template <typename T, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+#endif
+
+template <typename T, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
+ return pointer.Set(document, value);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
+ return pointer.Set(document, value);
+}
+#endif
+
+template <typename DocumentType, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+#endif
+
+template <typename DocumentType, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Swap(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
+ return pointer.Swap(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
+ return pointer.Erase(root);
+}
+
+template <typename T, typename CharType, size_t N>
+bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
+}
+
+//@}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POINTER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h
new file mode 100644
index 000000000..416dd492e
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h
@@ -0,0 +1,207 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Writer with indentation and spacing.
+/*!
+ \tparam OutputStream Type of ouptut os.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
+public:
+ typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+ typedef typename Base::Ch Ch;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param allocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+ //! Set custom indentation.
+ /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
+ \param indentCharCount Number of indent characters for each indentation level.
+ \note The default indentation is 4 spaces.
+ */
+ PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+ RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+ indentChar_ = indentChar;
+ indentCharCount_ = indentCharCount;
+ return *this;
+ }
+
+ /*! @name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
+ bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
+ bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
+ bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
+ bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
+ bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
+ bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kStringType);
+ return Base::WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ PrettyPrefix(kObjectType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+ return Base::WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndObject();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ bool StartArray() {
+ PrettyPrefix(kArrayType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+ return Base::WriteStartArray();
+ }
+
+ bool EndArray(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndArray();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! Simpler but slower overload.
+ bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+ //@}
+protected:
+ void PrettyPrefix(Type type) {
+ (void)type;
+ if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+ typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+ if (level->inArray) {
+ if (level->valueCount > 0) {
+ Base::os_->Put(','); // add comma if it is not the first element in array
+ Base::os_->Put('\n');
+ }
+ else
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ else { // in object
+ if (level->valueCount > 0) {
+ if (level->valueCount % 2 == 0) {
+ Base::os_->Put(',');
+ Base::os_->Put('\n');
+ }
+ else {
+ Base::os_->Put(':');
+ Base::os_->Put(' ');
+ }
+ }
+ else
+ Base::os_->Put('\n');
+
+ if (level->valueCount % 2 == 0)
+ WriteIndent();
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
+ Base::hasRoot_ = true;
+ }
+ }
+
+ void WriteIndent() {
+ size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
+ PutN(*Base::os_, indentChar_, count);
+ }
+
+ Ch indentChar_;
+ unsigned indentCharCount_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ PrettyWriter(const PrettyWriter&);
+ PrettyWriter& operator=(const PrettyWriter&);
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h
new file mode 100644
index 000000000..b83f8e22f
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h
@@ -0,0 +1,654 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+/*!\file rapidjson.h
+ \brief common definitions and configuration
+
+ \see RAPIDJSON_CONFIG
+ */
+
+/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
+ \brief Configuration macros for library features
+
+ Some RapidJSON features are configurable to adapt the library to a wide
+ variety of platforms, environments and usage scenarios. Most of the
+ features can be configured in terms of overriden or predefined
+ preprocessor macros at compile-time.
+
+ Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
+
+ \note These macros should be given on the compiler command-line
+ (where applicable) to avoid inconsistent values when compiling
+ different translation units of a single application.
+ */
+
+#include <cstdlib> // malloc(), realloc(), free(), size_t
+#include <cstring> // memset(), memcpy(), memmove(), memcmp()
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_VERSION_STRING
+//
+// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
+//
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+// token stringification
+#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
+#define RAPIDJSON_DO_STRINGIFY(x) #x
+//!@endcond
+
+/*! \def RAPIDJSON_MAJOR_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Major version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_MINOR_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Minor version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_PATCH_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Patch version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_VERSION_STRING
+ \ingroup RAPIDJSON_CONFIG
+ \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
+*/
+#define RAPIDJSON_MAJOR_VERSION 1
+#define RAPIDJSON_MINOR_VERSION 0
+#define RAPIDJSON_PATCH_VERSION 2
+#define RAPIDJSON_VERSION_STRING \
+ RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NAMESPACE_(BEGIN|END)
+/*! \def RAPIDJSON_NAMESPACE
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace
+
+ In order to avoid symbol clashes and/or "One Definition Rule" errors
+ between multiple inclusions of (different versions of) RapidJSON in
+ a single binary, users can customize the name of the main RapidJSON
+ namespace.
+
+ In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
+ to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple
+ levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
+ RAPIDJSON_NAMESPACE_END need to be defined as well:
+
+ \code
+ // in some .cpp file
+ #define RAPIDJSON_NAMESPACE my::rapidjson
+ #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
+ #define RAPIDJSON_NAMESPACE_END } }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson
+ */
+/*! \def RAPIDJSON_NAMESPACE_BEGIN
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (opening expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+/*! \def RAPIDJSON_NAMESPACE_END
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (closing expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+#ifndef RAPIDJSON_NAMESPACE
+#define RAPIDJSON_NAMESPACE rapidjson
+#endif
+#ifndef RAPIDJSON_NAMESPACE_BEGIN
+#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
+#endif
+#ifndef RAPIDJSON_NAMESPACE_END
+#define RAPIDJSON_NAMESPACE_END }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_INT64DEFINE
+
+/*! \def RAPIDJSON_NO_INT64DEFINE
+ \ingroup RAPIDJSON_CONFIG
+ \brief Use external 64-bit integer types.
+
+ RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types
+ to be available at global scope.
+
+ If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
+ prevent RapidJSON from defining its own types.
+*/
+#ifndef RAPIDJSON_NO_INT64DEFINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#ifdef _MSC_VER
+#include "msinttypes/stdint.h"
+#include "msinttypes/inttypes.h"
+#else
+// Other compilers should have this.
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+//!@endcond
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_INT64DEFINE
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_FORCEINLINE
+
+#ifndef RAPIDJSON_FORCEINLINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#if defined(_MSC_VER) && !defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
+#else
+#define RAPIDJSON_FORCEINLINE
+#endif
+//!@endcond
+#endif // RAPIDJSON_FORCEINLINE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
+
+//! Endianness of the machine.
+/*!
+ \def RAPIDJSON_ENDIAN
+ \ingroup RAPIDJSON_CONFIG
+
+ GCC 4.6 provided macro for detecting endianness of the target machine. But other
+ compilers may not have this. User can define RAPIDJSON_ENDIAN to either
+ \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
+
+ Default detection implemented with reference to
+ \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
+ \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
+*/
+#ifndef RAPIDJSON_ENDIAN
+// Detect with GCC 4.6's macro
+# ifdef __BYTE_ORDER__
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif // __BYTE_ORDER__
+// Detect with GLIBC's endian.h
+# elif defined(__GLIBC__)
+# include <endian.h>
+# if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif (__BYTE_ORDER == __BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif // __GLIBC__
+// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
+# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+// Detect with architecture macros
+# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
+# define RAPIDJSON_ENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_64BIT
+
+//! Whether using 64-bit architecture
+#ifndef RAPIDJSON_64BIT
+#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__)
+#define RAPIDJSON_64BIT 1
+#else
+#define RAPIDJSON_64BIT 0
+#endif
+#endif // RAPIDJSON_64BIT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ALIGN
+
+//! Data alignment of the machine.
+/*! \ingroup RAPIDJSON_CONFIG
+ \param x pointer to align
+
+ Some machines require strict data alignment. Currently the default uses 4 bytes
+ alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.
+*/
+#ifndef RAPIDJSON_ALIGN
+#if RAPIDJSON_64BIT == 1
+#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
+#else
+#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_UINT64_C2
+
+//! Construct a 64-bit literal by a pair of 32-bit integer.
+/*!
+ 64-bit literal with or without ULL suffix is prone to compiler warnings.
+ UINT64_C() is C macro which cause compilation problems.
+ Use this macro to define 64-bit constants by a pair of 32-bit integer.
+*/
+#ifndef RAPIDJSON_UINT64_C2
+#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+/*! \def RAPIDJSON_SIMD
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable SSE2/SSE4.2 optimization.
+
+ RapidJSON supports optimized implementations for some parsing operations
+ based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
+ processors.
+
+ To enable these optimizations, two different symbols can be defined;
+ \code
+ // Enable SSE2 optimization.
+ #define RAPIDJSON_SSE2
+
+ // Enable SSE4.2 optimization.
+ #define RAPIDJSON_SSE42
+ \endcode
+
+ \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+
+ If any of these symbols is defined, RapidJSON defines the macro
+ \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
+*/
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
+ || defined(RAPIDJSON_DOXYGEN_RUNNING)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
+/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-provided \c SizeType definition.
+
+ In order to avoid using 32-bit size types for indexing strings and arrays,
+ define this preprocessor symbol and provide the type rapidjson::SizeType
+ before including RapidJSON:
+ \code
+ #define RAPIDJSON_NO_SIZETYPEDEFINE
+ namespace rapidjson { typedef ::std::size_t SizeType; }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson::SizeType
+*/
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_SIZETYPEDEFINE
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+//! Size type (for string lengths, array sizes, etc.)
+/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
+ instead of using \c size_t. Users may override the SizeType by defining
+ \ref RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+RAPIDJSON_NAMESPACE_END
+#endif
+
+// always import std::size_t to rapidjson namespace
+RAPIDJSON_NAMESPACE_BEGIN
+using std::size_t;
+RAPIDJSON_NAMESPACE_END
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! \ingroup RAPIDJSON_CONFIG
+ By default, rapidjson uses C \c assert() for internal assertions.
+ User can override it by defining RAPIDJSON_ASSERT(x) macro.
+
+ \note Parsing errors are handled and can be customized by the
+ \ref RAPIDJSON_ERRORS APIs.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_STATIC_ASSERT
+
+// Adopt from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+RAPIDJSON_NAMESPACE_BEGIN
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+template<int x> struct StaticAssertTest {};
+RAPIDJSON_NAMESPACE_END
+
+#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
+#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
+#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
+
+#if defined(__GNUC__)
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+#else
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+//!@endcond
+
+/*! \def RAPIDJSON_STATIC_ASSERT
+ \brief (Internal) macro to check for conditions at compile-time
+ \param x compile-time condition
+ \hideinitializer
+ */
+#define RAPIDJSON_STATIC_ASSERT(x) \
+ typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
+ sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
+ RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+// adopted from Boost
+#define RAPIDJSON_VERSION_CODE(x,y,z) \
+ (((x)*100000) + ((y)*100) + (z))
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
+
+#if defined(__GNUC__)
+#define RAPIDJSON_GNUC \
+ RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
+
+#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
+#define RAPIDJSON_DIAG_OFF(x) \
+ RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
+
+// push/pop support in Clang and GCC>=4.6
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
+#else // GCC >= 4.2, < 4.6
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+#endif
+
+#elif defined(_MSC_VER)
+
+// pragma (MSVC specific)
+#define RAPIDJSON_PRAGMA(x) __pragma(x)
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
+
+#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
+
+#else
+
+#define RAPIDJSON_DIAG_OFF(x) /* ignored */
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+
+#endif // RAPIDJSON_DIAG_*
+
+///////////////////////////////////////////////////////////////////////////////
+// C++11 features
+
+#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \
+ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
+// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#else
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
+#endif
+#endif
+#if RAPIDJSON_HAS_CXX11_NOEXCEPT
+#define RAPIDJSON_NOEXCEPT noexcept
+#else
+#define RAPIDJSON_NOEXCEPT /* noexcept */
+#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
+
+// no automatic detection, yet
+#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
+#endif
+
+//!@endcond
+
+///////////////////////////////////////////////////////////////////////////////
+// new/delete
+
+#ifndef RAPIDJSON_NEW
+///! customization point for global \c new
+#define RAPIDJSON_NEW(x) new x
+#endif
+#ifndef RAPIDJSON_DELETE
+///! customization point for global \c delete
+#define RAPIDJSON_DELETE(x) delete x
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocators and Encodings
+
+#include "allocators.h"
+#include "encodings.h"
+
+/*! \namespace rapidjson
+ \brief main RapidJSON namespace
+ \see RAPIDJSON_NAMESPACE
+*/
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Stream
+
+/*! \class rapidjson::Stream
+ \brief Concept for reading and writing characters.
+
+ For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
+
+ For write-only stream, only need to implement Put() and Flush().
+
+\code
+concept Stream {
+ typename Ch; //!< Character type of the stream.
+
+ //! Read the current character from stream without moving the read cursor.
+ Ch Peek() const;
+
+ //! Read the current character from stream and moving the read cursor to next character.
+ Ch Take();
+
+ //! Get the current read cursor.
+ //! \return Number of characters read from start.
+ size_t Tell();
+
+ //! Begin writing operation at the current read pointer.
+ //! \return The begin writer pointer.
+ Ch* PutBegin();
+
+ //! Write a character.
+ void Put(Ch c);
+
+ //! Flush the buffer.
+ void Flush();
+
+ //! End the writing operation.
+ //! \param begin The begin write pointer returned by PutBegin().
+ //! \return Number of characters written.
+ size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Provides additional information for stream.
+/*!
+ By using traits pattern, this type provides a default configuration for stream.
+ For custom stream, this type can be specialized for other configuration.
+ See TEST(Reader, CustomStringStream) in readertest.cpp for example.
+*/
+template<typename Stream>
+struct StreamTraits {
+ //! Whether to make local copy of stream for optimization during parsing.
+ /*!
+ By default, for safety, streams do not use local copy optimization.
+ Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
+ */
+ enum { copyOptimization = 0 };
+};
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+ for (size_t i = 0; i < n; i++)
+ stream.Put(c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+ Ch Peek() const { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! String stream with UTF8 encoding.
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+ \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+ // Read
+ Ch Peek() { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() { return static_cast<size_t>(src_ - head_); }
+
+ // Write
+ void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
+
+ Ch* PutBegin() { return dst_ = src_; }
+ size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
+ void Flush() {}
+
+ Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
+ void Pop(size_t count) { dst_ -= count; }
+
+ Ch* src_;
+ Ch* dst_;
+ Ch* head_;
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericInsituStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! Insitu string stream with UTF8 encoding.
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+//! Type of JSON value
+enum Type {
+ kNullType = 0, //!< null
+ kFalseType = 1, //!< false
+ kTrueType = 2, //!< true
+ kObjectType = 3, //!< object
+ kArrayType = 4, //!< array
+ kStringType = 5, //!< string
+ kNumberType = 6 //!< number
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h
new file mode 100644
index 000000000..6fb29e908
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h
@@ -0,0 +1,1510 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+/*! \file reader.h */
+
+#include "rapidjson.h"
+#include "encodings.h"
+#include "internal/meta.h"
+#include "internal/stack.h"
+#include "internal/strtod.h"
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define RAPIDJSON_NOTHING /* deliberately empty */
+#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ if (HasParseError()) { return value; } \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
+//!@endcond
+
+/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
+ \ingroup RAPIDJSON_ERRORS
+ \brief Macro to indicate a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ This macros can be used as a customization point for the internal
+ error handling mechanism of RapidJSON.
+
+ A common usage model is to throw an exception instead of requiring the
+ caller to explicitly check the \ref rapidjson::GenericReader::Parse's
+ return value:
+
+ \code
+ #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
+ throw ParseException(parseErrorCode, #parseErrorCode, offset)
+
+ #include <stdexcept> // std::runtime_error
+ #include "rapidjson/error/error.h" // rapidjson::ParseResult
+
+ struct ParseException : std::runtime_error, rapidjson::ParseResult {
+ ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
+ : std::runtime_error(msg), ParseResult(code, offset) {}
+ };
+
+ #include "rapidjson/reader.h"
+ \endcode
+
+ \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
+ */
+#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
+#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
+ SetParseError(parseErrorCode, offset); \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+/*! \def RAPIDJSON_PARSE_ERROR
+ \ingroup RAPIDJSON_ERRORS
+ \brief (Internal) macro to indicate and handle a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
+
+ \see RAPIDJSON_PARSE_ERROR_NORETURN
+ \hideinitializer
+ */
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+#include "error/error.h" // ParseErrorCode, ParseResult
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kParseDefaultFlags definition.
+
+ User can define this as any \c ParseFlag combinations.
+*/
+#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
+#endif
+
+//! Combination of parseFlags
+/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
+ */
+enum ParseFlag {
+ kParseNoFlags = 0, //!< No flags are set.
+ kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
+ kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
+ kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
+ kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
+ kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
+ kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
+ kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+ \brief Concept for receiving events from GenericReader upon parsing.
+ The functions return true if no error occurs. If they return false,
+ the event publisher should terminate the process.
+\code
+concept Handler {
+ typename Ch;
+
+ bool Null();
+ bool Bool(bool b);
+ bool Int(int i);
+ bool Uint(unsigned i);
+ bool Int64(int64_t i);
+ bool Uint64(uint64_t i);
+ bool Double(double d);
+ bool String(const Ch* str, SizeType length, bool copy);
+ bool StartObject();
+ bool Key(const Ch* str, SizeType length, bool copy);
+ bool EndObject(SizeType memberCount);
+ bool StartArray();
+ bool EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+ \note implements Handler concept
+*/
+template<typename Encoding = UTF8<>, typename Derived = void>
+struct BaseReaderHandler {
+ typedef typename Encoding::Ch Ch;
+
+ typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
+
+ bool Default() { return true; }
+ bool Null() { return static_cast<Override&>(*this).Default(); }
+ bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
+ bool Int(int) { return static_cast<Override&>(*this).Default(); }
+ bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
+ bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
+ bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
+ bool Double(double) { return static_cast<Override&>(*this).Default(); }
+ bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
+ bool StartObject() { return static_cast<Override&>(*this).Default(); }
+ bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+ bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
+ bool StartArray() { return static_cast<Override&>(*this).Default(); }
+ bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamLocalCopy
+
+namespace internal {
+
+template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
+class StreamLocalCopy;
+
+//! Do copy optimization.
+template<typename Stream>
+class StreamLocalCopy<Stream, 1> {
+public:
+ StreamLocalCopy(Stream& original) : s(original), original_(original) {}
+ ~StreamLocalCopy() { original_ = s; }
+
+ Stream s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+
+ Stream& original_;
+};
+
+//! Keep reference.
+template<typename Stream>
+class StreamLocalCopy<Stream, 0> {
+public:
+ StreamLocalCopy(Stream& original) : s(original) {}
+
+ Stream& s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param is A input stream for skipping white spaces.
+ \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename InputStream>
+void SkipWhitespace(InputStream& is) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
+ s.Take();
+}
+
+#ifdef RAPIDJSON_SSE42
+//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128((const __m128i *)p);
+ const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+ if (r != 0) { // some of characters is non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ static const char whitespaces[4][17] = {
+ " ",
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
+ "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
+
+ const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
+ const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
+ const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
+ const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128((const __m128i *)p);
+ __m128i x = _mm_cmpeq_epi8(s, w0);
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+ unsigned short r = (unsigned short)~_mm_movemask_epi8(x);
+ if (r != 0) { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& is) {
+ is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& is) {
+ is.src_ = SkipWhitespace_SIMD(is.src_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an
+ object implementing Handler concept.
+
+ It needs to allocate a stack for storing a single decoded string during
+ non-destructive parsing.
+
+ For in-situ parsing, the decoded string is directly written to the source
+ text string, no temporary buffer is required.
+
+ A GenericReader object can be reused for parsing multiple JSON text.
+
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam TargetEncoding Encoding of the parse output.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
+class GenericReader {
+public:
+ typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
+
+ //! Constructor.
+ /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+ \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
+ */
+ GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
+
+ //! Parse JSON text.
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ if (parseFlags & kParseIterativeFlag)
+ return IterativeParse<parseFlags>(is, handler);
+
+ parseResult_.Clear();
+
+ ClearStackOnExit scope(*this);
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (is.Peek() == '\0') {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ else {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (!(parseFlags & kParseStopWhenDoneFlag)) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (is.Peek() != '\0') {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ }
+ }
+
+ return parseResult_;
+ }
+
+ //! Parse JSON text (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ return Parse<kParseDefaultFlags>(is, handler);
+ }
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+protected:
+ void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericReader(const GenericReader&);
+ GenericReader& operator=(const GenericReader&);
+
+ void ClearStack() { stack_.Clear(); }
+
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
+ ~ClearStackOnExit() { r_.ClearStack(); }
+ private:
+ GenericReader& r_;
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ };
+
+ template<unsigned parseFlags, typename InputStream>
+ void SkipWhitespaceAndComments(InputStream& is) {
+ SkipWhitespace(is);
+
+ if (parseFlags & kParseCommentsFlag) {
+ while (is.Peek() == '/') {
+ is.Take();
+
+ if (is.Peek() == '*') {
+ is.Take();
+ while (true) {
+ if (is.Peek() == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+
+ if (is.Take() == '*') {
+ if (is.Peek() == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+
+ if (is.Take() == '/')
+ break;
+ }
+ }
+ } else if (is.Peek() == '/') {
+ is.Take();
+ while (is.Peek() != '\0' && is.Take() != '\n') { }
+ } else {
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+ }
+
+ SkipWhitespace(is);
+ }
+ }
+ }
+
+ // Parse object: { string : value, ... }
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseObject(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '{');
+ is.Take(); // Skip '{'
+
+ if (!handler.StartObject())
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (is.Peek() == '}') {
+ is.Take();
+ if (!handler.EndObject(0)) // empty object
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType memberCount = 0;;) {
+ if (is.Peek() != '"')
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+
+ ParseString<parseFlags>(is, handler, true);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (is.Take() != ':')
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++memberCount;
+
+ switch (is.Take()) {
+ case ',':
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ break;
+ case '}':
+ if (!handler.EndObject(memberCount))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ default:
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+ break;
+ }
+ }
+ }
+
+ // Parse array: [ value, ... ]
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseArray(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '[');
+ is.Take(); // Skip '['
+
+ if (!handler.StartArray())
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (is.Peek() == ']') {
+ is.Take();
+ if (!handler.EndArray(0)) // empty array
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType elementCount = 0;;) {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++elementCount;
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ switch (is.Take()) {
+ case ',':
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ break;
+ case ']':
+ if (!handler.EndArray(elementCount))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ default:
+ RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+ break;
+ }
+ }
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNull(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'n');
+ is.Take();
+
+ if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
+ if (!handler.Null())
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseTrue(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 't');
+ is.Take();
+
+ if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
+ if (!handler.Bool(true))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseFalse(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'f');
+ is.Take();
+
+ if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
+ if (!handler.Bool(false))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ }
+
+ // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+ template<typename InputStream>
+ unsigned ParseHex4(InputStream& is) {
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; i++) {
+ Ch c = is.Take();
+ codepoint <<= 4;
+ codepoint += static_cast<unsigned>(c);
+ if (c >= '0' && c <= '9')
+ codepoint -= '0';
+ else if (c >= 'A' && c <= 'F')
+ codepoint -= 'A' - 10;
+ else if (c >= 'a' && c <= 'f')
+ codepoint -= 'a' - 10;
+ else {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
+ }
+ }
+ return codepoint;
+ }
+
+ template <typename CharType>
+ class StackStream {
+ public:
+ typedef CharType Ch;
+
+ StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
+ RAPIDJSON_FORCEINLINE void Put(Ch c) {
+ *stack_.template Push<Ch>() = c;
+ ++length_;
+ }
+ size_t Length() const { return length_; }
+ Ch* Pop() {
+ return stack_.template Pop<Ch>(length_);
+ }
+
+ private:
+ StackStream(const StackStream&);
+ StackStream& operator=(const StackStream&);
+
+ internal::Stack<StackAllocator>& stack_;
+ SizeType length_;
+ };
+
+ // Parse string and generate String event. Different code paths for kParseInsituFlag.
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ bool success = false;
+ if (parseFlags & kParseInsituFlag) {
+ typename InputStream::Ch *head = s.PutBegin();
+ ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ size_t length = s.PutEnd(head) - 1;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head;
+ success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
+ }
+ else {
+ StackStream<typename TargetEncoding::Ch> stackStream(stack_);
+ ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
+ const typename TargetEncoding::Ch* const str = stackStream.Pop();
+ success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
+ }
+ if (!success)
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ }
+
+ // Parse string to an output is
+ // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
+ template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ static const char escape[256] = {
+ Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
+ Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
+ 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
+ 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+ };
+#undef Z16
+//!@endcond
+
+ RAPIDJSON_ASSERT(is.Peek() == '\"');
+ is.Take(); // Skip '\"'
+
+ for (;;) {
+ Ch c = is.Peek();
+ if (c == '\\') { // Escape
+ is.Take();
+ Ch e = is.Take();
+ if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
+ os.Put(escape[(unsigned char)e]);
+ }
+ else if (e == 'u') { // Unicode
+ unsigned codepoint = ParseHex4(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
+ // Handle UTF-16 surrogate pair
+ if (is.Take() != '\\' || is.Take() != 'u')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+ unsigned codepoint2 = ParseHex4(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+ codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+ }
+ TEncoding::Encode(os, codepoint);
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+ }
+ else if (c == '"') { // Closing double quote
+ is.Take();
+ os.Put('\0'); // null-terminate the string
+ return;
+ }
+ else if (c == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
+ else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+ else {
+ if (parseFlags & kParseValidateEncodingFlag ?
+ !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
+ !Transcoder<SEncoding, TEncoding>::Transcode(is, os))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
+ }
+ }
+ }
+
+ template<typename InputStream, bool backup>
+ class NumberStream;
+
+ template<typename InputStream>
+ class NumberStream<InputStream, false> {
+ public:
+ NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
+ RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
+ RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
+ size_t Tell() { return is.Tell(); }
+ size_t Length() { return 0; }
+ const char* Pop() { return 0; }
+
+ protected:
+ NumberStream& operator=(const NumberStream&);
+
+ InputStream& is;
+ };
+
+ template<typename InputStream>
+ class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
+ typedef NumberStream<InputStream, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch TakePush() {
+ stackStream.Put((char)Base::is.Peek());
+ return Base::is.Take();
+ }
+
+ size_t Length() { return stackStream.Length(); }
+
+ const char* Pop() {
+ stackStream.Put('\0');
+ return stackStream.Pop();
+ }
+
+ private:
+ StackStream<char> stackStream;
+ };
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNumber(InputStream& is, Handler& handler) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ NumberStream<InputStream, (parseFlags & kParseFullPrecisionFlag) != 0> s(*this, copy.s);
+
+ // Parse minus
+ bool minus = false;
+ if (s.Peek() == '-') {
+ minus = true;
+ s.Take();
+ }
+
+ // Parse int: zero / ( digit1-9 *DIGIT )
+ unsigned i = 0;
+ uint64_t i64 = 0;
+ bool use64bit = false;
+ int significandDigit = 0;
+ if (s.Peek() == '0') {
+ i = 0;
+ s.TakePush();
+ }
+ else if (s.Peek() >= '1' && s.Peek() <= '9') {
+ i = static_cast<unsigned>(s.TakePush() - '0');
+
+ if (minus)
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i >= 214748364) { // 2^31 = 2147483648
+ if (i != 214748364 || s.Peek() > '8') {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i >= 429496729) { // 2^32 - 1 = 4294967295
+ if (i != 429496729 || s.Peek() > '5') {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+
+ // Parse 64bit int
+ bool useDouble = false;
+ double d = 0.0;
+ if (use64bit) {
+ if (minus)
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
+ if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
+ d = i64;
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
+ if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
+ d = i64;
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+
+ // Force double for big integer
+ if (useDouble) {
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+ d = d * 10 + (s.TakePush() - '0');
+ }
+ }
+
+ // Parse frac = decimal-point 1*DIGIT
+ int expFrac = 0;
+ size_t decimalPosition;
+ if (s.Peek() == '.') {
+ s.Take();
+ decimalPosition = s.Length();
+
+ if (!(s.Peek() >= '0' && s.Peek() <= '9'))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
+
+ if (!useDouble) {
+#if RAPIDJSON_64BIT
+ // Use i64 to store significand in 64-bit architecture
+ if (!use64bit)
+ i64 = i;
+
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
+ break;
+ else {
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ --expFrac;
+ if (i64 != 0)
+ significandDigit++;
+ }
+ }
+
+ d = (double)i64;
+#else
+ // Use double to store significand in 32-bit architecture
+ d = use64bit ? (double)i64 : (double)i;
+#endif
+ useDouble = true;
+ }
+
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (significandDigit < 17) {
+ d = d * 10.0 + (s.TakePush() - '0');
+ --expFrac;
+ if (d > 0.0)
+ significandDigit++;
+ }
+ else
+ s.TakePush();
+ }
+ }
+ else
+ decimalPosition = s.Length(); // decimal position at the end of integer.
+
+ // Parse exp = e [ minus / plus ] 1*DIGIT
+ int exp = 0;
+ if (s.Peek() == 'e' || s.Peek() == 'E') {
+ if (!useDouble) {
+ d = use64bit ? i64 : i;
+ useDouble = true;
+ }
+ s.Take();
+
+ bool expMinus = false;
+ if (s.Peek() == '+')
+ s.Take();
+ else if (s.Peek() == '-') {
+ s.Take();
+ expMinus = true;
+ }
+
+ if (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = s.Take() - '0';
+ if (expMinus) {
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = exp * 10 + (s.Take() - '0');
+ if (exp >= 214748364) { // Issue #313: prevent overflow exponent
+ while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent
+ s.Take();
+ }
+ }
+ }
+ else { // positive exp
+ int maxExp = 308 - expFrac;
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = exp * 10 + (s.Take() - '0');
+ if (exp > maxExp)
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+ }
+ }
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
+
+ if (expMinus)
+ exp = -exp;
+ }
+
+ // Finish parsing, call event according to the type of number.
+ bool cont = true;
+ size_t length = s.Length();
+ const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
+
+ if (useDouble) {
+ int p = exp + expFrac;
+ if (parseFlags & kParseFullPrecisionFlag)
+ d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
+ else
+ d = internal::StrtodNormalPrecision(d, p);
+
+ cont = handler.Double(minus ? -d : d);
+ }
+ else {
+ if (use64bit) {
+ if (minus)
+ cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
+ else
+ cont = handler.Uint64(i64);
+ }
+ else {
+ if (minus)
+ cont = handler.Int(static_cast<int32_t>(~i + 1));
+ else
+ cont = handler.Uint(i);
+ }
+ }
+ if (!cont)
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ }
+
+ // Parse any JSON value
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseValue(InputStream& is, Handler& handler) {
+ switch (is.Peek()) {
+ case 'n': ParseNull <parseFlags>(is, handler); break;
+ case 't': ParseTrue <parseFlags>(is, handler); break;
+ case 'f': ParseFalse <parseFlags>(is, handler); break;
+ case '"': ParseString<parseFlags>(is, handler); break;
+ case '{': ParseObject<parseFlags>(is, handler); break;
+ case '[': ParseArray <parseFlags>(is, handler); break;
+ default :
+ ParseNumber<parseFlags>(is, handler);
+ break;
+
+ }
+ }
+
+ // Iterative Parsing
+
+ // States
+ enum IterativeParsingState {
+ IterativeParsingStartState = 0,
+ IterativeParsingFinishState,
+ IterativeParsingErrorState,
+
+ // Object states
+ IterativeParsingObjectInitialState,
+ IterativeParsingMemberKeyState,
+ IterativeParsingKeyValueDelimiterState,
+ IterativeParsingMemberValueState,
+ IterativeParsingMemberDelimiterState,
+ IterativeParsingObjectFinishState,
+
+ // Array states
+ IterativeParsingArrayInitialState,
+ IterativeParsingElementState,
+ IterativeParsingElementDelimiterState,
+ IterativeParsingArrayFinishState,
+
+ // Single value state
+ IterativeParsingValueState,
+
+ cIterativeParsingStateCount
+ };
+
+ // Tokens
+ enum Token {
+ LeftBracketToken = 0,
+ RightBracketToken,
+
+ LeftCurlyBracketToken,
+ RightCurlyBracketToken,
+
+ CommaToken,
+ ColonToken,
+
+ StringToken,
+ FalseToken,
+ TrueToken,
+ NullToken,
+ NumberToken,
+
+ kTokenCount
+ };
+
+ RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define N NumberToken
+#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
+ // Maps from ASCII to Token
+ static const unsigned char tokenMap[256] = {
+ N16, // 00~0F
+ N16, // 10~1F
+ N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
+ N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
+ N16, // 40~4F
+ N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
+ N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
+ N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
+ N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
+ };
+#undef N
+#undef N16
+//!@endcond
+
+ if (sizeof(Ch) == 1 || unsigned(c) < 256)
+ return (Token)tokenMap[(unsigned char)c];
+ else
+ return NumberToken;
+ }
+
+ RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
+ // current state x one lookahead token -> new state
+ static const char G[cIterativeParsingStateCount][kTokenCount] = {
+ // Start
+ {
+ IterativeParsingArrayInitialState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingValueState, // String
+ IterativeParsingValueState, // False
+ IterativeParsingValueState, // True
+ IterativeParsingValueState, // Null
+ IterativeParsingValueState // Number
+ },
+ // Finish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Error(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ObjectInitial
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberKey
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingKeyValueDelimiterState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // KeyValueDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberValueState, // String
+ IterativeParsingMemberValueState, // False
+ IterativeParsingMemberValueState, // True
+ IterativeParsingMemberValueState, // Null
+ IterativeParsingMemberValueState // Number
+ },
+ // MemberValue
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingMemberDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberDelimiter
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ObjectFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ArrayInitial
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // Element
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingElementDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ElementDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // ArrayFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Single Value (sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ }
+ }; // End of G
+
+ return (IterativeParsingState)G[state][token];
+ }
+
+ // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
+ // May return a new state on state pop.
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
+ (void)token;
+
+ switch (dst) {
+ case IterativeParsingErrorState:
+ return dst;
+
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingArrayInitialState:
+ {
+ // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
+ // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
+ IterativeParsingState n = src;
+ if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
+ n = IterativeParsingElementState;
+ else if (src == IterativeParsingKeyValueDelimiterState)
+ n = IterativeParsingMemberValueState;
+ // Push current state.
+ *stack_.template Push<SizeType>(1) = n;
+ // Initialize and push the member/element count.
+ *stack_.template Push<SizeType>(1) = 0;
+ // Call handler
+ bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return dst;
+ }
+ }
+
+ case IterativeParsingMemberKeyState:
+ ParseString<parseFlags>(is, handler, true);
+ if (HasParseError())
+ return IterativeParsingErrorState;
+ else
+ return dst;
+
+ case IterativeParsingKeyValueDelimiterState:
+ RAPIDJSON_ASSERT(token == ColonToken);
+ is.Take();
+ return dst;
+
+ case IterativeParsingMemberValueState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingElementState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingMemberDelimiterState:
+ case IterativeParsingElementDelimiterState:
+ is.Take();
+ // Update member/element count.
+ *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
+ return dst;
+
+ case IterativeParsingObjectFinishState:
+ {
+ // Get member count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the object is not empty, count the last member.
+ if (src == IterativeParsingMemberValueState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndObject(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ case IterativeParsingArrayFinishState:
+ {
+ // Get element count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the array is not empty, count the last element.
+ if (src == IterativeParsingElementState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndArray(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ default:
+ // This branch is for IterativeParsingValueState actually.
+ // Use `default:` rather than
+ // `case IterativeParsingValueState:` is for code coverage.
+
+ // The IterativeParsingStartState is not enumerated in this switch-case.
+ // It is impossible for that case. And it can be caught by following assertion.
+
+ // The IterativeParsingFinishState is not enumerated in this switch-case either.
+ // It is a "derivative" state which cannot triggered from Predict() directly.
+ // Therefore it cannot happen here. And it can be caught by following assertion.
+ RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
+
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return IterativeParsingFinishState;
+ }
+ }
+
+ template <typename InputStream>
+ void HandleError(IterativeParsingState src, InputStream& is) {
+ if (HasParseError()) {
+ // Error flag has been set.
+ return;
+ }
+
+ switch (src) {
+ case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
+ case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
+ case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
+ case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
+ case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
+ default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return;
+ }
+ }
+
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult IterativeParse(InputStream& is, Handler& handler) {
+ parseResult_.Clear();
+ ClearStackOnExit scope(*this);
+ IterativeParsingState state = IterativeParsingStartState;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ while (is.Peek() != '\0') {
+ Token t = Tokenize(is.Peek());
+ IterativeParsingState n = Predict(state, t);
+ IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
+
+ if (d == IterativeParsingErrorState) {
+ HandleError(state, is);
+ break;
+ }
+
+ state = d;
+
+ // Do not further consume streams if a root JSON has been parsed.
+ if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
+ break;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+
+ // Handle the end of file.
+ if (state != IterativeParsingFinishState)
+ HandleError(state, is);
+
+ return parseResult_;
+ }
+
+ static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
+ internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
+ ParseResult parseResult_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<>, UTF8<> > Reader;
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_READER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h
new file mode 100644
index 000000000..1c9c80b79
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h
@@ -0,0 +1,93 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "rapidjson.h"
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output stream.
+/*!
+ \tparam Encoding Encoding of the stream.
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericStringBuffer {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
+ GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
+ if (&rhs != this)
+ stack_ = std::move(rhs.stack_);
+ return *this;
+ }
+#endif
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.ShrinkToFit();
+ stack_.template Pop<Ch>(1);
+ }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetString() const {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.template Pop<Ch>(1);
+
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericStringBuffer(const GenericStringBuffer&);
+ GenericStringBuffer& operator=(const GenericStringBuffer&);
+};
+
+//! String buffer with UTF8 encoding
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+ std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h
new file mode 100644
index 000000000..874faa881
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h
@@ -0,0 +1,395 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include "internal/dtoa.h"
+#include "internal/itoa.h"
+#include "stringbuffer.h"
+#include <new> // placement new
+
+#if RAPIDJSON_HAS_STDSTRING
+#include <string>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+ It generates JSON text by events to an output os.
+
+ User may programmatically calls the functions of a writer to generate JSON text.
+
+ On the other side, a writer can also be passed to objects that generates events,
+
+ for example Reader::Parse() and Document::Accept().
+
+ \tparam OutputStream Type of output stream.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+ \note implements Handler concept
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class Writer {
+public:
+ typedef typename SourceEncoding::Ch Ch;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param stackAllocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ explicit
+ Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+ explicit
+ Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+ //! Reset the writer with a new stream.
+ /*!
+ This function reset the writer with a new stream and default settings,
+ in order to make a Writer object reusable for output multiple JSONs.
+
+ \param os New output stream.
+ \code
+ Writer<OutputStream> writer(os1);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+
+ writer.Reset(os2);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+ \endcode
+ */
+ void Reset(OutputStream& os) {
+ os_ = &os;
+ hasRoot_ = false;
+ level_stack_.Clear();
+ }
+
+ //! Checks whether the output is a complete JSON.
+ /*!
+ A complete JSON has a complete root object or array.
+ */
+ bool IsComplete() const {
+ return hasRoot_ && level_stack_.Empty();
+ }
+
+ /*!@name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { Prefix(kNullType); return WriteNull(); }
+ bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
+ bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
+ bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
+ bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
+ bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
+
+ //! Writes the given \c double value to the stream
+ /*!
+ \param d The value to be written.
+ \return Whether it is succeed.
+ */
+ bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kStringType);
+ return WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ Prefix(kObjectType);
+ new (level_stack_.template Push<Level>()) Level(false);
+ return WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ bool ret = WriteEndObject();
+ if (level_stack_.Empty()) // end of json text
+ os_->Flush();
+ return ret;
+ }
+
+ bool StartArray() {
+ Prefix(kArrayType);
+ new (level_stack_.template Push<Level>()) Level(true);
+ return WriteStartArray();
+ }
+
+ bool EndArray(SizeType elementCount = 0) {
+ (void)elementCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ bool ret = WriteEndArray();
+ if (level_stack_.Empty()) // end of json text
+ os_->Flush();
+ return ret;
+ }
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! Simpler but slower overload.
+ bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+ //@}
+
+protected:
+ //! Information for each nested level
+ struct Level {
+ Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
+ size_t valueCount; //!< number of values in this level
+ bool inArray; //!< true if in array, otherwise in object
+ };
+
+ static const size_t kDefaultLevelDepth = 32;
+
+ bool WriteNull() {
+ os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
+ }
+
+ bool WriteBool(bool b) {
+ if (b) {
+ os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
+ }
+ else {
+ os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
+ }
+ return true;
+ }
+
+ bool WriteInt(int i) {
+ char buffer[11];
+ const char* end = internal::i32toa(i, buffer);
+ for (const char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteUint(unsigned u) {
+ char buffer[10];
+ const char* end = internal::u32toa(u, buffer);
+ for (const char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteInt64(int64_t i64) {
+ char buffer[21];
+ const char* end = internal::i64toa(i64, buffer);
+ for (const char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteUint64(uint64_t u64) {
+ char buffer[20];
+ char* end = internal::u64toa(u64, buffer);
+ for (char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteDouble(double d) {
+ char buffer[25];
+ char* end = internal::dtoa(d, buffer);
+ for (char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteString(const Ch* str, SizeType length) {
+ static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ static const char escape[256] = {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ //0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+ 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
+ Z16, Z16, // 30~4F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
+#undef Z16
+ };
+
+ os_->Put('\"');
+ GenericStringStream<SourceEncoding> is(str);
+ while (is.Tell() < length) {
+ const Ch c = is.Peek();
+ if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
+ // Unicode escaping
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ os_->Put('\\');
+ os_->Put('u');
+ if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
+ os_->Put(hexDigits[(codepoint >> 12) & 15]);
+ os_->Put(hexDigits[(codepoint >> 8) & 15]);
+ os_->Put(hexDigits[(codepoint >> 4) & 15]);
+ os_->Put(hexDigits[(codepoint ) & 15]);
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
+ // Surrogate pair
+ unsigned s = codepoint - 0x010000;
+ unsigned lead = (s >> 10) + 0xD800;
+ unsigned trail = (s & 0x3FF) + 0xDC00;
+ os_->Put(hexDigits[(lead >> 12) & 15]);
+ os_->Put(hexDigits[(lead >> 8) & 15]);
+ os_->Put(hexDigits[(lead >> 4) & 15]);
+ os_->Put(hexDigits[(lead ) & 15]);
+ os_->Put('\\');
+ os_->Put('u');
+ os_->Put(hexDigits[(trail >> 12) & 15]);
+ os_->Put(hexDigits[(trail >> 8) & 15]);
+ os_->Put(hexDigits[(trail >> 4) & 15]);
+ os_->Put(hexDigits[(trail ) & 15]);
+ }
+ }
+ else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
+ is.Take();
+ os_->Put('\\');
+ os_->Put(escape[(unsigned char)c]);
+ if (escape[(unsigned char)c] == 'u') {
+ os_->Put('0');
+ os_->Put('0');
+ os_->Put(hexDigits[(unsigned char)c >> 4]);
+ os_->Put(hexDigits[(unsigned char)c & 0xF]);
+ }
+ }
+ else
+ if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
+ return false;
+ }
+ os_->Put('\"');
+ return true;
+ }
+
+ bool WriteStartObject() { os_->Put('{'); return true; }
+ bool WriteEndObject() { os_->Put('}'); return true; }
+ bool WriteStartArray() { os_->Put('['); return true; }
+ bool WriteEndArray() { os_->Put(']'); return true; }
+
+ void Prefix(Type type) {
+ (void)type;
+ if (level_stack_.GetSize() != 0) { // this value is not at root
+ Level* level = level_stack_.template Top<Level>();
+ if (level->valueCount > 0) {
+ if (level->inArray)
+ os_->Put(','); // add comma if it is not the first element in array
+ else // in object
+ os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
+ hasRoot_ = true;
+ }
+ }
+
+ OutputStream* os_;
+ internal::Stack<StackAllocator> level_stack_;
+ bool hasRoot_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ Writer(const Writer&);
+ Writer& operator=(const Writer&);
+};
+
+// Full specialization for StringStream to prevent memory copying
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt(int i) {
+ char *buffer = os_->Push(11);
+ const char* end = internal::i32toa(i, buffer);
+ os_->Pop(static_cast<size_t>(11 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
+ char *buffer = os_->Push(10);
+ const char* end = internal::u32toa(u, buffer);
+ os_->Pop(static_cast<size_t>(10 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
+ char *buffer = os_->Push(21);
+ const char* end = internal::i64toa(i64, buffer);
+ os_->Pop(static_cast<size_t>(21 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
+ char *buffer = os_->Push(20);
+ const char* end = internal::u64toa(u, buffer);
+ os_->Pop(static_cast<size_t>(20 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteDouble(double d) {
+ char *buffer = os_->Push(25);
+ char* end = internal::dtoa(d, buffer);
+ os_->Pop(static_cast<size_t>(25 - (end - buffer)));
+ return true;
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/license.txt b/src/3rdparty/assimp/contrib/rapidjson/license.txt
new file mode 100644
index 000000000..7ccc161c8
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/license.txt
@@ -0,0 +1,57 @@
+Tencent is pleased to support the open source community by making RapidJSON available.
+
+Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+
+If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License.
+If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license.
+A copy of the MIT License is included in this file.
+
+Other dependencies and licenses:
+
+Open Source Software Licensed Under the BSD License:
+--------------------------------------------------------------------
+
+The msinttypes r29
+Copyright (c) 2006-2013 Alexander Chemeris
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND 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 Source Software Licensed Under the JSON License:
+--------------------------------------------------------------------
+
+json.org
+Copyright (c) 2002 JSON.org
+All Rights Reserved.
+
+JSON_checker
+Copyright (c) 2002 JSON.org
+All Rights Reserved.
+
+
+Terms of the JSON License:
+---------------------------------------------------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Terms of the MIT License:
+--------------------------------------------------------------------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/3rdparty/assimp/contrib/rapidjson/readme.md b/src/3rdparty/assimp/contrib/rapidjson/readme.md
new file mode 100644
index 000000000..fb270fb96
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/readme.md
@@ -0,0 +1,129 @@
+![](doc/logo/rapidjson.png)
+
+![](https://img.shields.io/badge/release-v1.0.2-blue.png)
+
+## A fast JSON parser/generator for C++ with both SAX/DOM style API
+
+Tencent is pleased to support the open source community by making RapidJSON available.
+
+Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+
+* [RapidJSON GitHub](https://github.com/miloyip/rapidjson/)
+* RapidJSON Documentation
+ * [English](http://rapidjson.org/)
+ * [简体中文](http://rapidjson.org/zh-cn/)
+ * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference.
+
+## Build status
+
+| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] |
+| :---------------: | :-----------------: | :-------------------: |
+| ![lin-badge] | ![win-badge] | ![cov-badge] |
+
+[lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status"
+[lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status"
+[win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status"
+[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status"
+[cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master
+[cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master
+
+## Introduction
+
+RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/).
+
+* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code.
+
+* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration.
+
+* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL.
+
+* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing.
+
+* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character).
+
+More features can be read [here](doc/features.md).
+
+JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in fully compliance with RFC7159/ECMA-404. More information about JSON can be obtained at
+* [Introducing JSON](http://json.org/)
+* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](http://www.ietf.org/rfc/rfc7159.txt)
+* [Standard ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/standards/Ecma-404.htm)
+
+## Compatibility
+
+RapidJSON is cross-platform. Some platform/compiler combinations which have been tested are shown as follows.
+* Visual C++ 2008/2010/2013 on Windows (32/64-bit)
+* GNU C++ 3.8.x on Cygwin
+* Clang 3.4 on Mac OS X (32/64-bit) and iOS
+* Clang 3.4 on Android NDK
+
+Users can build and run the unit tests on their platform/compiler.
+
+## Installation
+
+RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path.
+
+RapidJSON uses following software as its dependencies:
+* [CMake](http://www.cmake.org) as a general build tool
+* (optional)[Doxygen](http://www.doxygen.org) to build documentation
+* (optional)[googletest](https://code.google.com/p/googletest/) for unit and performance testing
+
+To generate user documentation and run tests please proceed with the steps below:
+
+1. Execute `git submodule update --init` to get the files of thirdparty submodules (google test).
+2. Create directory called `build` in rapidjson source directory.
+3. Change to `build` directory and run `cmake ..` command to configure your build. Windows users can do the same with cmake-gui application.
+4. On Windows, build the solution found in the build directory. On Linux, run `make` from the build directory.
+
+On successfull build you will find compiled test and example binaries in `bin`
+directory. The generated documentation will be available in `doc/html`
+directory of the build tree. To run tests after finished build please run `make
+test` or `ctest` from your build tree. You can get detailed output using `ctest
+-V` command.
+
+It is possible to install library system-wide by running `make install` command
+from the build tree with administrative privileges. This will install all files
+according to system preferences. Once RapidJSON is installed, it is possible
+to use it from other CMake projects by adding `find_package(RapidJSON)` line to
+your CMakeLists.txt.
+
+## Usage at a glance
+
+This simple example parses a JSON string into a document (DOM), make a simple modification of the DOM, and finally stringify the DOM to a JSON string.
+
+~~~~~~~~~~cpp
+// rapidjson/example/simpledom/simpledom.cpp`
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+#include "rapidjson/stringbuffer.h"
+#include <iostream>
+
+using namespace rapidjson;
+
+int main() {
+ // 1. Parse a JSON string into DOM.
+ const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
+ Document d;
+ d.Parse(json);
+
+ // 2. Modify it by DOM.
+ Value& s = d["stars"];
+ s.SetInt(s.GetInt() + 1);
+
+ // 3. Stringify the DOM
+ StringBuffer buffer;
+ Writer<StringBuffer> writer(buffer);
+ d.Accept(writer);
+
+ // Output {"project":"rapidjson","stars":11}
+ std::cout << buffer.GetString() << std::endl;
+ return 0;
+}
+~~~~~~~~~~
+
+Note that this example did not handle potential errors.
+
+The following diagram shows the process.
+
+![simpledom](doc/diagram/simpledom.png)
+
+More [examples](https://github.com/miloyip/rapidjson/tree/master/example) are available.
diff --git a/src/3rdparty/assimp/contrib/unzip/unzip.c b/src/3rdparty/assimp/contrib/unzip/unzip.c
index 2c9db1be8..af00f7d6f 100644
--- a/src/3rdparty/assimp/contrib/unzip/unzip.c
+++ b/src/3rdparty/assimp/contrib/unzip/unzip.c
@@ -1246,7 +1246,7 @@ extern int ZEXPORT unzReadCurrentFile (file, buf, len)
return UNZ_PARAMERROR;
- if ((pfile_in_zip_read_info->read_buffer == NULL))
+ if (pfile_in_zip_read_info->read_buffer == NULL)
return UNZ_END_OF_LIST_OF_FILE;
if (len==0)
return 0;
diff --git a/src/3rdparty/assimp/contrib/zlib_note.txt b/src/3rdparty/assimp/contrib/zlib_note.txt
deleted file mode 100644
index cc274f0bf..000000000
--- a/src/3rdparty/assimp/contrib/zlib_note.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a heavily modified and shrinked version of zlib 1.2.3
-
-- Removed comments from zlib.h
-- Removed gzip/zip archive I/O
-- Removed infback.c
-- Added Assimp #idefs to exclude it if not needed
-- Disabled debug macros in zutil.h
-
-Assimp itself does not use the compression part yet, so
-it needn't be compiled (trees.c, deflate.c, compress.c).
-Currently these units are just used by assimp_cmd. \ No newline at end of file
diff --git a/src/3rdparty/assimp/include/assimp/Compiler/pstdint.h b/src/3rdparty/assimp/include/assimp/Compiler/pstdint.h
index 5bc322fab..4de4ce2a9 100644
--- a/src/3rdparty/assimp/include/assimp/Compiler/pstdint.h
+++ b/src/3rdparty/assimp/include/assimp/Compiler/pstdint.h
@@ -3,7 +3,7 @@
* BSD License:
****************************************************************************
*
- * Copyright (c) 2005-2007 Paul Hsieh
+ * Copyright (c) 2005-2016 Paul Hsieh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
*
****************************************************************************
*
- * Version 0.1.10
+ * Version 0.1.15.4
*
* The ANSI C standard committee, for the C99 standard, specified the
* inclusion of a new standard include file called stdint.h. This is
@@ -42,19 +42,17 @@
* integer libraries and so on. But for most developers its likely
* useful just for programming sanity.
*
- * The problem is that most compiler vendors have decided not to
- * implement the C99 standard, and the next C++ language standard
- * (which has a lot more mindshare these days) will be a long time in
- * coming and its unknown whether or not it will include stdint.h or
- * how much adoption it will have. Either way, it will be a long time
- * before all compilers come with a stdint.h and it also does nothing
- * for the extremely large number of compilers available today which
- * do not include this file, or anything comparable to it.
+ * The problem is that some compiler vendors chose to ignore the C99
+ * standard and some older compilers have no opportunity to be updated.
+ * Because of this situation, simply including stdint.h in your code
+ * makes it unportable.
*
* So that's what this file is all about. Its an attempt to build a
* single universal include file that works on as many platforms as
- * possible to deliver what stdint.h is supposed to. A few things
- * that should be noted about this file:
+ * possible to deliver what stdint.h is supposed to. Even compilers
+ * that already come with stdint.h can use this file instead without
+ * any loss of functionality. A few things that should be noted about
+ * this file:
*
* 1) It is not guaranteed to be portable and/or present an identical
* interface on all platforms. The extreme variability of the
@@ -73,7 +71,7 @@
* include stdint.h. The hope is that one or the other can be
* used with no real difference.
*
- * 5) In the current verison, if your platform can't represent
+ * 5) In the current version, if your platform can't represent
* int32_t, int16_t and int8_t, it just dumps out with a compiler
* error.
*
@@ -154,7 +152,12 @@
* PRINTF_INT64_DEC_WIDTH
* PRINTF_INT32_DEC_WIDTH
* PRINTF_INT16_DEC_WIDTH
- * PRINTF_INT8_DEC_WIDTH
+ * PRINTF_UINT8_DEC_WIDTH
+ * PRINTF_UINTMAX_DEC_WIDTH
+ * PRINTF_UINT64_DEC_WIDTH
+ * PRINTF_UINT32_DEC_WIDTH
+ * PRINTF_UINT16_DEC_WIDTH
+ * PRINTF_UINT8_DEC_WIDTH
*
* Which specifies the maximum number of characters required to
* print the number of that type in either hexadecimal or decimal.
@@ -178,6 +181,10 @@
* Chris Howie
* John Steele Scott
* Dave Thorup
+ * John Dill
+ * Florian Wobbe
+ * Christopher Sean Morrison
+ * Mikkel Fahnoe Jorgensen
*
*/
@@ -190,14 +197,27 @@
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
*/
-#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)))) && !defined (_PSTDINT_H_INCLUDED) && !defined(_STDINT)
+#if ((defined(__SUNPRO_C) && __SUNPRO_C >= 0x570) || (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (__GNUC__ > 3 || defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
#include <stdint.h>
#define _PSTDINT_H_INCLUDED
-# ifndef PRINTF_INT64_MODIFIER
-# define PRINTF_INT64_MODIFIER "ll"
-# endif
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER "l"
+# if defined(__GNUC__) && (defined(__x86_64__) || defined(__ppc64__)) && !(defined(__APPLE__) && defined(__MACH__))
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "l"
+# endif
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+# else
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# ifndef PRINTF_INT32_MODIFIER
+# if (UINT_MAX == UINT32_MAX)
+# define PRINTF_INT32_MODIFIER ""
+# else
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+# endif
# endif
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
@@ -208,32 +228,62 @@
# ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
# endif
+# ifndef PRINTF_UINT64_HEX_WIDTH
+# define PRINTF_UINT64_HEX_WIDTH "16"
+# endif
# ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
# endif
+# ifndef PRINTF_UINT32_HEX_WIDTH
+# define PRINTF_UINT32_HEX_WIDTH "8"
+# endif
# ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
# endif
+# ifndef PRINTF_UINT16_HEX_WIDTH
+# define PRINTF_UINT16_HEX_WIDTH "4"
+# endif
# ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
# endif
+# ifndef PRINTF_UINT8_HEX_WIDTH
+# define PRINTF_UINT8_HEX_WIDTH "2"
+# endif
# ifndef PRINTF_INT64_DEC_WIDTH
-# define PRINTF_INT64_DEC_WIDTH "20"
+# define PRINTF_INT64_DEC_WIDTH "19"
+# endif
+# ifndef PRINTF_UINT64_DEC_WIDTH
+# define PRINTF_UINT64_DEC_WIDTH "20"
# endif
# ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
# endif
+# ifndef PRINTF_UINT32_DEC_WIDTH
+# define PRINTF_UINT32_DEC_WIDTH "10"
+# endif
# ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
# endif
+# ifndef PRINTF_UINT16_DEC_WIDTH
+# define PRINTF_UINT16_DEC_WIDTH "5"
+# endif
# ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
# endif
+# ifndef PRINTF_UINT8_DEC_WIDTH
+# define PRINTF_UINT8_DEC_WIDTH "3"
+# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
-# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
+# endif
+# ifndef PRINTF_UINTMAX_HEX_WIDTH
+# define PRINTF_UINTMAX_HEX_WIDTH PRINTF_UINT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
-# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
+# endif
+# ifndef PRINTF_UINTMAX_DEC_WIDTH
+# define PRINTF_UINTMAX_DEC_WIDTH PRINTF_UINT64_DEC_WIDTH
# endif
/*
@@ -287,6 +337,20 @@
# endif
#endif
+/*
+ * I have no idea what is the truly correct thing to do on older Solaris.
+ * From some online discussions, this seems to be what is being
+ * recommended. For people who actually are developing on older Solaris,
+ * what I would like to know is, does this define all of the relevant
+ * macros of a complete stdint.h? Remember, in pstdint.h 64 bit is
+ * considered optional.
+ */
+
+#if (defined(__SUNPRO_C) && __SUNPRO_C >= 0x420) && !defined(_PSTDINT_H_INCLUDED)
+#include <sys/inttypes.h>
+#define _PSTDINT_H_INCLUDED
+#endif
+
#ifndef _PSTDINT_H_INCLUDED
#define _PSTDINT_H_INCLUDED
@@ -303,7 +367,7 @@
#ifndef UINT8_MAX
# define UINT8_MAX 0xff
#endif
-#ifndef uint8_t
+#if !defined(uint8_t) && !defined(_UINT8_T) && !defined(vxWorks)
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
typedef unsigned char uint8_t;
# define UINT8_C(v) ((uint8_t) v)
@@ -318,7 +382,7 @@
#ifndef INT8_MIN
# define INT8_MIN INT8_C(0x80)
#endif
-#ifndef int8_t
+#if !defined(int8_t) && !defined(_INT8_T) && !defined(vxWorks)
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
typedef signed char int8_t;
# define INT8_C(v) ((int8_t) v)
@@ -330,7 +394,7 @@
#ifndef UINT16_MAX
# define UINT16_MAX 0xffff
#endif
-#ifndef uint16_t
+#if !defined(uint16_t) && !defined(_UINT16_T) && !defined(vxWorks)
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
typedef unsigned int uint16_t;
# ifndef PRINTF_INT16_MODIFIER
@@ -354,7 +418,7 @@
#ifndef INT16_MIN
# define INT16_MIN INT16_C(0x8000)
#endif
-#ifndef int16_t
+#if !defined(int16_t) && !defined(_INT16_T) && !defined(vxWorks)
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
typedef signed int int16_t;
# define INT16_C(v) ((int16_t) (v))
@@ -375,7 +439,7 @@
#ifndef UINT32_MAX
# define UINT32_MAX (0xffffffffUL)
#endif
-#ifndef uint32_t
+#if !defined(uint32_t) && !defined(_UINT32_T) && !defined(vxWorks)
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
typedef unsigned long uint32_t;
# define UINT32_C(v) v ## UL
@@ -405,7 +469,7 @@
#ifndef INT32_MIN
# define INT32_MIN INT32_C(0x80000000)
#endif
-#ifndef int32_t
+#if !defined(int32_t) && !defined(_INT32_T) && !defined(vxWorks)
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
typedef signed long int32_t;
# define INT32_C(v) v ## L
@@ -438,7 +502,7 @@
#undef stdint_int64_defined
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
-# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S)
+# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
@@ -451,7 +515,7 @@
#endif
#if !defined (stdint_int64_defined)
-# if defined(__GNUC__)
+# if defined(__GNUC__) && !defined(vxWorks)
# define stdint_int64_defined
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
@@ -514,9 +578,8 @@
#ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
#endif
-
#ifndef PRINTF_INT64_DEC_WIDTH
-# define PRINTF_INT64_DEC_WIDTH "20"
+# define PRINTF_INT64_DEC_WIDTH "19"
#endif
#ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
@@ -527,6 +590,18 @@
#ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
#endif
+#ifndef PRINTF_UINT64_DEC_WIDTH
+# define PRINTF_UINT64_DEC_WIDTH "20"
+#endif
+#ifndef PRINTF_UINT32_DEC_WIDTH
+# define PRINTF_UINT32_DEC_WIDTH "10"
+#endif
+#ifndef PRINTF_UINT16_DEC_WIDTH
+# define PRINTF_UINT16_DEC_WIDTH "5"
+#endif
+#ifndef PRINTF_UINT8_DEC_WIDTH
+# define PRINTF_UINT8_DEC_WIDTH "3"
+#endif
/*
* Ok, lets not worry about 128 bit integers for now. Moore's law says
@@ -646,7 +721,7 @@ typedef uint_least32_t uint_fast32_t;
* type limits.
*/
-#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
+#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) && !defined(vxWorks)
# include <wchar.h>
# ifndef WCHAR_MIN
# define WCHAR_MIN 0
@@ -661,12 +736,12 @@ typedef uint_least32_t uint_fast32_t;
* (u)intptr_t types and limits.
*/
-#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
+#if (defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)) || defined (_UINTPTR_T)
# define STDINT_H_UINTPTR_T_DEFINED
#endif
#ifndef STDINT_H_UINTPTR_T_DEFINED
-# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
+# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) || defined (__ppc64__)
# define stdint_intptr_bits 64
# elif defined (__WATCOMC__) || defined (__TURBOC__)
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
@@ -674,10 +749,12 @@ typedef uint_least32_t uint_fast32_t;
# else
# define stdint_intptr_bits 32
# endif
-# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
+# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) || defined (__ppc64__)
# define stdint_intptr_bits 32
# elif defined (__INTEL_COMPILER)
-/* TODO -- what will Intel do about x86-64? */
+/* TODO -- what did Intel do about x86-64? */
+# else
+/* #error "This platform might not be supported yet" */
# endif
# ifdef stdint_intptr_bits
@@ -727,3 +804,109 @@ typedef uint_least32_t uint_fast32_t;
#endif
+#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
+
+/*
+ * Please compile with the maximum warning settings to make sure macros are
+ * not defined more than once.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define glue3_aux(x,y,z) x ## y ## z
+#define glue3(x,y,z) glue3_aux(x,y,z)
+
+#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,) = glue3(UINT,bits,_C) (0);
+#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,) = glue3(INT,bits,_C) (0);
+
+#define DECL(us,bits) glue3(DECL,us,) (bits)
+
+#define TESTUMAX(bits) glue3(u,bits,) = ~glue3(u,bits,); if (glue3(UINT,bits,_MAX) != glue3(u,bits,)) printf ("Something wrong with UINT%d_MAX\n", bits)
+
+#define REPORTERROR(msg) { err_n++; if (err_first <= 0) err_first = __LINE__; printf msg; }
+
+int main () {
+ int err_n = 0;
+ int err_first = 0;
+ DECL(I,8)
+ DECL(U,8)
+ DECL(I,16)
+ DECL(U,16)
+ DECL(I,32)
+ DECL(U,32)
+#ifdef INT64_MAX
+ DECL(I,64)
+ DECL(U,64)
+#endif
+ intmax_t imax = INTMAX_C(0);
+ uintmax_t umax = UINTMAX_C(0);
+ char str0[256], str1[256];
+
+ sprintf (str0, "%" PRINTF_INT32_MODIFIER "d", INT32_C(2147483647));
+ if (0 != strcmp (str0, "2147483647")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
+ if (atoi(PRINTF_INT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_INT32_DEC_WIDTH : %s\n", PRINTF_INT32_DEC_WIDTH));
+ sprintf (str0, "%" PRINTF_INT32_MODIFIER "u", UINT32_C(4294967295));
+ if (0 != strcmp (str0, "4294967295")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str0));
+ if (atoi(PRINTF_UINT32_DEC_WIDTH) != (int) strlen(str0)) REPORTERROR (("Something wrong with PRINTF_UINT32_DEC_WIDTH : %s\n", PRINTF_UINT32_DEC_WIDTH));
+#ifdef INT64_MAX
+ sprintf (str1, "%" PRINTF_INT64_MODIFIER "d", INT64_C(9223372036854775807));
+ if (0 != strcmp (str1, "9223372036854775807")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
+ if (atoi(PRINTF_INT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_INT64_DEC_WIDTH : %s, %d\n", PRINTF_INT64_DEC_WIDTH, (int) strlen(str1)));
+ sprintf (str1, "%" PRINTF_INT64_MODIFIER "u", UINT64_C(18446744073709550591));
+ if (0 != strcmp (str1, "18446744073709550591")) REPORTERROR (("Something wrong with PRINTF_INT32_MODIFIER : %s\n", str1));
+ if (atoi(PRINTF_UINT64_DEC_WIDTH) != (int) strlen(str1)) REPORTERROR (("Something wrong with PRINTF_UINT64_DEC_WIDTH : %s, %d\n", PRINTF_UINT64_DEC_WIDTH, (int) strlen(str1)));
+#endif
+
+ sprintf (str0, "%d %x\n", 0, ~0);
+
+ sprintf (str1, "%d %x\n", i8, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i8 : %s\n", str1));
+ sprintf (str1, "%u %x\n", u8, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u8 : %s\n", str1));
+ sprintf (str1, "%d %x\n", i16, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i16 : %s\n", str1));
+ sprintf (str1, "%u %x\n", u16, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u16 : %s\n", str1));
+ sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i32 : %s\n", str1));
+ sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with u32 : %s\n", str1));
+#ifdef INT64_MAX
+ sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with i64 : %s\n", str1));
+#endif
+ sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with imax : %s\n", str1));
+ sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
+ if (0 != strcmp (str0, str1)) REPORTERROR (("Something wrong with umax : %s\n", str1));
+
+ TESTUMAX(8);
+ TESTUMAX(16);
+ TESTUMAX(32);
+#ifdef INT64_MAX
+ TESTUMAX(64);
+#endif
+
+#define STR(v) #v
+#define Q(v) printf ("sizeof " STR(v) " = %u\n", (unsigned) sizeof (v));
+ if (err_n) {
+ printf ("pstdint.h is not correct. Please use sizes below to correct it:\n");
+ }
+
+ Q(int)
+ Q(unsigned)
+ Q(long int)
+ Q(short int)
+ Q(int8_t)
+ Q(int16_t)
+ Q(int32_t)
+#ifdef INT64_MAX
+ Q(int64_t)
+#endif
+
+ return EXIT_SUCCESS;
+}
+
+#endif
diff --git a/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h b/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h
index a04f3ad12..73973c50d 100644
--- a/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h
+++ b/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h
@@ -26,7 +26,7 @@
# pragma pack(push,1)
# define PACK_STRUCT
#elif defined( __GNUC__ )
-# if defined(__clang__)
+# if !defined(HOST_MINGW)
# define PACK_STRUCT __attribute__((__packed__))
# else
# define PACK_STRUCT __attribute__((gcc_struct, __packed__))
@@ -37,7 +37,7 @@
#if defined(_MSC_VER)
-// C4103: Packing was changed after the inclusion of the header, propably missing #pragma pop
+// C4103: Packing was changed after the inclusion of the header, probably missing #pragma pop
# pragma warning (disable : 4103)
#endif
diff --git a/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp b/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp
index 390363dd1..52574d5ea 100644
--- a/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp
+++ b/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp
@@ -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,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.
----------------------------------------------------------------------
*/
-/** @file DefaultLogger.h
+/** @file DefaultLogger.hpp
*/
#ifndef INCLUDED_AI_DEFAULTLOGGER
@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "NullLogger.hpp"
#include <vector>
-namespace Assimp {
+namespace Assimp {
// ------------------------------------------------------------------------------------
class IOStream;
struct LogStreamInfo;
@@ -57,7 +57,7 @@ struct LogStreamInfo;
#define ASSIMP_DEFAULT_LOG_NAME "AssimpLog.txt"
// ------------------------------------------------------------------------------------
-/** @brief CPP-API: Primary logging facility of Assimp.
+/** @brief CPP-API: Primary logging facility of Assimp.
*
* The library stores its primary #Logger as a static member of this class.
* #get() returns this primary logger. By default the underlying implementation is
@@ -65,123 +65,123 @@ struct LogStreamInfo;
* is turned on. To capture the log output multiple log streams (#LogStream) can be
* attach to the logger. Some default streams for common streaming locations (such as
* a file, std::cout, OutputDebugString()) are also provided.
- *
+ *
* If you wish to customize the logging at an even deeper level supply your own
* implementation of #Logger to #set().
* @note The whole logging stuff causes a small extra overhead for all imports. */
class ASSIMP_API DefaultLogger :
- public Logger {
+ public Logger {
public:
- // ----------------------------------------------------------------------
- /** @brief Creates a logging instance.
- * @param name Name for log file. Only valid in combination
- * with the aiDefaultLogStream_FILE flag.
- * @param severity Log severity, VERBOSE turns on debug messages
- * @param defStreams Default log streams to be attached. Any bitwise
- * combination of the aiDefaultLogStream enumerated values.
- * If #aiDefaultLogStream_FILE is specified but an empty string is
- * passed for 'name', no log file is created at all.
- * @param io IOSystem to be used to open external files (such as the
- * log file). Pass NULL to rely on the default implementation.
- * This replaces the default #NullLogger with a #DefaultLogger instance. */
- static Logger *create(const char* name = ASSIMP_DEFAULT_LOG_NAME,
- LogSeverity severity = NORMAL,
- unsigned int defStreams = aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE,
- IOSystem* io = NULL);
-
- // ----------------------------------------------------------------------
- /** @brief Setup a custom #Logger implementation.
- *
- * Use this if the provided #DefaultLogger class doesn't fit into
- * your needs. If the provided message formatting is OK for you,
- * it's much easier to use #create() and to attach your own custom
- * output streams to it.
- * @param logger Pass NULL to setup a default NullLogger*/
- static void set (Logger *logger);
-
- // ----------------------------------------------------------------------
- /** @brief Getter for singleton instance
- * @return Only instance. This is never null, but it could be a
- * NullLogger. Use isNullLogger to check this.*/
- static Logger *get();
-
- // ----------------------------------------------------------------------
- /** @brief Return whether a #NullLogger is currently active
- * @return true if the current logger is a #NullLogger.
- * Use create() or set() to setup a logger that does actually do
- * something else than just rejecting all log messages. */
- static bool isNullLogger();
-
- // ----------------------------------------------------------------------
- /** @brief Kills the current singleton logger and replaces it with a
- * #NullLogger instance. */
- static void kill();
-
- // ----------------------------------------------------------------------
- /** @copydoc Logger::attachStream */
- bool attachStream(LogStream *pStream,
- unsigned int severity);
-
- // ----------------------------------------------------------------------
- /** @copydoc Logger::detatchStream */
- bool detatchStream(LogStream *pStream,
- unsigned int severity);
+ // ----------------------------------------------------------------------
+ /** @brief Creates a logging instance.
+ * @param name Name for log file. Only valid in combination
+ * with the aiDefaultLogStream_FILE flag.
+ * @param severity Log severity, VERBOSE turns on debug messages
+ * @param defStreams Default log streams to be attached. Any bitwise
+ * combination of the aiDefaultLogStream enumerated values.
+ * If #aiDefaultLogStream_FILE is specified but an empty string is
+ * passed for 'name', no log file is created at all.
+ * @param io IOSystem to be used to open external files (such as the
+ * log file). Pass NULL to rely on the default implementation.
+ * This replaces the default #NullLogger with a #DefaultLogger instance. */
+ static Logger *create(const char* name = ASSIMP_DEFAULT_LOG_NAME,
+ LogSeverity severity = NORMAL,
+ unsigned int defStreams = aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE,
+ IOSystem* io = NULL);
+
+ // ----------------------------------------------------------------------
+ /** @brief Setup a custom #Logger implementation.
+ *
+ * Use this if the provided #DefaultLogger class doesn't fit into
+ * your needs. If the provided message formatting is OK for you,
+ * it's much easier to use #create() and to attach your own custom
+ * output streams to it.
+ * @param logger Pass NULL to setup a default NullLogger*/
+ static void set (Logger *logger);
+
+ // ----------------------------------------------------------------------
+ /** @brief Getter for singleton instance
+ * @return Only instance. This is never null, but it could be a
+ * NullLogger. Use isNullLogger to check this.*/
+ static Logger *get();
+
+ // ----------------------------------------------------------------------
+ /** @brief Return whether a #NullLogger is currently active
+ * @return true if the current logger is a #NullLogger.
+ * Use create() or set() to setup a logger that does actually do
+ * something else than just rejecting all log messages. */
+ static bool isNullLogger();
+
+ // ----------------------------------------------------------------------
+ /** @brief Kills the current singleton logger and replaces it with a
+ * #NullLogger instance. */
+ static void kill();
+
+ // ----------------------------------------------------------------------
+ /** @copydoc Logger::attachStream */
+ bool attachStream(LogStream *pStream,
+ unsigned int severity);
+
+ // ----------------------------------------------------------------------
+ /** @copydoc Logger::detatchStream */
+ bool detatchStream(LogStream *pStream,
+ unsigned int severity);
private:
- // ----------------------------------------------------------------------
- /** @briefPrivate construction for internal use by create().
- * @param severity Logging granularity */
- DefaultLogger(LogSeverity severity);
-
- // ----------------------------------------------------------------------
- /** @briefDestructor */
- ~DefaultLogger();
+ // ----------------------------------------------------------------------
+ /** @briefPrivate construction for internal use by create().
+ * @param severity Logging granularity */
+ explicit DefaultLogger(LogSeverity severity);
+
+ // ----------------------------------------------------------------------
+ /** @briefDestructor */
+ ~DefaultLogger();
private:
- /** @brief Logs debug infos, only been written when severity level VERBOSE is set */
- void OnDebug(const char* message);
+ /** @brief Logs debug infos, only been written when severity level VERBOSE is set */
+ void OnDebug(const char* message);
+
+ /** @brief Logs an info message */
+ void OnInfo(const char* message);
- /** @brief Logs an info message */
- void OnInfo(const char* message);
+ /** @brief Logs a warning message */
+ void OnWarn(const char* message);
- /** @brief Logs a warning message */
- void OnWarn(const char* message);
-
- /** @brief Logs an error message */
- void OnError(const char* message);
+ /** @brief Logs an error message */
+ void OnError(const char* message);
- // ----------------------------------------------------------------------
- /** @brief Writes a message to all streams */
- void WriteToStreams(const char* message, ErrorSeverity ErrorSev );
+ // ----------------------------------------------------------------------
+ /** @brief Writes a message to all streams */
+ void WriteToStreams(const char* message, ErrorSeverity ErrorSev );
- // ----------------------------------------------------------------------
- /** @brief Returns the thread id.
- * @note This is an OS specific feature, if not supported, a
- * zero will be returned.
- */
- unsigned int GetThreadID();
+ // ----------------------------------------------------------------------
+ /** @brief Returns the thread id.
+ * @note This is an OS specific feature, if not supported, a
+ * zero will be returned.
+ */
+ unsigned int GetThreadID();
private:
- // Aliases for stream container
- typedef std::vector<LogStreamInfo*> StreamArray;
- typedef std::vector<LogStreamInfo*>::iterator StreamIt;
- typedef std::vector<LogStreamInfo*>::const_iterator ConstStreamIt;
+ // Aliases for stream container
+ typedef std::vector<LogStreamInfo*> StreamArray;
+ typedef std::vector<LogStreamInfo*>::iterator StreamIt;
+ typedef std::vector<LogStreamInfo*>::const_iterator ConstStreamIt;
- //! only logging instance
- static Logger *m_pLogger;
- static NullLogger s_pNullLogger;
+ //! only logging instance
+ static Logger *m_pLogger;
+ static NullLogger s_pNullLogger;
- //! Attached streams
- StreamArray m_StreamArray;
+ //! Attached streams
+ StreamArray m_StreamArray;
- bool noRepeatMsg;
- char lastMsg[MAX_LOG_MESSAGE_LENGTH*2];
- size_t lastLen;
+ bool noRepeatMsg;
+ char lastMsg[MAX_LOG_MESSAGE_LENGTH*2];
+ size_t lastLen;
};
// ------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/include/assimp/Exporter.hpp b/src/3rdparty/assimp/include/assimp/Exporter.hpp
index 55cc068e3..079060f4b 100644
--- a/src/3rdparty/assimp/include/assimp/Exporter.hpp
+++ b/src/3rdparty/assimp/include/assimp/Exporter.hpp
@@ -7,8 +7,8 @@ Copyright (c) 2006-2011, assimp 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 @@ 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 export.hpp
+/** @file Exporter.hpp
* @brief Defines the CPP-API for the Assimp export interface
*/
#ifndef AI_EXPORT_HPP_INC
@@ -48,268 +48,457 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_EXPORT
#include "cexport.h"
+#include <map>
-namespace Assimp {
- class ExporterPimpl;
- class IOSystem;
+namespace Assimp {
+ class ExporterPimpl;
+ class IOSystem;
// ----------------------------------------------------------------------------------
-/** CPP-API: The Exporter class forms an C++ interface to the export functionality
+/** CPP-API: The Exporter class forms an C++ interface to the export functionality
* of the Open Asset Import Library. Note that the export interface is available
* only if Assimp has been built with ASSIMP_BUILD_NO_EXPORT not defined.
- *
+ *
* The interface is modelled after the importer interface and mostly
* symmetric. The same rules for threading etc. apply.
*
* In a nutshell, there are two export interfaces: #Export, which writes the
- * output file(s) either to the regular file system or to a user-supplied
+ * output file(s) either to the regular file system or to a user-supplied
* #IOSystem, and #ExportToBlob which returns a linked list of memory
* buffers (blob), each referring to one output file (in most cases
* there will be only one output file of course, but this extra complexity is
- * needed since Assimp aims at supporting a wide range of file formats).
- *
- * #ExportToBlob is especially useful if you intend to work
- * with the data in-memory.
+ * needed since Assimp aims at supporting a wide range of file formats).
+ *
+ * #ExportToBlob is especially useful if you intend to work
+ * with the data in-memory.
*/
+
+class ASSIMP_API ExportProperties;
+
class ASSIMP_API Exporter
- // TODO: causes good ol' base class has no dll interface warning
+ // TODO: causes good ol' base class has no dll interface warning
//#ifdef __cplusplus
-// : public boost::noncopyable
+// : public boost::noncopyable
//#endif // __cplusplus
{
public:
- /** Function pointer type of a Export worker function */
- typedef void (*fpExportFunc)(const char*,IOSystem*,const aiScene*);
+ /** Function pointer type of a Export worker function */
+ typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+
+ /** Internal description of an Assimp export format option */
+ struct ExportFormatEntry
+ {
+ /// Public description structure to be returned by aiGetExportFormatDescription()
+ aiExportFormatDesc mDescription;
+
+ // Worker function to do the actual exporting
+ fpExportFunc mExportFunction;
+
+ // Postprocessing steps to be executed PRIOR to invoking mExportFunction
+ unsigned int mEnforcePP;
+
+ // Constructor to fill all entries
+ ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
+ {
+ mDescription.id = pId;
+ mDescription.description = pDesc;
+ mDescription.fileExtension = pExtension;
+ mExportFunction = pFunction;
+ mEnforcePP = pEnforcePP;
+ }
+
+ ExportFormatEntry() :
+ mExportFunction()
+ , mEnforcePP()
+ {
+ mDescription.id = NULL;
+ mDescription.description = NULL;
+ mDescription.fileExtension = NULL;
+ }
+ };
- /** Internal description of an Assimp export format option */
- struct ExportFormatEntry
- {
- /// Public description structure to be returned by aiGetExportFormatDescription()
- aiExportFormatDesc mDescription;
- // Worker function to do the actual exporting
- fpExportFunc mExportFunction;
+public:
- // Postprocessing steps to be executed PRIOR to invoking mExportFunction
- unsigned int mEnforcePP;
- // Constructor to fill all entries
- ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
- {
- mDescription.id = pId;
- mDescription.description = pDesc;
- mDescription.fileExtension = pExtension;
- mExportFunction = pFunction;
- mEnforcePP = pEnforcePP;
- }
+ Exporter();
+ ~Exporter();
- ExportFormatEntry() : mExportFunction(), mEnforcePP() {}
- };
+public:
-public:
+ // -------------------------------------------------------------------
+ /** Supplies a custom IO handler to the exporter to use to open and
+ * access files.
+ *
+ * If you need #Export to use custom IO logic to access the files,
+ * you need to supply a custom implementation of IOSystem and
+ * IOFile to the exporter.
+ *
+ * #Exporter takes ownership of the object and will destroy it
+ * afterwards. The previously assigned handler will be deleted.
+ * Pass NULL to take again ownership of your IOSystem and reset Assimp
+ * to use its default implementation, which uses plain file IO.
+ *
+ * @param pIOHandler The IO handler to be used in all file accesses
+ * of the Importer. */
+ void SetIOHandler( IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Retrieves the IO handler that is currently set.
+ * You can use #IsDefaultIOHandler() to check whether the returned
+ * interface is the default IO handler provided by ASSIMP. The default
+ * handler is active as long the application doesn't supply its own
+ * custom IO handler via #SetIOHandler().
+ * @return A valid IOSystem interface, never NULL. */
+ IOSystem* GetIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Checks whether a default IO handler is active
+ * A default handler is active as long the application doesn't
+ * supply its own custom IO handler via #SetIOHandler().
+ * @return true by default */
+ bool IsDefaultIOHandler() const;
+
+
+
+ // -------------------------------------------------------------------
+ /** Exports the given scene to a chosen file format. Returns the exported
+ * data as a binary blob which you can write into a file or something.
+ * When you're done with the data, simply let the #Exporter instance go
+ * out of scope to have it released automatically.
+ * @param pScene The scene to export. Stays in possession of the caller,
+ * is not changed by the function.
+ * @param pFormatId ID string to specify to which format you want to
+ * export to. Use
+ * #GetExportFormatCount / #GetExportFormatDescription to learn which
+ * export formats are available.
+ * @param pPreprocessing See the documentation for #Export
+ * @return the exported data or NULL in case of error.
+ * @note If the Exporter instance did already hold a blob from
+ * a previous call to #ExportToBlob, it will be disposed.
+ * Any IO handlers set via #SetIOHandler are ignored here.
+ * @note Use aiCopyScene() to get a modifiable copy of a previously
+ * imported scene. */
+ const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+ inline const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+
+
+ // -------------------------------------------------------------------
+ /** Convenience function to export directly to a file. Use
+ * #SetIOSystem to supply a custom IOSystem to gain fine-grained control
+ * about the output data flow of the export process.
+ * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be NULL.
+ * @param pPath Full target file name. Target must be accessible.
+ * @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
+ * flags, but in reality only a subset of them makes sense here. Specifying
+ * 'preprocessing' flags is useful if the input scene does not conform to
+ * Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
+ * In short, this means the geometry data should use a right-handed coordinate systems, face
+ * winding should be counter-clockwise and the UV coordinate origin is assumed to be in
+ * the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+ * #aiProcess_FlipWindingOrder flags are used in the import side to allow users
+ * to have those defaults automatically adapted to their conventions. Specifying those flags
+ * for exporting has the opposite effect, respectively. Some other of the
+ * #aiPostProcessSteps enumerated values may be useful as well, but you'll need
+ * to try out what their effect on the exported file is. Many formats impose
+ * their own restrictions on the structure of the geometry stored therein,
+ * so some preprocessing may have little or no effect at all, or may be
+ * redundant as exporters would apply them anyhow. A good example
+ * is triangulation - whilst you can enforce it by specifying
+ * the #aiProcess_Triangulate flag, most export formats support only
+ * triangulate data so they would run the step even if it wasn't requested.
+ *
+ * If assimp detects that the input scene was directly taken from the importer side of
+ * the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
+ * any postprocessing steps already applied to the scene will not be applied again, unless
+ * they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+ * #aiProcess_FlipWindingOrder).
+ * @return AI_SUCCESS if everything was fine.
+ * @note Use aiCopyScene() to get a modifiable copy of a previously
+ * imported scene.*/
+ aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+ inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL);
+
+
+ // -------------------------------------------------------------------
+ /** Returns an error description of an error that occurred in #Export
+ * or #ExportToBlob
+ *
+ * Returns an empty string if no error occurred.
+ * @return A description of the last error, an empty string if no
+ * error occurred. The string is never NULL.
+ *
+ * @note The returned function remains valid until one of the
+ * following methods is called: #Export, #ExportToBlob, #FreeBlob */
+ const char* GetErrorString() const;
+
+
+ // -------------------------------------------------------------------
+ /** Return the blob obtained from the last call to #ExportToBlob */
+ const aiExportDataBlob* GetBlob() const;
+
+
+ // -------------------------------------------------------------------
+ /** Orphan the blob from the last call to #ExportToBlob. This means
+ * the caller takes ownership and is thus responsible for calling
+ * the C API function #aiReleaseExportBlob to release it. */
+ const aiExportDataBlob* GetOrphanedBlob() const;
+
+
+ // -------------------------------------------------------------------
+ /** Frees the current blob.
+ *
+ * The function does nothing if no blob has previously been
+ * previously produced via #ExportToBlob. #FreeBlob is called
+ * automatically by the destructor. The only reason to call
+ * it manually would be to reclain as much storage as possible
+ * without giving up the #Exporter instance yet. */
+ void FreeBlob( );
+
+
+ // -------------------------------------------------------------------
+ /** Returns the number of export file formats available in the current
+ * Assimp build. Use #Exporter::GetExportFormatDescription to
+ * retrieve infos of a specific export format.
+ *
+ * This includes built-in exporters as well as exporters registered
+ * using #RegisterExporter.
+ **/
+ size_t GetExportFormatCount() const;
+
+
+ // -------------------------------------------------------------------
+ /** Returns a description of the nth export file format. Use #
+ * #Exporter::GetExportFormatCount to learn how many export
+ * formats are supported.
+ *
+ * The returned pointer is of static storage duration iff the
+ * pIndex pertains to a built-in exporter (i.e. one not registered
+ * via #RegistrerExporter). It is restricted to the life-time of the
+ * #Exporter instance otherwise.
+ *
+ * @param pIndex Index of the export format to retrieve information
+ * for. Valid range is 0 to #Exporter::GetExportFormatCount
+ * @return A description of that specific export format.
+ * NULL if pIndex is out of range. */
+ const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
+
+
+ // -------------------------------------------------------------------
+ /** Register a custom exporter. Custom export formats are limited to
+ * to the current #Exporter instance and do not affect the
+ * library globally. The indexes under which the format's
+ * export format description can be queried are assigned
+ * monotonously.
+ * @param desc Exporter description.
+ * @return aiReturn_SUCCESS if the export format was successfully
+ * registered. A common cause that would prevent an exporter
+ * from being registered is that its format id is already
+ * occupied by another format. */
+ aiReturn RegisterExporter(const ExportFormatEntry& desc);
+
+
+ // -------------------------------------------------------------------
+ /** Remove an export format previously registered with #RegisterExporter
+ * from the #Exporter instance (this can also be used to drop
+ * builtin exporters because those are implicitly registered
+ * using #RegisterExporter).
+ * @param id Format id to be unregistered, this refers to the
+ * 'id' field of #aiExportFormatDesc.
+ * @note Calling this method on a format description not yet registered
+ * has no effect.*/
+ void UnregisterExporter(const char* id);
+
+
+protected:
+
+ // Just because we don't want you to know how we're hacking around.
+ ExporterPimpl* pimpl;
+};
-
- Exporter();
- ~Exporter();
+class ASSIMP_API ExportProperties
+{
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;
- // -------------------------------------------------------------------
- /** Supplies a custom IO handler to the exporter to use to open and
- * access files.
- *
- * If you need #Export to use custom IO logic to access the files,
- * you need to supply a custom implementation of IOSystem and
- * IOFile to the exporter.
- *
- * #Exporter takes ownership of the object and will destroy it
- * afterwards. The previously assigned handler will be deleted.
- * Pass NULL to take again ownership of your IOSystem and reset Assimp
- * to use its default implementation, which uses plain file IO.
- *
- * @param pIOHandler The IO handler to be used in all file accesses
- * of the Importer. */
- void SetIOHandler( IOSystem* pIOHandler);
-
- // -------------------------------------------------------------------
- /** Retrieves the IO handler that is currently set.
- * You can use #IsDefaultIOHandler() to check whether the returned
- * interface is the default IO handler provided by ASSIMP. The default
- * handler is active as long the application doesn't supply its own
- * custom IO handler via #SetIOHandler().
- * @return A valid IOSystem interface, never NULL. */
- IOSystem* GetIOHandler() const;
-
- // -------------------------------------------------------------------
- /** Checks whether a default IO handler is active
- * A default handler is active as long the application doesn't
- * supply its own custom IO handler via #SetIOHandler().
- * @return true by default */
- bool IsDefaultIOHandler() const;
-
-
-
- // -------------------------------------------------------------------
- /** Exports the given scene to a chosen file format. Returns the exported
- * data as a binary blob which you can write into a file or something.
- * When you're done with the data, simply let the #Exporter instance go
- * out of scope to have it released automatically.
- * @param pScene The scene to export. Stays in possession of the caller,
- * is not changed by the function.
- * @param pFormatId ID string to specify to which format you want to
- * export to. Use
- * #GetExportFormatCount / #GetExportFormatDescription to learn which
- * export formats are available.
- * @param pPreprocessing See the documentation for #Export
- * @return the exported data or NULL in case of error.
- * @note If the Exporter instance did already hold a blob from
- * a previous call to #ExportToBlob, it will be disposed.
- * Any IO handlers set via #SetIOHandler are ignored here.
- * @note Use aiCopyScene() to get a modifiable copy of a previously
- * imported scene. */
- const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u );
- inline const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u );
-
-
- // -------------------------------------------------------------------
- /** Convenience function to export directly to a file. Use
- * #SetIOSystem to supply a custom IOSystem to gain fine-grained control
- * about the output data flow of the export process.
- * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be NULL.
- * @param pPath Full target file name. Target must be accessible.
- * @param pPreprocessing Accepts any choice of the #aiPostProcessing enumerated
- * flags, but in reality only a subset of them makes sense here. Specifying
- * 'preprocessing' flags is useful if the input scene does not conform to
- * Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
- * In short, this means the geometry data should use a right-handed coordinate systems, face
- * winding should be counter-clockwise and the UV coordinate origin is assumed to be in
- * the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
- * #aiProcess_FlipWindingOrder flags are used in the import side to allow users
- * to have those defaults automatically adapted to their conventions. Specifying those flags
- * for exporting has the opposite effect, respectively. Some other of the
- * #aiPostProcessSteps enumerated values may be useful as well, but you'll need
- * to try out what their effect on the exported file is. Many formats impose
- * their own restrictions on the structure of the geometry stored therein,
- * so some preprocessing may have little or no effect at all, or may be
- * redundant as exporters would apply them anyhow. A good example
- * is triangulation - whilst you can enforce it by specifying
- * the #aiProcess_Triangulate flag, most export formats support only
- * triangulate data so they would run the step even if it wasn't requested.
- *
- * If assimp detects that the input scene was directly taken from the importer side of
- * the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
- * any postprocessing steps already applied to the scene will not be applied again, unless
- * they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
- * #aiProcess_FlipWindingOrder).
- * @return AI_SUCCESS if everything was fine.
- * @note Use aiCopyScene() to get a modifiable copy of a previously
- * imported scene.*/
- aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u);
- inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing = 0u);
-
-
- // -------------------------------------------------------------------
- /** Returns an error description of an error that occurred in #Export
- * or #ExportToBlob
- *
- * Returns an empty string if no error occurred.
- * @return A description of the last error, an empty string if no
- * error occurred. The string is never NULL.
- *
- * @note The returned function remains valid until one of the
- * following methods is called: #Export, #ExportToBlob, #FreeBlob */
- const char* GetErrorString() const;
-
-
- // -------------------------------------------------------------------
- /** Return the blob obtained from the last call to #ExportToBlob */
- const aiExportDataBlob* GetBlob() const;
-
-
- // -------------------------------------------------------------------
- /** Orphan the blob from the last call to #ExportToBlob. This means
- * the caller takes ownership and is thus responsible for calling
- * the C API function #aiReleaseExportBlob to release it. */
- const aiExportDataBlob* GetOrphanedBlob() const;
-
-
- // -------------------------------------------------------------------
- /** Frees the current blob.
- *
- * The function does nothing if no blob has previously been
- * previously produced via #ExportToBlob. #FreeBlob is called
- * automatically by the destructor. The only reason to call
- * it manually would be to reclain as much storage as possible
- * without giving up the #Exporter instance yet. */
- void FreeBlob( );
-
-
- // -------------------------------------------------------------------
- /** Returns the number of export file formats available in the current
- * Assimp build. Use #Exporter::GetExportFormatDescription to
- * retrieve infos of a specific export format */
- size_t GetExportFormatCount() const;
-
-
- // -------------------------------------------------------------------
- /** Returns a description of the nth export file format. Use #
- * #Exporter::GetExportFormatCount to learn how many export
- * formats are supported.
- * @param pIndex Index of the export format to retrieve information
- * for. Valid range is 0 to #Exporter::GetExportFormatCount
- * @return A description of that specific export format.
- * NULL if pIndex is out of range. */
- const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
-
-
- // -------------------------------------------------------------------
- /** Register a custom exporter. Custom export formats are limited to
- * to the current #Exporter instance and do not affect the
- * library globally.
- * @param desc Exporter description.
- * @return aiReturn_SUCCESS if the export format was successfully
- * registered. A common cause that would prevent an exporter
- * from being registered is that its format id is already
- * occupied by another format. */
- aiReturn RegisterExporter(const ExportFormatEntry& desc);
-
-
- // -------------------------------------------------------------------
- /** Remove an export format previously registered with #RegisterExporter
- * from the #Exporter instance (this can also be used to drop
- * builtin exporters because those are implicitly registered
- * using #RegisterExporter).
- * @param id Format id to be unregistered, this refers to the
- * 'id' field of #aiExportFormatDesc.
- * @note Calling this method on a format description not yet registered
- * has no effect.*/
- void UnregisterExporter(const char* id);
+public:
+ /** Standard constructor
+ * @see ExportProperties()
+ */
+
+ ExportProperties();
+
+ // -------------------------------------------------------------------
+ /** Copy constructor.
+ *
+ * This copies the configuration properties of another ExportProperties.
+ * @see ExportProperties(const ExportProperties& other)
+ */
+ ExportProperties(const ExportProperties& other);
+
+ // -------------------------------------------------------------------
+ /** Set an integer configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX and are simple strings).
+ * @param iValue New value of the property
+ * @return true if the property was set before. The new value replaces
+ * the previous value in this case.
+ * @note Property of different types (float, int, string ..) are kept
+ * on different stacks, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ bool SetPropertyInteger(const char* szName, int iValue);
+
+ // -------------------------------------------------------------------
+ /** Set a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyBool(const char* szName, bool value) {
+ return SetPropertyInteger(szName,value);
+ }
+
+ // -------------------------------------------------------------------
+ /** Set a floating-point configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyFloat(const char* szName, float fValue);
+
+ // -------------------------------------------------------------------
+ /** Set a string configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyString(const char* szName, const std::string& sValue);
+
+ // -------------------------------------------------------------------
+ /** Set a matrix configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue);
+
+ // -------------------------------------------------------------------
+ /** Get a configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX).
+ * @param iErrorReturn Value that is returned if the property
+ * is not found.
+ * @return Current value of the property
+ * @note Property of different types (float, int, string ..) are kept
+ * on different lists, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ int GetPropertyInteger(const char* szName,
+ int iErrorReturn = 0xffffffff) const;
+
+ // -------------------------------------------------------------------
+ /** Get a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see GetPropertyInteger()
+ */
+ bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
+ return GetPropertyInteger(szName,bErrorReturn)!=0;
+ }
+
+ // -------------------------------------------------------------------
+ /** Get a floating-point configuration property
+ * @see GetPropertyInteger()
+ */
+ float GetPropertyFloat(const char* szName,
+ float fErrorReturn = 10e10f) const;
+
+ // -------------------------------------------------------------------
+ /** Get a string configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const std::string GetPropertyString(const char* szName,
+ const std::string& sErrorReturn = "") const;
+
+ // -------------------------------------------------------------------
+ /** Get a matrix configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
+
+ // -------------------------------------------------------------------
+ /** Determine a integer configuration property has been set.
+ * @see HasPropertyInteger()
+ */
+ bool HasPropertyInteger(const char* szName) const;
+
+ /** Determine a boolean configuration property has been set.
+ * @see HasPropertyBool()
+ */
+ bool HasPropertyBool(const char* szName) const;
+
+ /** Determine a boolean configuration property has been set.
+ * @see HasPropertyFloat()
+ */
+ bool HasPropertyFloat(const char* szName) const;
+
+ /** Determine a String configuration property has been set.
+ * @see HasPropertyString()
+ */
+ bool HasPropertyString(const char* szName) const;
+
+ /** Determine a Matrix configuration property has been set.
+ * @see HasPropertyMatrix()
+ */
+ bool HasPropertyMatrix(const char* szName) const;
protected:
- // Just because we don't want you to know how we're hacking around.
- ExporterPimpl* pimpl;
+ /** List of integer properties */
+ IntPropertyMap mIntProperties;
+
+ /** List of floating-point properties */
+ FloatPropertyMap mFloatProperties;
+
+ /** List of string properties */
+ StringPropertyMap mStringProperties;
+
+ /** List of Matrix properties */
+ MatrixPropertyMap mMatrixProperties;
};
// ----------------------------------------------------------------------------------
-inline const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing )
+inline const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing, const ExportProperties* pProperties)
{
- return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing);
+ return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties);
}
// ----------------------------------------------------------------------------------
-inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing )
+inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
{
- return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing);
+ return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties);
}
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_EXPORT
#endif // AI_EXPORT_HPP_INC
-
diff --git a/src/3rdparty/assimp/include/assimp/IOStream.hpp b/src/3rdparty/assimp/include/assimp/IOStream.hpp
index a36e65003..6cc231b3d 100644
--- a/src/3rdparty/assimp/include/assimp/IOStream.hpp
+++ b/src/3rdparty/assimp/include/assimp/IOStream.hpp
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file IOStream.h
- * @brief File I/O wrappers for C++.
+/** @file IOStream.hpp
+ * @brief File I/O wrappers for C++.
*/
#ifndef AI_IOSTREAM_H_INC
@@ -48,11 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "types.h"
#ifndef __cplusplus
-# error This header requires C++ to be used. aiFileIO.h is the \
- corresponding C interface.
+# error This header requires C++ to be used. aiFileIO.h is the \
+ corresponding C interface.
#endif
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
/** @brief CPP-API: Class to handle file I/O for C++
@@ -63,74 +63,74 @@ namespace Assimp {
*/
class ASSIMP_API IOStream
#ifndef SWIG
- : public Intern::AllocateFromAssimpHeap
+ : public Intern::AllocateFromAssimpHeap
#endif
{
protected:
- /** Constructor protected, use IOSystem::Open() to create an instance. */
- IOStream(void);
+ /** Constructor protected, use IOSystem::Open() to create an instance. */
+ IOStream(void);
public:
- // -------------------------------------------------------------------
- /** @brief Destructor. Deleting the object closes the underlying file,
- * alternatively you may use IOSystem::Close() to release the file.
- */
- virtual ~IOStream();
-
- // -------------------------------------------------------------------
- /** @brief Read from the file
- *
- * See fread() for more details
- * This fails for write-only files */
- virtual size_t Read(void* pvBuffer,
- size_t pSize,
- size_t pCount) = 0;
-
- // -------------------------------------------------------------------
- /** @brief Write to the file
- *
- * See fwrite() for more details
- * This fails for read-only files */
- virtual size_t Write(const void* pvBuffer,
- size_t pSize,
- size_t pCount) = 0;
-
- // -------------------------------------------------------------------
- /** @brief Set the read/write cursor of the file
- *
- * Note that the offset is _negative_ for aiOrigin_END.
- * See fseek() for more details */
- virtual aiReturn Seek(size_t pOffset,
- aiOrigin pOrigin) = 0;
-
- // -------------------------------------------------------------------
- /** @brief Get the current position of the read/write cursor
- *
- * See ftell() for more details */
+ // -------------------------------------------------------------------
+ /** @brief Destructor. Deleting the object closes the underlying file,
+ * alternatively you may use IOSystem::Close() to release the file.
+ */
+ virtual ~IOStream();
+
+ // -------------------------------------------------------------------
+ /** @brief Read from the file
+ *
+ * See fread() for more details
+ * This fails for write-only files */
+ virtual size_t Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Write to the file
+ *
+ * See fwrite() for more details
+ * This fails for read-only files */
+ virtual size_t Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Set the read/write cursor of the file
+ *
+ * Note that the offset is _negative_ for aiOrigin_END.
+ * See fseek() for more details */
+ virtual aiReturn Seek(size_t pOffset,
+ aiOrigin pOrigin) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Get the current position of the read/write cursor
+ *
+ * See ftell() for more details */
virtual size_t Tell() const = 0;
- // -------------------------------------------------------------------
- /** @brief Returns filesize
- * Returns the filesize. */
- virtual size_t FileSize() const = 0;
+ // -------------------------------------------------------------------
+ /** @brief Returns filesize
+ * Returns the filesize. */
+ virtual size_t FileSize() const = 0;
- // -------------------------------------------------------------------
- /** @brief Flush the contents of the file buffer (for writers)
- * See fflush() for more details.
- */
- virtual void Flush() = 0;
+ // -------------------------------------------------------------------
+ /** @brief Flush the contents of the file buffer (for writers)
+ * See fflush() for more details.
+ */
+ virtual void Flush() = 0;
}; //! class IOStream
// ----------------------------------------------------------------------------------
inline IOStream::IOStream()
{
- // empty
+ // empty
}
// ----------------------------------------------------------------------------------
inline IOStream::~IOStream()
{
- // empty
+ // empty
}
// ----------------------------------------------------------------------------------
} //!namespace Assimp
diff --git a/src/3rdparty/assimp/include/assimp/IOSystem.hpp b/src/3rdparty/assimp/include/assimp/IOSystem.hpp
index dfd90b92f..abd7e5837 100644
--- a/src/3rdparty/assimp/include/assimp/IOSystem.hpp
+++ b/src/3rdparty/assimp/include/assimp/IOSystem.hpp
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file IOSystem.h
+/** @file IOSystem.hpp
* @brief File system wrapper for C++. Inherit this class to supply
* custom file handling logic to the Import library.
*/
@@ -48,12 +48,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_IOSYSTEM_H_INC
#ifndef __cplusplus
-# error This header requires C++ to be used. aiFileIO.h is the \
- corresponding C interface.
+# error This header requires C++ to be used. aiFileIO.h is the \
+ corresponding C interface.
#endif
#include "types.h"
-namespace Assimp {
+
+#include <vector>
+
+namespace Assimp {
class IOStream;
// ---------------------------------------------------------------------------
@@ -66,160 +69,222 @@ class IOStream;
* @see Importer::SetIOHandler() */
class ASSIMP_API IOSystem
#ifndef SWIG
- : public Intern::AllocateFromAssimpHeap
+ : public Intern::AllocateFromAssimpHeap
#endif
{
public:
- // -------------------------------------------------------------------
- /** @brief Default constructor.
- *
- * Create an instance of your derived class and assign it to an
- * #Assimp::Importer instance by calling Importer::SetIOHandler().
- */
- IOSystem();
+ // -------------------------------------------------------------------
+ /** @brief Default constructor.
+ *
+ * Create an instance of your derived class and assign it to an
+ * #Assimp::Importer instance by calling Importer::SetIOHandler().
+ */
+ IOSystem();
- // -------------------------------------------------------------------
- /** @brief Virtual destructor.
- *
- * It is safe to be called from within DLL Assimp, we're constructed
- * on Assimp's heap.
- */
- virtual ~IOSystem();
+ // -------------------------------------------------------------------
+ /** @brief Virtual destructor.
+ *
+ * It is safe to be called from within DLL Assimp, we're constructed
+ * on Assimp's heap.
+ */
+ virtual ~IOSystem();
public:
- // -------------------------------------------------------------------
- /** @brief For backward compatibility
- * @see Exists(const char*)
- */
- AI_FORCE_INLINE bool Exists( const std::string& pFile) const;
-
- // -------------------------------------------------------------------
- /** @brief Tests for the existence of a file at the given path.
- *
- * @param pFile Path to the file
- * @return true if there is a file with this path, else false.
- */
-
- virtual bool Exists( const char* pFile) const = 0;
-
-
-
- // -------------------------------------------------------------------
- /** @brief Returns the system specific directory separator
- * @return System specific directory separator
- */
- virtual char getOsSeparator() const = 0;
-
-
- // -------------------------------------------------------------------
- /** @brief Open a new file with a given path.
- *
- * When the access to the file is finished, call Close() to release
- * all associated resources (or the virtual dtor of the IOStream).
- *
- * @param pFile Path to the file
- * @param pMode Desired file I/O mode. Required are: "wb", "w", "wt",
- * "rb", "r", "rt".
- *
- * @return New IOStream interface allowing the lib to access
- * the underlying file.
- * @note When implementing this class to provide custom IO handling,
- * you probably have to supply an own implementation of IOStream as well.
- */
- virtual IOStream* Open(const char* pFile,
- const char* pMode = "rb") = 0;
-
- // -------------------------------------------------------------------
- /** @brief For backward compatibility
- * @see Open(const char*, const char*)
- */
- inline IOStream* Open(const std::string& pFile,
- const std::string& pMode = std::string("rb"));
-
-
-
- // -------------------------------------------------------------------
- /** @brief Closes the given file and releases all resources
- * associated with it.
- * @param pFile The file instance previously created by Open().
- */
- virtual void Close( IOStream* pFile) = 0;
-
- // -------------------------------------------------------------------
- /** @brief Compares two paths and check whether the point to
- * identical files.
- *
- * The dummy implementation of this virtual member performs a
- * case-insensitive comparison of the given strings. The default IO
- * system implementation uses OS mechanisms to convert relative into
- * absolute paths, so the result can be trusted.
- * @param one First file
- * @param second Second file
- * @return true if the paths point to the same file. The file needn't
- * be existing, however.
- */
- virtual bool ComparePaths (const char* one,
- const char* second) const;
-
- // -------------------------------------------------------------------
- /** @brief For backward compatibility
- * @see ComparePaths(const char*, const char*)
- */
- inline bool ComparePaths (const std::string& one,
- const std::string& second) const;
+ // -------------------------------------------------------------------
+ /** @brief For backward compatibility
+ * @see Exists(const char*)
+ */
+ AI_FORCE_INLINE bool Exists( const std::string& pFile) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Tests for the existence of a file at the given path.
+ *
+ * @param pFile Path to the file
+ * @return true if there is a file with this path, else false.
+ */
+ virtual bool Exists( const char* pFile) const = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns the system specific directory separator
+ * @return System specific directory separator
+ */
+ virtual char getOsSeparator() const = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Open a new file with a given path.
+ *
+ * When the access to the file is finished, call Close() to release
+ * all associated resources (or the virtual dtor of the IOStream).
+ *
+ * @param pFile Path to the file
+ * @param pMode Desired file I/O mode. Required are: "wb", "w", "wt",
+ * "rb", "r", "rt".
+ *
+ * @return New IOStream interface allowing the lib to access
+ * the underlying file.
+ * @note When implementing this class to provide custom IO handling,
+ * you probably have to supply an own implementation of IOStream as well.
+ */
+ virtual IOStream* Open(const char* pFile,
+ const char* pMode = "rb") = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief For backward compatibility
+ * @see Open(const char*, const char*)
+ */
+ inline IOStream* Open(const std::string& pFile,
+ const std::string& pMode = std::string("rb"));
+
+ // -------------------------------------------------------------------
+ /** @brief Closes the given file and releases all resources
+ * associated with it.
+ * @param pFile The file instance previously created by Open().
+ */
+ virtual void Close( IOStream* pFile) = 0;
+
+ // -------------------------------------------------------------------
+ /** @brief Compares two paths and check whether the point to
+ * identical files.
+ *
+ * The dummy implementation of this virtual member performs a
+ * case-insensitive comparison of the given strings. The default IO
+ * system implementation uses OS mechanisms to convert relative into
+ * absolute paths, so the result can be trusted.
+ * @param one First file
+ * @param second Second file
+ * @return true if the paths point to the same file. The file needn't
+ * be existing, however.
+ */
+ virtual bool ComparePaths (const char* one,
+ const char* second) const;
+
+ // -------------------------------------------------------------------
+ /** @brief For backward compatibility
+ * @see ComparePaths(const char*, const char*)
+ */
+ inline bool ComparePaths (const std::string& one,
+ const std::string& second) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Pushes a new directory onto the directory stack.
+ * @param path Path to push onto the stack.
+ * @return True, when push was successful, false if path is empty.
+ */
+ virtual bool PushDirectory( const std::string &path );
+
+ // -------------------------------------------------------------------
+ /** @brief Returns the top directory from the stack.
+ * @return The directory on the top of the stack.
+ * Returns empty when no directory was pushed to the stack.
+ */
+ virtual const std::string &CurrentDirectory() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns the number of directories stored on the stack.
+ * @return The number of directories of the stack.
+ */
+ virtual size_t StackSize() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Pops the top directory from the stack.
+ * @return True, when a directory was on the stack. False if no
+ * directory was on the stack.
+ */
+ virtual bool PopDirectory();
+
+private:
+ std::vector<std::string> m_pathStack;
};
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE IOSystem::IOSystem()
+AI_FORCE_INLINE IOSystem::IOSystem() :
+ m_pathStack()
{
- // empty
+ // empty
}
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE IOSystem::~IOSystem()
+AI_FORCE_INLINE IOSystem::~IOSystem()
{
- // empty
+ // empty
}
// ----------------------------------------------------------------------------
// For compatibility, the interface of some functions taking a std::string was
-// changed to const char* to avoid crashes between binary incompatible STL
+// changed to const char* to avoid crashes between binary incompatible STL
// versions. This code her is inlined, so it shouldn't cause any problems.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
AI_FORCE_INLINE IOStream* IOSystem::Open(const std::string& pFile,
- const std::string& pMode)
+ const std::string& pMode)
{
- // NOTE:
- // For compatibility, interface was changed to const char* to
- // avoid crashes between binary incompatible STL versions
- return Open(pFile.c_str(),pMode.c_str());
+ // NOTE:
+ // For compatibility, interface was changed to const char* to
+ // avoid crashes between binary incompatible STL versions
+ return Open(pFile.c_str(),pMode.c_str());
}
// ----------------------------------------------------------------------------
AI_FORCE_INLINE bool IOSystem::Exists( const std::string& pFile) const
{
- // NOTE:
- // For compatibility, interface was changed to const char* to
- // avoid crashes between binary incompatible STL versions
- return Exists(pFile.c_str());
+ // NOTE:
+ // For compatibility, interface was changed to const char* to
+ // avoid crashes between binary incompatible STL versions
+ return Exists(pFile.c_str());
}
// ----------------------------------------------------------------------------
-inline bool IOSystem::ComparePaths (const std::string& one,
- const std::string& second) const
+inline bool IOSystem::ComparePaths (const std::string& one,
+ const std::string& second) const
{
- // NOTE:
- // For compatibility, interface was changed to const char* to
- // avoid crashes between binary incompatible STL versions
- return ComparePaths(one.c_str(),second.c_str());
+ // NOTE:
+ // For compatibility, interface was changed to const char* to
+ // avoid crashes between binary incompatible STL versions
+ return ComparePaths(one.c_str(),second.c_str());
+}
+
+// ----------------------------------------------------------------------------
+inline bool IOSystem::PushDirectory( const std::string &path ) {
+ if ( path.empty() ) {
+ return false;
+ }
+
+ m_pathStack.push_back( path );
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+inline const std::string &IOSystem::CurrentDirectory() const {
+ if ( m_pathStack.empty() ) {
+ static const std::string Dummy("");
+ return Dummy;
+ }
+ return m_pathStack[ m_pathStack.size()-1 ];
}
// ----------------------------------------------------------------------------
+inline size_t IOSystem::StackSize() const {
+ return m_pathStack.size();
+}
+
+// ----------------------------------------------------------------------------
+inline bool IOSystem::PopDirectory() {
+ if ( m_pathStack.empty() ) {
+ return false;
+ }
+
+ m_pathStack.pop_back();
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+
} //!ns Assimp
#endif //AI_IOSYSTEM_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/Importer.hpp b/src/3rdparty/assimp/include/assimp/Importer.hpp
index 20af0725b..4c01367ed 100644
--- a/src/3rdparty/assimp/include/assimp/Importer.hpp
+++ b/src/3rdparty/assimp/include/assimp/Importer.hpp
@@ -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,58 +25,58 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file assimp.hpp
+/** @file Importer.hpp
* @brief Defines the C++-API to the Open Asset Import Library.
*/
#ifndef INCLUDED_AI_ASSIMP_HPP
#define INCLUDED_AI_ASSIMP_HPP
#ifndef __cplusplus
-# error This header requires C++ to be used. Use assimp.h for plain C.
+# error This header requires C++ to be used. Use assimp.h for plain C.
#endif
// Public ASSIMP data structures
#include "types.h"
#include "config.h"
-namespace Assimp {
- // =======================================================================
- // Public interface to Assimp
- class Importer;
- class Exporter; // export.hpp
- class IOStream;
- class IOSystem;
- class ProgressHandler;
-
- // =======================================================================
- // Plugin development
- //
- // Include the following headers for the declarations:
- // BaseImporter.h
- // BaseProcess.h
- class BaseImporter;
- class BaseProcess;
- class SharedPostProcessInfo;
- class BatchLoader;
-
- // =======================================================================
- // Holy stuff, only for members of the high council of the Jedi.
- class ImporterPimpl;
- class ExporterPimpl; // export.hpp
+namespace Assimp {
+ // =======================================================================
+ // Public interface to Assimp
+ class Importer;
+ class Exporter; // export.hpp
+ class IOStream;
+ class IOSystem;
+ class ProgressHandler;
+
+ // =======================================================================
+ // Plugin development
+ //
+ // Include the following headers for the declarations:
+ // BaseImporter.h
+ // BaseProcess.h
+ class BaseImporter;
+ class BaseProcess;
+ class SharedPostProcessInfo;
+ class BatchLoader;
+
+ // =======================================================================
+ // Holy stuff, only for members of the high council of the Jedi.
+ class ImporterPimpl;
+ class ExporterPimpl; // export.hpp
} //! namespace Assimp
#define AI_PROPERTY_WAS_NOT_EXISTING 0xffffffff
@@ -87,572 +87,574 @@ struct aiScene;
struct aiImporterDesc;
/** @namespace Assimp Assimp's CPP-API and all internal APIs */
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
-/** CPP-API: The Importer class forms an C++ interface to the functionality of the
+/** CPP-API: The Importer class forms an C++ interface to the functionality of the
* Open Asset Import Library.
*
-* Create an object of this class and call ReadFile() to import a file.
-* If the import succeeds, the function returns a pointer to the imported data.
-* The data remains property of the object, it is intended to be accessed
-* read-only. The imported data will be destroyed along with the Importer
+* Create an object of this class and call ReadFile() to import a file.
+* If the import succeeds, the function returns a pointer to the imported data.
+* The data remains property of the object, it is intended to be accessed
+* read-only. The imported data will be destroyed along with the Importer
* object. If the import fails, ReadFile() returns a NULL pointer. In this
-* case you can retrieve a human-readable error description be calling
+* case you can retrieve a human-readable error description be calling
* GetErrorString(). You can call ReadFile() multiple times with a single Importer
* instance. Actually, constructing Importer objects involves quite many
* allocations and may take some time, so it's better to reuse them as often as
* possible.
*
* If you need the Importer to do custom file handling to access the files,
-* implement IOSystem and IOStream and supply an instance of your custom
+* implement IOSystem and IOStream and supply an instance of your custom
* IOSystem implementation by calling SetIOHandler() before calling ReadFile().
-* If you do not assign a custion IO handler, a default handler using the
+* If you do not assign a custion IO handler, a default handler using the
* standard C++ IO logic will be used.
*
* @note One Importer instance is not thread-safe. If you use multiple
* threads for loading, each thread should maintain its own Importer instance.
*/
-class ASSIMP_API Importer {
+class ASSIMP_API Importer {
+public:
+ /**
+ * @brief The upper limit for hints.
+ */
+ static const unsigned int MaxLenHint = 200;
public:
- // -------------------------------------------------------------------
- /** Constructor. Creates an empty importer object.
- *
- * Call ReadFile() to start the import process. The configuration
- * property table is initially empty.
- */
- Importer();
-
- // -------------------------------------------------------------------
- /** Copy constructor.
- *
- * This copies the configuration properties of another Importer.
- * If this Importer owns a scene it won't be copied.
- * Call ReadFile() to start the import process.
- */
- Importer(const Importer& other);
-
- // -------------------------------------------------------------------
- /** Destructor. The object kept ownership of the imported data,
- * which now will be destroyed along with the object.
- */
- ~Importer();
-
-
- // -------------------------------------------------------------------
- /** Registers a new loader.
- *
- * @param pImp Importer to be added. The Importer instance takes
- * ownership of the pointer, so it will be automatically deleted
- * with the Importer instance.
- * @return AI_SUCCESS if the loader has been added. The registration
- * fails if there is already a loader for a specific file extension.
- */
- aiReturn RegisterLoader(BaseImporter* pImp);
-
- // -------------------------------------------------------------------
- /** Unregisters a loader.
- *
- * @param pImp Importer to be unregistered.
- * @return AI_SUCCESS if the loader has been removed. The function
- * fails if the loader is currently in use (this could happen
- * if the #Importer instance is used by more than one thread) or
- * if it has not yet been registered.
- */
- aiReturn UnregisterLoader(BaseImporter* pImp);
-
- // -------------------------------------------------------------------
- /** Registers a new post-process step.
- *
- * At the moment, there's a small limitation: new post processing
- * steps are added to end of the list, or in other words, executed
- * last, after all built-in steps.
- * @param pImp Post-process step to be added. The Importer instance
- * takes ownership of the pointer, so it will be automatically
- * deleted with the Importer instance.
- * @return AI_SUCCESS if the step has been added correctly.
- */
- aiReturn RegisterPPStep(BaseProcess* pImp);
-
- // -------------------------------------------------------------------
- /** Unregisters a post-process step.
- *
- * @param pImp Step to be unregistered.
- * @return AI_SUCCESS if the step has been removed. The function
- * fails if the step is currently in use (this could happen
- * if the #Importer instance is used by more than one thread) or
- * if it has not yet been registered.
- */
- aiReturn UnregisterPPStep(BaseProcess* pImp);
-
-
- // -------------------------------------------------------------------
- /** Set an integer configuration property.
- * @param szName Name of the property. All supported properties
- * are defined in the aiConfig.g header (all constants share the
- * prefix AI_CONFIG_XXX and are simple strings).
- * @param iValue New value of the property
- * @param bWasExisting Optional pointer to receive true if the
- * property was set before. The new value replaces the previous value
- * in this case.
- * @note Property of different types (float, int, string ..) are kept
- * on different stacks, so calling SetPropertyInteger() for a
- * floating-point property has no effect - the loader will call
- * GetPropertyFloat() to read the property, but it won't be there.
- */
- void SetPropertyInteger(const char* szName, int iValue,
- bool* bWasExisting = NULL);
-
- // -------------------------------------------------------------------
- /** Set a boolean configuration property. Boolean properties
- * are stored on the integer stack internally so it's possible
- * to set them via #SetPropertyBool and query them with
- * #GetPropertyBool and vice versa.
- * @see SetPropertyInteger()
- */
- void SetPropertyBool(const char* szName, bool value, bool* bWasExisting = NULL) {
- SetPropertyInteger(szName,value,bWasExisting);
- }
-
- // -------------------------------------------------------------------
- /** Set a floating-point configuration property.
- * @see SetPropertyInteger()
- */
- void SetPropertyFloat(const char* szName, float fValue,
- bool* bWasExisting = NULL);
-
- // -------------------------------------------------------------------
- /** Set a string configuration property.
- * @see SetPropertyInteger()
- */
- void SetPropertyString(const char* szName, const std::string& sValue,
- bool* bWasExisting = NULL);
-
- // -------------------------------------------------------------------
- /** Set a matrix configuration property.
- * @see SetPropertyInteger()
- */
- void SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue,
- bool* bWasExisting = NULL);
-
- // -------------------------------------------------------------------
- /** Get a configuration property.
- * @param szName Name of the property. All supported properties
- * are defined in the aiConfig.g header (all constants share the
- * prefix AI_CONFIG_XXX).
- * @param iErrorReturn Value that is returned if the property
- * is not found.
- * @return Current value of the property
- * @note Property of different types (float, int, string ..) are kept
- * on different lists, so calling SetPropertyInteger() for a
- * floating-point property has no effect - the loader will call
- * GetPropertyFloat() to read the property, but it won't be there.
- */
- int GetPropertyInteger(const char* szName,
- int iErrorReturn = 0xffffffff) const;
-
- // -------------------------------------------------------------------
- /** Get a boolean configuration property. Boolean properties
- * are stored on the integer stack internally so it's possible
- * to set them via #SetPropertyBool and query them with
- * #GetPropertyBool and vice versa.
- * @see GetPropertyInteger()
- */
- bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
- return GetPropertyInteger(szName,bErrorReturn)!=0;
- }
-
- // -------------------------------------------------------------------
- /** Get a floating-point configuration property
- * @see GetPropertyInteger()
- */
- float GetPropertyFloat(const char* szName,
- float fErrorReturn = 10e10f) const;
-
- // -------------------------------------------------------------------
- /** Get a string configuration property
- *
- * The return value remains valid until the property is modified.
- * @see GetPropertyInteger()
- */
- const std::string GetPropertyString(const char* szName,
- const std::string& sErrorReturn = "") const;
-
- // -------------------------------------------------------------------
- /** Get a matrix configuration property
- *
- * The return value remains valid until the property is modified.
- * @see GetPropertyInteger()
- */
- const aiMatrix4x4 GetPropertyMatrix(const char* szName,
- const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
-
- // -------------------------------------------------------------------
- /** Supplies a custom IO handler to the importer to use to open and
- * access files. If you need the importer to use custion IO logic to
- * access the files, you need to provide a custom implementation of
- * IOSystem and IOFile to the importer. Then create an instance of
- * your custion IOSystem implementation and supply it by this function.
- *
- * The Importer takes ownership of the object and will destroy it
- * afterwards. The previously assigned handler will be deleted.
- * Pass NULL to take again ownership of your IOSystem and reset Assimp
- * to use its default implementation.
- *
- * @param pIOHandler The IO handler to be used in all file accesses
- * of the Importer.
- */
- void SetIOHandler( IOSystem* pIOHandler);
-
- // -------------------------------------------------------------------
- /** Retrieves the IO handler that is currently set.
- * You can use #IsDefaultIOHandler() to check whether the returned
- * interface is the default IO handler provided by ASSIMP. The default
- * handler is active as long the application doesn't supply its own
- * custom IO handler via #SetIOHandler().
- * @return A valid IOSystem interface, never NULL.
- */
- IOSystem* GetIOHandler() const;
-
- // -------------------------------------------------------------------
- /** Checks whether a default IO handler is active
- * A default handler is active as long the application doesn't
- * supply its own custom IO handler via #SetIOHandler().
- * @return true by default
- */
- bool IsDefaultIOHandler() const;
-
- // -------------------------------------------------------------------
- /** Supplies a custom progress handler to the importer. This
- * interface exposes a #Update() callback, which is called
- * more or less periodically (please don't sue us if it
- * isn't as periodically as you'd like it to have ...).
- * This can be used to implement progress bars and loading
- * timeouts.
- * @param pHandler Progress callback interface. Pass NULL to
- * disable progress reporting.
- * @note Progress handlers can be used to abort the loading
- * at almost any time.*/
- void SetProgressHandler ( ProgressHandler* pHandler );
-
- // -------------------------------------------------------------------
- /** Retrieves the progress handler that is currently set.
- * You can use #IsDefaultProgressHandler() to check whether the returned
- * interface is the default handler provided by ASSIMP. The default
- * handler is active as long the application doesn't supply its own
- * custom handler via #SetProgressHandler().
- * @return A valid ProgressHandler interface, never NULL.
- */
- ProgressHandler* GetProgressHandler() const;
-
- // -------------------------------------------------------------------
- /** Checks whether a default progress handler is active
- * A default handler is active as long the application doesn't
- * supply its own custom progress handler via #SetProgressHandler().
- * @return true by default
- */
- bool IsDefaultProgressHandler() const;
-
- // -------------------------------------------------------------------
- /** @brief Check whether a given set of postprocessing flags
- * is supported.
- *
- * Some flags are mutually exclusive, others are probably
- * not available because your excluded them from your
- * Assimp builds. Calling this function is recommended if
- * you're unsure.
- *
- * @param pFlags Bitwise combination of the aiPostProcess flags.
- * @return true if this flag combination is fine.
- */
- bool ValidateFlags(unsigned int pFlags) const;
-
- // -------------------------------------------------------------------
- /** Reads the given file and returns its contents if successful.
- *
- * If the call succeeds, the contents of the file are returned as a
- * pointer to an aiScene object. The returned data is intended to be
- * read-only, the importer object keeps ownership of the data and will
- * destroy it upon destruction. If the import fails, NULL is returned.
- * A human-readable error description can be retrieved by calling
- * GetErrorString(). The previous scene will be deleted during this call.
- * @param pFile Path and filename to the file to be imported.
- * @param pFlags Optional post processing steps to be executed after
- * a successful import. Provide a bitwise combination of the
- * #aiPostProcessSteps flags. If you wish to inspect the imported
- * scene first in order to fine-tune your post-processing setup,
- * consider to use #ApplyPostProcessing().
- * @return A pointer to the imported data, NULL if the import failed.
- * The pointer to the scene remains in possession of the Importer
- * instance. Use GetOrphanedScene() to take ownership of it.
- *
- * @note Assimp is able to determine the file format of a file
- * automatically.
- */
- const aiScene* ReadFile(
- const char* pFile,
- unsigned int pFlags);
-
- // -------------------------------------------------------------------
- /** Reads the given file from a memory buffer and returns its
- * contents if successful.
- *
- * If the call succeeds, the contents of the file are returned as a
- * pointer to an aiScene object. The returned data is intended to be
- * read-only, the importer object keeps ownership of the data and will
- * destroy it upon destruction. If the import fails, NULL is returned.
- * A human-readable error description can be retrieved by calling
- * GetErrorString(). The previous scene will be deleted during this call.
- * Calling this method doesn't affect the active IOSystem.
- * @param pBuffer Pointer to the file data
- * @param pLength Length of pBuffer, in bytes
- * @param pFlags Optional post processing steps to be executed after
- * a successful import. Provide a bitwise combination of the
- * #aiPostProcessSteps flags. If you wish to inspect the imported
- * scene first in order to fine-tune your post-processing setup,
- * consider to use #ApplyPostProcessing().
- * @param pHint An additional hint to the library. If this is a non
- * empty string, the library looks for a loader to support
- * the file extension specified by pHint and passes the file to
- * the first matching loader. If this loader is unable to completely
- * the request, the library continues and tries to determine the
- * file format on its own, a task that may or may not be successful.
- * Check the return value, and you'll know ...
- * @return A pointer to the imported data, NULL if the import failed.
- * The pointer to the scene remains in possession of the Importer
- * instance. Use GetOrphanedScene() to take ownership of it.
- *
- * @note This is a straightforward way to decode models from memory
- * buffers, but it doesn't handle model formats that spread their
- * data across multiple files or even directories. Examples include
- * OBJ or MD3, which outsource parts of their material info into
- * external scripts. If you need full functionality, provide
- * a custom IOSystem to make Assimp find these files and use
- * the regular ReadFile() API.
- */
- const aiScene* ReadFileFromMemory(
- const void* pBuffer,
- size_t pLength,
- unsigned int pFlags,
- const char* pHint = "");
-
- // -------------------------------------------------------------------
- /** Apply post-processing to an already-imported scene.
- *
- * This is strictly equivalent to calling #ReadFile() with the same
- * flags. However, you can use this separate function to inspect
- * the imported scene first to fine-tune your post-processing setup.
- * @param pFlags Provide a bitwise combination of the
- * #aiPostProcessSteps flags.
- * @return A pointer to the post-processed data. This is still the
- * same as the pointer returned by #ReadFile(). However, if
- * post-processing fails, the scene could now be NULL.
- * That's quite a rare case, post processing steps are not really
- * designed to 'fail'. To be exact, the #aiProcess_ValidateDS
- * flag is currently the only post processing step which can actually
- * cause the scene to be reset to NULL.
- *
- * @note The method does nothing if no scene is currently bound
- * to the #Importer instance. */
- const aiScene* ApplyPostProcessing(unsigned int pFlags);
-
- // -------------------------------------------------------------------
- /** @brief Reads the given file and returns its contents if successful.
- *
- * This function is provided for backward compatibility.
- * See the const char* version for detailled docs.
- * @see ReadFile(const char*, pFlags) */
- const aiScene* ReadFile(
- const std::string& pFile,
- unsigned int pFlags);
-
- // -------------------------------------------------------------------
- /** Frees the current scene.
- *
- * The function does nothing if no scene has previously been
- * read via ReadFile(). FreeScene() is called automatically by the
- * destructor and ReadFile() itself. */
- void FreeScene( );
-
- // -------------------------------------------------------------------
- /** Returns an error description of an error that occurred in ReadFile().
- *
- * Returns an empty string if no error occurred.
- * @return A description of the last error, an empty string if no
- * error occurred. The string is never NULL.
- *
- * @note The returned function remains valid until one of the
- * following methods is called: #ReadFile(), #FreeScene(). */
- const char* GetErrorString() const;
-
- // -------------------------------------------------------------------
- /** Returns the scene loaded by the last successful call to ReadFile()
- *
- * @return Current scene or NULL if there is currently no scene loaded */
- const aiScene* GetScene() const;
-
- // -------------------------------------------------------------------
- /** Returns the scene loaded by the last successful call to ReadFile()
- * and releases the scene from the ownership of the Importer
- * instance. The application is now responsible for deleting the
- * scene. Any further calls to GetScene() or GetOrphanedScene()
- * will return NULL - until a new scene has been loaded via ReadFile().
- *
- * @return Current scene or NULL if there is currently no scene loaded
- * @note Use this method with maximal caution, and only if you have to.
- * By design, aiScene's are exclusively maintained, allocated and
- * deallocated by Assimp and no one else. The reasoning behind this
- * is the golden rule that deallocations should always be done
- * by the module that did the original allocation because heaps
- * are not necessarily shared. GetOrphanedScene() enforces you
- * to delete the returned scene by yourself, but this will only
- * be fine if and only if you're using the same heap as assimp.
- * On Windows, it's typically fine provided everything is linked
- * against the multithreaded-dll version of the runtime library.
- * It will work as well for static linkage with Assimp.*/
- aiScene* GetOrphanedScene();
-
-
-
-
- // -------------------------------------------------------------------
- /** Returns whether a given file extension is supported by ASSIMP.
- *
- * @param szExtension Extension to be checked.
- * Must include a trailing dot '.'. Example: ".3ds", ".md3".
- * Cases-insensitive.
- * @return true if the extension is supported, false otherwise */
- bool IsExtensionSupported(const char* szExtension) const;
-
- // -------------------------------------------------------------------
- /** @brief Returns whether a given file extension is supported by ASSIMP.
- *
- * This function is provided for backward compatibility.
- * See the const char* version for detailed and up-to-date docs.
- * @see IsExtensionSupported(const char*) */
- inline bool IsExtensionSupported(const std::string& szExtension) const;
-
- // -------------------------------------------------------------------
- /** Get a full list of all file extensions supported by ASSIMP.
- *
- * If a file extension is contained in the list this does of course not
- * mean that ASSIMP is able to load all files with this extension ---
+ // -------------------------------------------------------------------
+ /** Constructor. Creates an empty importer object.
+ *
+ * Call ReadFile() to start the import process. The configuration
+ * property table is initially empty.
+ */
+ Importer();
+
+ // -------------------------------------------------------------------
+ /** Copy constructor.
+ *
+ * This copies the configuration properties of another Importer.
+ * If this Importer owns a scene it won't be copied.
+ * Call ReadFile() to start the import process.
+ */
+ Importer(const Importer& other);
+
+ // -------------------------------------------------------------------
+ /** Destructor. The object kept ownership of the imported data,
+ * which now will be destroyed along with the object.
+ */
+ ~Importer();
+
+
+ // -------------------------------------------------------------------
+ /** Registers a new loader.
+ *
+ * @param pImp Importer to be added. The Importer instance takes
+ * ownership of the pointer, so it will be automatically deleted
+ * with the Importer instance.
+ * @return AI_SUCCESS if the loader has been added. The registration
+ * fails if there is already a loader for a specific file extension.
+ */
+ aiReturn RegisterLoader(BaseImporter* pImp);
+
+ // -------------------------------------------------------------------
+ /** Unregisters a loader.
+ *
+ * @param pImp Importer to be unregistered.
+ * @return AI_SUCCESS if the loader has been removed. The function
+ * fails if the loader is currently in use (this could happen
+ * if the #Importer instance is used by more than one thread) or
+ * if it has not yet been registered.
+ */
+ aiReturn UnregisterLoader(BaseImporter* pImp);
+
+ // -------------------------------------------------------------------
+ /** Registers a new post-process step.
+ *
+ * At the moment, there's a small limitation: new post processing
+ * steps are added to end of the list, or in other words, executed
+ * last, after all built-in steps.
+ * @param pImp Post-process step to be added. The Importer instance
+ * takes ownership of the pointer, so it will be automatically
+ * deleted with the Importer instance.
+ * @return AI_SUCCESS if the step has been added correctly.
+ */
+ aiReturn RegisterPPStep(BaseProcess* pImp);
+
+ // -------------------------------------------------------------------
+ /** Unregisters a post-process step.
+ *
+ * @param pImp Step to be unregistered.
+ * @return AI_SUCCESS if the step has been removed. The function
+ * fails if the step is currently in use (this could happen
+ * if the #Importer instance is used by more than one thread) or
+ * if it has not yet been registered.
+ */
+ aiReturn UnregisterPPStep(BaseProcess* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** Set an integer configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX and are simple strings).
+ * @param iValue New value of the property
+ * @return true if the property was set before. The new value replaces
+ * the previous value in this case.
+ * @note Property of different types (float, int, string ..) are kept
+ * on different stacks, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ bool SetPropertyInteger(const char* szName, int iValue);
+
+ // -------------------------------------------------------------------
+ /** Set a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyBool(const char* szName, bool value) {
+ return SetPropertyInteger(szName,value);
+ }
+
+ // -------------------------------------------------------------------
+ /** Set a floating-point configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyFloat(const char* szName, float fValue);
+
+ // -------------------------------------------------------------------
+ /** Set a string configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyString(const char* szName, const std::string& sValue);
+
+ // -------------------------------------------------------------------
+ /** Set a matrix configuration property.
+ * @see SetPropertyInteger()
+ */
+ bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue);
+
+ // -------------------------------------------------------------------
+ /** Get a configuration property.
+ * @param szName Name of the property. All supported properties
+ * are defined in the aiConfig.g header (all constants share the
+ * prefix AI_CONFIG_XXX).
+ * @param iErrorReturn Value that is returned if the property
+ * is not found.
+ * @return Current value of the property
+ * @note Property of different types (float, int, string ..) are kept
+ * on different lists, so calling SetPropertyInteger() for a
+ * floating-point property has no effect - the loader will call
+ * GetPropertyFloat() to read the property, but it won't be there.
+ */
+ int GetPropertyInteger(const char* szName,
+ int iErrorReturn = 0xffffffff) const;
+
+ // -------------------------------------------------------------------
+ /** Get a boolean configuration property. Boolean properties
+ * are stored on the integer stack internally so it's possible
+ * to set them via #SetPropertyBool and query them with
+ * #GetPropertyBool and vice versa.
+ * @see GetPropertyInteger()
+ */
+ bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const {
+ return GetPropertyInteger(szName,bErrorReturn)!=0;
+ }
+
+ // -------------------------------------------------------------------
+ /** Get a floating-point configuration property
+ * @see GetPropertyInteger()
+ */
+ float GetPropertyFloat(const char* szName,
+ float fErrorReturn = 10e10f) const;
+
+ // -------------------------------------------------------------------
+ /** Get a string configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const std::string GetPropertyString(const char* szName,
+ const std::string& sErrorReturn = "") const;
+
+ // -------------------------------------------------------------------
+ /** Get a matrix configuration property
+ *
+ * The return value remains valid until the property is modified.
+ * @see GetPropertyInteger()
+ */
+ const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
+
+ // -------------------------------------------------------------------
+ /** Supplies a custom IO handler to the importer to use to open and
+ * access files. If you need the importer to use custion IO logic to
+ * access the files, you need to provide a custom implementation of
+ * IOSystem and IOFile to the importer. Then create an instance of
+ * your custion IOSystem implementation and supply it by this function.
+ *
+ * The Importer takes ownership of the object and will destroy it
+ * afterwards. The previously assigned handler will be deleted.
+ * Pass NULL to take again ownership of your IOSystem and reset Assimp
+ * to use its default implementation.
+ *
+ * @param pIOHandler The IO handler to be used in all file accesses
+ * of the Importer.
+ */
+ void SetIOHandler( IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Retrieves the IO handler that is currently set.
+ * You can use #IsDefaultIOHandler() to check whether the returned
+ * interface is the default IO handler provided by ASSIMP. The default
+ * handler is active as long the application doesn't supply its own
+ * custom IO handler via #SetIOHandler().
+ * @return A valid IOSystem interface, never NULL.
+ */
+ IOSystem* GetIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Checks whether a default IO handler is active
+ * A default handler is active as long the application doesn't
+ * supply its own custom IO handler via #SetIOHandler().
+ * @return true by default
+ */
+ bool IsDefaultIOHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Supplies a custom progress handler to the importer. This
+ * interface exposes a #Update() callback, which is called
+ * more or less periodically (please don't sue us if it
+ * isn't as periodically as you'd like it to have ...).
+ * This can be used to implement progress bars and loading
+ * timeouts.
+ * @param pHandler Progress callback interface. Pass NULL to
+ * disable progress reporting.
+ * @note Progress handlers can be used to abort the loading
+ * at almost any time.*/
+ void SetProgressHandler ( ProgressHandler* pHandler );
+
+ // -------------------------------------------------------------------
+ /** Retrieves the progress handler that is currently set.
+ * You can use #IsDefaultProgressHandler() to check whether the returned
+ * interface is the default handler provided by ASSIMP. The default
+ * handler is active as long the application doesn't supply its own
+ * custom handler via #SetProgressHandler().
+ * @return A valid ProgressHandler interface, never NULL.
+ */
+ ProgressHandler* GetProgressHandler() const;
+
+ // -------------------------------------------------------------------
+ /** Checks whether a default progress handler is active
+ * A default handler is active as long the application doesn't
+ * supply its own custom progress handler via #SetProgressHandler().
+ * @return true by default
+ */
+ bool IsDefaultProgressHandler() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether a given set of postprocessing flags
+ * is supported.
+ *
+ * Some flags are mutually exclusive, others are probably
+ * not available because your excluded them from your
+ * Assimp builds. Calling this function is recommended if
+ * you're unsure.
+ *
+ * @param pFlags Bitwise combination of the aiPostProcess flags.
+ * @return true if this flag combination is fine.
+ */
+ bool ValidateFlags(unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ /** Reads the given file and returns its contents if successful.
+ *
+ * If the call succeeds, the contents of the file are returned as a
+ * pointer to an aiScene object. The returned data is intended to be
+ * read-only, the importer object keeps ownership of the data and will
+ * destroy it upon destruction. If the import fails, NULL is returned.
+ * A human-readable error description can be retrieved by calling
+ * GetErrorString(). The previous scene will be deleted during this call.
+ * @param pFile Path and filename to the file to be imported.
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #ApplyPostProcessing().
+ * @return A pointer to the imported data, NULL if the import failed.
+ * The pointer to the scene remains in possession of the Importer
+ * instance. Use GetOrphanedScene() to take ownership of it.
+ *
+ * @note Assimp is able to determine the file format of a file
+ * automatically.
+ */
+ const aiScene* ReadFile(
+ const char* pFile,
+ unsigned int pFlags);
+
+ // -------------------------------------------------------------------
+ /** Reads the given file from a memory buffer and returns its
+ * contents if successful.
+ *
+ * If the call succeeds, the contents of the file are returned as a
+ * pointer to an aiScene object. The returned data is intended to be
+ * read-only, the importer object keeps ownership of the data and will
+ * destroy it upon destruction. If the import fails, NULL is returned.
+ * A human-readable error description can be retrieved by calling
+ * GetErrorString(). The previous scene will be deleted during this call.
+ * Calling this method doesn't affect the active IOSystem.
+ * @param pBuffer Pointer to the file data
+ * @param pLength Length of pBuffer, in bytes
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #ApplyPostProcessing().
+ * @param pHint An additional hint to the library. If this is a non
+ * empty string, the library looks for a loader to support
+ * the file extension specified by pHint and passes the file to
+ * the first matching loader. If this loader is unable to completely
+ * the request, the library continues and tries to determine the
+ * file format on its own, a task that may or may not be successful.
+ * Check the return value, and you'll know ...
+ * @return A pointer to the imported data, NULL if the import failed.
+ * The pointer to the scene remains in possession of the Importer
+ * instance. Use GetOrphanedScene() to take ownership of it.
+ *
+ * @note This is a straightforward way to decode models from memory
+ * buffers, but it doesn't handle model formats that spread their
+ * data across multiple files or even directories. Examples include
+ * OBJ or MD3, which outsource parts of their material info into
+ * external scripts. If you need full functionality, provide
+ * a custom IOSystem to make Assimp find these files and use
+ * the regular ReadFile() API.
+ */
+ const aiScene* ReadFileFromMemory(
+ const void* pBuffer,
+ size_t pLength,
+ unsigned int pFlags,
+ const char* pHint = "");
+
+ // -------------------------------------------------------------------
+ /** Apply post-processing to an already-imported scene.
+ *
+ * This is strictly equivalent to calling #ReadFile() with the same
+ * flags. However, you can use this separate function to inspect
+ * the imported scene first to fine-tune your post-processing setup.
+ * @param pFlags Provide a bitwise combination of the
+ * #aiPostProcessSteps flags.
+ * @return A pointer to the post-processed data. This is still the
+ * same as the pointer returned by #ReadFile(). However, if
+ * post-processing fails, the scene could now be NULL.
+ * That's quite a rare case, post processing steps are not really
+ * designed to 'fail'. To be exact, the #aiProcess_ValidateDS
+ * flag is currently the only post processing step which can actually
+ * cause the scene to be reset to NULL.
+ *
+ * @note The method does nothing if no scene is currently bound
+ * to the #Importer instance. */
+ const aiScene* ApplyPostProcessing(unsigned int pFlags);
+
+ const aiScene* ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation );
+
+ // -------------------------------------------------------------------
+ /** @brief Reads the given file and returns its contents if successful.
+ *
+ * This function is provided for backward compatibility.
+ * See the const char* version for detailed docs.
+ * @see ReadFile(const char*, pFlags) */
+ const aiScene* ReadFile(
+ const std::string& pFile,
+ unsigned int pFlags);
+
+ // -------------------------------------------------------------------
+ /** Frees the current scene.
+ *
+ * The function does nothing if no scene has previously been
+ * read via ReadFile(). FreeScene() is called automatically by the
+ * destructor and ReadFile() itself. */
+ void FreeScene( );
+
+ // -------------------------------------------------------------------
+ /** Returns an error description of an error that occurred in ReadFile().
+ *
+ * Returns an empty string if no error occurred.
+ * @return A description of the last error, an empty string if no
+ * error occurred. The string is never NULL.
+ *
+ * @note The returned function remains valid until one of the
+ * following methods is called: #ReadFile(), #FreeScene(). */
+ const char* GetErrorString() const;
+
+ // -------------------------------------------------------------------
+ /** Returns the scene loaded by the last successful call to ReadFile()
+ *
+ * @return Current scene or NULL if there is currently no scene loaded */
+ const aiScene* GetScene() const;
+
+ // -------------------------------------------------------------------
+ /** Returns the scene loaded by the last successful call to ReadFile()
+ * and releases the scene from the ownership of the Importer
+ * instance. The application is now responsible for deleting the
+ * scene. Any further calls to GetScene() or GetOrphanedScene()
+ * will return NULL - until a new scene has been loaded via ReadFile().
+ *
+ * @return Current scene or NULL if there is currently no scene loaded
+ * @note Use this method with maximal caution, and only if you have to.
+ * By design, aiScene's are exclusively maintained, allocated and
+ * deallocated by Assimp and no one else. The reasoning behind this
+ * is the golden rule that deallocations should always be done
+ * by the module that did the original allocation because heaps
+ * are not necessarily shared. GetOrphanedScene() enforces you
+ * to delete the returned scene by yourself, but this will only
+ * be fine if and only if you're using the same heap as assimp.
+ * On Windows, it's typically fine provided everything is linked
+ * against the multithreaded-dll version of the runtime library.
+ * It will work as well for static linkage with Assimp.*/
+ aiScene* GetOrphanedScene();
+
+
+
+
+ // -------------------------------------------------------------------
+ /** Returns whether a given file extension is supported by ASSIMP.
+ *
+ * @param szExtension Extension to be checked.
+ * Must include a trailing dot '.'. Example: ".3ds", ".md3".
+ * Cases-insensitive.
+ * @return true if the extension is supported, false otherwise */
+ bool IsExtensionSupported(const char* szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Returns whether a given file extension is supported by ASSIMP.
+ *
+ * This function is provided for backward compatibility.
+ * See the const char* version for detailed and up-to-date docs.
+ * @see IsExtensionSupported(const char*) */
+ inline bool IsExtensionSupported(const std::string& szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** Get a full list of all file extensions supported by ASSIMP.
+ *
+ * If a file extension is contained in the list this does of course not
+ * mean that ASSIMP is able to load all files with this extension ---
* it simply means there is an importer loaded which claims to handle
- * files with this file extension.
- * @param szOut String to receive the extension list.
- * Format of the list: "*.3ds;*.obj;*.dae". This is useful for
- * use with the WinAPI call GetOpenFileName(Ex). */
- void GetExtensionList(aiString& szOut) const;
-
- // -------------------------------------------------------------------
- /** @brief Get a full list of all file extensions supported by ASSIMP.
- *
- * This function is provided for backward compatibility.
- * See the aiString version for detailed and up-to-date docs.
- * @see GetExtensionList(aiString&)*/
- inline void GetExtensionList(std::string& szOut) const;
-
- // -------------------------------------------------------------------
- /** Get the number of importrs currently registered with Assimp. */
- size_t GetImporterCount() const;
-
- // -------------------------------------------------------------------
- /** Get meta data for the importer corresponding to a specific index..
- *
- * For the declaration of #aiImporterDesc, include <assimp/importerdesc.h>.
- * @param index Index to query, must be within [0,GetImporterCount())
- * @return Importer meta data structure, NULL if the index does not
- * exist or if the importer doesn't offer meta information (
- * importers may do this at the cost of being hated by their peers).*/
- const aiImporterDesc* GetImporterInfo(size_t index) const;
-
- // -------------------------------------------------------------------
- /** Find the importer corresponding to a specific index.
- *
- * @param index Index to query, must be within [0,GetImporterCount())
- * @return Importer instance. NULL if the index does not
- * exist. */
- BaseImporter* GetImporter(size_t index) const;
-
- // -------------------------------------------------------------------
- /** Find the importer corresponding to a specific file extension.
- *
- * This is quite similar to #IsExtensionSupported except a
- * BaseImporter instance is returned.
- * @param szExtension Extension to check for. The following formats
- * are recognized (BAH being the file extension): "BAH" (comparison
- * is case-insensitive), ".bah", "*.bah" (wild card and dot
- * characters at the beginning of the extension are skipped).
- * @return NULL if no importer is found*/
- BaseImporter* GetImporter (const char* szExtension) const;
-
- // -------------------------------------------------------------------
- /** Find the importer index corresponding to a specific file extension.
- *
- * @param szExtension Extension to check for. The following formats
- * are recognized (BAH being the file extension): "BAH" (comparison
- * is case-insensitive), ".bah", "*.bah" (wild card and dot
- * characters at the beginning of the extension are skipped).
- * @return (size_t)-1 if no importer is found */
- size_t GetImporterIndex (const char* szExtension) const;
-
-
-
-
- // -------------------------------------------------------------------
- /** Returns the storage allocated by ASSIMP to hold the scene data
- * in memory.
- *
- * This refers to the currently loaded file, see #ReadFile().
- * @param in Data structure to be filled.
- * @note The returned memory statistics refer to the actual
- * size of the use data of the aiScene. Heap-related overhead
- * is (naturally) not included.*/
- void GetMemoryRequirements(aiMemoryInfo& in) const;
-
- // -------------------------------------------------------------------
- /** Enables "extra verbose" mode.
- *
- * 'Extra verbose' means the data structure is validated after *every*
- * single post processing step to make sure everyone modifies the data
- * structure in a well-defined manner. This is a debug feature and not
- * intended for use in production environments. */
- void SetExtraVerbose(bool bDo);
-
-
- // -------------------------------------------------------------------
- /** Private, do not use. */
- ImporterPimpl* Pimpl() { return pimpl; };
- const ImporterPimpl* Pimpl() const { return pimpl; };
+ * files with this file extension.
+ * @param szOut String to receive the extension list.
+ * Format of the list: "*.3ds;*.obj;*.dae". This is useful for
+ * use with the WinAPI call GetOpenFileName(Ex). */
+ void GetExtensionList(aiString& szOut) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Get a full list of all file extensions supported by ASSIMP.
+ *
+ * This function is provided for backward compatibility.
+ * See the aiString version for detailed and up-to-date docs.
+ * @see GetExtensionList(aiString&)*/
+ inline void GetExtensionList(std::string& szOut) const;
+
+ // -------------------------------------------------------------------
+ /** Get the number of importrs currently registered with Assimp. */
+ size_t GetImporterCount() const;
+
+ // -------------------------------------------------------------------
+ /** Get meta data for the importer corresponding to a specific index..
+ *
+ * For the declaration of #aiImporterDesc, include <assimp/importerdesc.h>.
+ * @param index Index to query, must be within [0,GetImporterCount())
+ * @return Importer meta data structure, NULL if the index does not
+ * exist or if the importer doesn't offer meta information (
+ * importers may do this at the cost of being hated by their peers).*/
+ const aiImporterDesc* GetImporterInfo(size_t index) const;
+
+ // -------------------------------------------------------------------
+ /** Find the importer corresponding to a specific index.
+ *
+ * @param index Index to query, must be within [0,GetImporterCount())
+ * @return Importer instance. NULL if the index does not
+ * exist. */
+ BaseImporter* GetImporter(size_t index) const;
+
+ // -------------------------------------------------------------------
+ /** Find the importer corresponding to a specific file extension.
+ *
+ * This is quite similar to #IsExtensionSupported except a
+ * BaseImporter instance is returned.
+ * @param szExtension Extension to check for. The following formats
+ * are recognized (BAH being the file extension): "BAH" (comparison
+ * is case-insensitive), ".bah", "*.bah" (wild card and dot
+ * characters at the beginning of the extension are skipped).
+ * @return NULL if no importer is found*/
+ BaseImporter* GetImporter (const char* szExtension) const;
+
+ // -------------------------------------------------------------------
+ /** Find the importer index corresponding to a specific file extension.
+ *
+ * @param szExtension Extension to check for. The following formats
+ * are recognized (BAH being the file extension): "BAH" (comparison
+ * is case-insensitive), ".bah", "*.bah" (wild card and dot
+ * characters at the beginning of the extension are skipped).
+ * @return (size_t)-1 if no importer is found */
+ size_t GetImporterIndex (const char* szExtension) const;
+
+
+
+
+ // -------------------------------------------------------------------
+ /** Returns the storage allocated by ASSIMP to hold the scene data
+ * in memory.
+ *
+ * This refers to the currently loaded file, see #ReadFile().
+ * @param in Data structure to be filled.
+ * @note The returned memory statistics refer to the actual
+ * size of the use data of the aiScene. Heap-related overhead
+ * is (naturally) not included.*/
+ void GetMemoryRequirements(aiMemoryInfo& in) const;
+
+ // -------------------------------------------------------------------
+ /** Enables "extra verbose" mode.
+ *
+ * 'Extra verbose' means the data structure is validated after *every*
+ * single post processing step to make sure everyone modifies the data
+ * structure in a well-defined manner. This is a debug feature and not
+ * intended for use in production environments. */
+ void SetExtraVerbose(bool bDo);
+
+
+ // -------------------------------------------------------------------
+ /** Private, do not use. */
+ ImporterPimpl* Pimpl() { return pimpl; }
+ const ImporterPimpl* Pimpl() const { return pimpl; }
protected:
- // Just because we don't want you to know how we're hacking around.
- ImporterPimpl* pimpl;
+ // Just because we don't want you to know how we're hacking around.
+ ImporterPimpl* pimpl;
}; //! class Importer
// ----------------------------------------------------------------------------
// For compatibility, the interface of some functions taking a std::string was
-// changed to const char* to avoid crashes between binary incompatible STL
+// changed to const char* to avoid crashes between binary incompatible STL
// versions. This code her is inlined, so it shouldn't cause any problems.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
AI_FORCE_INLINE const aiScene* Importer::ReadFile( const std::string& pFile,unsigned int pFlags){
- return ReadFile(pFile.c_str(),pFlags);
+ return ReadFile(pFile.c_str(),pFlags);
}
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE void Importer::GetExtensionList(std::string& szOut) const {
- aiString s;
- GetExtensionList(s);
- szOut = s.data;
+AI_FORCE_INLINE void Importer::GetExtensionList(std::string& szOut) const {
+ aiString s;
+ GetExtensionList(s);
+ szOut = s.data;
}
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE bool Importer::IsExtensionSupported(const std::string& szExtension) const {
- return IsExtensionSupported(szExtension.c_str());
+AI_FORCE_INLINE bool Importer::IsExtensionSupported(const std::string& szExtension) const {
+ return IsExtensionSupported(szExtension.c_str());
}
} // !namespace Assimp
diff --git a/src/3rdparty/assimp/include/assimp/LogStream.hpp b/src/3rdparty/assimp/include/assimp/LogStream.hpp
index 2d7731baf..477fe5321 100644
--- a/src/3rdparty/assimp/include/assimp/LogStream.hpp
+++ b/src/3rdparty/assimp/include/assimp/LogStream.hpp
@@ -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 LogStream.h
+/** @file LogStream.hpp
* @brief Abstract base class 'LogStream', representing an output log stream.
*/
#ifndef INCLUDED_AI_LOGSTREAM_H
#define INCLUDED_AI_LOGSTREAM_H
#include "types.h"
-namespace Assimp {
+namespace Assimp {
class IOSystem;
// ------------------------------------------------------------------------------------
@@ -55,39 +55,39 @@ class IOSystem;
* are not enough for your purpose. */
class ASSIMP_API LogStream
#ifndef SWIG
- : public Intern::AllocateFromAssimpHeap
+ : public Intern::AllocateFromAssimpHeap
#endif
{
protected:
- /** @brief Default constructor */
- LogStream() {
- }
+ /** @brief Default constructor */
+ LogStream() {
+ }
public:
- /** @brief Virtual destructor */
- virtual ~LogStream() {
- }
+ /** @brief Virtual destructor */
+ virtual ~LogStream() {
+ }
- // -------------------------------------------------------------------
- /** @brief Overwrite this for your own output methods
- *
- * Log messages *may* consist of multiple lines and you shouldn't
- * expect a consistent formatting. If you want custom formatting
- * (e.g. generate HTML), supply a custom instance of Logger to
- * #DefaultLogger:set(). Usually you can *expect* that a log message
- * is exactly one line and terminated with a single \n character.
- * @param message Message to be written */
- virtual void write(const char* message) = 0;
+ // -------------------------------------------------------------------
+ /** @brief Overwrite this for your own output methods
+ *
+ * Log messages *may* consist of multiple lines and you shouldn't
+ * expect a consistent formatting. If you want custom formatting
+ * (e.g. generate HTML), supply a custom instance of Logger to
+ * #DefaultLogger:set(). Usually you can *expect* that a log message
+ * is exactly one line and terminated with a single \n character.
+ * @param message Message to be written */
+ virtual void write(const char* message) = 0;
- // -------------------------------------------------------------------
- /** @brief Creates a default log stream
- * @param streams Type of the default stream
- * @param name For aiDefaultLogStream_FILE: name of the output file
- * @param io For aiDefaultLogStream_FILE: IOSystem to be used to open the output
- * file. Pass NULL for the default implementation.
- * @return New LogStream instance. */
- static LogStream* createDefaultStream(aiDefaultLogStream stream,
- const char* name = "AssimpLog.txt",
- IOSystem* io = NULL);
+ // -------------------------------------------------------------------
+ /** @brief Creates a default log stream
+ * @param streams Type of the default stream
+ * @param name For aiDefaultLogStream_FILE: name of the output file
+ * @param io For aiDefaultLogStream_FILE: IOSystem to be used to open the output
+ * file. Pass NULL for the default implementation.
+ * @return New LogStream instance. */
+ static LogStream* createDefaultStream(aiDefaultLogStream stream,
+ const char* name = "AssimpLog.txt",
+ IOSystem* io = NULL);
}; // !class LogStream
// ------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/include/assimp/Logger.hpp b/src/3rdparty/assimp/include/assimp/Logger.hpp
index 38bb11790..7f355b5bf 100644
--- a/src/3rdparty/assimp/include/assimp/Logger.hpp
+++ b/src/3rdparty/assimp/include/assimp/Logger.hpp
@@ -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,239 +23,239 @@ 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 Logger.hpp
- * @brief Abstract base class 'Logger', base of the logging system.
+ * @brief Abstract base class 'Logger', base of the logging system.
*/
#ifndef INCLUDED_AI_LOGGER_H
#define INCLUDED_AI_LOGGER_H
#include "types.h"
-namespace Assimp {
+namespace Assimp {
class LogStream;
// Maximum length of a log message. Longer messages are rejected.
#define MAX_LOG_MESSAGE_LENGTH 1024u
// ----------------------------------------------------------------------------------
-/** @brief CPP-API: Abstract interface for logger implementations.
- * Assimp provides a default implementation and uses it for almost all
+/** @brief CPP-API: Abstract interface for logger implementations.
+ * Assimp provides a default implementation and uses it for almost all
* logging stuff ('DefaultLogger'). This class defines just basic logging
* behaviour and is not of interest for you. Instead, take a look at #DefaultLogger. */
class ASSIMP_API Logger
#ifndef SWIG
- : public Intern::AllocateFromAssimpHeap
+ : public Intern::AllocateFromAssimpHeap
#endif
{
public:
- // ----------------------------------------------------------------------
- /** @enum LogSeverity
- * @brief Log severity to describe the granularity of logging.
- */
- enum LogSeverity
- {
- NORMAL, //!< Normal granularity of logging
- VERBOSE //!< Debug infos will be logged, too
- };
-
- // ----------------------------------------------------------------------
- /** @enum ErrorSeverity
- * @brief Description for severity of a log message.
- *
- * Every LogStream has a bitwise combination of these flags.
- * A LogStream doesn't receive any messages of a specific type
- * if it doesn't specify the corresponding ErrorSeverity flag.
- */
- enum ErrorSeverity
- {
- Debugging = 1, //!< Debug log message
- Info = 2, //!< Info log message
- Warn = 4, //!< Warn log message
- Err = 8 //!< Error log message
- };
+ // ----------------------------------------------------------------------
+ /** @enum LogSeverity
+ * @brief Log severity to describe the granularity of logging.
+ */
+ enum LogSeverity
+ {
+ NORMAL, //!< Normal granularity of logging
+ VERBOSE //!< Debug infos will be logged, too
+ };
+
+ // ----------------------------------------------------------------------
+ /** @enum ErrorSeverity
+ * @brief Description for severity of a log message.
+ *
+ * Every LogStream has a bitwise combination of these flags.
+ * A LogStream doesn't receive any messages of a specific type
+ * if it doesn't specify the corresponding ErrorSeverity flag.
+ */
+ enum ErrorSeverity
+ {
+ Debugging = 1, //!< Debug log message
+ Info = 2, //!< Info log message
+ Warn = 4, //!< Warn log message
+ Err = 8 //!< Error log message
+ };
public:
- /** @brief Virtual destructor */
- virtual ~Logger();
-
- // ----------------------------------------------------------------------
- /** @brief Writes a debug message
- * @param message Debug message*/
- void debug(const char* message);
- inline void debug(const std::string &message);
-
- // ----------------------------------------------------------------------
- /** @brief Writes a info message
- * @param message Info message*/
- void info(const char* message);
- inline void info(const std::string &message);
-
- // ----------------------------------------------------------------------
- /** @brief Writes a warning message
- * @param message Warn message*/
- void warn(const char* message);
- inline void warn(const std::string &message);
-
- // ----------------------------------------------------------------------
- /** @brief Writes an error message
- * @param message Error message*/
- void error(const char* message);
- inline void error(const std::string &message);
-
- // ----------------------------------------------------------------------
- /** @brief Set a new log severity.
- * @param log_severity New severity for logging*/
- void setLogSeverity(LogSeverity log_severity);
-
- // ----------------------------------------------------------------------
- /** @brief Get the current log severity*/
- LogSeverity getLogSeverity() const;
-
- // ----------------------------------------------------------------------
- /** @brief Attach a new log-stream
- *
- * The logger takes ownership of the stream and is responsible
- * for its destruction (which is done using ::delete when the logger
- * itself is destroyed). Call detachStream to detach a stream and to
- * gain ownership of it again.
- * @param pStream Log-stream to attach
- * @param severity Message filter, specified which types of log
- * messages are dispatched to the stream. Provide a bitwise
- * combination of the ErrorSeverity flags.
- * @return true if the stream has been attached, false otherwise.*/
- virtual bool attachStream(LogStream *pStream,
- unsigned int severity = Debugging | Err | Warn | Info) = 0;
-
- // ----------------------------------------------------------------------
- /** @brief Detach a still attached stream from the logger (or
- * modify the filter flags bits)
- * @param pStream Log-stream instance for detaching
- * @param severity Provide a bitwise combination of the ErrorSeverity
- * flags. This value is &~ed with the current flags of the stream,
- * if the result is 0 the stream is detached from the Logger and
- * the caller retakes the possession of the stream.
- * @return true if the stream has been detached, false otherwise.*/
- virtual bool detatchStream(LogStream *pStream,
- unsigned int severity = Debugging | Err | Warn | Info) = 0;
+ /** @brief Virtual destructor */
+ virtual ~Logger();
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a debug message
+ * @param message Debug message*/
+ void debug(const char* message);
+ inline void debug(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a info message
+ * @param message Info message*/
+ void info(const char* message);
+ inline void info(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes a warning message
+ * @param message Warn message*/
+ void warn(const char* message);
+ inline void warn(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Writes an error message
+ * @param message Error message*/
+ void error(const char* message);
+ inline void error(const std::string &message);
+
+ // ----------------------------------------------------------------------
+ /** @brief Set a new log severity.
+ * @param log_severity New severity for logging*/
+ void setLogSeverity(LogSeverity log_severity);
+
+ // ----------------------------------------------------------------------
+ /** @brief Get the current log severity*/
+ LogSeverity getLogSeverity() const;
+
+ // ----------------------------------------------------------------------
+ /** @brief Attach a new log-stream
+ *
+ * The logger takes ownership of the stream and is responsible
+ * for its destruction (which is done using ::delete when the logger
+ * itself is destroyed). Call detachStream to detach a stream and to
+ * gain ownership of it again.
+ * @param pStream Log-stream to attach
+ * @param severity Message filter, specified which types of log
+ * messages are dispatched to the stream. Provide a bitwise
+ * combination of the ErrorSeverity flags.
+ * @return true if the stream has been attached, false otherwise.*/
+ virtual bool attachStream(LogStream *pStream,
+ unsigned int severity = Debugging | Err | Warn | Info) = 0;
+
+ // ----------------------------------------------------------------------
+ /** @brief Detach a still attached stream from the logger (or
+ * modify the filter flags bits)
+ * @param pStream Log-stream instance for detaching
+ * @param severity Provide a bitwise combination of the ErrorSeverity
+ * flags. This value is &~ed with the current flags of the stream,
+ * if the result is 0 the stream is detached from the Logger and
+ * the caller retakes the possession of the stream.
+ * @return true if the stream has been detached, false otherwise.*/
+ virtual bool detatchStream(LogStream *pStream,
+ unsigned int severity = Debugging | Err | Warn | Info) = 0;
protected:
- /** Default constructor */
- Logger();
-
- /** Construction with a given log severity */
- Logger(LogSeverity severity);
-
- // ----------------------------------------------------------------------
- /** @brief Called as a request to write a specific debug message
- * @param message Debug message. Never longer than
- * MAX_LOG_MESSAGE_LENGTH characters (excluding the '0').
- * @note The message string is only valid until the scope of
- * the function is left.
- */
- virtual void OnDebug(const char* message)= 0;
-
- // ----------------------------------------------------------------------
- /** @brief Called as a request to write a specific info message
- * @param message Info message. Never longer than
- * MAX_LOG_MESSAGE_LENGTH characters (ecxluding the '0').
- * @note The message string is only valid until the scope of
- * the function is left.
- */
- virtual void OnInfo(const char* message) = 0;
-
- // ----------------------------------------------------------------------
- /** @brief Called as a request to write a specific warn message
- * @param message Warn message. Never longer than
- * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0').
- * @note The message string is only valid until the scope of
- * the function is left.
- */
- virtual void OnWarn(const char* essage) = 0;
-
- // ----------------------------------------------------------------------
- /** @brief Called as a request to write a specific error message
- * @param message Error message. Never longer than
- * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0').
- * @note The message string is only valid until the scope of
- * the function is left.
- */
- virtual void OnError(const char* message) = 0;
+ /** Default constructor */
+ Logger();
+
+ /** Construction with a given log severity */
+ explicit Logger(LogSeverity severity);
+
+ // ----------------------------------------------------------------------
+ /** @brief Called as a request to write a specific debug message
+ * @param message Debug message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (excluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnDebug(const char* message)= 0;
+
+ // ----------------------------------------------------------------------
+ /** @brief Called as a request to write a specific info message
+ * @param message Info message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (ecxluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnInfo(const char* message) = 0;
+
+ // ----------------------------------------------------------------------
+ /** @brief Called as a request to write a specific warn message
+ * @param message Warn message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnWarn(const char* essage) = 0;
+
+ // ----------------------------------------------------------------------
+ /** @brief Called as a request to write a specific error message
+ * @param message Error message. Never longer than
+ * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0').
+ * @note The message string is only valid until the scope of
+ * the function is left.
+ */
+ virtual void OnError(const char* message) = 0;
protected:
- //! Logger severity
- LogSeverity m_Severity;
+ //! Logger severity
+ LogSeverity m_Severity;
};
// ----------------------------------------------------------------------------------
-// Default constructor
-inline Logger::Logger() {
- setLogSeverity(NORMAL);
+// Default constructor
+inline Logger::Logger() {
+ setLogSeverity(NORMAL);
}
// ----------------------------------------------------------------------------------
-// Virtual destructor
+// Virtual destructor
inline Logger::~Logger()
{
}
// ----------------------------------------------------------------------------------
// Construction with given logging severity
-inline Logger::Logger(LogSeverity severity) {
- setLogSeverity(severity);
+inline Logger::Logger(LogSeverity severity) {
+ setLogSeverity(severity);
}
// ----------------------------------------------------------------------------------
// Log severity setter
inline void Logger::setLogSeverity(LogSeverity log_severity){
- m_Severity = log_severity;
+ m_Severity = log_severity;
}
// ----------------------------------------------------------------------------------
// Log severity getter
inline Logger::LogSeverity Logger::getLogSeverity() const {
- return m_Severity;
+ return m_Severity;
}
// ----------------------------------------------------------------------------------
inline void Logger::debug(const std::string &message)
{
- return debug(message.c_str());
+ return debug(message.c_str());
}
// ----------------------------------------------------------------------------------
inline void Logger::error(const std::string &message)
{
- return error(message.c_str());
+ return error(message.c_str());
}
// ----------------------------------------------------------------------------------
inline void Logger::warn(const std::string &message)
{
- return warn(message.c_str());
+ return warn(message.c_str());
}
// ----------------------------------------------------------------------------------
inline void Logger::info(const std::string &message)
{
- return info(message.c_str());
+ return info(message.c_str());
}
// ----------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/include/assimp/NullLogger.hpp b/src/3rdparty/assimp/include/assimp/NullLogger.hpp
index e87584a34..64b59a4a0 100644
--- a/src/3rdparty/assimp/include/assimp/NullLogger.hpp
+++ b/src/3rdparty/assimp/include/assimp/NullLogger.hpp
@@ -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 NullLogger.h
+/** @file NullLogger.hpp
* @brief Dummy logger
*/
@@ -46,48 +46,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_NULLLOGGER_H
#include "Logger.hpp"
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** @brief CPP-API: Empty logging implementation.
*
- * Does nothing! Used by default if the application hasn't requested a
+ * Does nothing! Used by default if the application hasn't requested a
* custom logger via #DefaultLogger::set() or #DefaultLogger::create(); */
-class ASSIMP_API NullLogger
- : public Logger {
+class ASSIMP_API NullLogger
+ : public Logger {
public:
- /** @brief Logs a debug message */
- void OnDebug(const char* message) {
- (void)message; //this avoids compiler warnings
- }
-
- /** @brief Logs an info message */
- void OnInfo(const char* message) {
- (void)message; //this avoids compiler warnings
- }
-
- /** @brief Logs a warning message */
- void OnWarn(const char* message) {
- (void)message; //this avoids compiler warnings
- }
-
- /** @brief Logs an error message */
- void OnError(const char* message) {
- (void)message; //this avoids compiler warnings
- }
-
- /** @brief Detach a still attached stream from logger */
- bool attachStream(LogStream *pStream, unsigned int severity) {
- (void)pStream; (void)severity; //this avoids compiler warnings
- return false;
- }
-
- /** @brief Detach a still attached stream from logger */
- bool detatchStream(LogStream *pStream, unsigned int severity) {
- (void)pStream; (void)severity; //this avoids compiler warnings
- return false;
- }
+ /** @brief Logs a debug message */
+ void OnDebug(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Logs an info message */
+ void OnInfo(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Logs a warning message */
+ void OnWarn(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Logs an error message */
+ void OnError(const char* message) {
+ (void)message; //this avoids compiler warnings
+ }
+
+ /** @brief Detach a still attached stream from logger */
+ bool attachStream(LogStream *pStream, unsigned int severity) {
+ (void)pStream; (void)severity; //this avoids compiler warnings
+ return false;
+ }
+
+ /** @brief Detach a still attached stream from logger */
+ bool detatchStream(LogStream *pStream, unsigned int severity) {
+ (void)pStream; (void)severity; //this avoids compiler warnings
+ return false;
+ }
private:
};
diff --git a/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp b/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp
index a6cddab94..8b069c82e 100644
--- a/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp
+++ b/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp
@@ -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,73 +23,99 @@ 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 ProgressHandler.h
+/** @file ProgressHandler.hpp
* @brief Abstract base class 'ProgressHandler'.
*/
#ifndef INCLUDED_AI_PROGRESSHANDLER_H
#define INCLUDED_AI_PROGRESSHANDLER_H
#include "types.h"
-namespace Assimp {
+namespace Assimp {
// ------------------------------------------------------------------------------------
/** @brief CPP-API: Abstract interface for custom progress report receivers.
*
- * Each #Importer instance maintains its own #ProgressHandler. The default
+ * Each #Importer instance maintains its own #ProgressHandler. The default
* implementation provided by Assimp doesn't do anything at all. */
class ASSIMP_API ProgressHandler
#ifndef SWIG
- : public Intern::AllocateFromAssimpHeap
+ : public Intern::AllocateFromAssimpHeap
#endif
{
protected:
- /** @brief Default constructor */
- ProgressHandler () {
- }
+ /** @brief Default constructor */
+ ProgressHandler () {
+ }
public:
- /** @brief Virtual destructor */
- virtual ~ProgressHandler () {
- }
+ /** @brief Virtual destructor */
+ virtual ~ProgressHandler () {
+ }
- // -------------------------------------------------------------------
- /** @brief Progress callback.
- * @param percentage An estimate of the current loading progress,
- * in percent. Or -1.f if such an estimate is not available.
- *
- * There are restriction on what you may do from within your
- * implementation of this method: no exceptions may be thrown and no
- * non-const #Importer methods may be called. It is
- * not generally possible to predict the number of callbacks
- * fired during a single import.
- *
- * @return Return false to abort loading at the next possible
- * occasion (loaders and Assimp are generally allowed to perform
- * all needed cleanup tasks prior to returning control to the
- * caller). If the loading is aborted, #Importer::ReadFile()
- * returns always NULL.
- *
- * @note Currently, percentage is always -1.f because there is
- * no reliable way to compute it.
- * */
- virtual bool Update(float percentage = -1.f) = 0;
+ // -------------------------------------------------------------------
+ /** @brief Progress callback.
+ * @param percentage An estimate of the current loading progress,
+ * in percent. Or -1.f if such an estimate is not available.
+ *
+ * There are restriction on what you may do from within your
+ * implementation of this method: no exceptions may be thrown and no
+ * non-const #Importer methods may be called. It is
+ * not generally possible to predict the number of callbacks
+ * fired during a single import.
+ *
+ * @return Return false to abort loading at the next possible
+ * occasion (loaders and Assimp are generally allowed to perform
+ * all needed cleanup tasks prior to returning control to the
+ * caller). If the loading is aborted, #Importer::ReadFile()
+ * returns always NULL.
+ * */
+ virtual bool Update(float percentage = -1.f) = 0;
+ // -------------------------------------------------------------------
+ /** @brief Progress callback for file loading steps
+ * @param numberOfSteps The number of total post-processing
+ * steps
+ * @param currentStep The index of the current post-processing
+ * step that will run, or equal to numberOfSteps if all of
+ * them has finished. This number is always strictly monotone
+ * increasing, although not necessarily linearly.
+ *
+ * @note This is currently only used at the start and the end
+ * of the file parsing.
+ * */
+ virtual void UpdateFileRead(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+ float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+ Update( f * 0.5f );
+ }
+ // -------------------------------------------------------------------
+ /** @brief Progress callback for post-processing steps
+ * @param numberOfSteps The number of total post-processing
+ * steps
+ * @param currentStep The index of the current post-processing
+ * step that will run, or equal to numberOfSteps if all of
+ * them has finished. This number is always strictly monotone
+ * increasing, although not necessarily linearly.
+ * */
+ virtual void UpdatePostProcess(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) {
+ float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f;
+ Update( f * 0.5f + 0.5f );
+ }
-}; // !class ProgressHandler
+}; // !class ProgressHandler
// ------------------------------------------------------------------------------------
} // Namespace Assimp
diff --git a/src/3rdparty/assimp/include/assimp/ai_assert.h b/src/3rdparty/assimp/include/assimp/ai_assert.h
index f42f909d5..0caeff673 100644
--- a/src/3rdparty/assimp/include/assimp/ai_assert.h
+++ b/src/3rdparty/assimp/include/assimp/ai_assert.h
@@ -1,13 +1,51 @@
-/** @file assert.h
- */
+/*
+---------------------------------------------------------------------------
+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_DEBUG_H_INC
#define AI_DEBUG_H_INC
-#ifdef ASSIMP_BUILD_DEBUG
-# include <assert.h>
-# define ai_assert(expression) assert(expression)
+#ifdef ASSIMP_BUILD_DEBUG
+# include <assert.h>
+# define ai_assert(expression) assert(expression)
#else
-# define ai_assert(expression)
+# define ai_assert(expression)
#endif
diff --git a/src/3rdparty/assimp/include/assimp/anim.h b/src/3rdparty/assimp/include/assimp/anim.h
index b32d749ba..393224e40 100644
--- a/src/3rdparty/assimp/include/assimp/anim.h
+++ b/src/3rdparty/assimp/include/assimp/anim.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.
---------------------------------------------------------------------------
*/
@@ -57,126 +57,126 @@ extern "C" {
/** A time-value pair specifying a certain 3D vector for the given time. */
struct aiVectorKey
{
- /** The time of this key */
- double mTime;
-
- /** The value of this key */
- C_STRUCT aiVector3D mValue;
+ /** The time of this key */
+ double mTime;
+
+ /** The value of this key */
+ C_STRUCT aiVector3D mValue;
#ifdef __cplusplus
- //! Default constructor
- aiVectorKey(){}
+ //! Default constructor
+ aiVectorKey(){}
- //! Construction from a given time and key value
- aiVectorKey(double time, const aiVector3D& value)
- : mTime (time)
- , mValue (value)
- {}
+ //! Construction from a given time and key value
+ aiVectorKey(double time, const aiVector3D& value)
+ : mTime (time)
+ , mValue (value)
+ {}
- typedef aiVector3D elem_type;
+ typedef aiVector3D elem_type;
- // Comparison operators. For use with std::find();
- bool operator == (const aiVectorKey& o) const {
- return o.mValue == this->mValue;
- }
- bool operator != (const aiVectorKey& o) const {
- return o.mValue != this->mValue;
- }
+ // Comparison operators. For use with std::find();
+ bool operator == (const aiVectorKey& o) const {
+ return o.mValue == this->mValue;
+ }
+ bool operator != (const aiVectorKey& o) const {
+ return o.mValue != this->mValue;
+ }
- // Relational operators. For use with std::sort();
- bool operator < (const aiVectorKey& o) const {
- return mTime < o.mTime;
- }
- bool operator > (const aiVectorKey& o) const {
- return mTime > o.mTime;
- }
+ // Relational operators. For use with std::sort();
+ bool operator < (const aiVectorKey& o) const {
+ return mTime < o.mTime;
+ }
+ bool operator > (const aiVectorKey& o) const {
+ return mTime > o.mTime;
+ }
#endif
};
// ---------------------------------------------------------------------------
-/** A time-value pair specifying a rotation for the given time.
+/** A time-value pair specifying a rotation for the given time.
* Rotations are expressed with quaternions. */
struct aiQuatKey
{
- /** The time of this key */
- double mTime;
+ /** The time of this key */
+ double mTime;
- /** The value of this key */
- C_STRUCT aiQuaternion mValue;
+ /** The value of this key */
+ C_STRUCT aiQuaternion mValue;
#ifdef __cplusplus
- aiQuatKey(){
- }
+ aiQuatKey(){
+ }
- /** Construction from a given time and key value */
- aiQuatKey(double time, const aiQuaternion& value)
- : mTime (time)
- , mValue (value)
- {}
+ /** Construction from a given time and key value */
+ aiQuatKey(double time, const aiQuaternion& value)
+ : mTime (time)
+ , mValue (value)
+ {}
- typedef aiQuaternion elem_type;
+ typedef aiQuaternion elem_type;
- // Comparison operators. For use with std::find();
- bool operator == (const aiQuatKey& o) const {
- return o.mValue == this->mValue;
- }
- bool operator != (const aiQuatKey& o) const {
- return o.mValue != this->mValue;
- }
+ // Comparison operators. For use with std::find();
+ bool operator == (const aiQuatKey& o) const {
+ return o.mValue == this->mValue;
+ }
+ bool operator != (const aiQuatKey& o) const {
+ return o.mValue != this->mValue;
+ }
- // Relational operators. For use with std::sort();
- bool operator < (const aiQuatKey& o) const {
- return mTime < o.mTime;
- }
- bool operator > (const aiQuatKey& o) const {
- return mTime > o.mTime;
- }
+ // Relational operators. For use with std::sort();
+ bool operator < (const aiQuatKey& o) const {
+ return mTime < o.mTime;
+ }
+ bool operator > (const aiQuatKey& o) const {
+ return mTime > o.mTime;
+ }
#endif
};
// ---------------------------------------------------------------------------
/** Binds a anim mesh to a specific point in time. */
-struct aiMeshKey
+struct aiMeshKey
{
- /** The time of this key */
- double mTime;
+ /** The time of this key */
+ double mTime;
- /** Index into the aiMesh::mAnimMeshes array of the
- * mesh coresponding to the #aiMeshAnim hosting this
- * key frame. The referenced anim mesh is evaluated
- * according to the rules defined in the docs for #aiAnimMesh.*/
- unsigned int mValue;
+ /** Index into the aiMesh::mAnimMeshes array of the
+ * mesh coresponding to the #aiMeshAnim hosting this
+ * key frame. The referenced anim mesh is evaluated
+ * according to the rules defined in the docs for #aiAnimMesh.*/
+ unsigned int mValue;
#ifdef __cplusplus
- aiMeshKey() {
- }
+ aiMeshKey() {
+ }
- /** Construction from a given time and key value */
- aiMeshKey(double time, const unsigned int value)
- : mTime (time)
- , mValue (value)
- {}
+ /** Construction from a given time and key value */
+ aiMeshKey(double time, const unsigned int value)
+ : mTime (time)
+ , mValue (value)
+ {}
- typedef unsigned int elem_type;
+ typedef unsigned int elem_type;
- // Comparison operators. For use with std::find();
- bool operator == (const aiMeshKey& o) const {
- return o.mValue == this->mValue;
- }
- bool operator != (const aiMeshKey& o) const {
- return o.mValue != this->mValue;
- }
+ // Comparison operators. For use with std::find();
+ bool operator == (const aiMeshKey& o) const {
+ return o.mValue == this->mValue;
+ }
+ bool operator != (const aiMeshKey& o) const {
+ return o.mValue != this->mValue;
+ }
- // Relational operators. For use with std::sort();
- bool operator < (const aiMeshKey& o) const {
- return mTime < o.mTime;
- }
- bool operator > (const aiMeshKey& o) const {
- return mTime > o.mTime;
- }
+ // Relational operators. For use with std::sort();
+ bool operator < (const aiMeshKey& o) const {
+ return mTime < o.mTime;
+ }
+ bool operator > (const aiMeshKey& o) const {
+ return mTime > o.mTime;
+ }
#endif
};
@@ -197,10 +197,10 @@ struct aiMeshMorphKey
unsigned int mNumValuesAndWeights;
#ifdef __cplusplus
aiMeshMorphKey()
- : mTime(0.0)
- , mValues(NULL)
- , mWeights(NULL)
- , mNumValuesAndWeights(0)
+ : mTime(0.0)
+ , mValues(NULL)
+ , mWeights(NULL)
+ , mNumValuesAndWeights(0)
{
}
@@ -217,37 +217,39 @@ struct aiMeshMorphKey
// ---------------------------------------------------------------------------
/** Defines how an animation channel behaves outside the defined time
- * range. This corresponds to aiNodeAnim::mPreState and
+ * range. This corresponds to aiNodeAnim::mPreState and
* aiNodeAnim::mPostState.*/
enum aiAnimBehaviour
{
- /** The value from the default node transformation is taken*/
- aiAnimBehaviour_DEFAULT = 0x0,
+ /** The value from the default node transformation is taken*/
+ aiAnimBehaviour_DEFAULT = 0x0,
+
+ /** The nearest key value is used without interpolation */
+ aiAnimBehaviour_CONSTANT = 0x1,
+
+ /** The value of the nearest two keys is linearly
+ * extrapolated for the current time value.*/
+ aiAnimBehaviour_LINEAR = 0x2,
- /** The nearest key value is used without interpolation */
- aiAnimBehaviour_CONSTANT = 0x1,
+ /** The animation is repeated.
+ *
+ * If the animation key go from n to m and the current
+ * time is t, use the value at (t-n) % (|m-n|).*/
+ aiAnimBehaviour_REPEAT = 0x3,
- /** The value of the nearest two keys is linearly
- * extrapolated for the current time value.*/
- aiAnimBehaviour_LINEAR = 0x2,
- /** The animation is repeated.
- *
- * If the animation key go from n to m and the current
- * time is t, use the value at (t-n) % (|m-n|).*/
- aiAnimBehaviour_REPEAT = 0x3,
- /** This value is not used, it is just here to force the
- * the compiler to map this enum to a 32 Bit integer */
+ /** This value is not used, it is just here to force the
+ * the compiler to map this enum to a 32 Bit integer */
#ifndef SWIG
- _aiAnimBehaviour_Force32Bit = INT_MAX
+ _aiAnimBehaviour_Force32Bit = INT_MAX
#endif
};
// ---------------------------------------------------------------------------
-/** Describes the animation of a single node. The name specifies the
+/** Describes the animation of a single node. The name specifies the
* bone/node which is affected by this animation channel. The keyframes
- * are given in three separate series of values, one each for position,
+ * are given in three separate series of values, one each for position,
* rotation and scaling. The transformation matrix computed from these
* values replaces the node's original transformation matrix at a
* specific time.
@@ -257,111 +259,111 @@ enum aiAnimBehaviour
*
* @note All keys are returned in their correct, chronological order.
* Duplicate keys don't pass the validation step. Most likely there
- * will be no negative time values, but they are not forbidden also ( so
+ * will be no negative time values, but they are not forbidden also ( so
* implementations need to cope with them! ) */
struct aiNodeAnim
{
- /** The name of the node affected by this animation. The node
- * must exist and it must be unique.*/
- C_STRUCT aiString mNodeName;
-
- /** The number of position keys */
- unsigned int mNumPositionKeys;
-
- /** The position keys of this animation channel. Positions are
- * specified as 3D vector. The array is mNumPositionKeys in size.
- *
- * If there are position keys, there will also be at least one
- * scaling and one rotation key.*/
- C_STRUCT aiVectorKey* mPositionKeys;
-
- /** The number of rotation keys */
- unsigned int mNumRotationKeys;
-
- /** The rotation keys of this animation channel. Rotations are
- * given as quaternions, which are 4D vectors. The array is
- * mNumRotationKeys in size.
- *
- * If there are rotation keys, there will also be at least one
- * scaling and one position key. */
- C_STRUCT aiQuatKey* mRotationKeys;
-
-
- /** The number of scaling keys */
- unsigned int mNumScalingKeys;
-
- /** The scaling keys of this animation channel. Scalings are
- * specified as 3D vector. The array is mNumScalingKeys in size.
- *
- * If there are scaling keys, there will also be at least one
- * position and one rotation key.*/
- C_STRUCT aiVectorKey* mScalingKeys;
-
-
- /** Defines how the animation behaves before the first
- * key is encountered.
- *
- * The default value is aiAnimBehaviour_DEFAULT (the original
- * transformation matrix of the affected node is used).*/
- C_ENUM aiAnimBehaviour mPreState;
-
- /** Defines how the animation behaves after the last
- * key was processed.
- *
- * The default value is aiAnimBehaviour_DEFAULT (the original
- * transformation matrix of the affected node is taken).*/
- C_ENUM aiAnimBehaviour mPostState;
+ /** The name of the node affected by this animation. The node
+ * must exist and it must be unique.*/
+ C_STRUCT aiString mNodeName;
+
+ /** The number of position keys */
+ unsigned int mNumPositionKeys;
+
+ /** The position keys of this animation channel. Positions are
+ * specified as 3D vector. The array is mNumPositionKeys in size.
+ *
+ * If there are position keys, there will also be at least one
+ * scaling and one rotation key.*/
+ C_STRUCT aiVectorKey* mPositionKeys;
+
+ /** The number of rotation keys */
+ unsigned int mNumRotationKeys;
+
+ /** The rotation keys of this animation channel. Rotations are
+ * given as quaternions, which are 4D vectors. The array is
+ * mNumRotationKeys in size.
+ *
+ * If there are rotation keys, there will also be at least one
+ * scaling and one position key. */
+ C_STRUCT aiQuatKey* mRotationKeys;
+
+
+ /** The number of scaling keys */
+ unsigned int mNumScalingKeys;
+
+ /** The scaling keys of this animation channel. Scalings are
+ * specified as 3D vector. The array is mNumScalingKeys in size.
+ *
+ * If there are scaling keys, there will also be at least one
+ * position and one rotation key.*/
+ C_STRUCT aiVectorKey* mScalingKeys;
+
+
+ /** Defines how the animation behaves before the first
+ * key is encountered.
+ *
+ * The default value is aiAnimBehaviour_DEFAULT (the original
+ * transformation matrix of the affected node is used).*/
+ C_ENUM aiAnimBehaviour mPreState;
+
+ /** Defines how the animation behaves after the last
+ * key was processed.
+ *
+ * The default value is aiAnimBehaviour_DEFAULT (the original
+ * transformation matrix of the affected node is taken).*/
+ C_ENUM aiAnimBehaviour mPostState;
#ifdef __cplusplus
- aiNodeAnim()
- {
- mNumPositionKeys = 0; mPositionKeys = NULL;
- mNumRotationKeys = 0; mRotationKeys = NULL;
- mNumScalingKeys = 0; mScalingKeys = NULL;
+ aiNodeAnim()
+ {
+ mNumPositionKeys = 0; mPositionKeys = NULL;
+ mNumRotationKeys = 0; mRotationKeys = NULL;
+ mNumScalingKeys = 0; mScalingKeys = NULL;
- mPreState = mPostState = aiAnimBehaviour_DEFAULT;
- }
+ mPreState = mPostState = aiAnimBehaviour_DEFAULT;
+ }
- ~aiNodeAnim()
- {
- delete [] mPositionKeys;
- delete [] mRotationKeys;
- delete [] mScalingKeys;
- }
+ ~aiNodeAnim()
+ {
+ delete [] mPositionKeys;
+ delete [] mRotationKeys;
+ delete [] mScalingKeys;
+ }
#endif // __cplusplus
};
// ---------------------------------------------------------------------------
/** Describes vertex-based animations for a single mesh or a group of
* meshes. Meshes carry the animation data for each frame in their
- * aiMesh::mAnimMeshes array. The purpose of aiMeshAnim is to
+ * aiMesh::mAnimMeshes array. The purpose of aiMeshAnim is to
* define keyframes linking each mesh attachment to a particular
* point in time. */
struct aiMeshAnim
{
- /** Name of the mesh to be animated. An empty string is not allowed,
- * animated meshes need to be named (not necessarily uniquely,
- * the name can basically serve as wildcard to select a group
- * of meshes with similar animation setup)*/
- C_STRUCT aiString mName;
+ /** Name of the mesh to be animated. An empty string is not allowed,
+ * animated meshes need to be named (not necessarily uniquely,
+ * the name can basically serve as wildcard to select a group
+ * of meshes with similar animation setup)*/
+ C_STRUCT aiString mName;
- /** Size of the #mKeys array. Must be 1, at least. */
- unsigned int mNumKeys;
+ /** Size of the #mKeys array. Must be 1, at least. */
+ unsigned int mNumKeys;
- /** Key frames of the animation. May not be NULL. */
- C_STRUCT aiMeshKey* mKeys;
+ /** Key frames of the animation. May not be NULL. */
+ C_STRUCT aiMeshKey* mKeys;
#ifdef __cplusplus
- aiMeshAnim()
- : mNumKeys()
- , mKeys()
- {}
+ aiMeshAnim()
+ : mNumKeys()
+ , mKeys()
+ {}
- ~aiMeshAnim()
- {
- delete[] mKeys;
- }
+ ~aiMeshAnim()
+ {
+ delete[] mKeys;
+ }
#endif
};
@@ -398,37 +400,37 @@ struct aiMeshMorphAnim
};
// ---------------------------------------------------------------------------
-/** An animation consists of keyframe data for a number of nodes. For
+/** An animation consists of keyframe data for a number of nodes. For
* each node affected by the animation a separate series of data is given.*/
struct aiAnimation
{
- /** The name of the animation. If the modeling package this data was
- * exported from does support only a single animation channel, this
- * name is usually empty (length is zero). */
- C_STRUCT aiString mName;
+ /** The name of the animation. If the modeling package this data was
+ * exported from does support only a single animation channel, this
+ * name is usually empty (length is zero). */
+ C_STRUCT aiString mName;
- /** Duration of the animation in ticks. */
- double mDuration;
+ /** Duration of the animation in ticks. */
+ double mDuration;
- /** Ticks per second. 0 if not specified in the imported file */
- double mTicksPerSecond;
+ /** Ticks per second. 0 if not specified in the imported file */
+ double mTicksPerSecond;
- /** The number of bone animation channels. Each channel affects
- * a single node. */
- unsigned int mNumChannels;
+ /** The number of bone animation channels. Each channel affects
+ * a single node. */
+ unsigned int mNumChannels;
- /** The node animation channels. Each channel affects a single node.
- * The array is mNumChannels in size. */
- C_STRUCT aiNodeAnim** mChannels;
+ /** The node animation channels. Each channel affects a single node.
+ * The array is mNumChannels in size. */
+ C_STRUCT aiNodeAnim** mChannels;
- /** The number of mesh animation channels. Each channel affects
- * a single mesh and defines vertex-based animation. */
- unsigned int mNumMeshChannels;
+ /** The number of mesh animation channels. Each channel affects
+ * a single mesh and defines vertex-based animation. */
+ unsigned int mNumMeshChannels;
- /** The mesh animation channels. Each channel affects a single mesh.
- * The array is mNumMeshChannels in size. */
- C_STRUCT aiMeshAnim** mMeshChannels;
+ /** The mesh animation channels. Each channel affects a single mesh.
+ * The array is mNumMeshChannels in size. */
+ C_STRUCT aiMeshAnim** mMeshChannels;
/** The number of mesh animation channels. Each channel affects
@@ -441,14 +443,14 @@ struct aiAnimation
#ifdef __cplusplus
aiAnimation()
- : mDuration(-1.)
- , mTicksPerSecond()
- , mNumChannels()
- , mChannels()
- , mNumMeshChannels()
- , mMeshChannels()
- , mNumMorphMeshChannels()
- , mMorphMeshChannels()
+ : mDuration(-1.)
+ , mTicksPerSecond()
+ , mNumChannels()
+ , mChannels()
+ , mNumMeshChannels()
+ , mMeshChannels()
+ , mNumMorphMeshChannels()
+ , mMorphMeshChannels()
{
}
@@ -469,11 +471,11 @@ struct aiAnimation
delete [] mMeshChannels;
}
- if (mNumMorphMeshChannels && mMorphMeshChannels) {
- for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) {
- delete mMorphMeshChannels[a];
- }
- }
+ if (mNumMorphMeshChannels && mMorphMeshChannels) {
+ for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) {
+ delete mMorphMeshChannels[a];
+ }
+ }
}
#endif // __cplusplus
};
@@ -488,70 +490,70 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** @brief CPP-API: Utility class to simplify interpolations of various data types.
*
- * The type of interpolation is choosen automatically depending on the
+ * The type of interpolation is chosen automatically depending on the
* types of the arguments. */
template <typename T>
-struct Interpolator
-{
- // ------------------------------------------------------------------
- /** @brief Get the result of the interpolation between a,b.
- *
- * The interpolation algorithm depends on the type of the operands.
- * aiQuaternion's and aiQuatKey's SLERP, the rest does a simple
- * linear interpolation. */
- void operator () (T& out,const T& a, const T& b, float d) const {
- out = a + (b-a)*d;
- }
+struct Interpolator
+{
+ // ------------------------------------------------------------------
+ /** @brief Get the result of the interpolation between a,b.
+ *
+ * The interpolation algorithm depends on the type of the operands.
+ * aiQuaternion's and aiQuatKey's SLERP, the rest does a simple
+ * linear interpolation. */
+ void operator () (T& out,const T& a, const T& b, float d) const {
+ out = a + (b-a)*d;
+ }
}; // ! Interpolator <T>
//! @cond Never
template <>
-struct Interpolator <aiQuaternion> {
- void operator () (aiQuaternion& out,const aiQuaternion& a,
- const aiQuaternion& b, float d) const
- {
- aiQuaternion::Interpolate(out,a,b,d);
- }
+struct Interpolator <aiQuaternion> {
+ void operator () (aiQuaternion& out,const aiQuaternion& a,
+ const aiQuaternion& b, float d) const
+ {
+ aiQuaternion::Interpolate(out,a,b,d);
+ }
}; // ! Interpolator <aiQuaternion>
template <>
-struct Interpolator <unsigned int> {
- void operator () (unsigned int& out,unsigned int a,
- unsigned int b, float d) const
- {
- out = d>0.5f ? b : a;
- }
+struct Interpolator <unsigned int> {
+ void operator () (unsigned int& out,unsigned int a,
+ unsigned int b, float d) const
+ {
+ out = d>0.5f ? b : a;
+ }
}; // ! Interpolator <aiQuaternion>
template <>
-struct Interpolator <aiVectorKey> {
- void operator () (aiVector3D& out,const aiVectorKey& a,
- const aiVectorKey& b, float d) const
- {
- Interpolator<aiVector3D> ipl;
- ipl(out,a.mValue,b.mValue,d);
- }
+struct Interpolator <aiVectorKey> {
+ void operator () (aiVector3D& out,const aiVectorKey& a,
+ const aiVectorKey& b, float d) const
+ {
+ Interpolator<aiVector3D> ipl;
+ ipl(out,a.mValue,b.mValue,d);
+ }
}; // ! Interpolator <aiVectorKey>
template <>
-struct Interpolator <aiQuatKey> {
- void operator () (aiQuaternion& out, const aiQuatKey& a,
- const aiQuatKey& b, float d) const
- {
- Interpolator<aiQuaternion> ipl;
- ipl(out,a.mValue,b.mValue,d);
- }
+struct Interpolator <aiQuatKey> {
+ void operator () (aiQuaternion& out, const aiQuatKey& a,
+ const aiQuatKey& b, float d) const
+ {
+ Interpolator<aiQuaternion> ipl;
+ ipl(out,a.mValue,b.mValue,d);
+ }
}; // ! Interpolator <aiQuatKey>
template <>
-struct Interpolator <aiMeshKey> {
- void operator () (unsigned int& out, const aiMeshKey& a,
- const aiMeshKey& b, float d) const
- {
- Interpolator<unsigned int> ipl;
- ipl(out,a.mValue,b.mValue,d);
- }
+struct Interpolator <aiMeshKey> {
+ void operator () (unsigned int& out, const aiMeshKey& a,
+ const aiMeshKey& b, float d) const
+ {
+ Interpolator<unsigned int> ipl;
+ ipl(out,a.mValue,b.mValue,d);
+ }
}; // ! Interpolator <aiQuatKey>
//! @endcond
diff --git a/src/3rdparty/assimp/include/assimp/camera.h b/src/3rdparty/assimp/include/assimp/camera.h
index 78d3a9e57..37f1bdaa0 100644
--- a/src/3rdparty/assimp/include/assimp/camera.h
+++ b/src/3rdparty/assimp/include/assimp/camera.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.
---------------------------------------------------------------------------
*/
@@ -53,16 +53,16 @@ extern "C" {
#endif
// ---------------------------------------------------------------------------
-/** Helper structure to describe a virtual camera.
+/** Helper structure to describe a virtual camera.
*
* Cameras have a representation in the node graph and can be animated.
* An important aspect is that the camera itself is also part of the
- * scenegraph. This means, any values such as the look-at vector are not
+ * scenegraph. This means, any values such as the look-at vector are not
* *absolute*, they're <b>relative</b> to the coordinate system defined
* by the node which corresponds to the camera. This allows for camera
* animations. For static cameras parameters like the 'look-at' or 'up' vectors
* are usually specified directly in aiCamera, but beware, they could also
- * be encoded in the node transformation. The following (pseudo)code sample
+ * be encoded in the node transformation. The following (pseudo)code sample
* shows how to do it: <br><br>
* @code
* // Get the camera matrix for a camera at a specific time
@@ -93,124 +93,124 @@ extern "C" {
* called "<camName>.Target". However this is just additional information
* then the transformation tracks of the camera main node make the
* camera already look in the right direction.
- *
+ *
*/
struct aiCamera
{
- /** The name of the camera.
- *
- * There must be a node in the scenegraph with the same name.
- * This node specifies the position of the camera in the scene
- * hierarchy and can be animated.
- */
- C_STRUCT aiString mName;
-
- /** Position of the camera relative to the coordinate space
- * defined by the corresponding node.
- *
- * The default value is 0|0|0.
- */
- C_STRUCT aiVector3D mPosition;
-
-
- /** 'Up' - vector of the camera coordinate system relative to
- * the coordinate space defined by the corresponding node.
- *
- * The 'right' vector of the camera coordinate system is
- * the cross product of the up and lookAt vectors.
- * The default value is 0|1|0. The vector
- * may be normalized, but it needn't.
- */
- C_STRUCT aiVector3D mUp;
-
-
- /** 'LookAt' - vector of the camera coordinate system relative to
- * the coordinate space defined by the corresponding node.
- *
- * This is the viewing direction of the user.
- * The default value is 0|0|1. The vector
- * may be normalized, but it needn't.
- */
- C_STRUCT aiVector3D mLookAt;
-
-
- /** Half horizontal field of view angle, in radians.
- *
- * The field of view angle is the angle between the center
- * line of the screen and the left or right border.
- * The default value is 1/4PI.
- */
- float mHorizontalFOV;
-
- /** Distance of the near clipping plane from the camera.
- *
- * The value may not be 0.f (for arithmetic reasons to prevent
- * a division through zero). The default value is 0.1f.
- */
- float mClipPlaneNear;
-
- /** Distance of the far clipping plane from the camera.
- *
- * The far clipping plane must, of course, be further away than the
- * near clipping plane. The default value is 1000.f. The ratio
- * between the near and the far plane should not be too
- * large (between 1000-10000 should be ok) to avoid floating-point
- * inaccuracies which could lead to z-fighting.
- */
- float mClipPlaneFar;
-
-
- /** Screen aspect ratio.
- *
- * This is the ration between the width and the height of the
- * screen. Typical values are 4/3, 1/2 or 1/1. This value is
- * 0 if the aspect ratio is not defined in the source file.
- * 0 is also the default value.
- */
- float mAspect;
+ /** The name of the camera.
+ *
+ * There must be a node in the scenegraph with the same name.
+ * This node specifies the position of the camera in the scene
+ * hierarchy and can be animated.
+ */
+ C_STRUCT aiString mName;
+
+ /** Position of the camera relative to the coordinate space
+ * defined by the corresponding node.
+ *
+ * The default value is 0|0|0.
+ */
+ C_STRUCT aiVector3D mPosition;
+
+
+ /** 'Up' - vector of the camera coordinate system relative to
+ * the coordinate space defined by the corresponding node.
+ *
+ * The 'right' vector of the camera coordinate system is
+ * the cross product of the up and lookAt vectors.
+ * The default value is 0|1|0. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mUp;
+
+
+ /** 'LookAt' - vector of the camera coordinate system relative to
+ * the coordinate space defined by the corresponding node.
+ *
+ * This is the viewing direction of the user.
+ * The default value is 0|0|1. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mLookAt;
+
+
+ /** Half horizontal field of view angle, in radians.
+ *
+ * The field of view angle is the angle between the center
+ * line of the screen and the left or right border.
+ * The default value is 1/4PI.
+ */
+ float mHorizontalFOV;
+
+ /** Distance of the near clipping plane from the camera.
+ *
+ * The value may not be 0.f (for arithmetic reasons to prevent
+ * a division through zero). The default value is 0.1f.
+ */
+ float mClipPlaneNear;
+
+ /** Distance of the far clipping plane from the camera.
+ *
+ * The far clipping plane must, of course, be further away than the
+ * near clipping plane. The default value is 1000.f. The ratio
+ * between the near and the far plane should not be too
+ * large (between 1000-10000 should be ok) to avoid floating-point
+ * inaccuracies which could lead to z-fighting.
+ */
+ float mClipPlaneFar;
+
+
+ /** Screen aspect ratio.
+ *
+ * This is the ration between the width and the height of the
+ * screen. Typical values are 4/3, 1/2 or 1/1. This value is
+ * 0 if the aspect ratio is not defined in the source file.
+ * 0 is also the default value.
+ */
+ float mAspect;
#ifdef __cplusplus
- aiCamera()
- : mUp (0.f,1.f,0.f)
- , mLookAt (0.f,0.f,1.f)
- , mHorizontalFOV (0.25f * (float)AI_MATH_PI)
- , mClipPlaneNear (0.1f)
- , mClipPlaneFar (1000.f)
- , mAspect (0.f)
- {}
-
- /** @brief Get a *right-handed* camera matrix from me
- * @param out Camera matrix to be filled
- */
- void GetCameraMatrix (aiMatrix4x4& out) const
- {
- /** todo: test ... should work, but i'm not absolutely sure */
-
- /** We don't know whether these vectors are already normalized ...*/
- aiVector3D zaxis = mLookAt; zaxis.Normalize();
- aiVector3D yaxis = mUp; yaxis.Normalize();
- aiVector3D xaxis = mUp^mLookAt; xaxis.Normalize();
-
- out.a4 = -(xaxis * mPosition);
- out.b4 = -(yaxis * mPosition);
- out.c4 = -(zaxis * mPosition);
-
- out.a1 = xaxis.x;
- out.a2 = xaxis.y;
- out.a3 = xaxis.z;
-
- out.b1 = yaxis.x;
- out.b2 = yaxis.y;
- out.b3 = yaxis.z;
-
- out.c1 = zaxis.x;
- out.c2 = zaxis.y;
- out.c3 = zaxis.z;
-
- out.d1 = out.d2 = out.d3 = 0.f;
- out.d4 = 1.f;
- }
+ aiCamera()
+ : mUp (0.f,1.f,0.f)
+ , mLookAt (0.f,0.f,1.f)
+ , mHorizontalFOV (0.25f * (float)AI_MATH_PI)
+ , mClipPlaneNear (0.1f)
+ , mClipPlaneFar (1000.f)
+ , mAspect (0.f)
+ {}
+
+ /** @brief Get a *right-handed* camera matrix from me
+ * @param out Camera matrix to be filled
+ */
+ void GetCameraMatrix (aiMatrix4x4& out) const
+ {
+ /** todo: test ... should work, but i'm not absolutely sure */
+
+ /** We don't know whether these vectors are already normalized ...*/
+ aiVector3D zaxis = mLookAt; zaxis.Normalize();
+ aiVector3D yaxis = mUp; yaxis.Normalize();
+ aiVector3D xaxis = mUp^mLookAt; xaxis.Normalize();
+
+ out.a4 = -(xaxis * mPosition);
+ out.b4 = -(yaxis * mPosition);
+ out.c4 = -(zaxis * mPosition);
+
+ out.a1 = xaxis.x;
+ out.a2 = xaxis.y;
+ out.a3 = xaxis.z;
+
+ out.b1 = yaxis.x;
+ out.b2 = yaxis.y;
+ out.b3 = yaxis.z;
+
+ out.c1 = zaxis.x;
+ out.c2 = zaxis.y;
+ out.c3 = zaxis.z;
+
+ out.d1 = out.d2 = out.d3 = 0.f;
+ out.d4 = 1.f;
+ }
#endif
};
diff --git a/src/3rdparty/assimp/include/assimp/cexport.h b/src/3rdparty/assimp/include/assimp/cexport.h
index 9041621a1..71cb1f8ec 100644
--- a/src/3rdparty/assimp/include/assimp/cexport.h
+++ b/src/3rdparty/assimp/include/assimp/cexport.h
@@ -7,8 +7,8 @@ Copyright (c) 2006-2011, assimp 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.
---------------------------------------------------------------------------
*/
@@ -57,23 +57,23 @@ struct aiScene; // aiScene.h
struct aiFileIO; // aiFileIO.h
// --------------------------------------------------------------------------------
-/** Describes an file format which Assimp can export to. Use #aiGetExportFormatCount() to
+/** Describes an file format which Assimp can export to. Use #aiGetExportFormatCount() to
* learn how many export formats the current Assimp build supports and #aiGetExportFormatDescription()
* to retrieve a description of an export format option.
*/
struct aiExportFormatDesc
{
- /// a short string ID to uniquely identify the export format. Use this ID string to
- /// specify which file format you want to export to when calling #aiExportScene().
- /// Example: "dae" or "obj"
- const char* id;
+ /// a short string ID to uniquely identify the export format. Use this ID string to
+ /// specify which file format you want to export to when calling #aiExportScene().
+ /// Example: "dae" or "obj"
+ const char* id;
- /// A short description of the file format to present to users. Useful if you want
- /// to allow the user to select an export format.
- const char* description;
+ /// A short description of the file format to present to users. Useful if you want
+ /// to allow the user to select an export format.
+ const char* description;
- /// Recommended file extension for the exported file in lower case.
- const char* fileExtension;
+ /// Recommended file extension for the exported file in lower case.
+ const char* fileExtension;
};
@@ -86,25 +86,32 @@ ASSIMP_API size_t aiGetExportFormatCount(void);
// --------------------------------------------------------------------------------
/** Returns a description of the nth export file format. Use #aiGetExportFormatCount()
- * to learn how many export formats are supported.
+ * to learn how many export formats are supported. The description must be released by
+ * calling aiReleaseExportFormatDescription afterwards.
* @param pIndex Index of the export format to retrieve information for. Valid range is
* 0 to #aiGetExportFormatCount()
* @return A description of that specific export format. NULL if pIndex is out of range.
*/
ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex);
+// --------------------------------------------------------------------------------
+/** Release a description of the nth export file format. Must be returned by
+* aiGetExportFormatDescription
+* @param desc Pointer to the description
+*/
+ASSIMP_API void aiReleaseExportFormatDescription( const C_STRUCT aiExportFormatDesc *desc );
// --------------------------------------------------------------------------------
/** Create a modifiable copy of a scene.
- * This is useful to import files via Assimp, change their topology and
+ * This is useful to import files via Assimp, change their topology and
* export them again. Since the scene returned by the various importer functions
* is const, a modifiable copy is needed.
* @param pIn Valid scene to be copied
* @param pOut Receives a modifyable copy of the scene. Use aiFreeScene() to
* delete it again.
*/
-ASSIMP_API void aiCopyScene(const C_STRUCT aiScene* pIn,
- C_STRUCT aiScene** pOut);
+ASSIMP_API void aiCopyScene(const C_STRUCT aiScene* pIn,
+ C_STRUCT aiScene** pOut);
// --------------------------------------------------------------------------------
@@ -119,19 +126,16 @@ ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn);
* should use a right-handed coordinate systems, face winding should be counter-clockwise
* and the UV coordinate origin is assumed to be in the upper left. If your input data
* uses different conventions, have a look at the last parameter.
-* @param pFormatId ID string to specify to which format you want to export to. Use
+* @param pFormatId ID string to specify to which format you want to export to. Use
* aiGetExportFormatCount() / aiGetExportFormatDescription() to learn which export formats are available.
* @param pFileName Output file to write
-* @param pIO custom IO implementation to be used. Use this if you use your own storage methods.
-* If none is supplied, a default implementation using standard file IO is used. Note that
-* #aiExportSceneToBlob is provided as convenience function to export to memory buffers.
-* @param pPreprocessing Accepts any choice of the #aiPostProcessing enumerated
+* @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
* flags, but in reality only a subset of them makes sense here. Specifying
-* 'preprocessing' flags is useful if the input scene does not conform to
-* Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
-* In short, this means the geometry data should use a right-handed coordinate systems, face
+* 'preprocessing' flags is useful if the input scene does not conform to
+* Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
+* In short, this means the geometry data should use a right-handed coordinate systems, face
* winding should be counter-clockwise and the UV coordinate origin is assumed to be in
-* the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+* the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
* #aiProcess_FlipWindingOrder flags are used in the import side to allow users
* to have those defaults automatically adapted to their conventions. Specifying those flags
* for exporting has the opposite effect, respectively. Some other of the
@@ -139,30 +143,30 @@ ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn);
* to try out what their effect on the exported file is. Many formats impose
* their own restrictions on the structure of the geometry stored therein,
* so some preprocessing may have little or no effect at all, or may be
-* redundant as exporters would apply them anyhow. A good example
+* redundant as exporters would apply them anyhow. A good example
* is triangulation - whilst you can enforce it by specifying
* the #aiProcess_Triangulate flag, most export formats support only
* triangulate data so they would run the step anyway.
*
-* If assimp detects that the input scene was directly taken from the importer side of
-* the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
+* If assimp detects that the input scene was directly taken from the importer side of
+* the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
* any postprocessing steps already applied to the scene will not be applied again, unless
-* they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
+* they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
* #aiProcess_FlipWindingOrder).
* @return a status code indicating the result of the export
* @note Use aiCopyScene() to get a modifiable copy of a previously
* imported scene.
*/
-ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene,
- const char* pFormatId,
- const char* pFileName,
- unsigned int pPreprocessing);
+ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene,
+ const char* pFormatId,
+ const char* pFileName,
+ unsigned int pPreprocessing);
// --------------------------------------------------------------------------------
/** Exports the given scene to a chosen file format using custom IO logic supplied by you.
* @param pScene The scene to export. Stays in possession of the caller, is not changed by the function.
-* @param pFormatId ID string to specify to which format you want to export to. Use
+* @param pFormatId ID string to specify to which format you want to export to. Use
* aiGetExportFormatCount() / aiGetExportFormatDescription() to learn which export formats are available.
* @param pFileName Output file to write
* @param pIO custom IO implementation to be used. Use this if you use your own storage methods.
@@ -174,16 +178,16 @@ ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene,
* @note Use aiCopyScene() to get a modifiable copy of a previously
* imported scene.
*/
-ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
- const char* pFormatId,
- const char* pFileName,
- C_STRUCT aiFileIO* pIO,
- unsigned int pPreprocessing );
+ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
+ const char* pFormatId,
+ const char* pFileName,
+ C_STRUCT aiFileIO* pIO,
+ unsigned int pPreprocessing );
// --------------------------------------------------------------------------------
/** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an
-* exported scene. The memory referred by this structure is owned by Assimp. Use #aiReleaseExportedFile()
+* exported scene. The memory referred by this structure is owned by Assimp.
* to free its resources. Don't try to free the memory on your side - it will crash for most build configurations
* due to conflicting heaps.
*
@@ -191,50 +195,50 @@ ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
* This is used when exporters write more than one output file for a given #aiScene. See the remarks for
* #aiExportDataBlob::name for more information.
*/
-struct aiExportDataBlob
+struct aiExportDataBlob
{
- /// Size of the data in bytes
- size_t size;
+ /// Size of the data in bytes
+ size_t size;
- /// The data.
- void* data;
+ /// The data.
+ void* data;
- /** Name of the blob. An empty string always
- indicates the first (and primary) blob,
- which contains the actual file data.
+ /** Name of the blob. An empty string always
+ indicates the first (and primary) blob,
+ which contains the actual file data.
Any other blobs are auxiliary files produced
- by exporters (i.e. material files). Existence
- of such files depends on the file format. Most
- formats don't split assets across multiple files.
-
- If used, blob names usually contain the file
- extension that should be used when writing
- the data to disc.
- */
+ by exporters (i.e. material files). Existence
+ of such files depends on the file format. Most
+ formats don't split assets across multiple files.
+
+ If used, blob names usually contain the file
+ extension that should be used when writing
+ the data to disc.
+ */
C_STRUCT aiString name;
- /** Pointer to the next blob in the chain or NULL if there is none. */
- C_STRUCT aiExportDataBlob * next;
+ /** Pointer to the next blob in the chain or NULL if there is none. */
+ C_STRUCT aiExportDataBlob * next;
#ifdef __cplusplus
- /// Default constructor
- aiExportDataBlob() { size = 0; data = next = NULL; }
- /// Releases the data
- ~aiExportDataBlob() { delete [] static_cast<unsigned char*>( data ); delete next; }
+ /// Default constructor
+ aiExportDataBlob() { size = 0; data = next = NULL; }
+ /// Releases the data
+ ~aiExportDataBlob() { delete [] static_cast<unsigned char*>( data ); delete next; }
private:
- // no copying
- aiExportDataBlob(const aiExportDataBlob& );
- aiExportDataBlob& operator= (const aiExportDataBlob& );
+ // no copying
+ aiExportDataBlob(const aiExportDataBlob& );
+ aiExportDataBlob& operator= (const aiExportDataBlob& );
#endif // __cplusplus
};
// --------------------------------------------------------------------------------
/** Exports the given scene to a chosen file format. Returns the exported data as a binary blob which
* you can write into a file or something. When you're done with the data, use #aiReleaseExportBlob()
-* to free the resources associated with the export.
+* to free the resources associated with the export.
* @param pScene The scene to export. Stays in possession of the caller, is not changed by the function.
-* @param pFormatId ID string to specify to which format you want to export to. Use
+* @param pFormatId ID string to specify to which format you want to export to. Use
* #aiGetExportFormatCount() / #aiGetExportFormatDescription() to learn which export formats are available.
* @param pPreprocessing Please see the documentation for #aiExportScene
* @return the exported data or NULL in case of error
@@ -244,7 +248,7 @@ ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT
// --------------------------------------------------------------------------------
/** Releases the memory associated with the given exported data. Use this function to free a data blob
-* returned by aiExportScene().
+* returned by aiExportScene().
* @param pData the data blob returned by #aiExportSceneToBlob
*/
ASSIMP_API void aiReleaseExportBlob( const C_STRUCT aiExportDataBlob* pData );
diff --git a/src/3rdparty/assimp/include/assimp/cfileio.h b/src/3rdparty/assimp/include/assimp/cfileio.h
index 83145e789..d91974b78 100644
--- a/src/3rdparty/assimp/include/assimp/cfileio.h
+++ b/src/3rdparty/assimp/include/assimp/cfileio.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,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.
---------------------------------------------------------------------------
*/
-/** @file aiFileIO.h
+/** @file cfileio.h
* @brief Defines generic C routines to access memory-mapped files
*/
#ifndef AI_FILEIO_H_INC
@@ -71,62 +71,62 @@ typedef char* aiUserData;
*
* Provided are functions to open and close files. Supply a custom structure to
* the import function. If you don't, a default implementation is used. Use custom
- * file systems to enable reading from other sources, such as ZIPs
+ * file systems to enable reading from other sources, such as ZIPs
* or memory locations. */
struct aiFileIO
{
- /** Function used to open a new file
- */
- aiFileOpenProc OpenProc;
+ /** Function used to open a new file
+ */
+ aiFileOpenProc OpenProc;
- /** Function used to close an existing file
- */
- aiFileCloseProc CloseProc;
+ /** Function used to close an existing file
+ */
+ aiFileCloseProc CloseProc;
- /** User-defined, opaque data */
- aiUserData UserData;
+ /** User-defined, opaque data */
+ aiUserData UserData;
};
// ----------------------------------------------------------------------------------
/** @brief C-API: File callbacks
*
- * Actually, it's a data structure to wrap a set of fXXXX (e.g fopen)
+ * Actually, it's a data structure to wrap a set of fXXXX (e.g fopen)
* replacement functions.
*
- * The default implementation of the functions utilizes the fXXX functions from
+ * The default implementation of the functions utilizes the fXXX functions from
* the CRT. However, you can supply a custom implementation to Assimp by
- * delivering a custom aiFileIO. Use this to enable reading from other sources,
+ * delivering a custom aiFileIO. Use this to enable reading from other sources,
* such as ZIP archives or memory locations. */
struct aiFile
{
- /** Callback to read from a file */
- aiFileReadProc ReadProc;
-
- /** Callback to write to a file */
- aiFileWriteProc WriteProc;
-
- /** Callback to retrieve the current position of
- * the file cursor (ftell())
- */
- aiFileTellProc TellProc;
-
- /** Callback to retrieve the size of the file,
- * in bytes
- */
- aiFileTellProc FileSizeProc;
-
- /** Callback to set the current position
- * of the file cursor (fseek())
- */
- aiFileSeek SeekProc;
-
- /** Callback to flush the file contents
- */
- aiFileFlushProc FlushProc;
-
- /** User-defined, opaque data
- */
- aiUserData UserData;
+ /** Callback to read from a file */
+ aiFileReadProc ReadProc;
+
+ /** Callback to write to a file */
+ aiFileWriteProc WriteProc;
+
+ /** Callback to retrieve the current position of
+ * the file cursor (ftell())
+ */
+ aiFileTellProc TellProc;
+
+ /** Callback to retrieve the size of the file,
+ * in bytes
+ */
+ aiFileTellProc FileSizeProc;
+
+ /** Callback to set the current position
+ * of the file cursor (fseek())
+ */
+ aiFileSeek SeekProc;
+
+ /** Callback to flush the file contents
+ */
+ aiFileFlushProc FlushProc;
+
+ /** User-defined, opaque data
+ */
+ aiUserData UserData;
};
#ifdef __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/cimport.h b/src/3rdparty/assimp/include/assimp/cimport.h
index bc2c99e6d..de0cbae30 100644
--- a/src/3rdparty/assimp/include/assimp/cimport.h
+++ b/src/3rdparty/assimp/include/assimp/cimport.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,26 +25,27 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file assimp.h
- * @brief Defines the C-API to the Open Asset Import Library.
+/** @file cimport.h
+ * @brief Defines the C-API to the Open Asset Import Library.
*/
#ifndef AI_ASSIMP_H_INC
#define AI_ASSIMP_H_INC
#include "types.h"
+#include "importerdesc.h"
#ifdef __cplusplus
extern "C" {
@@ -63,11 +64,11 @@ typedef void (*aiLogStreamCallback)(const char* /* message */, char* /* user */)
// --------------------------------------------------------------------------------
struct aiLogStream
{
- /** callback to be called */
- aiLogStreamCallback callback;
+ /** callback to be called */
+ aiLogStreamCallback callback;
- /** user data to be passed to the callback */
- char* user;
+ /** user data to be passed to the callback */
+ char* user;
};
@@ -92,135 +93,167 @@ typedef int aiBool;
// --------------------------------------------------------------------------------
/** Reads the given file and returns its content.
- *
- * If the call succeeds, the imported data is returned in an aiScene structure.
- * The data is intended to be read-only, it stays property of the ASSIMP
- * library and will be stable until aiReleaseImport() is called. After you're
- * done with it, call aiReleaseImport() to free the resources associated with
- * this file. If the import fails, NULL is returned instead. Call
+ *
+ * If the call succeeds, the imported data is returned in an aiScene structure.
+ * The data is intended to be read-only, it stays property of the ASSIMP
+ * library and will be stable until aiReleaseImport() is called. After you're
+ * done with it, call aiReleaseImport() to free the resources associated with
+ * this file. If the import fails, NULL is returned instead. Call
* aiGetErrorString() to retrieve a human-readable error text.
- * @param pFile Path and filename of the file to be imported,
+ * @param pFile Path and filename of the file to be imported,
* expected to be a null-terminated c-string. NULL is not a valid value.
- * @param pFlags Optional post processing steps to be executed after
- * a successful import. Provide a bitwise combination of the
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
* #aiPostProcessSteps flags.
- * @return Pointer to the imported data or NULL if the import failed.
+ * @return Pointer to the imported data or NULL if the import failed.
*/
-ASSIMP_API const C_STRUCT aiScene* aiImportFile(
- const char* pFile,
- unsigned int pFlags);
+ASSIMP_API const C_STRUCT aiScene* aiImportFile(
+ const char* pFile,
+ unsigned int pFlags);
// --------------------------------------------------------------------------------
-/** Reads the given file using user-defined I/O functions and returns
+/** Reads the given file using user-defined I/O functions and returns
* its content.
- *
- * If the call succeeds, the imported data is returned in an aiScene structure.
- * The data is intended to be read-only, it stays property of the ASSIMP
- * library and will be stable until aiReleaseImport() is called. After you're
- * done with it, call aiReleaseImport() to free the resources associated with
- * this file. If the import fails, NULL is returned instead. Call
+ *
+ * If the call succeeds, the imported data is returned in an aiScene structure.
+ * The data is intended to be read-only, it stays property of the ASSIMP
+ * library and will be stable until aiReleaseImport() is called. After you're
+ * done with it, call aiReleaseImport() to free the resources associated with
+ * this file. If the import fails, NULL is returned instead. Call
* aiGetErrorString() to retrieve a human-readable error text.
- * @param pFile Path and filename of the file to be imported,
+ * @param pFile Path and filename of the file to be imported,
* expected to be a null-terminated c-string. NULL is not a valid value.
- * @param pFlags Optional post processing steps to be executed after
+ * @param pFlags Optional post processing steps to be executed after
* a successful import. Provide a bitwise combination of the
* #aiPostProcessSteps flags.
* @param pFS aiFileIO structure. Will be used to open the model file itself
* and any other files the loader needs to open. Pass NULL to use the default
* implementation.
- * @return Pointer to the imported data or NULL if the import failed.
+ * @return Pointer to the imported data or NULL if the import failed.
* @note Include <aiFileIO.h> for the definition of #aiFileIO.
*/
-ASSIMP_API const C_STRUCT aiScene* aiImportFileEx(
- const char* pFile,
- unsigned int pFlags,
- C_STRUCT aiFileIO* pFS);
+ASSIMP_API const C_STRUCT aiScene* aiImportFileEx(
+ const char* pFile,
+ unsigned int pFlags,
+ C_STRUCT aiFileIO* pFS);
// --------------------------------------------------------------------------------
/** Same as #aiImportFileEx, but adds an extra parameter containing importer settings.
*
- * @param pProps #aiPropertyStore instance containing import settings.
+ * @param pFile Path and filename of the file to be imported,
+ * expected to be a null-terminated c-string. NULL is not a valid value.
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags.
+ * @param pFS aiFileIO structure. Will be used to open the model file itself
+ * and any other files the loader needs to open. Pass NULL to use the default
+ * implementation.
+ * @param pProps #aiPropertyStore instance containing import settings.
+ * @return Pointer to the imported data or NULL if the import failed.
+ * @note Include <aiFileIO.h> for the definition of #aiFileIO.
* @see aiImportFileEx
*/
-ASSIMP_API const C_STRUCT aiScene* aiImportFileExWithProperties(
- const char* pFile,
- unsigned int pFlags,
- C_STRUCT aiFileIO* pFS,
- const C_STRUCT aiPropertyStore* pProps);
+ASSIMP_API const C_STRUCT aiScene* aiImportFileExWithProperties(
+ const char* pFile,
+ unsigned int pFlags,
+ C_STRUCT aiFileIO* pFS,
+ const C_STRUCT aiPropertyStore* pProps);
// --------------------------------------------------------------------------------
/** Reads the given file from a given memory buffer,
- *
+ *
* If the call succeeds, the contents of the file are returned as a pointer to an
- * aiScene object. The returned data is intended to be read-only, the importer keeps
- * ownership of the data and will destroy it upon destruction. If the import fails,
+ * aiScene object. The returned data is intended to be read-only, the importer keeps
+ * ownership of the data and will destroy it upon destruction. If the import fails,
* NULL is returned.
- * A human-readable error description can be retrieved by calling aiGetErrorString().
+ * A human-readable error description can be retrieved by calling aiGetErrorString().
* @param pBuffer Pointer to the file data
* @param pLength Length of pBuffer, in bytes
- * @param pFlags Optional post processing steps to be executed after
- * a successful import. Provide a bitwise combination of the
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
* #aiPostProcessSteps flags. If you wish to inspect the imported
* scene first in order to fine-tune your post-processing setup,
* consider to use #aiApplyPostProcessing().
* @param pHint An additional hint to the library. If this is a non empty string,
* the library looks for a loader to support the file extension specified by pHint
- * and passes the file to the first matching loader. If this loader is unable to
+ * and passes the file to the first matching loader. If this loader is unable to
* completely the request, the library continues and tries to determine the file
- * format on its own, a task that may or may not be successful.
+ * format on its own, a task that may or may not be successful.
* Check the return value, and you'll know ...
* @return A pointer to the imported data, NULL if the import failed.
*
* @note This is a straightforward way to decode models from memory
- * buffers, but it doesn't handle model formats that spread their
+ * buffers, but it doesn't handle model formats that spread their
* data across multiple files or even directories. Examples include
* OBJ or MD3, which outsource parts of their material info into
* external scripts. If you need full functionality, provide
* a custom IOSystem to make Assimp find these files and use
* the regular aiImportFileEx()/aiImportFileExWithProperties() API.
*/
-ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory(
- const char* pBuffer,
- unsigned int pLength,
- unsigned int pFlags,
- const char* pHint);
+ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemory(
+ const char* pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char* pHint);
// --------------------------------------------------------------------------------
/** Same as #aiImportFileFromMemory, but adds an extra parameter containing importer settings.
*
- * @param pProps #aiPropertyStore instance containing import settings.
+ * @param pBuffer Pointer to the file data
+ * @param pLength Length of pBuffer, in bytes
+ * @param pFlags Optional post processing steps to be executed after
+ * a successful import. Provide a bitwise combination of the
+ * #aiPostProcessSteps flags. If you wish to inspect the imported
+ * scene first in order to fine-tune your post-processing setup,
+ * consider to use #aiApplyPostProcessing().
+ * @param pHint An additional hint to the library. If this is a non empty string,
+ * the library looks for a loader to support the file extension specified by pHint
+ * and passes the file to the first matching loader. If this loader is unable to
+ * completely the request, the library continues and tries to determine the file
+ * format on its own, a task that may or may not be successful.
+ * Check the return value, and you'll know ...
+ * @param pProps #aiPropertyStore instance containing import settings.
+ * @return A pointer to the imported data, NULL if the import failed.
+ *
+ * @note This is a straightforward way to decode models from memory
+ * buffers, but it doesn't handle model formats that spread their
+ * data across multiple files or even directories. Examples include
+ * OBJ or MD3, which outsource parts of their material info into
+ * external scripts. If you need full functionality, provide
+ * a custom IOSystem to make Assimp find these files and use
+ * the regular aiImportFileEx()/aiImportFileExWithProperties() API.
* @see aiImportFileFromMemory
*/
-ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemoryWithProperties(
- const char* pBuffer,
- unsigned int pLength,
- unsigned int pFlags,
- const char* pHint,
- const C_STRUCT aiPropertyStore* pProps);
+ASSIMP_API const C_STRUCT aiScene* aiImportFileFromMemoryWithProperties(
+ const char* pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char* pHint,
+ const C_STRUCT aiPropertyStore* pProps);
// --------------------------------------------------------------------------------
/** Apply post-processing to an already-imported scene.
*
* This is strictly equivalent to calling #aiImportFile()/#aiImportFileEx with the
- * same flags. However, you can use this separate function to inspect the imported
- * scene first to fine-tune your post-processing setup.
+ * same flags. However, you can use this separate function to inspect the imported
+ * scene first to fine-tune your post-processing setup.
* @param pScene Scene to work on.
* @param pFlags Provide a bitwise combination of the #aiPostProcessSteps flags.
* @return A pointer to the post-processed data. Post processing is done in-place,
* meaning this is still the same #aiScene which you passed for pScene. However,
* _if_ post-processing failed, the scene could now be NULL. That's quite a rare
- * case, post processing steps are not really designed to 'fail'. To be exact,
- * the #aiProcess_ValidateDS flag is currently the only post processing step
+ * case, post processing steps are not really designed to 'fail'. To be exact,
+ * the #aiProcess_ValidateDataStructure flag is currently the only post processing step
* which can actually cause the scene to be reset to NULL.
*/
ASSIMP_API const C_STRUCT aiScene* aiApplyPostProcessing(
- const C_STRUCT aiScene* pScene,
- unsigned int pFlags);
+ const C_STRUCT aiScene* pScene,
+ unsigned int pFlags);
// --------------------------------------------------------------------------------
-/** Get one of the predefine log streams. This is the quick'n'easy solution to
+/** Get one of the predefine log streams. This is the quick'n'easy solution to
* access Assimp's log system. Attaching a log stream can slightly reduce Assimp's
- * overall import performance.
+ * overall import performance.
*
* Usage is rather simple (this will stream the log to a file, named log.txt, and
* the stdout stream of the process:
@@ -232,27 +265,27 @@ ASSIMP_API const C_STRUCT aiScene* aiApplyPostProcessing(
* aiAttachLogStream(&c);
* @endcode
*
- * @param pStreams One of the #aiDefaultLogStream enumerated values.
+ * @param pStreams One of the #aiDefaultLogStream enumerated values.
* @param file Solely for the #aiDefaultLogStream_FILE flag: specifies the file to write to.
* Pass NULL for all other flags.
* @return The log stream. callback is set to NULL if something went wrong.
*/
ASSIMP_API C_STRUCT aiLogStream aiGetPredefinedLogStream(
- C_ENUM aiDefaultLogStream pStreams,
- const char* file);
+ C_ENUM aiDefaultLogStream pStreams,
+ const char* file);
// --------------------------------------------------------------------------------
/** Attach a custom log stream to the libraries' logging system.
*
* Attaching a log stream can slightly reduce Assimp's overall import
- * performance. Multiple log-streams can be attached.
+ * performance. Multiple log-streams can be attached.
* @param stream Describes the new log stream.
- * @note To ensure proepr destruction of the logging system, you need to manually
- * call aiDetachLogStream() on every single log stream you attach.
+ * @note To ensure proper destruction of the logging system, you need to manually
+ * call aiDetachLogStream() on every single log stream you attach.
* Alternatively (for the lazy folks) #aiDetachAllLogStreams is provided.
*/
ASSIMP_API void aiAttachLogStream(
- const C_STRUCT aiLogStream* stream);
+ const C_STRUCT aiLogStream* stream);
// --------------------------------------------------------------------------------
/** Enable verbose logging. Verbose logging includes debug-related stuff and
@@ -266,14 +299,14 @@ ASSIMP_API void aiEnableVerboseLogging(aiBool d);
// --------------------------------------------------------------------------------
/** Detach a custom log stream from the libraries' logging system.
*
- * This is the counterpart of #aiAttachPredefinedLogStream. If you attached a stream,
+ * This is the counterpart of #aiAttachLogStream. If you attached a stream,
* don't forget to detach it again.
* @param stream The log stream to be detached.
* @return AI_SUCCESS if the log stream has been detached successfully.
* @see aiDetachAllLogStreams
*/
ASSIMP_API C_ENUM aiReturn aiDetachLogStream(
- const C_STRUCT aiLogStream* stream);
+ const C_STRUCT aiLogStream* stream);
// --------------------------------------------------------------------------------
/** Detach all active log streams from the libraries' logging system.
@@ -291,11 +324,11 @@ ASSIMP_API void aiDetachAllLogStreams(void);
* Call this function after you're done with the imported data.
* @param pScene The imported data to release. NULL is a valid value.
*/
-ASSIMP_API void aiReleaseImport(
- const C_STRUCT aiScene* pScene);
+ASSIMP_API void aiReleaseImport(
+ const C_STRUCT aiScene* pScene);
// --------------------------------------------------------------------------------
-/** Returns the error text of the last failed import process.
+/** Returns the error text of the last failed import process.
*
* @return A textual description of the error that occurred at the last
* import process. NULL if there was no error. There can't be an error if you
@@ -311,7 +344,7 @@ ASSIMP_API const char* aiGetErrorString();
* @return AI_TRUE if the file extension is supported.
*/
ASSIMP_API aiBool aiIsExtensionSupported(
- const char* szExtension);
+ const char* szExtension);
// --------------------------------------------------------------------------------
/** Get a list of all file extensions supported by ASSIMP.
@@ -322,16 +355,16 @@ ASSIMP_API aiBool aiIsExtensionSupported(
* Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter.
*/
ASSIMP_API void aiGetExtensionList(
- C_STRUCT aiString* szOut);
+ C_STRUCT aiString* szOut);
// --------------------------------------------------------------------------------
/** Get the approximated storage required by an imported asset
* @param pIn Input asset.
- * @param in Data structure to be filled.
+ * @param in Data structure to be filled.
*/
ASSIMP_API void aiGetMemoryRequirements(
- const C_STRUCT aiScene* pIn,
- C_STRUCT aiMemoryInfo* in);
+ const C_STRUCT aiScene* pIn,
+ C_STRUCT aiMemoryInfo* in);
@@ -350,70 +383,72 @@ ASSIMP_API C_STRUCT aiPropertyStore* aiCreatePropertyStore(void);
ASSIMP_API void aiReleasePropertyStore(C_STRUCT aiPropertyStore* p);
// --------------------------------------------------------------------------------
-/** Set an integer property.
+/** Set an integer property.
*
- * This is the C-version of #Assimp::Importer::SetPropertyInteger(). In the C
- * interface, properties are always shared by all imports. It is not possible to
+ * This is the C-version of #Assimp::Importer::SetPropertyInteger(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
* specify them per import.
*
- * @param szName Name of the configuration property to be set. All supported
- * public properties are defined in the config.h header file (#AI_CONFIG_XXX).
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
* @param value New value for the property
*/
ASSIMP_API void aiSetImportPropertyInteger(
- C_STRUCT aiPropertyStore* store,
- const char* szName,
- int value);
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ int value);
// --------------------------------------------------------------------------------
-/** Set a floating-point property.
+/** Set a floating-point property.
*
- * This is the C-version of #Assimp::Importer::SetPropertyFloat(). In the C
- * interface, properties are always shared by all imports. It is not possible to
+ * This is the C-version of #Assimp::Importer::SetPropertyFloat(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
* specify them per import.
*
- * @param szName Name of the configuration property to be set. All supported
- * public properties are defined in the config.h header file (#AI_CONFIG_XXX).
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
* @param value New value for the property
*/
ASSIMP_API void aiSetImportPropertyFloat(
- C_STRUCT aiPropertyStore* store,
- const char* szName,
- float value);
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ float value);
// --------------------------------------------------------------------------------
-/** Set a string property.
+/** Set a string property.
*
- * This is the C-version of #Assimp::Importer::SetPropertyString(). In the C
- * interface, properties are always shared by all imports. It is not possible to
+ * This is the C-version of #Assimp::Importer::SetPropertyString(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
* specify them per import.
*
- * @param property store to modify. Use #aiCreatePropertyStore to obtain a store.
- * @param szName Name of the configuration property to be set. All supported
- * public properties are defined in the config.h header file (#AI_CONFIG_XXX).
- * @param value New value for the property
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
+ * @param st New value for the property
*/
ASSIMP_API void aiSetImportPropertyString(
- C_STRUCT aiPropertyStore* store,
- const char* szName,
- const C_STRUCT aiString* st);
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ const C_STRUCT aiString* st);
// --------------------------------------------------------------------------------
-/** Set a matrix property.
+/** Set a matrix property.
*
- * This is the C-version of #Assimp::Importer::SetPropertyMatrix(). In the C
- * interface, properties are always shared by all imports. It is not possible to
+ * This is the C-version of #Assimp::Importer::SetPropertyMatrix(). In the C
+ * interface, properties are always shared by all imports. It is not possible to
* specify them per import.
*
- * @param property store to modify. Use #aiCreatePropertyStore to obtain a store.
- * @param szName Name of the configuration property to be set. All supported
- * public properties are defined in the config.h header file (#AI_CONFIG_XXX).
- * @param value New value for the property
+ * @param store Store to modify. Use #aiCreatePropertyStore to obtain a store.
+ * @param szName Name of the configuration property to be set. All supported
+ * public properties are defined in the config.h header file (AI_CONFIG_XXX).
+ * @param mat New value for the property
*/
ASSIMP_API void aiSetImportPropertyMatrix(
- C_STRUCT aiPropertyStore* store,
- const char* szName,
- const C_STRUCT aiMatrix4x4* mat);
+ C_STRUCT aiPropertyStore* store,
+ const char* szName,
+ const C_STRUCT aiMatrix4x4* mat);
// --------------------------------------------------------------------------------
/** Construct a quaternion from a 3x3 rotation matrix.
@@ -422,13 +457,13 @@ ASSIMP_API void aiSetImportPropertyMatrix(
* @see aiQuaternion(const aiMatrix3x3& pRotMatrix)
*/
ASSIMP_API void aiCreateQuaternionFromMatrix(
- C_STRUCT aiQuaternion* quat,
- const C_STRUCT aiMatrix3x3* mat);
+ C_STRUCT aiQuaternion* quat,
+ const C_STRUCT aiMatrix3x3* mat);
// --------------------------------------------------------------------------------
/** Decompose a transformation matrix into its rotational, translational and
* scaling components.
- *
+ *
* @param mat Matrix to decompose
* @param scaling Receives the scaling component
* @param rotation Receives the rotational component
@@ -436,24 +471,24 @@ ASSIMP_API void aiCreateQuaternionFromMatrix(
* @see aiMatrix4x4::Decompose (aiVector3D&, aiQuaternion&, aiVector3D&) const;
*/
ASSIMP_API void aiDecomposeMatrix(
- const C_STRUCT aiMatrix4x4* mat,
- C_STRUCT aiVector3D* scaling,
- C_STRUCT aiQuaternion* rotation,
- C_STRUCT aiVector3D* position);
+ const C_STRUCT aiMatrix4x4* mat,
+ C_STRUCT aiVector3D* scaling,
+ C_STRUCT aiQuaternion* rotation,
+ C_STRUCT aiVector3D* position);
// --------------------------------------------------------------------------------
/** Transpose a 4x4 matrix.
* @param mat Pointer to the matrix to be transposed
*/
ASSIMP_API void aiTransposeMatrix4(
- C_STRUCT aiMatrix4x4* mat);
+ C_STRUCT aiMatrix4x4* mat);
// --------------------------------------------------------------------------------
/** Transpose a 3x3 matrix.
* @param mat Pointer to the matrix to be transposed
*/
ASSIMP_API void aiTransposeMatrix3(
- C_STRUCT aiMatrix3x3* mat);
+ C_STRUCT aiMatrix3x3* mat);
// --------------------------------------------------------------------------------
/** Transform a vector by a 3x3 matrix
@@ -461,8 +496,8 @@ ASSIMP_API void aiTransposeMatrix3(
* @param mat Matrix to transform the vector with.
*/
ASSIMP_API void aiTransformVecByMatrix3(
- C_STRUCT aiVector3D* vec,
- const C_STRUCT aiMatrix3x3* mat);
+ C_STRUCT aiVector3D* vec,
+ const C_STRUCT aiMatrix3x3* mat);
// --------------------------------------------------------------------------------
/** Transform a vector by a 4x4 matrix
@@ -470,8 +505,8 @@ ASSIMP_API void aiTransformVecByMatrix3(
* @param mat Matrix to transform the vector with.
*/
ASSIMP_API void aiTransformVecByMatrix4(
- C_STRUCT aiVector3D* vec,
- const C_STRUCT aiMatrix4x4* mat);
+ C_STRUCT aiVector3D* vec,
+ const C_STRUCT aiMatrix4x4* mat);
// --------------------------------------------------------------------------------
/** Multiply two 4x4 matrices.
@@ -479,8 +514,8 @@ ASSIMP_API void aiTransformVecByMatrix4(
* @param src Matrix to be multiplied with 'dst'.
*/
ASSIMP_API void aiMultiplyMatrix4(
- C_STRUCT aiMatrix4x4* dst,
- const C_STRUCT aiMatrix4x4* src);
+ C_STRUCT aiMatrix4x4* dst,
+ const C_STRUCT aiMatrix4x4* src);
// --------------------------------------------------------------------------------
/** Multiply two 3x3 matrices.
@@ -488,24 +523,37 @@ ASSIMP_API void aiMultiplyMatrix4(
* @param src Matrix to be multiplied with 'dst'.
*/
ASSIMP_API void aiMultiplyMatrix3(
- C_STRUCT aiMatrix3x3* dst,
- const C_STRUCT aiMatrix3x3* src);
+ C_STRUCT aiMatrix3x3* dst,
+ const C_STRUCT aiMatrix3x3* src);
// --------------------------------------------------------------------------------
/** Get a 3x3 identity matrix.
* @param mat Matrix to receive its personal identity
*/
ASSIMP_API void aiIdentityMatrix3(
- C_STRUCT aiMatrix3x3* mat);
+ C_STRUCT aiMatrix3x3* mat);
// --------------------------------------------------------------------------------
/** Get a 4x4 identity matrix.
* @param mat Matrix to receive its personal identity
*/
ASSIMP_API void aiIdentityMatrix4(
- C_STRUCT aiMatrix4x4* mat);
+ C_STRUCT aiMatrix4x4* mat);
+// --------------------------------------------------------------------------------
+/** Returns the number of import file formats available in the current Assimp build.
+ * Use aiGetImportFormatDescription() to retrieve infos of a specific import format.
+ */
+ASSIMP_API size_t aiGetImportFormatCount(void);
+// --------------------------------------------------------------------------------
+/** Returns a description of the nth import file format. Use #aiGetImportFormatCount()
+ * to learn how many import formats are supported.
+ * @param pIndex Index of the import format to retrieve information for. Valid range is
+ * 0 to #aiGetImportFormatCount()
+ * @return A description of that specific import format. NULL if pIndex is out of range.
+ */
+ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImportFormatDescription( size_t pIndex);
#ifdef __cplusplus
}
#endif
diff --git a/src/3rdparty/assimp/include/assimp/color4.h b/src/3rdparty/assimp/include/assimp/color4.h
index 52c3c7ec6..6bcab45df 100644
--- a/src/3rdparty/assimp/include/assimp/color4.h
+++ b/src/3rdparty/assimp/include/assimp/color4.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,20 +25,20 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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 aiColor4D.h
+/** @file color4.h
* @brief RGBA color structure, including operators when compiling in C++
*/
#ifndef AI_COLOR4D_H_INC
@@ -49,44 +49,44 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
// ----------------------------------------------------------------------------------
-/** Represents a color in Red-Green-Blue space including an
+/** Represents a color in Red-Green-Blue space including an
* alpha component. Color values range from 0 to 1. */
// ----------------------------------------------------------------------------------
template <typename TReal>
class aiColor4t
{
public:
- aiColor4t () : r(), g(), b(), a() {}
- aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a)
- : r(_r), g(_g), b(_b), a(_a) {}
- aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {}
- aiColor4t (const aiColor4t& o)
- : r(o.r), g(o.g), b(o.b), a(o.a) {}
+ aiColor4t () : r(), g(), b(), a() {}
+ aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a)
+ : r(_r), g(_g), b(_b), a(_a) {}
+ explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {}
+ aiColor4t (const aiColor4t& o)
+ : r(o.r), g(o.g), b(o.b), a(o.a) {}
public:
- // combined operators
- const aiColor4t& operator += (const aiColor4t& o);
- const aiColor4t& operator -= (const aiColor4t& o);
- const aiColor4t& operator *= (TReal f);
- const aiColor4t& operator /= (TReal f);
+ // combined operators
+ const aiColor4t& operator += (const aiColor4t& o);
+ const aiColor4t& operator -= (const aiColor4t& o);
+ const aiColor4t& operator *= (TReal f);
+ const aiColor4t& operator /= (TReal f);
public:
- // comparison
- bool operator == (const aiColor4t& other) const;
- bool operator != (const aiColor4t& other) const;
- bool operator < (const aiColor4t& other) const;
+ // comparison
+ bool operator == (const aiColor4t& other) const;
+ bool operator != (const aiColor4t& other) const;
+ bool operator < (const aiColor4t& other) const;
- // color tuple access, rgba order
- inline TReal operator[](unsigned int i) const;
- inline TReal& operator[](unsigned int i);
+ // color tuple access, rgba order
+ inline TReal operator[](unsigned int i) const;
+ inline TReal& operator[](unsigned int i);
- /** check whether a color is (close to) black */
- inline bool IsBlack() const;
+ /** check whether a color is (close to) black */
+ inline bool IsBlack() const;
public:
- // Red, green, blue and alpha color values
- TReal r, g, b, a;
+ // Red, green, blue and alpha color values
+ TReal r, g, b, a;
} PACK_STRUCT; // !struct aiColor4D
typedef aiColor4t<float> aiColor4D;
@@ -94,7 +94,7 @@ typedef aiColor4t<float> aiColor4D;
#else
struct aiColor4D {
- float r, g, b, a;
+ float r, g, b, a;
} PACK_STRUCT;
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/color4.inl b/src/3rdparty/assimp/include/assimp/color4.inl
index b0791facd..d69814714 100644
--- a/src/3rdparty/assimp/include/assimp/color4.inl
+++ b/src/3rdparty/assimp/include/assimp/color4.inl
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file aiColor4D.inl
+/** @file color4.inl
* @brief Inline implementation of aiColor4t<TReal> operators
*/
#ifndef AI_COLOR4D_INL_INC
@@ -51,131 +51,131 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator += (const aiColor4t<TReal>& o) {
- r += o.r; g += o.g; b += o.b; a += o.a;
- return *this;
+ r += o.r; g += o.g; b += o.b; a += o.a;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator -= (const aiColor4t<TReal>& o) {
- r -= o.r; g -= o.g; b -= o.b; a -= o.a;
- return *this;
+ r -= o.r; g -= o.g; b -= o.b; a -= o.a;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator *= (TReal f) {
- r *= f; g *= f; b *= f; a *= f;
- return *this;
+ r *= f; g *= f; b *= f; a *= f;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f) {
- r /= f; g /= f; b /= f; a /= f;
- return *this;
+ r /= f; g /= f; b /= f; a /= f;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
- return *(&r + i);
+ return *(&r + i);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
- return *(&r + i);
+ return *(&r + i);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiColor4t<TReal>::operator== (const aiColor4t<TReal>& other) const {
- return r == other.r && g == other.g && b == other.b && a == other.a;
+ return r == other.r && g == other.g && b == other.b && a == other.a;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiColor4t<TReal>::operator!= (const aiColor4t<TReal>& other) const {
- return r != other.r || g != other.g || b != other.b || a != other.a;
+ return r != other.r || g != other.g || b != other.b || a != other.a;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiColor4t<TReal>::operator< (const aiColor4t<TReal>& other) const {
- return r < other.r || (
- r == other.r && (
- g < other.g || (
- g == other.g && (
- b < other.b || (
- b == other.b && (
- a < other.a
- )
- )
- )
- )
- )
- );
+ return r < other.r || (
+ r == other.r && (
+ g < other.g || (
+ g == other.g && (
+ b < other.b || (
+ b == other.b && (
+ a < other.a
+ )
+ )
+ )
+ )
+ )
+ );
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator + (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
- return aiColor4t<TReal>( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator + (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator - (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
- return aiColor4t<TReal>( v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator - (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator * (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
- return aiColor4t<TReal>( v1.r * v2.r, v1.g * v2.g, v1.b * v2.b, v1.a * v2.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator * (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r * v2.r, v1.g * v2.g, v1.b * v2.b, v1.a * v2.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator / (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
- return aiColor4t<TReal>( v1.r / v2.r, v1.g / v2.g, v1.b / v2.b, v1.a / v2.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator / (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
+ return aiColor4t<TReal>( v1.r / v2.r, v1.g / v2.g, v1.b / v2.b, v1.a / v2.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator * ( TReal f, const aiColor4t<TReal>& v) {
- return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator * ( TReal f, const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator * ( const aiColor4t<TReal>& v, TReal f) {
- return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator * ( const aiColor4t<TReal>& v, TReal f) {
+ return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator / ( const aiColor4t<TReal>& v, TReal f) {
- return v * (1/f);
+AI_FORCE_INLINE aiColor4t<TReal> operator / ( const aiColor4t<TReal>& v, TReal f) {
+ return v * (1/f);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator / ( TReal f,const aiColor4t<TReal>& v) {
- return aiColor4t<TReal>(f,f,f,f)/v;
+AI_FORCE_INLINE aiColor4t<TReal> operator / ( TReal f,const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>(f,f,f,f)/v;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator + ( const aiColor4t<TReal>& v, TReal f) {
- return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator + ( const aiColor4t<TReal>& v, TReal f) {
+ return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator - ( const aiColor4t<TReal>& v, TReal f) {
- return aiColor4t<TReal>( v.r-f, v.g-f, v.b-f, v.a-f);
+AI_FORCE_INLINE aiColor4t<TReal> operator - ( const aiColor4t<TReal>& v, TReal f) {
+ return aiColor4t<TReal>( v.r-f, v.g-f, v.b-f, v.a-f);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator + ( TReal f, const aiColor4t<TReal>& v) {
- return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator + ( TReal f, const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiColor4t<TReal> operator - ( TReal f, const aiColor4t<TReal>& v) {
- return aiColor4t<TReal>( f-v.r, f-v.g, f-v.b, f-v.a);
+AI_FORCE_INLINE aiColor4t<TReal> operator - ( TReal f, const aiColor4t<TReal>& v) {
+ return aiColor4t<TReal>( f-v.r, f-v.g, f-v.b, f-v.a);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-inline bool aiColor4t<TReal> :: IsBlack() const {
- // The alpha component doesn't care here. black is black.
- static const TReal epsilon = 10e-3f;
- return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
+inline bool aiColor4t<TReal> :: IsBlack() const {
+ // The alpha component doesn't care here. black is black.
+ static const TReal epsilon = 10e-3f;
+ return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
}
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/config.h b/src/3rdparty/assimp/include/assimp/config.h
index 941f3c1cc..3db8a5697 100644
--- a/src/3rdparty/assimp/include/assimp/config.h
+++ b/src/3rdparty/assimp/include/assimp/config.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.
---------------------------------------------------------------------------
*/
@@ -42,11 +42,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file config.h
* @brief Defines constants for configurable properties for the library
*
- * Typically these properties are set via
+ * Typically these properties are set via
* #Assimp::Importer::SetPropertyFloat,
* #Assimp::Importer::SetPropertyInteger or
- * #Assimp::Importer::SetPropertyString,
- * depending on the data type of a property. All properties have a
+ * #Assimp::Importer::SetPropertyString,
+ * depending on the data type of a property. All properties have a
* default value. See the doc for the mentioned methods for more details.
*
* <br><br>
@@ -71,11 +71,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* process (i.e. IO time, importing, postprocessing, ..) and dumps
* these timings to the DefaultLogger. See the @link perf Performance
* Page@endlink for more information on this topic.
- *
+ *
* Property type: bool. Default value: false.
*/
#define AI_CONFIG_GLOB_MEASURE_TIME \
- "GLOB_MEASURE_TIME"
+ "GLOB_MEASURE_TIME"
// ---------------------------------------------------------------------------
@@ -87,7 +87,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// ---------------------------------------------------------------------------
#define AI_CONFIG_IMPORT_NO_SKELETON_MESHES \
- "IMPORT_NO_SKELETON_MESHES"
+ "IMPORT_NO_SKELETON_MESHES"
@@ -108,7 +108,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: int, default value: -1.
*/
#define AI_CONFIG_GLOB_MULTITHREADING \
- "GLOB_MULTITHREADING"
+ "GLOB_MULTITHREADING"
#endif
// ###########################################################################
@@ -127,12 +127,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// ---------------------------------------------------------------------------
#define AI_CONFIG_PP_SBBC_MAX_BONES \
- "PP_SBBC_MAX_BONES"
+ "PP_SBBC_MAX_BONES"
-// default limit for bone count
+// default limit for bone count
#if (!defined AI_SBBC_DEFAULT_MAX_BONES)
-# define AI_SBBC_DEFAULT_MAX_BONES 60
+# define AI_SBBC_DEFAULT_MAX_BONES 60
#endif
@@ -145,17 +145,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: float. Default value: 45 degrees
*/
#define AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE \
- "PP_CT_MAX_SMOOTHING_ANGLE"
+ "PP_CT_MAX_SMOOTHING_ANGLE"
// ---------------------------------------------------------------------------
/** @brief Source UV channel for tangent space computation.
*
- * The specified channel must exist or an error will be raised.
+ * The specified channel must exist or an error will be raised.
* Property type: integer. Default value: 0
*/
// ---------------------------------------------------------------------------
#define AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX \
- "PP_CT_TEXTURE_CHANNEL_INDEX"
+ "PP_CT_TEXTURE_CHANNEL_INDEX"
// ---------------------------------------------------------------------------
/** @brief Specifies the maximum angle that may be between two face normals
@@ -163,14 +163,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Sometimes referred to as 'crease angle'.
* This applies to the GenSmoothNormals-Step. The angle is specified
- * in degrees, so 180 is PI. The default value is 175 degrees (all vertex
- * normals are smoothed). The maximum value is 175, too. Property type: float.
+ * in degrees, so 180 is PI. The default value is 175 degrees (all vertex
+ * normals are smoothed). The maximum value is 175, too. Property type: float.
* Warning: setting this option may cause a severe loss of performance. The
* performance is unaffected if the #AI_CONFIG_FAVOUR_SPEED flag is set but
* the output quality may be reduced.
*/
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE \
- "PP_GSN_MAX_SMOOTHING_ANGLE"
+ "PP_GSN_MAX_SMOOTHING_ANGLE"
// ---------------------------------------------------------------------------
@@ -180,14 +180,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This must be a valid path to a file. The file is 768 (256*3) bytes
* large and contains RGB triplets for each of the 256 palette entries.
* The default value is colormap.lmp. If the file is not found,
- * a default palette (from Quake 1) is used.
+ * a default palette (from Quake 1) is used.
* Property type: string.
*/
-#define AI_CONFIG_IMPORT_MDL_COLORMAP \
- "IMPORT_MDL_COLORMAP"
+#define AI_CONFIG_IMPORT_MDL_COLORMAP \
+ "IMPORT_MDL_COLORMAP"
// ---------------------------------------------------------------------------
-/** @brief Configures the #aiProcess_RemoveRedundantMaterials step to
+/** @brief Configures the #aiProcess_RemoveRedundantMaterials step to
* keep materials matching a name in a given list.
*
* This is a list of 1 to n strings, ' ' serves as delimiter character.
@@ -196,61 +196,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* "keep-me and_me_to anotherMaterialToBeKept \'name with whitespace\'"</tt>.
* If a material matches on of these names, it will not be modified or
* removed by the postprocessing step nor will other materials be replaced
- * by a reference to it. <br>
+ * by a reference to it. <br>
* This option might be useful if you are using some magic material names
* to pass additional semantics through the content pipeline. This ensures
- * they won't be optimized away, but a general optimization is still
+ * they won't be optimized away, but a general optimization is still
* performed for materials not contained in the list.
* Property type: String. Default value: n/a
* @note Linefeeds, tabs or carriage returns are treated as whitespace.
* Material names are case sensitive.
*/
-#define AI_CONFIG_PP_RRM_EXCLUDE_LIST \
- "PP_RRM_EXCLUDE_LIST"
+#define AI_CONFIG_PP_RRM_EXCLUDE_LIST \
+ "PP_RRM_EXCLUDE_LIST"
// ---------------------------------------------------------------------------
-/** @brief Configures the #aiProcess_PretransformVertices step to
+/** @brief Configures the #aiProcess_PreTransformVertices step to
* keep the scene hierarchy. Meshes are moved to worldspace, but
- * no optimization is performed (read: meshes with equal materials are not
+ * no optimization is performed (read: meshes with equal materials are not
* joined. The total number of meshes won't change).
*
* This option could be of use for you if the scene hierarchy contains
- * important additional information which you intend to parse.
+ * important additional information which you intend to parse.
* For rendering, you can still render all meshes in the scene without
* any transformations.
* Property type: bool. Default value: false.
*/
-#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
- "PP_PTV_KEEP_HIERARCHY"
+#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
+ "PP_PTV_KEEP_HIERARCHY"
// ---------------------------------------------------------------------------
-/** @brief Configures the #aiProcess_PretransformVertices step to normalize
+/** @brief Configures the #aiProcess_PreTransformVertices step to normalize
* all vertex components into the [-1,1] range. That is, a bounding box
* for the whole scene is computed, the maximum component is taken and all
* meshes are scaled appropriately (uniformly of course!).
- * This might be useful if you don't know the spatial dimension of the input
+ * This might be useful if you don't know the spatial dimension of the input
* data*/
-#define AI_CONFIG_PP_PTV_NORMALIZE \
- "PP_PTV_NORMALIZE"
+#define AI_CONFIG_PP_PTV_NORMALIZE \
+ "PP_PTV_NORMALIZE"
// ---------------------------------------------------------------------------
-/** @brief Configures the #aiProcess_PretransformVertices step to use
+/** @brief Configures the #aiProcess_PreTransformVertices step to use
* a users defined matrix as the scene root node transformation before
- * transforming vertices.
+ * transforming vertices.
* Property type: bool. Default value: false.
*/
-#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \
- "PP_PTV_ADD_ROOT_TRANSFORMATION"
+#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \
+ "PP_PTV_ADD_ROOT_TRANSFORMATION"
// ---------------------------------------------------------------------------
-/** @brief Configures the #aiProcess_PretransformVertices step to use
+/** @brief Configures the #aiProcess_PreTransformVertices step to use
* a users defined matrix as the scene root node transformation before
* transforming vertices. This property correspond to the 'a1' component
* of the transformation matrix.
* Property type: aiMatrix4x4.
*/
-#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \
- "PP_PTV_ROOT_TRANSFORMATION"
+#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \
+ "PP_PTV_ROOT_TRANSFORMATION"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_FindDegenerates step to
@@ -263,7 +263,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: bool. Default value: false.
*/
#define AI_CONFIG_PP_FD_REMOVE \
- "PP_FD_REMOVE"
+ "PP_FD_REMOVE"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
@@ -274,17 +274,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* quotation marks. For example:<tt>
* "keep-me and_me_to anotherNodeToBeKept \'name with whitespace\'"</tt>.
* If a node matches on of these names, it will not be modified or
- * removed by the postprocessing step.<br>
+ * removed by the postprocessing step.<br>
* This option might be useful if you are using some magic node names
* to pass additional semantics through the content pipeline. This ensures
- * they won't be optimized away, but a general optimization is still
+ * they won't be optimized away, but a general optimization is still
* performed for nodes not contained in the list.
* Property type: String. Default value: n/a
* @note Linefeeds, tabs or carriage returns are treated as whitespace.
* Node names are case sensitive.
*/
-#define AI_CONFIG_PP_OG_EXCLUDE_LIST \
- "PP_OG_EXCLUDE_LIST"
+#define AI_CONFIG_PP_OG_EXCLUDE_LIST \
+ "PP_OG_EXCLUDE_LIST"
// ---------------------------------------------------------------------------
/** @brief Set the maximum number of triangles in a mesh.
@@ -294,12 +294,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES
* Property type: integer.
*/
-#define AI_CONFIG_PP_SLM_TRIANGLE_LIMIT \
- "PP_SLM_TRIANGLE_LIMIT"
+#define AI_CONFIG_PP_SLM_TRIANGLE_LIMIT \
+ "PP_SLM_TRIANGLE_LIMIT"
// default value for AI_CONFIG_PP_SLM_TRIANGLE_LIMIT
#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
-# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
#endif
// ---------------------------------------------------------------------------
@@ -308,14 +308,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This is used by the "SplitLargeMeshes" PostProcess-Step to determine
* whether a mesh must be split or not.
* @note The default value is AI_SLM_DEFAULT_MAX_VERTICES
- * Property type: integer.
+ * Property type: integer.
*/
#define AI_CONFIG_PP_SLM_VERTEX_LIMIT \
- "PP_SLM_VERTEX_LIMIT"
+ "PP_SLM_VERTEX_LIMIT"
// default value for AI_CONFIG_PP_SLM_VERTEX_LIMIT
#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
-# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
#endif
// ---------------------------------------------------------------------------
@@ -324,12 +324,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This is used by the #aiProcess_LimitBoneWeights PostProcess-Step.
* @note The default value is AI_LBW_MAX_WEIGHTS
* Property type: integer.*/
-#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
- "PP_LBW_MAX_WEIGHTS"
+#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
+ "PP_LBW_MAX_WEIGHTS"
// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
#if (!defined AI_LMW_MAX_WEIGHTS)
-# define AI_LMW_MAX_WEIGHTS 0x4
+# define AI_LMW_MAX_WEIGHTS 0x4
#endif // !! AI_LMW_MAX_WEIGHTS
// ---------------------------------------------------------------------------
@@ -339,11 +339,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note The default value is AI_DEBONE_THRESHOLD
* Property type: float.*/
#define AI_CONFIG_PP_DB_THRESHOLD \
- "PP_DB_THRESHOLD"
+ "PP_DB_THRESHOLD"
// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
#if (!defined AI_DEBONE_THRESHOLD)
-# define AI_DEBONE_THRESHOLD 1.0f
+# define AI_DEBONE_THRESHOLD 1.0f
#endif // !! AI_DEBONE_THRESHOLD
// ---------------------------------------------------------------------------
@@ -353,12 +353,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note The default value is 0
* Property type: bool.*/
#define AI_CONFIG_PP_DB_ALL_OR_NONE \
- "PP_DB_ALL_OR_NONE"
+ "PP_DB_ALL_OR_NONE"
/** @brief Default value for the #AI_CONFIG_PP_ICL_PTCACHE_SIZE property
*/
#ifndef PP_ICL_PTCACHE_SIZE
-# define PP_ICL_PTCACHE_SIZE 12
+# define PP_ICL_PTCACHE_SIZE 12
#endif
// ---------------------------------------------------------------------------
@@ -372,73 +372,73 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* performance improvements for most nVidia/AMD cards since 2002.
* Property type: integer.
*/
-#define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
+#define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
// ---------------------------------------------------------------------------
/** @brief Enumerates components of the aiScene and aiMesh data structures
- * that can be excluded from the import using the #aiPrpcess_RemoveComponent step.
+ * that can be excluded from the import using the #aiProcess_RemoveComponent step.
*
* See the documentation to #aiProcess_RemoveComponent for more details.
*/
enum aiComponent
{
- /** Normal vectors */
+ /** Normal vectors */
#ifdef SWIG
- aiComponent_NORMALS = 0x2,
+ aiComponent_NORMALS = 0x2,
#else
- aiComponent_NORMALS = 0x2u,
+ aiComponent_NORMALS = 0x2u,
#endif
- /** Tangents and bitangents go always together ... */
+ /** Tangents and bitangents go always together ... */
#ifdef SWIG
- aiComponent_TANGENTS_AND_BITANGENTS = 0x4,
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4,
#else
- aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
#endif
- /** ALL color sets
- * Use aiComponent_COLORn(N) to specify the N'th set */
- aiComponent_COLORS = 0x8,
+ /** ALL color sets
+ * Use aiComponent_COLORn(N) to specify the N'th set */
+ aiComponent_COLORS = 0x8,
- /** ALL texture UV sets
- * aiComponent_TEXCOORDn(N) to specify the N'th set */
- aiComponent_TEXCOORDS = 0x10,
+ /** ALL texture UV sets
+ * aiComponent_TEXCOORDn(N) to specify the N'th set */
+ aiComponent_TEXCOORDS = 0x10,
- /** Removes all bone weights from all meshes.
- * The scenegraph nodes corresponding to the bones are NOT removed.
- * use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_BONEWEIGHTS = 0x20,
+ /** Removes all bone weights from all meshes.
+ * The scenegraph nodes corresponding to the bones are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_BONEWEIGHTS = 0x20,
- /** Removes all node animations (aiScene::mAnimations).
- * The corresponding scenegraph nodes are NOT removed.
- * use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_ANIMATIONS = 0x40,
+ /** Removes all node animations (aiScene::mAnimations).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_ANIMATIONS = 0x40,
- /** Removes all embedded textures (aiScene::mTextures) */
- aiComponent_TEXTURES = 0x80,
+ /** Removes all embedded textures (aiScene::mTextures) */
+ aiComponent_TEXTURES = 0x80,
- /** Removes all light sources (aiScene::mLights).
- * The corresponding scenegraph nodes are NOT removed.
- * use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_LIGHTS = 0x100,
+ /** Removes all light sources (aiScene::mLights).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_LIGHTS = 0x100,
- /** Removes all cameras (aiScene::mCameras).
- * The corresponding scenegraph nodes are NOT removed.
- * use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_CAMERAS = 0x200,
+ /** Removes all cameras (aiScene::mCameras).
+ * The corresponding scenegraph nodes are NOT removed.
+ * use the #aiProcess_OptimizeGraph step to do this */
+ aiComponent_CAMERAS = 0x200,
- /** Removes all meshes (aiScene::mMeshes). */
- aiComponent_MESHES = 0x400,
+ /** Removes all meshes (aiScene::mMeshes). */
+ aiComponent_MESHES = 0x400,
- /** Removes all materials. One default material will
- * be generated, so aiScene::mNumMaterials will be 1. */
- aiComponent_MATERIALS = 0x800,
+ /** Removes all materials. One default material will
+ * be generated, so aiScene::mNumMaterials will be 1. */
+ aiComponent_MATERIALS = 0x800,
- /** This value is not used. It is just there to force the
- * compiler to map this enum to a 32 Bit integer. */
+ /** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer. */
#ifndef SWIG
- _aiComponent_Force32Bit = 0x9fffffff
+ _aiComponent_Force32Bit = 0x9fffffff
#endif
};
@@ -460,8 +460,8 @@ enum aiComponent
* of the flags defined above) the import FAILS. Mainly because there is
* no data to work on anymore ...
*/
-#define AI_CONFIG_PP_RVC_FLAGS \
- "PP_RVC_FLAGS"
+#define AI_CONFIG_PP_RVC_FLAGS \
+ "PP_RVC_FLAGS"
// ---------------------------------------------------------------------------
/** @brief Input parameter to the #aiProcess_SortByPType step:
@@ -472,20 +472,20 @@ enum aiComponent
* be to exclude all line and point meshes from the import. This
* is an integer property, its default value is 0.
*/
-#define AI_CONFIG_PP_SBP_REMOVE \
- "PP_SBP_REMOVE"
+#define AI_CONFIG_PP_SBP_REMOVE \
+ "PP_SBP_REMOVE"
// ---------------------------------------------------------------------------
/** @brief Input parameter to the #aiProcess_FindInvalidData step:
* Specifies the floating-point accuracy for animation values. The step
* checks for animation tracks where all frame values are absolutely equal
* and removes them. This tweakable controls the epsilon for floating-point
- * comparisons - two keys are considered equal if the invariant
+ * comparisons - two keys are considered equal if the invariant
* abs(n0-n1)>epsilon holds true for all vector respectively quaternion
* components. The default value is 0.f - comparisons are exact then.
*/
-#define AI_CONFIG_PP_FID_ANIM_ACCURACY \
- "PP_FID_ANIM_ACCURACY"
+#define AI_CONFIG_PP_FID_ANIM_ACCURACY \
+ "PP_FID_ANIM_ACCURACY"
// TransformUVCoords evaluates UV scalings
@@ -505,22 +505,22 @@ enum aiComponent
* Specifies which UV transformations are evaluated.
*
* This is a bitwise combination of the AI_UVTRAFO_XXX flags (integer
- * property, of course). By default all transformations are enabled
+ * property, of course). By default all transformations are enabled
* (AI_UVTRAFO_ALL).
*/
-#define AI_CONFIG_PP_TUV_EVALUATE \
- "PP_TUV_EVALUATE"
+#define AI_CONFIG_PP_TUV_EVALUATE \
+ "PP_TUV_EVALUATE"
// ---------------------------------------------------------------------------
/** @brief A hint to assimp to favour speed against import quality.
*
* Enabling this option may result in faster loading, but it needn't.
* It represents just a hint to loaders and post-processing steps to use
- * faster code paths, if possible.
+ * faster code paths, if possible.
* This property is expected to be an integer, != 0 stands for true.
* The default value is 0.
*/
-#define AI_CONFIG_FAVOUR_SPEED \
+#define AI_CONFIG_FAVOUR_SPEED \
"FAVOUR_SPEED"
@@ -538,7 +538,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS \
- "IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS"
+ "IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read all materials present in the
@@ -550,7 +550,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS \
- "IMPORT_FBX_READ_ALL_MATERIALS"
+ "IMPORT_FBX_READ_ALL_MATERIALS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read materials.
@@ -559,7 +559,16 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_MATERIALS \
- "IMPORT_FBX_READ_MATERIALS"
+ "IMPORT_FBX_READ_MATERIALS"
+
+// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will read embedded textures.
+ *
+ * The default value is true (1)
+ * Property type: bool
+ */
+#define AI_CONFIG_IMPORT_FBX_READ_TEXTURES \
+ "IMPORT_FBX_READ_TEXTURES"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read cameras.
@@ -568,7 +577,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_CAMERAS \
- "IMPORT_FBX_READ_CAMERAS"
+ "IMPORT_FBX_READ_CAMERAS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read light sources.
@@ -577,7 +586,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_LIGHTS \
- "IMPORT_FBX_READ_LIGHTS"
+ "IMPORT_FBX_READ_LIGHTS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read animations.
@@ -586,7 +595,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS \
- "IMPORT_FBX_READ_ANIMATIONS"
+ "IMPORT_FBX_READ_ANIMATIONS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will act in strict mode in which only
@@ -598,7 +607,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_STRICT_MODE \
- "IMPORT_FBX_STRICT_MODE"
+ "IMPORT_FBX_STRICT_MODE"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will preserve pivot points for
@@ -609,7 +618,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS \
- "IMPORT_FBX_PRESERVE_PIVOTS"
+ "IMPORT_FBX_PRESERVE_PIVOTS"
// ---------------------------------------------------------------------------
/** @brief Specifies whether the importer will drop empty animation curves or
@@ -620,7 +629,7 @@ enum aiComponent
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
- "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
+ "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
@@ -637,35 +646,35 @@ enum aiComponent
* want to override the global setting).
* Property type: integer.
*/
-#define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
+#define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
-#define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
-#define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
-#define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
-#define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
-#define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
-#define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
+#define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
+#define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
+#define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
+#define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
// ---------------------------------------------------------------------------
/** @brief Configures the AC loader to collect all surfaces which have the
- * "Backface cull" flag set in separate meshes.
+ * "Backface cull" flag set in separate meshes.
*
* Property type: bool. Default value: true.
*/
-#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
- "IMPORT_AC_SEPARATE_BFCULL"
+#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
+ "IMPORT_AC_SEPARATE_BFCULL"
// ---------------------------------------------------------------------------
/** @brief Configures whether the AC loader evaluates subdivision surfaces (
* indicated by the presence of the 'subdiv' attribute in the file). By
- * default, Assimp performs the subdivision using the standard
+ * default, Assimp performs the subdivision using the standard
* Catmull-Clark algorithm
*
* * Property type: bool. Default value: true.
*/
-#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
- "IMPORT_AC_EVAL_SUBDIVISION"
+#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
+ "IMPORT_AC_EVAL_SUBDIVISION"
// ---------------------------------------------------------------------------
/** @brief Configures the UNREAL 3D loader to separate faces with different
@@ -674,10 +683,10 @@ enum aiComponent
* * Property type: bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \
- "UNREAL_HANDLE_FLAGS"
+ "UNREAL_HANDLE_FLAGS"
// ---------------------------------------------------------------------------
-/** @brief Configures the terragen import plugin to compute uv's for
+/** @brief Configures the terragen import plugin to compute uv's for
* terrains, if not given. Furthermore a default texture is assigned.
*
* UV coordinates for terrains are so simple to compute that you'll usually
@@ -687,63 +696,63 @@ enum aiComponent
* * Property type: bool. Default value: false.
*/
#define AI_CONFIG_IMPORT_TER_MAKE_UVS \
- "IMPORT_TER_MAKE_UVS"
+ "IMPORT_TER_MAKE_UVS"
// ---------------------------------------------------------------------------
/** @brief Configures the ASE loader to always reconstruct normal vectors
- * basing on the smoothing groups loaded from the file.
- *
+ * basing on the smoothing groups loaded from the file.
+ *
* Some ASE files have carry invalid normals, other don't.
* * Property type: bool. Default value: true.
*/
-#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
- "IMPORT_ASE_RECONSTRUCT_NORMALS"
+#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
+ "IMPORT_ASE_RECONSTRUCT_NORMALS"
// ---------------------------------------------------------------------------
-/** @brief Configures the M3D loader to detect and process multi-part
+/** @brief Configures the M3D loader to detect and process multi-part
* Quake player models.
*
* These models usually consist of 3 files, lower.md3, upper.md3 and
* head.md3. If this property is set to true, Assimp will try to load and
- * combine all three files if one of them is loaded.
+ * combine all three files if one of them is loaded.
* Property type: bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \
- "IMPORT_MD3_HANDLE_MULTIPART"
+ "IMPORT_MD3_HANDLE_MULTIPART"
// ---------------------------------------------------------------------------
/** @brief Tells the MD3 loader which skin files to load.
*
- * When loading MD3 files, Assimp checks whether a file
- * <md3_file_name>_<skin_name>.skin is existing. These files are used by
- * Quake III to be able to assign different skins (e.g. red and blue team)
+ * When loading MD3 files, Assimp checks whether a file
+ * [md3_file_name]_[skin_name].skin is existing. These files are used by
+ * Quake III to be able to assign different skins (e.g. red and blue team)
* to models. 'default', 'red', 'blue' are typical skin names.
* Property type: String. Default value: "default".
*/
#define AI_CONFIG_IMPORT_MD3_SKIN_NAME \
- "IMPORT_MD3_SKIN_NAME"
+ "IMPORT_MD3_SKIN_NAME"
// ---------------------------------------------------------------------------
/** @brief Specify the Quake 3 shader file to be used for a particular
* MD3 file. This can also be a search path.
*
- * By default Assimp's behaviour is as follows: If a MD3 file
- * <tt><any_path>/models/<any_q3_subdir>/<model_name>/<file_name>.md3</tt> is
+ * By default Assimp's behaviour is as follows: If a MD3 file
+ * <tt>any_path/models/any_q3_subdir/model_name/file_name.md3</tt> is
* loaded, the library tries to locate the corresponding shader file in
- * <tt><any_path>/scripts/<model_name>.shader</tt>. This property overrides this
+ * <tt>any_path/scripts/model_name.shader</tt>. This property overrides this
* behaviour. It can either specify a full path to the shader to be loaded
* or alternatively the path (relative or absolute) to the directory where
- * the shaders for all MD3s to be loaded reside. Assimp attempts to open
- * <tt><dir>/<model_name>.shader</tt> first, <tt><dir>/<file_name>.shader</tt>
- * is the fallback file. Note that <dir> should have a terminal (back)slash.
+ * the shaders for all MD3s to be loaded reside. Assimp attempts to open
+ * <tt>IMPORT_MD3_SHADER_SRC/model_name.shader</tt> first, <tt>IMPORT_MD3_SHADER_SRC/file_name.shader</tt>
+ * is the fallback file. Note that IMPORT_MD3_SHADER_SRC should have a terminal (back)slash.
* Property type: String. Default value: n/a.
*/
#define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
- "IMPORT_MD3_SHADER_SRC"
+ "IMPORT_MD3_SHADER_SRC"
// ---------------------------------------------------------------------------
/** @brief Configures the LWO loader to load just one layer from the model.
- *
+ *
* LWO files consist of layers and in some cases it could be useful to load
* only one of them. This property can be either a string - which specifies
* the name of the layer - or an integer - the index of the layer. If the
@@ -752,27 +761,27 @@ enum aiComponent
* layer name may not be empty.<br>
* Property type: Integer. Default value: all layers are loaded.
*/
-#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
- "IMPORT_LWO_ONE_LAYER_ONLY"
+#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
+ "IMPORT_LWO_ONE_LAYER_ONLY"
// ---------------------------------------------------------------------------
/** @brief Configures the MD5 loader to not load the MD5ANIM file for
* a MD5MESH file automatically.
- *
+ *
* The default strategy is to look for a file with the same name but the
* MD5ANIM extension in the same directory. If it is found, it is loaded
* and combined with the MD5MESH file. This configuration option can be
* used to disable this behaviour.
- *
+ *
* * Property type: bool. Default value: false.
*/
-#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
- "IMPORT_MD5_NO_ANIM_AUTOLOAD"
+#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
+ "IMPORT_MD5_NO_ANIM_AUTOLOAD"
// ---------------------------------------------------------------------------
/** @brief Defines the begin of the time range for which the LWS loader
* evaluates animations and computes aiNodeAnim's.
- *
+ *
* Assimp provides full conversion of LightWave's envelope system, including
* pre and post conditions. The loader computes linearly subsampled animation
* chanels with the frame rate given in the LWS file. This property defines
@@ -785,53 +794,54 @@ enum aiComponent
*
* @see AI_CONFIG_IMPORT_LWS_ANIM_END - end of the imported time range
*/
-#define AI_CONFIG_IMPORT_LWS_ANIM_START \
- "IMPORT_LWS_ANIM_START"
-#define AI_CONFIG_IMPORT_LWS_ANIM_END \
- "IMPORT_LWS_ANIM_END"
+#define AI_CONFIG_IMPORT_LWS_ANIM_START \
+ "IMPORT_LWS_ANIM_START"
+#define AI_CONFIG_IMPORT_LWS_ANIM_END \
+ "IMPORT_LWS_ANIM_END"
// ---------------------------------------------------------------------------
/** @brief Defines the output frame rate of the IRR loader.
- *
+ *
* IRR animations are difficult to convert for Assimp and there will
* always be a loss of quality. This setting defines how many keys per second
* are returned by the converter.<br>
* Property type: integer. Default value: 100
*/
-#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
- "IMPORT_IRR_ANIM_FPS"
+#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
+ "IMPORT_IRR_ANIM_FPS"
// ---------------------------------------------------------------------------
/** @brief Ogre Importer will try to find referenced materials from this file.
*
* Ogre meshes reference with material names, this does not tell Assimp the file
- * where it is located in. Assimp will try to find the source file in the following
+ * where it is located in. Assimp will try to find the source file in the following
* order: <material-name>.material, <mesh-filename-base>.material and
* lastly the material name defined by this config property.
* <br>
* Property type: String. Default value: Scene.material.
*/
-#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE \
- "IMPORT_OGRE_MATERIAL_FILE"
+#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE \
+ "IMPORT_OGRE_MATERIAL_FILE"
// ---------------------------------------------------------------------------
/** @brief Ogre Importer detect the texture usage from its filename.
*
* Ogre material texture units do not define texture type, the textures usage
- * depends on the used shader or Ogres fixed pipeline. If this config property
+ * depends on the used shader or Ogre's fixed pipeline. If this config property
* is true Assimp will try to detect the type from the textures filename postfix:
* _n, _nrm, _nrml, _normal, _normals and _normalmap for normal map, _s, _spec,
- * _specular and _specularmap for specular map, _l, _light, _lightmap, _occ
+ * _specular and _specularmap for specular map, _l, _light, _lightmap, _occ
* and _occlusion for light map, _disp and _displacement for displacement map.
- * The matching is case insensitive. Post fix is taken between last "_" and last ".".
- * Default behavior is to detect type from lower cased texture unit name by
+ * The matching is case insensitive. Post fix is taken between the last
+ * underscore and the last period.
+ * Default behavior is to detect type from lower cased texture unit name by
* matching against: normalmap, specularmap, lightmap and displacementmap.
* For both cases if no match is found aiTextureType_DIFFUSE is used.
* <br>
* Property type: Bool. Default value: false.
*/
#define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \
- "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
+ "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
/** @brief Specifies whether the IFC loader skips over IfcSpace elements.
*
@@ -841,9 +851,17 @@ enum aiComponent
*/
#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS"
+ /** @brief Specifies whether the Android JNI asset extraction is supported.
+ *
+ * Turn on this option if you want to manage assets in native
+ * Android application without having to keep the internal directory and asset
+ * manager pointer.
+ */
+ #define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT"
+
// ---------------------------------------------------------------------------
-/** @brief Specifies whether the IFC loader skips over
+/** @brief Specifies whether the IFC loader skips over
* shape representations of type 'Curve2D'.
*
* A lot of files contain both a faceted mesh representation and a outline
@@ -858,7 +876,7 @@ enum aiComponent
* algorithm to triangulate wall and floor meshes.
*
* If this property is set to false, walls will be either triangulated by
- * #aiProcess_Triangulate or will be passed through as huge polygons with
+ * #aiProcess_Triangulate or will be passed through as huge polygons with
* faked holes (i.e. holes that are connected with the outer boundary using
* a dummy edge). It is highly recommended to set this property to true
* if you want triangulated data because #aiProcess_Triangulate is known to
@@ -868,6 +886,22 @@ enum aiComponent
*/
#define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the Collada loader will ignore the provided up direction.
+ *
+ * If this property is set to true, the up direction provided in the file header will
+ * be ignored and the file will be loaded as is.
+ * Property type: Bool. Default value: false.
+ */
#define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
+// ---------- All the Export defines ------------
+
+/** @brief Specifies the xfile use double for real values of float
+ *
+ * Property type: Bool. Default value: false.
+ */
+
+#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
+
#endif // !! AI_CONFIG_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/defs.h b/src/3rdparty/assimp/include/assimp/defs.h
index b1f0b9839..2c9749357 100644
--- a/src/3rdparty/assimp/include/assimp/defs.h
+++ b/src/3rdparty/assimp/include/assimp/defs.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,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.
---------------------------------------------------------------------------
*/
-/** @file aiDefines.h
+/** @file defs.h
* @brief Assimp build configuration setup. See the notes in the comment
* blocks to find out how to customize _your_ Assimp build.
*/
@@ -47,233 +47,226 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_DEFINES_H
#define INCLUDED_AI_DEFINES_H
- //////////////////////////////////////////////////////////////////////////
- /* Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific
- * file format loader. The loader is be excluded from the
- * build in this case. 'XX' stands for the most common file
- * extension of the file format. E.g.:
- * ASSIMP_BUILD_NO_X_IMPORTER disables the X loader.
- *
- * If you're unsure about that, take a look at the implementation of the
- * import plugin you wish to disable. You'll find the right define in the
- * first lines of the corresponding unit.
- *
- * Other (mixed) configuration switches are listed here:
- * ASSIMP_BUILD_NO_COMPRESSED_X
- * - Disable support for compressed X files (zip)
- * ASSIMP_BUILD_NO_COMPRESSED_BLEND
- * - Disable support for compressed Blender files (zip)
- * ASSIMP_BUILD_NO_COMPRESSED_IFC
- * - Disable support for IFCZIP files (unzip)
- */
- //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ /* Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific
+ * file format loader. The loader is be excluded from the
+ * build in this case. 'XX' stands for the most common file
+ * extension of the file format. E.g.:
+ * ASSIMP_BUILD_NO_X_IMPORTER disables the X loader.
+ *
+ * If you're unsure about that, take a look at the implementation of the
+ * import plugin you wish to disable. You'll find the right define in the
+ * first lines of the corresponding unit.
+ *
+ * Other (mixed) configuration switches are listed here:
+ * ASSIMP_BUILD_NO_COMPRESSED_X
+ * - Disable support for compressed X files (zip)
+ * ASSIMP_BUILD_NO_COMPRESSED_BLEND
+ * - Disable support for compressed Blender files (zip)
+ * ASSIMP_BUILD_NO_COMPRESSED_IFC
+ * - Disable support for IFCZIP files (unzip)
+ */
+ //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X
-# define ASSIMP_BUILD_NEED_Z_INFLATE
+# define ASSIMP_BUILD_NEED_Z_INFLATE
#endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-# define ASSIMP_BUILD_NEED_Z_INFLATE
+# define ASSIMP_BUILD_NEED_Z_INFLATE
#endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
-# define ASSIMP_BUILD_NEED_Z_INFLATE
-# define ASSIMP_BUILD_NEED_UNZIP
+# define ASSIMP_BUILD_NEED_Z_INFLATE
+# define ASSIMP_BUILD_NEED_UNZIP
#endif
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
-# define ASSIMP_BUILD_NEED_Z_INFLATE
-# define ASSIMP_BUILD_NEED_UNZIP
+# define ASSIMP_BUILD_NEED_Z_INFLATE
+# define ASSIMP_BUILD_NEED_UNZIP
#endif
- //////////////////////////////////////////////////////////////////////////
- /* Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific
- * post processing step. This is the current list of process names ('XX'):
- * CALCTANGENTS
- * JOINVERTICES
- * TRIANGULATE
- * GENFACENORMALS
- * GENVERTEXNORMALS
- * REMOVEVC
- * SPLITLARGEMESHES
- * PRETRANSFORMVERTICES
- * LIMITBONEWEIGHTS
- * VALIDATEDS
- * IMPROVECACHELOCALITY
- * FIXINFACINGNORMALS
- * REMOVE_REDUNDANTMATERIALS
- * OPTIMIZEGRAPH
- * SORTBYPTYPE
- * FINDINVALIDDATA
- * TRANSFORMTEXCOORDS
- * GENUVCOORDS
- * ENTITYMESHBUILDER
- * MAKELEFTHANDED
- * FLIPUVS
- * FLIPWINDINGORDER
- * OPTIMIZEMESHES
- * OPTIMIZEANIMS
- * OPTIMIZEGRAPH
- * GENENTITYMESHES
- * FIXTEXTUREPATHS */
- //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ /* Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific
+ * post processing step. This is the current list of process names ('XX'):
+ * CALCTANGENTS
+ * JOINVERTICES
+ * TRIANGULATE
+ * GENFACENORMALS
+ * GENVERTEXNORMALS
+ * REMOVEVC
+ * SPLITLARGEMESHES
+ * PRETRANSFORMVERTICES
+ * LIMITBONEWEIGHTS
+ * VALIDATEDS
+ * IMPROVECACHELOCALITY
+ * FIXINFACINGNORMALS
+ * REMOVE_REDUNDANTMATERIALS
+ * OPTIMIZEGRAPH
+ * SORTBYPTYPE
+ * FINDINVALIDDATA
+ * TRANSFORMTEXCOORDS
+ * GENUVCOORDS
+ * ENTITYMESHBUILDER
+ * MAKELEFTHANDED
+ * FLIPUVS
+ * FLIPWINDINGORDER
+ * OPTIMIZEMESHES
+ * OPTIMIZEANIMS
+ * OPTIMIZEGRAPH
+ * GENENTITYMESHES
+ * FIXTEXTUREPATHS */
+ //////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
-# undef ASSIMP_API
-
- //////////////////////////////////////////////////////////////////////////
- /* Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library */
- //////////////////////////////////////////////////////////////////////////
-# ifdef ASSIMP_BUILD_DLL_EXPORT
-# define ASSIMP_API __declspec(dllexport)
-# define ASSIMP_API_WINONLY __declspec(dllexport)
-# pragma warning (disable : 4251)
-
- //////////////////////////////////////////////////////////////////////////
- /* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in
- * an external DLL under Windows. Default is static linkage. */
- //////////////////////////////////////////////////////////////////////////
-# elif (defined ASSIMP_DLL)
-# define ASSIMP_API __declspec(dllimport)
-# define ASSIMP_API_WINONLY __declspec(dllimport)
-# else
-# define ASSIMP_API
-# define ASSIMP_API_WINONLY
-# endif
-
- /* Force the compiler to inline a function, if possible
- */
-# define AI_FORCE_INLINE __forceinline
-
- /* Tells the compiler that a function never returns. Used in code analysis
- * to skip dead paths (e.g. after an assertion evaluated to false). */
-# define AI_WONT_RETURN __declspec(noreturn)
+# undef ASSIMP_API
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library */
+ //////////////////////////////////////////////////////////////////////////
+# ifdef ASSIMP_BUILD_DLL_EXPORT
+# define ASSIMP_API __declspec(dllexport)
+# define ASSIMP_API_WINONLY __declspec(dllexport)
+# pragma warning (disable : 4251)
+
+ //////////////////////////////////////////////////////////////////////////
+ /* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in
+ * an external DLL under Windows. Default is static linkage. */
+ //////////////////////////////////////////////////////////////////////////
+# elif (defined ASSIMP_DLL)
+# define ASSIMP_API __declspec(dllimport)
+# define ASSIMP_API_WINONLY __declspec(dllimport)
+# else
+# define ASSIMP_API
+# define ASSIMP_API_WINONLY
+# endif
+
+ /* Force the compiler to inline a function, if possible
+ */
+# define AI_FORCE_INLINE __forceinline
+
+ /* Tells the compiler that a function never returns. Used in code analysis
+ * to skip dead paths (e.g. after an assertion evaluated to false). */
+# define AI_WONT_RETURN __declspec(noreturn)
#elif defined(SWIG)
- /* Do nothing, the relevant defines are all in AssimpSwigPort.i */
+ /* Do nothing, the relevant defines are all in AssimpSwigPort.i */
#else
-
-# define AI_WONT_RETURN
-# define ASSIMP_API __attribute__ ((visibility("default")))
-# define ASSIMP_API_WINONLY
-# define AI_FORCE_INLINE inline
+# define AI_WONT_RETURN
+
+# define ASSIMP_API __attribute__ ((visibility("default")))
+# define ASSIMP_API_WINONLY
+# define AI_FORCE_INLINE inline
#endif // (defined _MSC_VER)
-#ifdef __clang__
-# define AI_WONT_RETURN_SUFFIX __attribute__((analyzer_noreturn))
+#ifdef __GNUC__
+# define AI_WONT_RETURN_SUFFIX __attribute__((noreturn))
#else
-# define AI_WONT_RETURN_SUFFIX
+# define AI_WONT_RETURN_SUFFIX
#endif // (defined __clang__)
#ifdef __cplusplus
- /* No explicit 'struct' and 'enum' tags for C++, this keeps showing up
- * in doxydocs.
- */
-# define C_STRUCT
-# define C_ENUM
+ /* No explicit 'struct' and 'enum' tags for C++, this keeps showing up
+ * in doxydocs.
+ */
+# define C_STRUCT
+# define C_ENUM
#else
- //////////////////////////////////////////////////////////////////////////
- /* To build the documentation, make sure ASSIMP_DOXYGEN_BUILD
- * is defined by Doxygen's preprocessor. The corresponding
- * entries in the DOXYFILE are: */
- //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ /* To build the documentation, make sure ASSIMP_DOXYGEN_BUILD
+ * is defined by Doxygen's preprocessor. The corresponding
+ * entries in the DOXYFILE are: */
+ //////////////////////////////////////////////////////////////////////////
#if 0
- ENABLE_PREPROCESSING = YES
- MACRO_EXPANSION = YES
- EXPAND_ONLY_PREDEF = YES
- SEARCH_INCLUDES = YES
- INCLUDE_PATH =
- INCLUDE_FILE_PATTERNS =
- PREDEFINED = ASSIMP_DOXYGEN_BUILD=1
- EXPAND_AS_DEFINED = C_STRUCT C_ENUM
- SKIP_FUNCTION_MACROS = YES
+ ENABLE_PREPROCESSING = YES
+ MACRO_EXPANSION = YES
+ EXPAND_ONLY_PREDEF = YES
+ SEARCH_INCLUDES = YES
+ INCLUDE_PATH =
+ INCLUDE_FILE_PATTERNS =
+ PREDEFINED = ASSIMP_DOXYGEN_BUILD=1
+ EXPAND_AS_DEFINED = C_STRUCT C_ENUM
+ SKIP_FUNCTION_MACROS = YES
#endif
- //////////////////////////////////////////////////////////////////////////
- /* Doxygen gets confused if we use c-struct typedefs to avoid
- * the explicit 'struct' notation. This trick here has the same
- * effect as the TYPEDEF_HIDES_STRUCT option, but we don't need
- * to typedef all structs/enums. */
- //////////////////////////////////////////////////////////////////////////
-# if (defined ASSIMP_DOXYGEN_BUILD)
-# define C_STRUCT
-# define C_ENUM
-# else
-# define C_STRUCT struct
-# define C_ENUM enum
-# endif
+ //////////////////////////////////////////////////////////////////////////
+ /* Doxygen gets confused if we use c-struct typedefs to avoid
+ * the explicit 'struct' notation. This trick here has the same
+ * effect as the TYPEDEF_HIDES_STRUCT option, but we don't need
+ * to typedef all structs/enums. */
+ //////////////////////////////////////////////////////////////////////////
+# if (defined ASSIMP_DOXYGEN_BUILD)
+# define C_STRUCT
+# define C_ENUM
+# else
+# define C_STRUCT struct
+# define C_ENUM enum
+# endif
#endif
#if (defined(__BORLANDC__) || defined (__BCPLUSPLUS__))
#error Currently, Borland is unsupported. Feel free to port Assimp.
-// "W8059 Packgröße der Struktur geändert"
+// "W8059 Packgr��e der Struktur ge�ndert"
#endif
- //////////////////////////////////////////////////////////////////////////
- /* Define 'ASSIMP_BUILD_BOOST_WORKAROUND' to compile assimp
- * without boost. This is done by using a few workaround
- * classes and brings some limitations (e.g. some logging won't be done,
- * the library won't utilize threads or be threadsafe at all).
- * This implies the 'ASSIMP_BUILD_SINGLETHREADED' setting. */
- //////////////////////////////////////////////////////////////////////////
-#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
-
- // threading support requires boost
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-# define ASSIMP_BUILD_SINGLETHREADED
-#endif
-#endif // !! ASSIMP_BUILD_BOOST_WORKAROUND
- //////////////////////////////////////////////////////////////////////////
- /* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp
- * without threading support. The library doesn't utilize
- * threads then and is itself not threadsafe.
- * If this flag is specified boost::threads is *not* required. */
- //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ /* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp
+ * without threading support. The library doesn't utilize
+ * threads then and is itself not threadsafe. */
+ //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_SINGLETHREADED
-# define ASSIMP_BUILD_SINGLETHREADED
+# define ASSIMP_BUILD_SINGLETHREADED
#endif
#if defined(_DEBUG) || ! defined(NDEBUG)
-# define ASSIMP_BUILD_DEBUG
+# define ASSIMP_BUILD_DEBUG
#endif
- //////////////////////////////////////////////////////////////////////////
- /* Useful constants */
- //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ /* Useful constants */
+ //////////////////////////////////////////////////////////////////////////
/* This is PI. Hi PI. */
-#define AI_MATH_PI (3.141592653589793238462643383279 )
-#define AI_MATH_TWO_PI (AI_MATH_PI * 2.0)
-#define AI_MATH_HALF_PI (AI_MATH_PI * 0.5)
+#define AI_MATH_PI (3.141592653589793238462643383279 )
+#define AI_MATH_TWO_PI (AI_MATH_PI * 2.0)
+#define AI_MATH_HALF_PI (AI_MATH_PI * 0.5)
/* And this is to avoid endless casts to float */
-#define AI_MATH_PI_F (3.1415926538f)
-#define AI_MATH_TWO_PI_F (AI_MATH_PI_F * 2.0f)
-#define AI_MATH_HALF_PI_F (AI_MATH_PI_F * 0.5f)
+#define AI_MATH_PI_F (3.1415926538f)
+#define AI_MATH_TWO_PI_F (AI_MATH_PI_F * 2.0f)
+#define AI_MATH_HALF_PI_F (AI_MATH_PI_F * 0.5f)
/* Tiny macro to convert from radians to degrees and back */
-#define AI_DEG_TO_RAD(x) (x*0.0174532925f)
-#define AI_RAD_TO_DEG(x) (x*57.2957795f)
+#define AI_DEG_TO_RAD(x) ((x)*0.0174532925f)
+#define AI_RAD_TO_DEG(x) ((x)*57.2957795f)
/* Support for big-endian builds */
#if defined(__BYTE_ORDER__)
-# if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-# if !defined(__BIG_ENDIAN__)
-# define __BIG_ENDIAN__
-# endif
-# else /* little endian */
-# if defined (__BIG_ENDIAN__)
-# undef __BIG_ENDIAN__
-# endif
-# endif
+# if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# if !defined(__BIG_ENDIAN__)
+# define __BIG_ENDIAN__
+# endif
+# else /* little endian */
+# if defined (__BIG_ENDIAN__)
+# undef __BIG_ENDIAN__
+# endif
+# endif
#endif
#if defined(__BIG_ENDIAN__)
-# define AI_BUILD_BIG_ENDIAN
+# define AI_BUILD_BIG_ENDIAN
#endif
+
+/* To avoid running out of memory
+ * This can be adjusted for specific use cases
+ * It's NOT a total limit, just a limit for individual allocations
+ */
+#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type))
+
+
#endif // !! INCLUDED_AI_DEFINES_H
diff --git a/src/3rdparty/assimp/include/assimp/importerdesc.h b/src/3rdparty/assimp/include/assimp/importerdesc.h
index 0d93c3f89..b2b123aca 100644
--- a/src/3rdparty/assimp/include/assimp/importerdesc.h
+++ b/src/3rdparty/assimp/include/assimp/importerdesc.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.
---------------------------------------------------------------------------
*/
@@ -48,89 +48,96 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** Mixed set of flags for #aiImporterDesc, indicating some features
* common to many importers*/
-enum aiImporterFlags
+enum aiImporterFlags
{
- /** Indicates that there is a textual encoding of the
- * file format; and that it is supported.*/
- aiImporterFlags_SupportTextFlavour = 0x1,
-
- /** Indicates that there is a binary encoding of the
- * file format; and that it is supported.*/
- aiImporterFlags_SupportBinaryFlavour = 0x2,
-
- /** Indicates that there is a compressed encoding of the
- * file format; and that it is supported.*/
- aiImporterFlags_SupportCompressedFlavour = 0x4,
-
- /** Indicates that the importer reads only a very particular
- * subset of the file format. This happens commonly for
- * declarative or procedural formats which cannot easily
- * be mapped to #aiScene */
- aiImporterFlags_LimitedSupport = 0x8,
-
- /** Indicates that the importer is highly experimental and
- * should be used with care. This only happens for trunk
- * (i.e. SVN) versions, experimental code is not included
- * in releases. */
- aiImporterFlags_Experimental = 0x10,
+ /** Indicates that there is a textual encoding of the
+ * file format; and that it is supported.*/
+ aiImporterFlags_SupportTextFlavour = 0x1,
+
+ /** Indicates that there is a binary encoding of the
+ * file format; and that it is supported.*/
+ aiImporterFlags_SupportBinaryFlavour = 0x2,
+
+ /** Indicates that there is a compressed encoding of the
+ * file format; and that it is supported.*/
+ aiImporterFlags_SupportCompressedFlavour = 0x4,
+
+ /** Indicates that the importer reads only a very particular
+ * subset of the file format. This happens commonly for
+ * declarative or procedural formats which cannot easily
+ * be mapped to #aiScene */
+ aiImporterFlags_LimitedSupport = 0x8,
+
+ /** Indicates that the importer is highly experimental and
+ * should be used with care. This only happens for trunk
+ * (i.e. SVN) versions, experimental code is not included
+ * in releases. */
+ aiImporterFlags_Experimental = 0x10
};
/** Meta information about a particular importer. Importers need to fill
- * this structure, but they can freely decide how talkative they are.
+ * this structure, but they can freely decide how talkative they are.
* A common use case for loader meta info is a user interface
* in which the user can choose between various import/export file
* formats. Building such an UI by hand means a lot of maintenance
* as importers/exporters are added to Assimp, so it might be useful
* to have a common mechanism to query some rough importer
* characteristics. */
-struct aiImporterDesc
+struct aiImporterDesc
{
- /** Full name of the importer (i.e. Blender3D importer)*/
- const char* mName;
-
- /** Original author (left blank if unknown or whole assimp team) */
- const char* mAuthor;
-
- /** Current maintainer, left blank if the author maintains */
- const char* mMaintainer;
-
- /** Implementation comments, i.e. unimplemented features*/
- const char* mComments;
-
- /** Any combination of the #aiLoaderFlags enumerated values.
- These flags indicate some characteristics common to many
- importers. */
- unsigned int mFlags;
-
- /** Minimum format version that can be loaded im major.minor format,
- both are set to 0 if there is either no version scheme
- or if the loader doesn't care. */
- unsigned int mMinMajor;
- unsigned int mMinMinor;
-
- /** Maximum format version that can be loaded im major.minor format,
- both are set to 0 if there is either no version scheme
- or if the loader doesn't care. Loaders that expect to be
- forward-compatible to potential future format versions should
- indicate zero, otherwise they should specify the current
- maximum version.*/
- unsigned int mMaxMajor;
- unsigned int mMaxMinor;
-
- /** List of file extensions this importer can handle.
- List entries are separated by space characters.
- All entries are lower case without a leading dot (i.e.
- "xml dae" would be a valid value. Note that multiple
- importers may respond to the same file extension -
- assimp calls all importers in the order in which they
- are registered and each importer gets the opportunity
- to load the file until one importer "claims" the file. Apart
- from file extension checks, importers typically use
- other methods to quickly reject files (i.e. magic
- words) so this does not mean that common or generic
- file extensions such as XML would be tediously slow. */
- const char* mFileExtensions;
+ /** Full name of the importer (i.e. Blender3D importer)*/
+ const char* mName;
+
+ /** Original author (left blank if unknown or whole assimp team) */
+ const char* mAuthor;
+
+ /** Current maintainer, left blank if the author maintains */
+ const char* mMaintainer;
+
+ /** Implementation comments, i.e. unimplemented features*/
+ const char* mComments;
+
+ /** These flags indicate some characteristics common to many
+ importers. */
+ unsigned int mFlags;
+
+ /** Minimum format version that can be loaded im major.minor format,
+ both are set to 0 if there is either no version scheme
+ or if the loader doesn't care. */
+ unsigned int mMinMajor;
+ unsigned int mMinMinor;
+
+ /** Maximum format version that can be loaded im major.minor format,
+ both are set to 0 if there is either no version scheme
+ or if the loader doesn't care. Loaders that expect to be
+ forward-compatible to potential future format versions should
+ indicate zero, otherwise they should specify the current
+ maximum version.*/
+ unsigned int mMaxMajor;
+ unsigned int mMaxMinor;
+
+ /** List of file extensions this importer can handle.
+ List entries are separated by space characters.
+ All entries are lower case without a leading dot (i.e.
+ "xml dae" would be a valid value. Note that multiple
+ importers may respond to the same file extension -
+ assimp calls all importers in the order in which they
+ are registered and each importer gets the opportunity
+ to load the file until one importer "claims" the file. Apart
+ from file extension checks, importers typically use
+ other methods to quickly reject files (i.e. magic
+ words) so this does not mean that common or generic
+ file extensions such as XML would be tediously slow. */
+ const char* mFileExtensions;
};
-#endif
+/** \brief Returns the Importer description for a given extension.
+
+Will return a NULL-pointer if no assigned importer desc. was found for the given extension
+ \param extension [in] The extension to look for
+ \return A pointer showing to the ImporterDesc, \see aiImporterDesc.
+*/
+ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImporterDesc( const char *extension );
+
+#endif
diff --git a/src/3rdparty/assimp/include/assimp/light.h b/src/3rdparty/assimp/include/assimp/light.h
index 81aceccf4..939d5b6cd 100644
--- a/src/3rdparty/assimp/include/assimp/light.h
+++ b/src/3rdparty/assimp/include/assimp/light.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.
---------------------------------------------------------------------------
*/
@@ -57,30 +57,41 @@ extern "C" {
*/
enum aiLightSourceType
{
- aiLightSource_UNDEFINED = 0x0,
-
- //! A directional light source has a well-defined direction
- //! but is infinitely far away. That's quite a good
- //! approximation for sun light.
- aiLightSource_DIRECTIONAL = 0x1,
-
- //! A point light source has a well-defined position
- //! in space but no direction - it emits light in all
- //! directions. A normal bulb is a point light.
- aiLightSource_POINT = 0x2,
-
- //! A spot light source emits light in a specific
- //! angle. It has a position and a direction it is pointing to.
- //! A good example for a spot light is a light spot in
- //! sport arenas.
- aiLightSource_SPOT = 0x3,
-
-
- /** This value is not used. It is just there to force the
- * compiler to map this enum to a 32 Bit integer.
- */
+ aiLightSource_UNDEFINED = 0x0,
+
+ //! A directional light source has a well-defined direction
+ //! but is infinitely far away. That's quite a good
+ //! approximation for sun light.
+ aiLightSource_DIRECTIONAL = 0x1,
+
+ //! A point light source has a well-defined position
+ //! in space but no direction - it emits light in all
+ //! directions. A normal bulb is a point light.
+ aiLightSource_POINT = 0x2,
+
+ //! A spot light source emits light in a specific
+ //! angle. It has a position and a direction it is pointing to.
+ //! A good example for a spot light is a light spot in
+ //! sport arenas.
+ aiLightSource_SPOT = 0x3,
+
+ //! The generic light level of the world, including the bounces
+ //! of all other light sources.
+ //! Typically, there's at most one ambient light in a scene.
+ //! This light type doesn't have a valid position, direction, or
+ //! other properties, just a color.
+ aiLightSource_AMBIENT = 0x4,
+
+ //! An area light is a rectangle with predefined size that uniformly
+ //! emits light from one of its sides. The position is center of the
+ //! rectangle and direction is its normal vector.
+ aiLightSource_AREA = 0x5,
+
+ /** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
#ifndef SWIG
- _aiLightSource_Force32Bit = INT_MAX
+ _aiLightSource_Force32Bit = INT_MAX
#endif
};
@@ -99,128 +110,140 @@ enum aiLightSourceType
*/
struct aiLight
{
- /** The name of the light source.
- *
- * There must be a node in the scenegraph with the same name.
- * This node specifies the position of the light in the scene
- * hierarchy and can be animated.
- */
- C_STRUCT aiString mName;
-
- /** The type of the light source.
- *
- * aiLightSource_UNDEFINED is not a valid value for this member.
- */
- C_ENUM aiLightSourceType mType;
-
- /** Position of the light source in space. Relative to the
- * transformation of the node corresponding to the light.
- *
- * The position is undefined for directional lights.
- */
- C_STRUCT aiVector3D mPosition;
-
- /** Direction of the light source in space. Relative to the
- * transformation of the node corresponding to the light.
- *
- * The direction is undefined for point lights. The vector
- * may be normalized, but it needn't.
- */
- C_STRUCT aiVector3D mDirection;
-
- /** Constant light attenuation factor.
- *
- * The intensity of the light source at a given distance 'd' from
- * the light's position is
- * @code
- * Atten = 1/( att0 + att1 * d + att2 * d*d)
- * @endcode
- * This member corresponds to the att0 variable in the equation.
- * Naturally undefined for directional lights.
- */
- float mAttenuationConstant;
-
- /** Linear light attenuation factor.
- *
- * The intensity of the light source at a given distance 'd' from
- * the light's position is
- * @code
- * Atten = 1/( att0 + att1 * d + att2 * d*d)
- * @endcode
- * This member corresponds to the att1 variable in the equation.
- * Naturally undefined for directional lights.
- */
- float mAttenuationLinear;
-
- /** Quadratic light attenuation factor.
- *
- * The intensity of the light source at a given distance 'd' from
- * the light's position is
- * @code
- * Atten = 1/( att0 + att1 * d + att2 * d*d)
- * @endcode
- * This member corresponds to the att2 variable in the equation.
- * Naturally undefined for directional lights.
- */
- float mAttenuationQuadratic;
-
- /** Diffuse color of the light source
- *
- * The diffuse light color is multiplied with the diffuse
- * material color to obtain the final color that contributes
- * to the diffuse shading term.
- */
- C_STRUCT aiColor3D mColorDiffuse;
-
- /** Specular color of the light source
- *
- * The specular light color is multiplied with the specular
- * material color to obtain the final color that contributes
- * to the specular shading term.
- */
- C_STRUCT aiColor3D mColorSpecular;
-
- /** Ambient color of the light source
- *
- * The ambient light color is multiplied with the ambient
- * material color to obtain the final color that contributes
- * to the ambient shading term. Most renderers will ignore
- * this value it, is just a remaining of the fixed-function pipeline
- * that is still supported by quite many file formats.
- */
- C_STRUCT aiColor3D mColorAmbient;
-
- /** Inner angle of a spot light's light cone.
- *
- * The spot light has maximum influence on objects inside this
- * angle. The angle is given in radians. It is 2PI for point
- * lights and undefined for directional lights.
- */
- float mAngleInnerCone;
-
- /** Outer angle of a spot light's light cone.
- *
- * The spot light does not affect objects outside this angle.
- * The angle is given in radians. It is 2PI for point lights and
- * undefined for directional lights. The outer angle must be
- * greater than or equal to the inner angle.
- * It is assumed that the application uses a smooth
- * interpolation between the inner and the outer cone of the
- * spot light.
- */
- float mAngleOuterCone;
+ /** The name of the light source.
+ *
+ * There must be a node in the scenegraph with the same name.
+ * This node specifies the position of the light in the scene
+ * hierarchy and can be animated.
+ */
+ C_STRUCT aiString mName;
+
+ /** The type of the light source.
+ *
+ * aiLightSource_UNDEFINED is not a valid value for this member.
+ */
+ C_ENUM aiLightSourceType mType;
+
+ /** Position of the light source in space. Relative to the
+ * transformation of the node corresponding to the light.
+ *
+ * The position is undefined for directional lights.
+ */
+ C_STRUCT aiVector3D mPosition;
+
+ /** Direction of the light source in space. Relative to the
+ * transformation of the node corresponding to the light.
+ *
+ * The direction is undefined for point lights. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mDirection;
+
+ /** Up direction of the light source in space. Relative to the
+ * transformation of the node corresponding to the light.
+ *
+ * The direction is undefined for point lights. The vector
+ * may be normalized, but it needn't.
+ */
+ C_STRUCT aiVector3D mUp;
+
+ /** Constant light attenuation factor.
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * @code
+ * Atten = 1/( att0 + att1 * d + att2 * d*d)
+ * @endcode
+ * This member corresponds to the att0 variable in the equation.
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationConstant;
+
+ /** Linear light attenuation factor.
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * @code
+ * Atten = 1/( att0 + att1 * d + att2 * d*d)
+ * @endcode
+ * This member corresponds to the att1 variable in the equation.
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationLinear;
+
+ /** Quadratic light attenuation factor.
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * @code
+ * Atten = 1/( att0 + att1 * d + att2 * d*d)
+ * @endcode
+ * This member corresponds to the att2 variable in the equation.
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationQuadratic;
+
+ /** Diffuse color of the light source
+ *
+ * The diffuse light color is multiplied with the diffuse
+ * material color to obtain the final color that contributes
+ * to the diffuse shading term.
+ */
+ C_STRUCT aiColor3D mColorDiffuse;
+
+ /** Specular color of the light source
+ *
+ * The specular light color is multiplied with the specular
+ * material color to obtain the final color that contributes
+ * to the specular shading term.
+ */
+ C_STRUCT aiColor3D mColorSpecular;
+
+ /** Ambient color of the light source
+ *
+ * The ambient light color is multiplied with the ambient
+ * material color to obtain the final color that contributes
+ * to the ambient shading term. Most renderers will ignore
+ * this value it, is just a remaining of the fixed-function pipeline
+ * that is still supported by quite many file formats.
+ */
+ C_STRUCT aiColor3D mColorAmbient;
+
+ /** Inner angle of a spot light's light cone.
+ *
+ * The spot light has maximum influence on objects inside this
+ * angle. The angle is given in radians. It is 2PI for point
+ * lights and undefined for directional lights.
+ */
+ float mAngleInnerCone;
+
+ /** Outer angle of a spot light's light cone.
+ *
+ * The spot light does not affect objects outside this angle.
+ * The angle is given in radians. It is 2PI for point lights and
+ * undefined for directional lights. The outer angle must be
+ * greater than or equal to the inner angle.
+ * It is assumed that the application uses a smooth
+ * interpolation between the inner and the outer cone of the
+ * spot light.
+ */
+ float mAngleOuterCone;
+
+ /** Size of area light source. */
+ C_STRUCT aiVector2D mSize;
#ifdef __cplusplus
- aiLight()
- : mType (aiLightSource_UNDEFINED)
- , mAttenuationConstant (0.f)
- , mAttenuationLinear (1.f)
- , mAttenuationQuadratic (0.f)
- , mAngleInnerCone ((float)AI_MATH_TWO_PI)
- , mAngleOuterCone ((float)AI_MATH_TWO_PI)
- {
- }
+ aiLight()
+ : mType (aiLightSource_UNDEFINED)
+ , mAttenuationConstant (0.f)
+ , mAttenuationLinear (1.f)
+ , mAttenuationQuadratic (0.f)
+ , mAngleInnerCone ((float)AI_MATH_TWO_PI)
+ , mAngleOuterCone ((float)AI_MATH_TWO_PI)
+ , mSize (0.f, 0.f)
+ {
+ }
#endif
};
diff --git a/src/3rdparty/assimp/include/assimp/material.h b/src/3rdparty/assimp/include/assimp/material.h
index daf6a8e09..87d27c569 100644
--- a/src/3rdparty/assimp/include/assimp/material.h
+++ b/src/3rdparty/assimp/include/assimp/material.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.
---------------------------------------------------------------------------
*/
@@ -67,52 +67,47 @@ extern "C" {
* DiffTextureOp0 - aiTextureOpAdd
* DiffTexture1 - tex2.png
* @endcode
- * Written as equation, the final diffuse term for a specific pixel would be:
+ * Written as equation, the final diffuse term for a specific pixel would be:
* @code
- * diffFinal = DiffColor0 * sampleTex(DiffTexture0,UV0) +
+ * diffFinal = DiffColor0 * sampleTex(DiffTexture0,UV0) +
* sampleTex(DiffTexture1,UV0) * diffContrib;
* @endcode
* where 'diffContrib' is the intensity of the incoming light for that pixel.
*/
enum aiTextureOp
{
- /** T = T1 * T2 */
- aiTextureOp_Multiply = 0x0,
+ /** T = T1 * T2 */
+ aiTextureOp_Multiply = 0x0,
- /** T = T1 + T2 */
- aiTextureOp_Add = 0x1,
+ /** T = T1 + T2 */
+ aiTextureOp_Add = 0x1,
- /** T = T1 - T2 */
- aiTextureOp_Subtract = 0x2,
+ /** T = T1 - T2 */
+ aiTextureOp_Subtract = 0x2,
- /** T = T1 / T2 */
- aiTextureOp_Divide = 0x3,
+ /** T = T1 / T2 */
+ aiTextureOp_Divide = 0x3,
- /** T = (T1 + T2) - (T1 * T2) */
- aiTextureOp_SmoothAdd = 0x4,
+ /** T = (T1 + T2) - (T1 * T2) */
+ aiTextureOp_SmoothAdd = 0x4,
- /** T = T1 + (T2-0.5) */
- aiTextureOp_SignedAdd = 0x5,
+ /** T = T1 + (T2-0.5) */
+ aiTextureOp_SignedAdd = 0x5,
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
#ifndef SWIG
- _aiTextureOp_Force32Bit = INT_MAX
+ _aiTextureOp_Force32Bit = INT_MAX
#endif
- //! @endcond
};
// ---------------------------------------------------------------------------
/** @brief Defines how UV coordinates outside the [0...1] range are handled.
*
- * Commonly refered to as 'wrapping mode'.
+ * Commonly referred to as 'wrapping mode'.
*/
enum aiTextureMapMode
{
- /** A texture coordinate u|v is translated to u%1|v%1
+ /** A texture coordinate u|v is translated to u%1|v%1
*/
aiTextureMapMode_Wrap = 0x0,
@@ -121,8 +116,8 @@ enum aiTextureMapMode
*/
aiTextureMapMode_Clamp = 0x1,
- /** If the texture coordinates for a pixel are outside [0...1]
- * the texture is not applied to that pixel
+ /** If the texture coordinates for a pixel are outside [0...1]
+ * the texture is not applied to that pixel
*/
aiTextureMapMode_Decal = 0x3,
@@ -131,14 +126,9 @@ enum aiTextureMapMode
*/
aiTextureMapMode_Mirror = 0x2,
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
#ifndef SWIG
- _aiTextureMapMode_Force32Bit = INT_MAX
+ _aiTextureMapMode_Force32Bit = INT_MAX
#endif
- //! @endcond
};
// ---------------------------------------------------------------------------
@@ -153,157 +143,147 @@ enum aiTextureMapMode
enum aiTextureMapping
{
/** The mapping coordinates are taken from an UV channel.
- *
- * The #AI_MATKEY_UVWSRC key specifies from which UV channel
- * the texture coordinates are to be taken from (remember,
- * meshes can have more than one UV channel).
+ *
+ * The #AI_MATKEY_UVWSRC key specifies from which UV channel
+ * the texture coordinates are to be taken from (remember,
+ * meshes can have more than one UV channel).
*/
aiTextureMapping_UV = 0x0,
- /** Spherical mapping */
+ /** Spherical mapping */
aiTextureMapping_SPHERE = 0x1,
- /** Cylindrical mapping */
+ /** Cylindrical mapping */
aiTextureMapping_CYLINDER = 0x2,
- /** Cubic mapping */
+ /** Cubic mapping */
aiTextureMapping_BOX = 0x3,
- /** Planar mapping */
+ /** Planar mapping */
aiTextureMapping_PLANE = 0x4,
- /** Undefined mapping. Have fun. */
+ /** Undefined mapping. Have fun. */
aiTextureMapping_OTHER = 0x5,
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
#ifndef SWIG
- _aiTextureMapping_Force32Bit = INT_MAX
+ _aiTextureMapping_Force32Bit = INT_MAX
#endif
- //! @endcond
};
// ---------------------------------------------------------------------------
-/** @brief Defines the purpose of a texture
+/** @brief Defines the purpose of a texture
*
* This is a very difficult topic. Different 3D packages support different
* kinds of textures. For very common texture types, such as bumpmaps, the
- * rendering results depend on implementation details in the rendering
+ * rendering results depend on implementation details in the rendering
* pipelines of these applications. Assimp loads all texture references from
* the model file and tries to determine which of the predefined texture
* types below is the best choice to match the original use of the texture
* as closely as possible.<br>
- *
+ *
* In content pipelines you'll usually define how textures have to be handled,
* and the artists working on models have to conform to this specification,
* regardless which 3D tool they're using.
*/
enum aiTextureType
{
- /** Dummy value.
- *
- * No texture, but the value to be used as 'texture semantic'
- * (#aiMaterialProperty::mSemantic) for all material properties
- * *not* related to textures.
- */
- aiTextureType_NONE = 0x0,
+ /** Dummy value.
+ *
+ * No texture, but the value to be used as 'texture semantic'
+ * (#aiMaterialProperty::mSemantic) for all material properties
+ * *not* related to textures.
+ */
+ aiTextureType_NONE = 0x0,
/** The texture is combined with the result of the diffuse
- * lighting equation.
+ * lighting equation.
*/
aiTextureType_DIFFUSE = 0x1,
- /** The texture is combined with the result of the specular
- * lighting equation.
+ /** The texture is combined with the result of the specular
+ * lighting equation.
*/
aiTextureType_SPECULAR = 0x2,
- /** The texture is combined with the result of the ambient
- * lighting equation.
+ /** The texture is combined with the result of the ambient
+ * lighting equation.
*/
aiTextureType_AMBIENT = 0x3,
- /** The texture is added to the result of the lighting
- * calculation. It isn't influenced by incoming light.
+ /** The texture is added to the result of the lighting
+ * calculation. It isn't influenced by incoming light.
*/
aiTextureType_EMISSIVE = 0x4,
- /** The texture is a height map.
- *
- * By convention, higher gray-scale values stand for
- * higher elevations from the base height.
+ /** The texture is a height map.
+ *
+ * By convention, higher gray-scale values stand for
+ * higher elevations from the base height.
*/
aiTextureType_HEIGHT = 0x5,
- /** The texture is a (tangent space) normal-map.
- *
- * Again, there are several conventions for tangent-space
- * normal maps. Assimp does (intentionally) not
- * distinguish here.
+ /** The texture is a (tangent space) normal-map.
+ *
+ * Again, there are several conventions for tangent-space
+ * normal maps. Assimp does (intentionally) not
+ * distinguish here.
*/
aiTextureType_NORMALS = 0x6,
- /** The texture defines the glossiness of the material.
- *
- * The glossiness is in fact the exponent of the specular
- * (phong) lighting equation. Usually there is a conversion
- * function defined to map the linear color values in the
- * texture to a suitable exponent. Have fun.
+ /** The texture defines the glossiness of the material.
+ *
+ * The glossiness is in fact the exponent of the specular
+ * (phong) lighting equation. Usually there is a conversion
+ * function defined to map the linear color values in the
+ * texture to a suitable exponent. Have fun.
*/
aiTextureType_SHININESS = 0x7,
- /** The texture defines per-pixel opacity.
- *
- * Usually 'white' means opaque and 'black' means
- * 'transparency'. Or quite the opposite. Have fun.
+ /** The texture defines per-pixel opacity.
+ *
+ * Usually 'white' means opaque and 'black' means
+ * 'transparency'. Or quite the opposite. Have fun.
*/
aiTextureType_OPACITY = 0x8,
- /** Displacement texture
- *
- * The exact purpose and format is application-dependent.
+ /** Displacement texture
+ *
+ * The exact purpose and format is application-dependent.
* Higher color values stand for higher vertex displacements.
*/
aiTextureType_DISPLACEMENT = 0x9,
- /** Lightmap texture (aka Ambient Occlusion)
- *
- * Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
- * covered by this material property. The texture contains a
- * scaling value for the final color value of a pixel. Its
- * intensity is not affected by incoming light.
+ /** Lightmap texture (aka Ambient Occlusion)
+ *
+ * Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
+ * covered by this material property. The texture contains a
+ * scaling value for the final color value of a pixel. Its
+ * intensity is not affected by incoming light.
*/
aiTextureType_LIGHTMAP = 0xA,
- /** Reflection texture
- *
- * Contains the color of a perfect mirror reflection.
- * Rarely used, almost never for real-time applications.
+ /** Reflection texture
+ *
+ * Contains the color of a perfect mirror reflection.
+ * Rarely used, almost never for real-time applications.
*/
aiTextureType_REFLECTION = 0xB,
- /** Unknown texture
- *
- * A texture reference that does not match any of the definitions
- * above is considered to be 'unknown'. It is still imported,
- * but is excluded from any further postprocessing.
+ /** Unknown texture
+ *
+ * A texture reference that does not match any of the definitions
+ * above is considered to be 'unknown'. It is still imported,
+ * but is excluded from any further postprocessing.
*/
aiTextureType_UNKNOWN = 0xC,
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
#ifndef SWIG
- _aiTextureType_Force32Bit = INT_MAX
+ _aiTextureType_Force32Bit = INT_MAX
#endif
- //! @endcond
};
#define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN
@@ -322,14 +302,14 @@ enum aiTextureType
*/
enum aiShadingMode
{
- /** Flat shading. Shading is done on per-face base,
+ /** Flat shading. Shading is done on per-face base,
* diffuse only. Also known as 'faceted shading'.
*/
aiShadingMode_Flat = 0x1,
- /** Simple Gouraud shading.
+ /** Simple Gouraud shading.
*/
- aiShadingMode_Gouraud = 0x2,
+ aiShadingMode_Gouraud = 0x2,
/** Phong-Shading -
*/
@@ -337,11 +317,11 @@ enum aiShadingMode
/** Phong-Blinn-Shading
*/
- aiShadingMode_Blinn = 0x4,
+ aiShadingMode_Blinn = 0x4,
/** Toon-Shading per pixel
*
- * Also known as 'comic' shader.
+ * Also known as 'comic' shader.
*/
aiShadingMode_Toon = 0x5,
@@ -360,8 +340,8 @@ enum aiShadingMode
aiShadingMode_Minnaert = 0x7,
/** CookTorrance-Shading per pixel
- *
- * Special shader for metallic surfaces.
+ *
+ * Special shader for metallic surfaces.
*/
aiShadingMode_CookTorrance = 0x8,
@@ -369,19 +349,14 @@ enum aiShadingMode
*/
aiShadingMode_NoShading = 0x9,
- /** Fresnel shading
+ /** Fresnel shading
*/
aiShadingMode_Fresnel = 0xa,
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
#ifndef SWIG
- _aiShadingMode_Force32Bit = INT_MAX
+ _aiShadingMode_Force32Bit = INT_MAX
#endif
- //! @endcond
};
@@ -390,44 +365,39 @@ enum aiShadingMode
*
* Usually you'll instruct your cg artists how textures have to look like ...
* and how they will be processed in your application. However, if you use
- * Assimp for completely generic loading purposes you might also need to
- * process these flags in order to display as many 'unknown' 3D models as
+ * Assimp for completely generic loading purposes you might also need to
+ * process these flags in order to display as many 'unknown' 3D models as
* possible correctly.
*
* This corresponds to the #AI_MATKEY_TEXFLAGS property.
*/
enum aiTextureFlags
{
- /** The texture's color values have to be inverted (componentwise 1-n)
- */
- aiTextureFlags_Invert = 0x1,
-
- /** Explicit request to the application to process the alpha channel
- * of the texture.
- *
- * Mutually exclusive with #aiTextureFlags_IgnoreAlpha. These
- * flags are set if the library can say for sure that the alpha
- * channel is used/is not used. If the model format does not
- * define this, it is left to the application to decide whether
- * the texture alpha channel - if any - is evaluated or not.
- */
- aiTextureFlags_UseAlpha = 0x2,
-
- /** Explicit request to the application to ignore the alpha channel
- * of the texture.
- *
- * Mutually exclusive with #aiTextureFlags_UseAlpha.
- */
- aiTextureFlags_IgnoreAlpha = 0x4,
-
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
+ /** The texture's color values have to be inverted (componentwise 1-n)
+ */
+ aiTextureFlags_Invert = 0x1,
+
+ /** Explicit request to the application to process the alpha channel
+ * of the texture.
+ *
+ * Mutually exclusive with #aiTextureFlags_IgnoreAlpha. These
+ * flags are set if the library can say for sure that the alpha
+ * channel is used/is not used. If the model format does not
+ * define this, it is left to the application to decide whether
+ * the texture alpha channel - if any - is evaluated or not.
+ */
+ aiTextureFlags_UseAlpha = 0x2,
+
+ /** Explicit request to the application to ignore the alpha channel
+ * of the texture.
+ *
+ * Mutually exclusive with #aiTextureFlags_UseAlpha.
+ */
+ aiTextureFlags_IgnoreAlpha = 0x4,
+
#ifndef SWIG
- _aiTextureFlags_Force32Bit = INT_MAX
+ _aiTextureFlags_Force32Bit = INT_MAX
#endif
- //! @endcond
};
@@ -442,41 +412,36 @@ enum aiTextureFlags
* @code
* SourceColor * SourceBlend + DestColor * DestBlend
* @endcode
- * where <DestColor> is the previous color in the framebuffer at this
- * position and <SourceColor> is the material colro before the transparency
+ * where DestColor is the previous color in the framebuffer at this
+ * position and SourceColor is the material colro before the transparency
* calculation.<br>
* This corresponds to the #AI_MATKEY_BLEND_FUNC property.
*/
enum aiBlendMode
{
- /**
- * Formula:
- * @code
- * SourceColor*SourceAlpha + DestColor*(1-SourceAlpha)
- * @endcode
- */
- aiBlendMode_Default = 0x0,
-
- /** Additive blending
- *
- * Formula:
- * @code
- * SourceColor*1 + DestColor*1
- * @endcode
- */
- aiBlendMode_Additive = 0x1,
-
- // we don't need more for the moment, but we might need them
- // in future versions ...
-
- /** @cond never
- * This value is not used. It forces the compiler to use at least
- * 32 Bit integers to represent this enum.
- */
+ /**
+ * Formula:
+ * @code
+ * SourceColor*SourceAlpha + DestColor*(1-SourceAlpha)
+ * @endcode
+ */
+ aiBlendMode_Default = 0x0,
+
+ /** Additive blending
+ *
+ * Formula:
+ * @code
+ * SourceColor*1 + DestColor*1
+ * @endcode
+ */
+ aiBlendMode_Additive = 0x1,
+
+ // we don't need more for the moment, but we might need them
+ // in future versions ...
+
#ifndef SWIG
- _aiBlendMode_Force32Bit = INT_MAX
+ _aiBlendMode_Force32Bit = INT_MAX
#endif
- //! @endcond
};
@@ -486,7 +451,7 @@ enum aiBlendMode
/** @brief Defines how an UV channel is transformed.
*
* This is just a helper structure for the #AI_MATKEY_UVTRANSFORM key.
- * See its documentation for more details.
+ * See its documentation for more details.
*
* Typically you'll want to build a matrix of this information. However,
* we keep separate scaling/translation/rotation values to make it
@@ -494,34 +459,34 @@ enum aiBlendMode
*/
struct aiUVTransform
{
- /** Translation on the u and v axes.
- *
- * The default value is (0|0).
- */
- C_STRUCT aiVector2D mTranslation;
-
- /** Scaling on the u and v axes.
- *
- * The default value is (1|1).
- */
- C_STRUCT aiVector2D mScaling;
-
- /** Rotation - in counter-clockwise direction.
- *
- * The rotation angle is specified in radians. The
- * rotation center is 0.5f|0.5f. The default value
+ /** Translation on the u and v axes.
+ *
+ * The default value is (0|0).
+ */
+ C_STRUCT aiVector2D mTranslation;
+
+ /** Scaling on the u and v axes.
+ *
+ * The default value is (1|1).
+ */
+ C_STRUCT aiVector2D mScaling;
+
+ /** Rotation - in counter-clockwise direction.
+ *
+ * The rotation angle is specified in radians. The
+ * rotation center is 0.5f|0.5f. The default value
* 0.f.
- */
- float mRotation;
+ */
+ float mRotation;
#ifdef __cplusplus
- aiUVTransform()
- : mScaling (1.f,1.f)
- , mRotation (0.f)
- {
- // nothing to be done here ...
- }
+ aiUVTransform()
+ : mScaling (1.f,1.f)
+ , mRotation (0.f)
+ {
+ // nothing to be done here ...
+ }
#endif
} PACK_STRUCT;
@@ -530,31 +495,31 @@ struct aiUVTransform
//! @cond AI_DOX_INCLUDE_INTERNAL
// ---------------------------------------------------------------------------
-/** @brief A very primitive RTTI system for the contents of material
+/** @brief A very primitive RTTI system for the contents of material
* properties.
*/
enum aiPropertyTypeInfo
{
/** Array of single-precision (32 Bit) floats
- *
- * It is possible to use aiGetMaterialInteger[Array]() (or the C++-API
- * aiMaterial::Get()) to query properties stored in floating-point format.
- * The material system performs the type conversion automatically.
+ *
+ * It is possible to use aiGetMaterialInteger[Array]() (or the C++-API
+ * aiMaterial::Get()) to query properties stored in floating-point format.
+ * The material system performs the type conversion automatically.
*/
aiPTI_Float = 0x1,
/** The material property is an aiString.
- *
- * Arrays of strings aren't possible, aiGetMaterialString() (or the
- * C++-API aiMaterial::Get()) *must* be used to query a string property.
+ *
+ * Arrays of strings aren't possible, aiGetMaterialString() (or the
+ * C++-API aiMaterial::Get()) *must* be used to query a string property.
*/
aiPTI_String = 0x3,
/** Array of (32 Bit) integers
- *
- * It is possible to use aiGetMaterialFloat[Array]() (or the C++-API
- * aiMaterial::Get()) to query properties stored in integer format.
- * The material system performs the type conversion automatically.
+ *
+ * It is possible to use aiGetMaterialFloat[Array]() (or the C++-API
+ * aiMaterial::Get()) to query properties stored in integer format.
+ * The material system performs the type conversion automatically.
*/
aiPTI_Integer = 0x4,
@@ -564,11 +529,11 @@ enum aiPropertyTypeInfo
aiPTI_Buffer = 0x5,
- /** This value is not used. It is just there to force the
- * compiler to map this enum to a 32 Bit integer.
- */
+ /** This value is not used. It is just there to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
#ifndef SWIG
- _aiPTI_Force32Bit = INT_MAX
+ _aiPTI_Force32Bit = INT_MAX
#endif
};
@@ -577,7 +542,7 @@ enum aiPropertyTypeInfo
*
* As an user, you'll probably never need to deal with this data structure.
* Just use the provided aiGetMaterialXXX() or aiMaterial::Get() family
- * of functions to query material properties easily. Processing them
+ * of functions to query material properties easily. Processing them
* manually is faster, but it is not the recommended way. It isn't worth
* the effort. <br>
* Material property names follow a simple scheme:
@@ -585,64 +550,64 @@ enum aiPropertyTypeInfo
* $<name>
* ?<name>
* A public property, there must be corresponding AI_MATKEY_XXX define
- * 2nd: Public, but ignored by the #aiProcess_RemoveRedundantMaterials
+ * 2nd: Public, but ignored by the #aiProcess_RemoveRedundantMaterials
* post-processing step.
* ~<name>
- * A temporary property for internal use.
+ * A temporary property for internal use.
* @endcode
* @see aiMaterial
*/
struct aiMaterialProperty
{
/** Specifies the name of the property (key)
- * Keys are generally case insensitive.
+ * Keys are generally case insensitive.
*/
C_STRUCT aiString mKey;
- /** Textures: Specifies their exact usage semantic.
- * For non-texture properties, this member is always 0
- * (or, better-said, #aiTextureType_NONE).
- */
- unsigned int mSemantic;
+ /** Textures: Specifies their exact usage semantic.
+ * For non-texture properties, this member is always 0
+ * (or, better-said, #aiTextureType_NONE).
+ */
+ unsigned int mSemantic;
- /** Textures: Specifies the index of the texture.
- * For non-texture properties, this member is always 0.
- */
- unsigned int mIndex;
+ /** Textures: Specifies the index of the texture.
+ * For non-texture properties, this member is always 0.
+ */
+ unsigned int mIndex;
- /** Size of the buffer mData is pointing to, in bytes.
- * This value may not be 0.
+ /** Size of the buffer mData is pointing to, in bytes.
+ * This value may not be 0.
*/
unsigned int mDataLength;
/** Type information for the property.
*
* Defines the data layout inside the data buffer. This is used
- * by the library internally to perform debug checks and to
- * utilize proper type conversions.
- * (It's probably a hacky solution, but it works.)
+ * by the library internally to perform debug checks and to
+ * utilize proper type conversions.
+ * (It's probably a hacky solution, but it works.)
*/
C_ENUM aiPropertyTypeInfo mType;
- /** Binary buffer to hold the property's value.
+ /** Binary buffer to hold the property's value.
* The size of the buffer is always mDataLength.
*/
char* mData;
#ifdef __cplusplus
- aiMaterialProperty()
- : mSemantic( 0 )
- , mIndex( 0 )
- , mDataLength( 0 )
- , mType( aiPTI_Float )
- , mData( NULL )
- {
- }
+ aiMaterialProperty()
+ : mSemantic( 0 )
+ , mIndex( 0 )
+ , mDataLength( 0 )
+ , mType( aiPTI_Float )
+ , mData( NULL )
+ {
+ }
- ~aiMaterialProperty() {
- delete[] mData;
- }
+ ~aiMaterialProperty() {
+ delete[] mData;
+ }
#endif
};
@@ -672,214 +637,216 @@ struct aiMaterial
public:
- aiMaterial();
- ~aiMaterial();
+ aiMaterial();
+ ~aiMaterial();
- // -------------------------------------------------------------------
- /** @brief Retrieve an array of Type values with a specific key
+ // -------------------------------------------------------------------
+ /** @brief Retrieve an array of Type values with a specific key
* from the material
*
* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
* @param type .. set by AI_MATKEY_XXX
* @param idx .. set by AI_MATKEY_XXX
- * @param pOut Pointer to a buffer to receive the result.
+ * @param pOut Pointer to a buffer to receive the result.
* @param pMax Specifies the size of the given buffer, in Type's.
- * Receives the number of values (not bytes!) read.
+ * Receives the number of values (not bytes!) read.
* NULL is a valid value for this parameter.
*/
template <typename Type>
aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, Type* pOut, unsigned int* pMax) const;
+ unsigned int idx, Type* pOut, unsigned int* pMax) const;
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, int* pOut, unsigned int* pMax) const;
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, int* pOut, unsigned int* pMax) const;
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, float* pOut, unsigned int* pMax) const;
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, float* pOut, unsigned int* pMax) const;
// -------------------------------------------------------------------
- /** @brief Retrieve a Type value with a specific key
+ /** @brief Retrieve a Type value with a specific key
* from the material
- *
- * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+ *
+ * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
* @param type Specifies the type of the texture to be retrieved (
* e.g. diffuse, specular, height map ...)
* @param idx Index of the texture to be retrieved.
- * @param pOut Reference to receive the output value
- */
- template <typename Type>
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx,Type& pOut) const;
-
-
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, int& pOut) const;
-
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, float& pOut) const;
-
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, aiString& pOut) const;
-
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, aiColor3D& pOut) const;
-
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, aiColor4D& pOut) const;
-
- aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, aiUVTransform& pOut) const;
-
- // -------------------------------------------------------------------
- /** Get the number of textures for a particular texture type.
- * @param type Texture type to check for
- * @return Number of textures for this type.
- * @note A texture can be easily queried using #GetTexture() */
- unsigned int GetTextureCount(aiTextureType type) const;
-
- // -------------------------------------------------------------------
- /** Helper function to get all parameters pertaining to a
- * particular texture slot from a material.
- *
- * This function is provided just for convenience, you could also
- * read the single material properties manually.
- * @param type Specifies the type of the texture to be retrieved (
- * e.g. diffuse, specular, height map ...)
- * @param index Index of the texture to be retrieved. The function fails
- * if there is no texture of that type with this index.
- * #GetTextureCount() can be used to determine the number of textures
- * per texture type.
- * @param path Receives the path to the texture.
- * NULL is a valid value.
+ * @param pOut Reference to receive the output value
+ */
+ template <typename Type>
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx,Type& pOut) const;
+
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, int& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, float& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiString& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiColor3D& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiColor4D& pOut) const;
+
+ aiReturn Get(const char* pKey,unsigned int type,
+ unsigned int idx, aiUVTransform& pOut) const;
+
+ // -------------------------------------------------------------------
+ /** Get the number of textures for a particular texture type.
+ * @param type Texture type to check for
+ * @return Number of textures for this type.
+ * @note A texture can be easily queried using #GetTexture() */
+ unsigned int GetTextureCount(aiTextureType type) const;
+
+ // -------------------------------------------------------------------
+ /** Helper function to get all parameters pertaining to a
+ * particular texture slot from a material.
+ *
+ * This function is provided just for convenience, you could also
+ * read the single material properties manually.
+ * @param type Specifies the type of the texture to be retrieved (
+ * e.g. diffuse, specular, height map ...)
+ * @param index Index of the texture to be retrieved. The function fails
+ * if there is no texture of that type with this index.
+ * #GetTextureCount() can be used to determine the number of textures
+ * per texture type.
+ * @param path Receives the path to the texture.
+ * NULL is a valid value.
* @param mapping The texture mapping.
- * NULL is allowed as value.
- * @param uvindex Receives the UV index of the texture.
- * NULL is a valid value.
- * @param blend Receives the blend factor for the texture
- * NULL is a valid value.
- * @param op Receives the texture operation to be performed between
- * this texture and the previous texture. NULL is allowed as value.
- * @param mapmode Receives the mapping modes to be used for the texture.
- * The parameter may be NULL but if it is a valid pointer it MUST
- * point to an array of 3 aiTextureMapMode's (one for each
- * axis: UVW order (=XYZ)).
- */
- // -------------------------------------------------------------------
- aiReturn GetTexture(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) const;
-
-
- // Setters
-
-
- // ------------------------------------------------------------------------------
- /** @brief Add a property with a given key and type info to the material
- * structure
- *
- * @param pInput Pointer to input data
- * @param pSizeInBytes Size of input data
- * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
- * @param type Set by the AI_MATKEY_XXX macro
- * @param index Set by the AI_MATKEY_XXX macro
- * @param pType Type information hint */
- aiReturn AddBinaryProperty (const void* pInput,
- unsigned int pSizeInBytes,
- const char* pKey,
- unsigned int type ,
- unsigned int index ,
- aiPropertyTypeInfo pType);
-
- // ------------------------------------------------------------------------------
- /** @brief Add a string property with a given key and type info to the
- * material structure
- *
- * @param pInput Input string
- * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
- * @param type Set by the AI_MATKEY_XXX macro
- * @param index Set by the AI_MATKEY_XXX macro */
- aiReturn AddProperty (const aiString* pInput,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- // ------------------------------------------------------------------------------
- /** @brief Add a property with a given key to the material structure
- * @param pInput Pointer to the input data
- * @param pNumValues Number of values in the array
- * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
- * @param type Set by the AI_MATKEY_XXX macro
- * @param index Set by the AI_MATKEY_XXX macro */
- template<class TYPE>
- aiReturn AddProperty (const TYPE* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- aiReturn AddProperty (const aiVector3D* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- aiReturn AddProperty (const aiColor3D* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- aiReturn AddProperty (const aiColor4D* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- aiReturn AddProperty (const int* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- aiReturn AddProperty (const float* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- aiReturn AddProperty (const aiUVTransform* pInput,
- unsigned int pNumValues,
- const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- // ------------------------------------------------------------------------------
- /** @brief Remove a given key from the list.
- *
- * The function fails if the key isn't found
- * @param pKey Key to be deleted */
- aiReturn RemoveProperty (const char* pKey,
- unsigned int type = 0,
- unsigned int index = 0);
-
- // ------------------------------------------------------------------------------
- /** @brief Removes all properties from the material.
- *
- * The data array remains allocated so adding new properties is quite fast. */
- void Clear();
-
- // ------------------------------------------------------------------------------
- /** Copy the property list of a material
- * @param pcDest Destination material
- * @param pcSrc Source material
- */
- static void CopyPropertyList(aiMaterial* pcDest,
- const aiMaterial* pcSrc);
+ * NULL is allowed as value.
+ * @param uvindex Receives the UV index of the texture.
+ * NULL is a valid value.
+ * @param blend Receives the blend factor for the texture
+ * NULL is a valid value.
+ * @param op Receives the texture operation to be performed between
+ * this texture and the previous texture. NULL is allowed as value.
+ * @param mapmode Receives the mapping modes to be used for the texture.
+ * The parameter may be NULL but if it is a valid pointer it MUST
+ * point to an array of 3 aiTextureMapMode's (one for each
+ * axis: UVW order (=XYZ)).
+ */
+ // -------------------------------------------------------------------
+ aiReturn GetTexture(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) const;
+
+
+ // Setters
+
+
+ // ------------------------------------------------------------------------------
+ /** @brief Add a property with a given key and type info to the material
+ * structure
+ *
+ * @param pInput Pointer to input data
+ * @param pSizeInBytes Size of input data
+ * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro
+ * @param pType Type information hint */
+ aiReturn AddBinaryProperty (const void* pInput,
+ unsigned int pSizeInBytes,
+ const char* pKey,
+ unsigned int type ,
+ unsigned int index ,
+ aiPropertyTypeInfo pType);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Add a string property with a given key and type info to the
+ * material structure
+ *
+ * @param pInput Input string
+ * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro */
+ aiReturn AddProperty (const aiString* pInput,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Add a property with a given key to the material structure
+ * @param pInput Pointer to the input data
+ * @param pNumValues Number of values in the array
+ * @param pKey Key/Usage of the property (AI_MATKEY_XXX)
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro */
+ template<class TYPE>
+ aiReturn AddProperty (const TYPE* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiVector3D* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiColor3D* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiColor4D* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const int* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const float* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ aiReturn AddProperty (const aiUVTransform* pInput,
+ unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Remove a given key from the list.
+ *
+ * The function fails if the key isn't found
+ * @param pKey Key to be deleted
+ * @param type Set by the AI_MATKEY_XXX macro
+ * @param index Set by the AI_MATKEY_XXX macro */
+ aiReturn RemoveProperty (const char* pKey,
+ unsigned int type = 0,
+ unsigned int index = 0);
+
+ // ------------------------------------------------------------------------------
+ /** @brief Removes all properties from the material.
+ *
+ * The data array remains allocated so adding new properties is quite fast. */
+ void Clear();
+
+ // ------------------------------------------------------------------------------
+ /** Copy the property list of a material
+ * @param pcDest Destination material
+ * @param pcSrc Source material
+ */
+ static void CopyPropertyList(aiMaterial* pcDest,
+ const aiMaterial* pcSrc);
#endif
@@ -890,7 +857,7 @@ public:
/** Number of properties in the data base */
unsigned int mNumProperties;
- /** Storage allocated */
+ /** Storage allocated */
unsigned int mNumAllocated;
};
@@ -922,16 +889,16 @@ extern "C" {
// ---------------------------------------------------------------------------
// Pure key names for all texture-related properties
//! @cond MATS_DOC_FULL
-#define _AI_MATKEY_TEXTURE_BASE "$tex.file"
-#define _AI_MATKEY_UVWSRC_BASE "$tex.uvwsrc"
-#define _AI_MATKEY_TEXOP_BASE "$tex.op"
-#define _AI_MATKEY_MAPPING_BASE "$tex.mapping"
-#define _AI_MATKEY_TEXBLEND_BASE "$tex.blend"
-#define _AI_MATKEY_MAPPINGMODE_U_BASE "$tex.mapmodeu"
-#define _AI_MATKEY_MAPPINGMODE_V_BASE "$tex.mapmodev"
-#define _AI_MATKEY_TEXMAP_AXIS_BASE "$tex.mapaxis"
-#define _AI_MATKEY_UVTRANSFORM_BASE "$tex.uvtrafo"
-#define _AI_MATKEY_TEXFLAGS_BASE "$tex.flags"
+#define _AI_MATKEY_TEXTURE_BASE "$tex.file"
+#define _AI_MATKEY_UVWSRC_BASE "$tex.uvwsrc"
+#define _AI_MATKEY_TEXOP_BASE "$tex.op"
+#define _AI_MATKEY_MAPPING_BASE "$tex.mapping"
+#define _AI_MATKEY_TEXBLEND_BASE "$tex.blend"
+#define _AI_MATKEY_MAPPINGMODE_U_BASE "$tex.mapmodeu"
+#define _AI_MATKEY_MAPPINGMODE_V_BASE "$tex.mapmodev"
+#define _AI_MATKEY_TEXMAP_AXIS_BASE "$tex.mapaxis"
+#define _AI_MATKEY_UVTRANSFORM_BASE "$tex.uvtrafo"
+#define _AI_MATKEY_TEXFLAGS_BASE "$tex.flags"
//! @endcond
// ---------------------------------------------------------------------------
@@ -939,38 +906,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_TEXTURE_DIFFUSE(N) \
- AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_TEXTURE_DIFFUSE(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_TEXTURE_SPECULAR(N) \
- AI_MATKEY_TEXTURE(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_TEXTURE_SPECULAR(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_TEXTURE_AMBIENT(N) \
- AI_MATKEY_TEXTURE(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_TEXTURE_AMBIENT(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_TEXTURE_EMISSIVE(N) \
- AI_MATKEY_TEXTURE(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_TEXTURE_EMISSIVE(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_TEXTURE_NORMALS(N) \
- AI_MATKEY_TEXTURE(aiTextureType_NORMALS,N)
+#define AI_MATKEY_TEXTURE_NORMALS(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_NORMALS,N)
-#define AI_MATKEY_TEXTURE_HEIGHT(N) \
- AI_MATKEY_TEXTURE(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_TEXTURE_HEIGHT(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_TEXTURE_SHININESS(N) \
- AI_MATKEY_TEXTURE(aiTextureType_SHININESS,N)
+#define AI_MATKEY_TEXTURE_SHININESS(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_SHININESS,N)
-#define AI_MATKEY_TEXTURE_OPACITY(N) \
- AI_MATKEY_TEXTURE(aiTextureType_OPACITY,N)
+#define AI_MATKEY_TEXTURE_OPACITY(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_OPACITY,N)
-#define AI_MATKEY_TEXTURE_DISPLACEMENT(N) \
- AI_MATKEY_TEXTURE(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_TEXTURE_DISPLACEMENT(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_TEXTURE_LIGHTMAP(N) \
- AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_TEXTURE_LIGHTMAP(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_TEXTURE_REFLECTION(N) \
- AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_TEXTURE_REFLECTION(N) \
+ AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,N)
//! @endcond
@@ -979,38 +946,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_UVWSRC_DIFFUSE(N) \
- AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_UVWSRC_DIFFUSE(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_UVWSRC_SPECULAR(N) \
- AI_MATKEY_UVWSRC(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_UVWSRC_SPECULAR(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_UVWSRC_AMBIENT(N) \
- AI_MATKEY_UVWSRC(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_UVWSRC_AMBIENT(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_UVWSRC_EMISSIVE(N) \
- AI_MATKEY_UVWSRC(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_UVWSRC_EMISSIVE(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_UVWSRC_NORMALS(N) \
- AI_MATKEY_UVWSRC(aiTextureType_NORMALS,N)
+#define AI_MATKEY_UVWSRC_NORMALS(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_NORMALS,N)
-#define AI_MATKEY_UVWSRC_HEIGHT(N) \
- AI_MATKEY_UVWSRC(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_UVWSRC_HEIGHT(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_UVWSRC_SHININESS(N) \
- AI_MATKEY_UVWSRC(aiTextureType_SHININESS,N)
+#define AI_MATKEY_UVWSRC_SHININESS(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_SHININESS,N)
-#define AI_MATKEY_UVWSRC_OPACITY(N) \
- AI_MATKEY_UVWSRC(aiTextureType_OPACITY,N)
+#define AI_MATKEY_UVWSRC_OPACITY(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_OPACITY,N)
-#define AI_MATKEY_UVWSRC_DISPLACEMENT(N) \
- AI_MATKEY_UVWSRC(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_UVWSRC_DISPLACEMENT(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_UVWSRC_LIGHTMAP(N) \
- AI_MATKEY_UVWSRC(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_UVWSRC_LIGHTMAP(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_UVWSRC_REFLECTION(N) \
- AI_MATKEY_UVWSRC(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_UVWSRC_REFLECTION(N) \
+ AI_MATKEY_UVWSRC(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1018,38 +985,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_TEXOP_DIFFUSE(N) \
- AI_MATKEY_TEXOP(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_TEXOP_DIFFUSE(N) \
+ AI_MATKEY_TEXOP(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_TEXOP_SPECULAR(N) \
- AI_MATKEY_TEXOP(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_TEXOP_SPECULAR(N) \
+ AI_MATKEY_TEXOP(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_TEXOP_AMBIENT(N) \
- AI_MATKEY_TEXOP(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_TEXOP_AMBIENT(N) \
+ AI_MATKEY_TEXOP(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_TEXOP_EMISSIVE(N) \
- AI_MATKEY_TEXOP(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_TEXOP_EMISSIVE(N) \
+ AI_MATKEY_TEXOP(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_TEXOP_NORMALS(N) \
- AI_MATKEY_TEXOP(aiTextureType_NORMALS,N)
+#define AI_MATKEY_TEXOP_NORMALS(N) \
+ AI_MATKEY_TEXOP(aiTextureType_NORMALS,N)
-#define AI_MATKEY_TEXOP_HEIGHT(N) \
- AI_MATKEY_TEXOP(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_TEXOP_HEIGHT(N) \
+ AI_MATKEY_TEXOP(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_TEXOP_SHININESS(N) \
- AI_MATKEY_TEXOP(aiTextureType_SHININESS,N)
+#define AI_MATKEY_TEXOP_SHININESS(N) \
+ AI_MATKEY_TEXOP(aiTextureType_SHININESS,N)
-#define AI_MATKEY_TEXOP_OPACITY(N) \
- AI_MATKEY_TEXOP(aiTextureType_OPACITY,N)
+#define AI_MATKEY_TEXOP_OPACITY(N) \
+ AI_MATKEY_TEXOP(aiTextureType_OPACITY,N)
-#define AI_MATKEY_TEXOP_DISPLACEMENT(N) \
- AI_MATKEY_TEXOP(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_TEXOP_DISPLACEMENT(N) \
+ AI_MATKEY_TEXOP(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_TEXOP_LIGHTMAP(N) \
- AI_MATKEY_TEXOP(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_TEXOP_LIGHTMAP(N) \
+ AI_MATKEY_TEXOP(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_TEXOP_REFLECTION(N) \
- AI_MATKEY_TEXOP(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_TEXOP_REFLECTION(N) \
+ AI_MATKEY_TEXOP(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1057,38 +1024,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_MAPPING_DIFFUSE(N) \
- AI_MATKEY_MAPPING(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_MAPPING_DIFFUSE(N) \
+ AI_MATKEY_MAPPING(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_MAPPING_SPECULAR(N) \
- AI_MATKEY_MAPPING(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_MAPPING_SPECULAR(N) \
+ AI_MATKEY_MAPPING(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_MAPPING_AMBIENT(N) \
- AI_MATKEY_MAPPING(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_MAPPING_AMBIENT(N) \
+ AI_MATKEY_MAPPING(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_MAPPING_EMISSIVE(N) \
- AI_MATKEY_MAPPING(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_MAPPING_EMISSIVE(N) \
+ AI_MATKEY_MAPPING(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_MAPPING_NORMALS(N) \
- AI_MATKEY_MAPPING(aiTextureType_NORMALS,N)
+#define AI_MATKEY_MAPPING_NORMALS(N) \
+ AI_MATKEY_MAPPING(aiTextureType_NORMALS,N)
-#define AI_MATKEY_MAPPING_HEIGHT(N) \
- AI_MATKEY_MAPPING(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_MAPPING_HEIGHT(N) \
+ AI_MATKEY_MAPPING(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_MAPPING_SHININESS(N) \
- AI_MATKEY_MAPPING(aiTextureType_SHININESS,N)
+#define AI_MATKEY_MAPPING_SHININESS(N) \
+ AI_MATKEY_MAPPING(aiTextureType_SHININESS,N)
-#define AI_MATKEY_MAPPING_OPACITY(N) \
- AI_MATKEY_MAPPING(aiTextureType_OPACITY,N)
+#define AI_MATKEY_MAPPING_OPACITY(N) \
+ AI_MATKEY_MAPPING(aiTextureType_OPACITY,N)
-#define AI_MATKEY_MAPPING_DISPLACEMENT(N) \
- AI_MATKEY_MAPPING(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_MAPPING_DISPLACEMENT(N) \
+ AI_MATKEY_MAPPING(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_MAPPING_LIGHTMAP(N) \
- AI_MATKEY_MAPPING(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_MAPPING_LIGHTMAP(N) \
+ AI_MATKEY_MAPPING(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_MAPPING_REFLECTION(N) \
- AI_MATKEY_MAPPING(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_MAPPING_REFLECTION(N) \
+ AI_MATKEY_MAPPING(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1096,38 +1063,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_TEXBLEND_DIFFUSE(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_TEXBLEND_DIFFUSE(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_TEXBLEND_SPECULAR(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_TEXBLEND_SPECULAR(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_TEXBLEND_AMBIENT(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_TEXBLEND_AMBIENT(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_TEXBLEND_EMISSIVE(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_TEXBLEND_EMISSIVE(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_TEXBLEND_NORMALS(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_NORMALS,N)
+#define AI_MATKEY_TEXBLEND_NORMALS(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_NORMALS,N)
-#define AI_MATKEY_TEXBLEND_HEIGHT(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_TEXBLEND_HEIGHT(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_TEXBLEND_SHININESS(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_SHININESS,N)
+#define AI_MATKEY_TEXBLEND_SHININESS(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_SHININESS,N)
-#define AI_MATKEY_TEXBLEND_OPACITY(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_OPACITY,N)
+#define AI_MATKEY_TEXBLEND_OPACITY(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_OPACITY,N)
-#define AI_MATKEY_TEXBLEND_DISPLACEMENT(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_TEXBLEND_DISPLACEMENT(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_TEXBLEND_LIGHTMAP(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_TEXBLEND_LIGHTMAP(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_TEXBLEND_REFLECTION(N) \
- AI_MATKEY_TEXBLEND(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_TEXBLEND_REFLECTION(N) \
+ AI_MATKEY_TEXBLEND(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1135,38 +1102,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_MAPPINGMODE_U_SPECULAR(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_MAPPINGMODE_U_SPECULAR(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_MAPPINGMODE_U_AMBIENT(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_MAPPINGMODE_U_AMBIENT(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_MAPPINGMODE_U_NORMALS(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_NORMALS,N)
+#define AI_MATKEY_MAPPINGMODE_U_NORMALS(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_NORMALS,N)
-#define AI_MATKEY_MAPPINGMODE_U_HEIGHT(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_MAPPINGMODE_U_HEIGHT(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_MAPPINGMODE_U_SHININESS(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_SHININESS,N)
+#define AI_MATKEY_MAPPINGMODE_U_SHININESS(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_SHININESS,N)
-#define AI_MATKEY_MAPPINGMODE_U_OPACITY(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_OPACITY,N)
+#define AI_MATKEY_MAPPINGMODE_U_OPACITY(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_OPACITY,N)
-#define AI_MATKEY_MAPPINGMODE_U_DISPLACEMENT(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_MAPPINGMODE_U_DISPLACEMENT(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_MAPPINGMODE_U_REFLECTION(N) \
- AI_MATKEY_MAPPINGMODE_U(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_MAPPINGMODE_U_REFLECTION(N) \
+ AI_MATKEY_MAPPINGMODE_U(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1174,38 +1141,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_MAPPINGMODE_V_SPECULAR(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_MAPPINGMODE_V_SPECULAR(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_MAPPINGMODE_V_AMBIENT(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_MAPPINGMODE_V_AMBIENT(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_MAPPINGMODE_V_NORMALS(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_NORMALS,N)
+#define AI_MATKEY_MAPPINGMODE_V_NORMALS(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_NORMALS,N)
-#define AI_MATKEY_MAPPINGMODE_V_HEIGHT(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_MAPPINGMODE_V_HEIGHT(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_MAPPINGMODE_V_SHININESS(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_SHININESS,N)
+#define AI_MATKEY_MAPPINGMODE_V_SHININESS(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_SHININESS,N)
-#define AI_MATKEY_MAPPINGMODE_V_OPACITY(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_OPACITY,N)
+#define AI_MATKEY_MAPPINGMODE_V_OPACITY(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_OPACITY,N)
-#define AI_MATKEY_MAPPINGMODE_V_DISPLACEMENT(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_MAPPINGMODE_V_DISPLACEMENT(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_MAPPINGMODE_V_REFLECTION(N) \
- AI_MATKEY_MAPPINGMODE_V(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_MAPPINGMODE_V_REFLECTION(N) \
+ AI_MATKEY_MAPPINGMODE_V(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1213,38 +1180,38 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_TEXMAP_AXIS_DIFFUSE(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_TEXMAP_AXIS_DIFFUSE(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_TEXMAP_AXIS_SPECULAR(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_TEXMAP_AXIS_SPECULAR(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_TEXMAP_AXIS_AMBIENT(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_TEXMAP_AXIS_AMBIENT(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_TEXMAP_AXIS_EMISSIVE(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_TEXMAP_AXIS_EMISSIVE(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_TEXMAP_AXIS_NORMALS(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_NORMALS,N)
+#define AI_MATKEY_TEXMAP_AXIS_NORMALS(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_NORMALS,N)
-#define AI_MATKEY_TEXMAP_AXIS_HEIGHT(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_TEXMAP_AXIS_HEIGHT(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_TEXMAP_AXIS_SHININESS(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_SHININESS,N)
+#define AI_MATKEY_TEXMAP_AXIS_SHININESS(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_SHININESS,N)
-#define AI_MATKEY_TEXMAP_AXIS_OPACITY(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_OPACITY,N)
+#define AI_MATKEY_TEXMAP_AXIS_OPACITY(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_OPACITY,N)
-#define AI_MATKEY_TEXMAP_AXIS_DISPLACEMENT(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_TEXMAP_AXIS_DISPLACEMENT(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_TEXMAP_AXIS_LIGHTMAP(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_TEXMAP_AXIS_LIGHTMAP(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_TEXMAP_AXIS_REFLECTION(N) \
- AI_MATKEY_TEXMAP_AXIS(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_TEXMAP_AXIS_REFLECTION(N) \
+ AI_MATKEY_TEXMAP_AXIS(aiTextureType_REFLECTION,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1252,41 +1219,41 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_UVTRANSFORM_DIFFUSE(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_UVTRANSFORM_DIFFUSE(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_UVTRANSFORM_SPECULAR(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_UVTRANSFORM_SPECULAR(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_UVTRANSFORM_AMBIENT(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_UVTRANSFORM_AMBIENT(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_UVTRANSFORM_EMISSIVE(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_UVTRANSFORM_EMISSIVE(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_UVTRANSFORM_NORMALS(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_NORMALS,N)
+#define AI_MATKEY_UVTRANSFORM_NORMALS(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_NORMALS,N)
-#define AI_MATKEY_UVTRANSFORM_HEIGHT(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_UVTRANSFORM_HEIGHT(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_UVTRANSFORM_SHININESS(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_SHININESS,N)
+#define AI_MATKEY_UVTRANSFORM_SHININESS(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_SHININESS,N)
-#define AI_MATKEY_UVTRANSFORM_OPACITY(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_OPACITY,N)
+#define AI_MATKEY_UVTRANSFORM_OPACITY(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_OPACITY,N)
-#define AI_MATKEY_UVTRANSFORM_DISPLACEMENT(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_UVTRANSFORM_DISPLACEMENT(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_UVTRANSFORM_LIGHTMAP(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_UVTRANSFORM_LIGHTMAP(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_UVTRANSFORM_REFLECTION(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_UVTRANSFORM_REFLECTION(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_REFLECTION,N)
-#define AI_MATKEY_UVTRANSFORM_UNKNOWN(N) \
- AI_MATKEY_UVTRANSFORM(aiTextureType_UNKNOWN,N)
+#define AI_MATKEY_UVTRANSFORM_UNKNOWN(N) \
+ AI_MATKEY_UVTRANSFORM(aiTextureType_UNKNOWN,N)
//! @endcond
// ---------------------------------------------------------------------------
@@ -1294,42 +1261,44 @@ extern "C" {
// For backward compatibility and simplicity
//! @cond MATS_DOC_FULL
-#define AI_MATKEY_TEXFLAGS_DIFFUSE(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_DIFFUSE,N)
+#define AI_MATKEY_TEXFLAGS_DIFFUSE(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_DIFFUSE,N)
-#define AI_MATKEY_TEXFLAGS_SPECULAR(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_SPECULAR,N)
+#define AI_MATKEY_TEXFLAGS_SPECULAR(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_SPECULAR,N)
-#define AI_MATKEY_TEXFLAGS_AMBIENT(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_AMBIENT,N)
+#define AI_MATKEY_TEXFLAGS_AMBIENT(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_AMBIENT,N)
-#define AI_MATKEY_TEXFLAGS_EMISSIVE(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_EMISSIVE,N)
+#define AI_MATKEY_TEXFLAGS_EMISSIVE(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_EMISSIVE,N)
-#define AI_MATKEY_TEXFLAGS_NORMALS(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_NORMALS,N)
+#define AI_MATKEY_TEXFLAGS_NORMALS(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_NORMALS,N)
-#define AI_MATKEY_TEXFLAGS_HEIGHT(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_HEIGHT,N)
+#define AI_MATKEY_TEXFLAGS_HEIGHT(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_HEIGHT,N)
-#define AI_MATKEY_TEXFLAGS_SHININESS(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_SHININESS,N)
+#define AI_MATKEY_TEXFLAGS_SHININESS(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_SHININESS,N)
-#define AI_MATKEY_TEXFLAGS_OPACITY(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_OPACITY,N)
+#define AI_MATKEY_TEXFLAGS_OPACITY(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_OPACITY,N)
-#define AI_MATKEY_TEXFLAGS_DISPLACEMENT(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_DISPLACEMENT,N)
+#define AI_MATKEY_TEXFLAGS_DISPLACEMENT(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_DISPLACEMENT,N)
-#define AI_MATKEY_TEXFLAGS_LIGHTMAP(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_LIGHTMAP,N)
+#define AI_MATKEY_TEXFLAGS_LIGHTMAP(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_LIGHTMAP,N)
-#define AI_MATKEY_TEXFLAGS_REFLECTION(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_REFLECTION,N)
+#define AI_MATKEY_TEXFLAGS_REFLECTION(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_REFLECTION,N)
-#define AI_MATKEY_TEXFLAGS_UNKNOWN(N) \
- AI_MATKEY_TEXFLAGS(aiTextureType_UNKNOWN,N)
+#define AI_MATKEY_TEXFLAGS_UNKNOWN(N) \
+ AI_MATKEY_TEXFLAGS(aiTextureType_UNKNOWN,N)
+//! @endcond
+//!
// ---------------------------------------------------------------------------
/** @brief Retrieve a material property with a specific key from the material
*
@@ -1342,14 +1311,14 @@ extern "C" {
* structure or NULL if the key has not been found. */
// ---------------------------------------------------------------------------
ASSIMP_API C_ENUM aiReturn aiGetMaterialProperty(
- const C_STRUCT aiMaterial* pMat,
+ const C_STRUCT aiMaterial* pMat,
const char* pKey,
- unsigned int type,
+ unsigned int type,
unsigned int index,
const C_STRUCT aiMaterialProperty** pPropOut);
// ---------------------------------------------------------------------------
-/** @brief Retrieve an array of float values with a specific key
+/** @brief Retrieve an array of float values with a specific key
* from the material
*
* Pass one of the AI_MATKEY_XXX constants for the last three parameters (the
@@ -1360,24 +1329,24 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialProperty(
* if (AI_SUCCESS != aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,0),
* (float*)&trafo, &max) || sizeof(aiUVTransform) != max)
* {
- * // error handling
+ * // error handling
* }
* @endcode
*
* @param pMat Pointer to the input material. May not be NULL
* @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
- * @param pOut Pointer to a buffer to receive the result.
+ * @param pOut Pointer to a buffer to receive the result.
* @param pMax Specifies the size of the given buffer, in float's.
- * Receives the number of values (not bytes!) read.
+ * Receives the number of values (not bytes!) read.
* @param type (see the code sample above)
* @param index (see the code sample above)
* @return Specifies whether the key has been found. If not, the output
* arrays remains unmodified and pMax is set to 0.*/
// ---------------------------------------------------------------------------
ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray(
- const C_STRUCT aiMaterial* pMat,
+ const C_STRUCT aiMaterial* pMat,
const char* pKey,
- unsigned int type,
+ unsigned int type,
unsigned int index,
float* pOut,
unsigned int* pMax);
@@ -1404,16 +1373,16 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray(
* @return Specifies whether the key has been found. If not, the output
* float remains unmodified.*/
// ---------------------------------------------------------------------------
-inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat,
- const char* pKey,
- unsigned int type,
- unsigned int index,
- float* pOut)
+inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ float* pOut)
{
- return aiGetMaterialFloatArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
+ return aiGetMaterialFloatArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
}
-#else
+#else
// Use our friend, the C preprocessor
#define aiGetMaterialFloat (pMat, type, index, pKey, pOut) \
@@ -1423,16 +1392,16 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat,
// ---------------------------------------------------------------------------
-/** @brief Retrieve an array of integer values with a specific key
+/** @brief Retrieve an array of integer values with a specific key
* from a material
*
* See the sample for aiGetMaterialFloatArray for more information.*/
-ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat,
- const char* pKey,
- unsigned int type,
- unsigned int index,
- int* pOut,
- unsigned int* pMax);
+ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ int* pOut,
+ unsigned int* pMax);
#ifdef __cplusplus
@@ -1442,16 +1411,16 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial*
*
* See the sample for aiGetMaterialFloat for more information.*/
// ---------------------------------------------------------------------------
-inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
- const char* pKey,
- unsigned int type,
+inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
unsigned int index,
- int* pOut)
+ int* pOut)
{
- return aiGetMaterialIntegerArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
+ return aiGetMaterialIntegerArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
}
-#else
+#else
// use our friend, the C preprocessor
#define aiGetMaterialInteger (pMat, type, index, pKey, pOut) \
@@ -1466,11 +1435,11 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
*
* See the sample for aiGetMaterialFloat for more information*/
// ---------------------------------------------------------------------------
-ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
+ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
const char* pKey,
- unsigned int type,
+ unsigned int type,
unsigned int index,
- C_STRUCT aiColor4D* pOut);
+ C_STRUCT aiColor4D* pOut);
// ---------------------------------------------------------------------------
@@ -1478,11 +1447,11 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
*
* See the sample for aiGetMaterialFloat for more information*/
// ---------------------------------------------------------------------------
-ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* pMat,
+ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* pMat,
const char* pKey,
- unsigned int type,
+ unsigned int type,
unsigned int index,
- C_STRUCT aiUVTransform* pOut);
+ C_STRUCT aiUVTransform* pOut);
// ---------------------------------------------------------------------------
@@ -1490,9 +1459,9 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* p
*
* See the sample for aiGetMaterialFloat for more information.*/
// ---------------------------------------------------------------------------
-ASSIMP_API C_ENUM aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
+ASSIMP_API C_ENUM aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
const char* pKey,
- unsigned int type,
+ unsigned int type,
unsigned int index,
C_STRUCT aiString* pOut);
@@ -1503,8 +1472,8 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
* @return Number of textures for this type.
* @note A texture can be easily queried using #aiGetMaterialTexture() */
// ---------------------------------------------------------------------------
-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);
// ---------------------------------------------------------------------------
/** @brief Helper function to get all values pertaining to a particular
@@ -1516,9 +1485,9 @@ ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMa
*
* @param[in] mat Pointer to the input material. May not be NULL
* @param[in] type Specifies the texture stack to read from (e.g. diffuse,
- * specular, height map ...).
- * @param[in] index Index of the texture. The function fails if the
- * requested index is not available for this texture type.
+ * specular, height map ...).
+ * @param[in] index Index of the texture. The function fails if the
+ * requested index is not available for this texture type.
* #aiGetMaterialTextureCount() can be used to determine the number of
* textures in a particular texture stack.
* @param[out] path Receives the output path
@@ -1531,36 +1500,37 @@ ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMa
* @param[out] blend Receives the blend factor for the texture
* Pass NULL if you're not interested in this information.
* @param[out] op Receives the texture blend operation to be perform between
- * this texture and the previous texture.
+ * this texture and the previous texture.
* Pass NULL if you're not interested in this information.
* @param[out] mapmode Receives the mapping modes to be used for the texture.
* Pass NULL if you're not interested in this information. Otherwise,
* pass a pointer to an array of two aiTextureMapMode's (one for each
* axis, UV order).
+ * @param[out] flags Receives the the texture flags.
* @return AI_SUCCESS on success, otherwise something else. Have fun.*/
// ---------------------------------------------------------------------------
#ifdef __cplusplus
ASSIMP_API aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
- aiTextureType type,
+ aiTextureType type,
unsigned int index,
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);
#else
C_ENUM aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
C_ENUM aiTextureType type,
unsigned int index,
C_STRUCT aiString* path,
- C_ENUM aiTextureMapping* mapping /*= NULL*/,
- unsigned int* uvindex /*= NULL*/,
- float* blend /*= NULL*/,
- C_ENUM aiTextureOp* op /*= NULL*/,
- C_ENUM aiTextureMapMode* mapmode /*= NULL*/,
- unsigned int* flags /*= NULL*/);
+ C_ENUM aiTextureMapping* mapping /*= NULL*/,
+ unsigned int* uvindex /*= NULL*/,
+ float* blend /*= NULL*/,
+ C_ENUM aiTextureOp* op /*= NULL*/,
+ C_ENUM aiTextureMapMode* mapmode /*= NULL*/,
+ unsigned int* flags /*= NULL*/);
#endif // !#ifdef __cplusplus
#ifdef __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/material.inl b/src/3rdparty/assimp/include/assimp/material.inl
index 64d5b749b..994e608b4 100644
--- a/src/3rdparty/assimp/include/assimp/material.inl
+++ b/src/3rdparty/assimp/include/assimp/material.inl
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file aiMaterial.inl
+/** @file material.inl
* @brief Defines the C++ getters for the material system
*/
@@ -52,212 +52,212 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
inline aiReturn aiMaterial::GetTexture( 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*/) const
+ aiTextureMapping* mapping /*= NULL*/,
+ unsigned int* uvindex /*= NULL*/,
+ float* blend /*= NULL*/,
+ aiTextureOp* op /*= NULL*/,
+ aiTextureMapMode* mapmode /*= NULL*/) const
{
- return ::aiGetMaterialTexture(this,type,index,path,mapping,uvindex,blend,op,mapmode);
+ return ::aiGetMaterialTexture(this,type,index,path,mapping,uvindex,blend,op,mapmode);
}
// ---------------------------------------------------------------------------
inline unsigned int aiMaterial::GetTextureCount(aiTextureType type) const
{
- return ::aiGetMaterialTextureCount(this,type);
+ return ::aiGetMaterialTextureCount(this,type);
}
// ---------------------------------------------------------------------------
template <typename Type>
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx, Type* pOut,
- unsigned int* pMax) const
+ unsigned int idx, Type* pOut,
+ unsigned int* pMax) const
{
- unsigned int iNum = pMax ? *pMax : 1;
-
- const aiMaterialProperty* prop;
- const aiReturn ret = ::aiGetMaterialProperty(this,pKey,type,idx,
- (const aiMaterialProperty**)&prop);
- if ( AI_SUCCESS == ret ) {
-
- if (prop->mDataLength < sizeof(Type)*iNum) {
- return AI_FAILURE;
- }
-
- if (prop->mType != aiPTI_Buffer) {
- return AI_FAILURE;
- }
-
- iNum = std::min((size_t)iNum,prop->mDataLength / sizeof(Type));
- ::memcpy(pOut,prop->mData,iNum * sizeof(Type));
- if (pMax) {
- *pMax = iNum;
- }
- }
- return ret;
+ unsigned int iNum = pMax ? *pMax : 1;
+
+ const aiMaterialProperty* prop;
+ const aiReturn ret = ::aiGetMaterialProperty(this,pKey,type,idx,
+ (const aiMaterialProperty**)&prop);
+ if ( AI_SUCCESS == ret ) {
+
+ if (prop->mDataLength < sizeof(Type)*iNum) {
+ return AI_FAILURE;
+ }
+
+ if (prop->mType != aiPTI_Buffer) {
+ return AI_FAILURE;
+ }
+
+ iNum = std::min((size_t)iNum,prop->mDataLength / sizeof(Type));
+ ::memcpy(pOut,prop->mData,iNum * sizeof(Type));
+ if (pMax) {
+ *pMax = iNum;
+ }
+ }
+ return ret;
}
// ---------------------------------------------------------------------------
template <typename Type>
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,Type& pOut) const
+ unsigned int idx,Type& pOut) const
{
- const aiMaterialProperty* prop;
- const aiReturn ret = ::aiGetMaterialProperty(this,pKey,type,idx,
- (const aiMaterialProperty**)&prop);
- if ( AI_SUCCESS == ret ) {
-
- if (prop->mDataLength < sizeof(Type)) {
- return AI_FAILURE;
- }
-
- if (prop->mType != aiPTI_Buffer) {
- return AI_FAILURE;
- }
-
- ::memcpy(&pOut,prop->mData,sizeof(Type));
- }
- return ret;
+ const aiMaterialProperty* prop;
+ const aiReturn ret = ::aiGetMaterialProperty(this,pKey,type,idx,
+ (const aiMaterialProperty**)&prop);
+ if ( AI_SUCCESS == ret ) {
+
+ if (prop->mDataLength < sizeof(Type)) {
+ return AI_FAILURE;
+ }
+
+ if (prop->mType != aiPTI_Buffer) {
+ return AI_FAILURE;
+ }
+
+ ::memcpy(&pOut,prop->mData,sizeof(Type));
+ }
+ return ret;
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,float* pOut,
- unsigned int* pMax) const
+ unsigned int idx,float* pOut,
+ unsigned int* pMax) const
{
- return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
+ return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,int* pOut,
- unsigned int* pMax) const
+ unsigned int idx,int* pOut,
+ unsigned int* pMax) const
{
- return ::aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
+ return ::aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,float& pOut) const
+ unsigned int idx,float& pOut) const
{
- return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
+ return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,int& pOut) const
+ unsigned int idx,int& pOut) const
{
- return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
+ return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,aiColor4D& pOut) const
+ unsigned int idx,aiColor4D& pOut) const
{
- return aiGetMaterialColor(this,pKey,type,idx,&pOut);
+ return aiGetMaterialColor(this,pKey,type,idx,&pOut);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,aiColor3D& pOut) const
+ unsigned int idx,aiColor3D& pOut) const
{
- aiColor4D c;
- const aiReturn ret = aiGetMaterialColor(this,pKey,type,idx,&c);
- pOut = aiColor3D(c.r,c.g,c.b);
- return ret;
+ aiColor4D c;
+ const aiReturn ret = aiGetMaterialColor(this,pKey,type,idx,&c);
+ pOut = aiColor3D(c.r,c.g,c.b);
+ return ret;
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,aiString& pOut) const
+ unsigned int idx,aiString& pOut) const
{
- return aiGetMaterialString(this,pKey,type,idx,&pOut);
+ return aiGetMaterialString(this,pKey,type,idx,&pOut);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,aiUVTransform& pOut) const
+ unsigned int idx,aiUVTransform& pOut) const
{
- return aiGetMaterialUVTransform(this,pKey,type,idx,&pOut);
+ return aiGetMaterialUVTransform(this,pKey,type,idx,&pOut);
}
// ---------------------------------------------------------------------------
template<class TYPE>
aiReturn aiMaterial::AddProperty (const TYPE* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(TYPE),
- pKey,type,index,aiPTI_Buffer);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(TYPE),
+ pKey,type,index,aiPTI_Buffer);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const float* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(float),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(float),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiUVTransform),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiUVTransform),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiColor4D),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor4D),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiColor3D),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor3D),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiVector3D),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiVector3D),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const int* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(int),
- pKey,type,index,aiPTI_Integer);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(int),
+ pKey,type,index,aiPTI_Integer);
}
@@ -270,79 +270,79 @@ inline aiReturn aiMaterial::AddProperty(const int* pInput,
// ---------------------------------------------------------------------------
template<>
inline aiReturn aiMaterial::AddProperty<float>(const float* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(float),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(float),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
template<>
inline aiReturn aiMaterial::AddProperty<aiUVTransform>(const aiUVTransform* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiUVTransform),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiUVTransform),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
template<>
inline aiReturn aiMaterial::AddProperty<aiColor4D>(const aiColor4D* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiColor4D),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor4D),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
template<>
inline aiReturn aiMaterial::AddProperty<aiColor3D>(const aiColor3D* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiColor3D),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiColor3D),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
template<>
inline aiReturn aiMaterial::AddProperty<aiVector3D>(const aiVector3D* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(aiVector3D),
- pKey,type,index,aiPTI_Float);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(aiVector3D),
+ pKey,type,index,aiPTI_Float);
}
// ---------------------------------------------------------------------------
template<>
inline aiReturn aiMaterial::AddProperty<int>(const int* pInput,
- const unsigned int pNumValues,
- const char* pKey,
- unsigned int type,
- unsigned int index)
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
{
- return AddBinaryProperty((const void*)pInput,
- pNumValues * sizeof(int),
- pKey,type,index,aiPTI_Integer);
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(int),
+ pKey,type,index,aiPTI_Integer);
}
//! @endcond
diff --git a/src/3rdparty/assimp/include/assimp/matrix3x3.h b/src/3rdparty/assimp/include/assimp/matrix3x3.h
index 0cff32157..725b1c34c 100644
--- a/src/3rdparty/assimp/include/assimp/matrix3x3.h
+++ b/src/3rdparty/assimp/include/assimp/matrix3x3.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.
---------------------------------------------------------------------------
*/
@@ -55,7 +55,7 @@ template <typename T> class aiVector2t;
// ---------------------------------------------------------------------------
/** @brief Represents a row-major 3x3 matrix
*
- * There's much confusion about matrix layouts (column vs. row order).
+ * There's much confusion about matrix layouts (column vs. row order).
* This is *always* a row-major matrix. Not even with the
* #aiProcess_ConvertToLeftHanded flag, which absolutely does not affect
* matrix order - it just affects the handedness of the coordinate system
@@ -66,105 +66,103 @@ class aiMatrix3x3t
{
public:
- aiMatrix3x3t () :
- a1(static_cast<TReal>(1.0f)), a2(), a3(),
- b1(), b2(static_cast<TReal>(1.0f)), b3(),
- c1(), c2(), c3(static_cast<TReal>(1.0f)) {}
+ aiMatrix3x3t () :
+ a1(static_cast<TReal>(1.0f)), a2(), a3(),
+ b1(), b2(static_cast<TReal>(1.0f)), b3(),
+ c1(), c2(), c3(static_cast<TReal>(1.0f)) {}
- aiMatrix3x3t ( TReal _a1, TReal _a2, TReal _a3,
- TReal _b1, TReal _b2, TReal _b3,
- TReal _c1, TReal _c2, TReal _c3) :
- a1(_a1), a2(_a2), a3(_a3),
- b1(_b1), b2(_b2), b3(_b3),
- c1(_c1), c2(_c2), c3(_c3)
- {}
+ aiMatrix3x3t ( TReal _a1, TReal _a2, TReal _a3,
+ TReal _b1, TReal _b2, TReal _b3,
+ TReal _c1, TReal _c2, TReal _c3) :
+ a1(_a1), a2(_a2), a3(_a3),
+ b1(_b1), b2(_b2), b3(_b3),
+ c1(_c1), c2(_c2), c3(_c3)
+ {}
public:
- // matrix multiplication.
- aiMatrix3x3t& operator *= (const aiMatrix3x3t& m);
- aiMatrix3x3t operator * (const aiMatrix3x3t& m) const;
+ // matrix multiplication.
+ aiMatrix3x3t& operator *= (const aiMatrix3x3t& m);
+ aiMatrix3x3t operator * (const aiMatrix3x3t& m) const;
- // array access operators
- TReal* operator[] (unsigned int p_iIndex);
- const TReal* operator[] (unsigned int p_iIndex) const;
+ // array access operators
+ TReal* operator[] (unsigned int p_iIndex);
+ const TReal* operator[] (unsigned int p_iIndex) const;
- // comparison operators
- bool operator== (const aiMatrix4x4t<TReal>& m) const;
- bool operator!= (const aiMatrix4x4t<TReal>& m) const;
+ // comparison operators
+ bool operator== (const aiMatrix4x4t<TReal>& m) const;
+ bool operator!= (const aiMatrix4x4t<TReal>& m) const;
- bool Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon = 1e-6) const;
+ bool Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon = 1e-6) const;
- template <typename TOther>
- operator aiMatrix3x3t<TOther> () const;
+ template <typename TOther>
+ operator aiMatrix3x3t<TOther> () const;
public:
- // -------------------------------------------------------------------
- /** @brief Construction from a 4x4 matrix. The remaining parts
- * of the matrix are ignored.
- */
- explicit aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix);
-
- // -------------------------------------------------------------------
- /** @brief Transpose the matrix
- */
- aiMatrix3x3t& Transpose();
-
- // -------------------------------------------------------------------
- /** @brief Invert the matrix.
- * If the matrix is not invertible all elements are set to qnan.
- * Beware, use (f != f) to check whether a TReal f is qnan.
- */
- aiMatrix3x3t& Inverse();
- TReal Determinant() const;
+ // -------------------------------------------------------------------
+ /** @brief Construction from a 4x4 matrix. The remaining parts
+ * of the matrix are ignored.
+ */
+ explicit aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix);
+
+ // -------------------------------------------------------------------
+ /** @brief Transpose the matrix
+ */
+ aiMatrix3x3t& Transpose();
+
+ // -------------------------------------------------------------------
+ /** @brief Invert the matrix.
+ * If the matrix is not invertible all elements are set to qnan.
+ * Beware, use (f != f) to check whether a TReal f is qnan.
+ */
+ aiMatrix3x3t& Inverse();
+ TReal Determinant() const;
public:
- // -------------------------------------------------------------------
- /** @brief Returns a rotation matrix for a rotation around z
- * @param a Rotation angle, in radians
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix3x3t& RotationZ(TReal a, aiMatrix3x3t& out);
-
- // -------------------------------------------------------------------
- /** @brief Returns a rotation matrix for a rotation around
- * an arbitrary axis.
- *
- * @param a Rotation angle, in radians
- * @param axis Axis to rotate around
- * @param out To be filled
- */
- static aiMatrix3x3t& Rotation( TReal a,
- const aiVector3t<TReal>& axis, aiMatrix3x3t& out);
-
- // -------------------------------------------------------------------
- /** @brief Returns a translation matrix
- * @param v Translation vector
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix3x3t& Translation( const aiVector2t<TReal>& v, aiMatrix3x3t& out);
-
- // -------------------------------------------------------------------
- /** @brief A function for creating a rotation matrix that rotates a
- * vector called "from" into another vector called "to".
- * Input : from[3], to[3] which both must be *normalized* non-zero vectors
- * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
- * Authors: Tomas Möller, John Hughes
- * "Efficiently Building a Matrix to Rotate One Vector to Another"
- * Journal of Graphics Tools, 4(4):1-4, 1999
- */
- static aiMatrix3x3t& FromToMatrix(const aiVector3t<TReal>& from,
- const aiVector3t<TReal>& to, aiMatrix3x3t& out);
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around z
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix3x3t& RotationZ(TReal a, aiMatrix3x3t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around
+ * an arbitrary axis.
+ *
+ * @param a Rotation angle, in radians
+ * @param axis Axis to rotate around
+ * @param out To be filled
+ */
+ static aiMatrix3x3t& Rotation( TReal a,
+ const aiVector3t<TReal>& axis, aiMatrix3x3t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a translation matrix
+ * @param v Translation vector
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix3x3t& Translation( const aiVector2t<TReal>& v, aiMatrix3x3t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief A function for creating a rotation matrix that rotates a
+ * vector called "from" into another vector called "to".
+ * Input : from[3], to[3] which both must be *normalized* non-zero vectors
+ * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
+ * Authors: Tomas M�ller, John Hughes
+ * "Efficiently Building a Matrix to Rotate One Vector to Another"
+ * Journal of Graphics Tools, 4(4):1-4, 1999
+ */
+ static aiMatrix3x3t& FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix3x3t& out);
public:
-
-
- TReal a1, a2, a3;
- TReal b1, b2, b3;
- TReal c1, c2, c3;
+ TReal a1, a2, a3;
+ TReal b1, b2, b3;
+ TReal c1, c2, c3;
} PACK_STRUCT;
typedef aiMatrix3x3t<float> aiMatrix3x3;
@@ -172,13 +170,12 @@ typedef aiMatrix3x3t<float> aiMatrix3x3;
#else
struct aiMatrix3x3 {
-
- float a1, a2, a3;
- float b1, b2, b3;
- float c1, c2, c3;
+ float a1, a2, a3;
+ float b1, b2, b3;
+ float c1, c2, c3;
} PACK_STRUCT;
-#endif
+#endif // __cplusplus
#include "./Compiler/poppack1.h"
diff --git a/src/3rdparty/assimp/include/assimp/matrix3x3.inl b/src/3rdparty/assimp/include/assimp/matrix3x3.inl
index dcced7bab..9ace3f97b 100644
--- a/src/3rdparty/assimp/include/assimp/matrix3x3.inl
+++ b/src/3rdparty/assimp/include/assimp/matrix3x3.inl
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file aiMatrix3x3.inl
+/** @file matrix3x3.inl
* @brief Inline implementation of the 3x3 matrix operators
*/
#ifndef AI_MATRIX3x3_INL_INC
@@ -58,25 +58,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template <typename TReal>
inline aiMatrix3x3t<TReal>::aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix)
{
- a1 = pMatrix.a1; a2 = pMatrix.a2; a3 = pMatrix.a3;
- b1 = pMatrix.b1; b2 = pMatrix.b2; b3 = pMatrix.b3;
- c1 = pMatrix.c1; c2 = pMatrix.c2; c3 = pMatrix.c3;
+ a1 = pMatrix.a1; a2 = pMatrix.a2; a3 = pMatrix.a3;
+ b1 = pMatrix.b1; b2 = pMatrix.b2; b3 = pMatrix.b3;
+ c1 = pMatrix.c1; c2 = pMatrix.c2; c3 = pMatrix.c3;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& m)
{
- *this = aiMatrix3x3t<TReal>(m.a1 * a1 + m.b1 * a2 + m.c1 * a3,
- m.a2 * a1 + m.b2 * a2 + m.c2 * a3,
- m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
- m.a1 * b1 + m.b1 * b2 + m.c1 * b3,
- m.a2 * b1 + m.b2 * b2 + m.c2 * b3,
- m.a3 * b1 + m.b3 * b2 + m.c3 * b3,
- m.a1 * c1 + m.b1 * c2 + m.c1 * c3,
- m.a2 * c1 + m.b2 * c2 + m.c2 * c3,
- m.a3 * c1 + m.b3 * c2 + m.c3 * c3);
- return *this;
+ *this = aiMatrix3x3t<TReal>(m.a1 * a1 + m.b1 * a2 + m.c1 * a3,
+ m.a2 * a1 + m.b2 * a2 + m.c2 * a3,
+ m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
+ m.a1 * b1 + m.b1 * b2 + m.c1 * b3,
+ m.a2 * b1 + m.b2 * b2 + m.c2 * b3,
+ m.a3 * b1 + m.b3 * b2 + m.c3 * b3,
+ m.a1 * c1 + m.b1 * c2 + m.c1 * c3,
+ m.a2 * c1 + m.b2 * c2 + m.c2 * c3,
+ m.a3 * c1 + m.b3 * c2 + m.c3 * c3);
+ return *this;
}
// ------------------------------------------------------------------------------------------------
@@ -84,116 +84,116 @@ template <typename TReal>
template <typename TOther>
aiMatrix3x3t<TReal>::operator aiMatrix3x3t<TOther> () const
{
- return aiMatrix3x3t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),
- static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),
- static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3));
+ return aiMatrix3x3t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),
+ static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),
+ static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3));
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix3x3t<TReal> aiMatrix3x3t<TReal>::operator* (const aiMatrix3x3t<TReal>& m) const
{
- aiMatrix3x3t<TReal> temp( *this);
- temp *= m;
- return temp;
+ aiMatrix3x3t<TReal> temp( *this);
+ temp *= m;
+ return temp;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex)
{
- return &this->a1 + p_iIndex * 3;
+ return &this->a1 + p_iIndex * 3;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const
{
- return &this->a1 + p_iIndex * 3;
+ return &this->a1 + p_iIndex * 3;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const
{
- return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
- b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
- c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
+ return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
+ b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
+ c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const
{
- return !(*this == m);
+ return !(*this == m);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline bool aiMatrix3x3t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon) const {
- return
- std::abs(a1 - m.a1) <= epsilon &&
- std::abs(a2 - m.a2) <= epsilon &&
- std::abs(a3 - m.a3) <= epsilon &&
- std::abs(b1 - m.b1) <= epsilon &&
- std::abs(b2 - m.b2) <= epsilon &&
- std::abs(b3 - m.b3) <= epsilon &&
- std::abs(c1 - m.c1) <= epsilon &&
- std::abs(c2 - m.c2) <= epsilon &&
- std::abs(c3 - m.c3) <= epsilon;
+ return
+ std::abs(a1 - m.a1) <= epsilon &&
+ std::abs(a2 - m.a2) <= epsilon &&
+ std::abs(a3 - m.a3) <= epsilon &&
+ std::abs(b1 - m.b1) <= epsilon &&
+ std::abs(b2 - m.b2) <= epsilon &&
+ std::abs(b3 - m.b3) <= epsilon &&
+ std::abs(c1 - m.c1) <= epsilon &&
+ std::abs(c2 - m.c2) <= epsilon &&
+ std::abs(c3 - m.c3) <= epsilon;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Transpose()
{
- // (TReal&) don't remove, GCC complains cause of packed fields
- std::swap( (TReal&)a2, (TReal&)b1);
- std::swap( (TReal&)a3, (TReal&)c1);
- std::swap( (TReal&)b3, (TReal&)c2);
- return *this;
+ // (TReal&) don't remove, GCC complains cause of packed fields
+ std::swap( (TReal&)a2, (TReal&)b1);
+ std::swap( (TReal&)a3, (TReal&)c1);
+ std::swap( (TReal&)b3, (TReal&)c2);
+ return *this;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline TReal aiMatrix3x3t<TReal>::Determinant() const
{
- return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1;
+ return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Inverse()
{
- // Compute the reciprocal determinant
- TReal det = Determinant();
- if(det == static_cast<TReal>(0.0))
- {
- // Matrix not invertible. Setting all elements to nan is not really
- // correct in a mathematical sense; but at least qnans are easy to
- // spot. XXX we might throw an exception instead, which would
- // be even much better to spot :/.
- const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
- *this = aiMatrix3x3t<TReal>( nan,nan,nan,nan,nan,nan,nan,nan,nan);
-
- return *this;
- }
-
- TReal invdet = static_cast<TReal>(1.0) / det;
-
- aiMatrix3x3t<TReal> res;
- res.a1 = invdet * (b2 * c3 - b3 * c2);
- res.a2 = -invdet * (a2 * c3 - a3 * c2);
- res.a3 = invdet * (a2 * b3 - a3 * b2);
- res.b1 = -invdet * (b1 * c3 - b3 * c1);
- res.b2 = invdet * (a1 * c3 - a3 * c1);
- res.b3 = -invdet * (a1 * b3 - a3 * b1);
- res.c1 = invdet * (b1 * c2 - b2 * c1);
- res.c2 = -invdet * (a1 * c2 - a2 * c1);
- res.c3 = invdet * (a1 * b2 - a2 * b1);
- *this = res;
-
- return *this;
+ // Compute the reciprocal determinant
+ TReal det = Determinant();
+ if(det == static_cast<TReal>(0.0))
+ {
+ // Matrix not invertible. Setting all elements to nan is not really
+ // correct in a mathematical sense; but at least qnans are easy to
+ // spot. XXX we might throw an exception instead, which would
+ // be even much better to spot :/.
+ const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
+ *this = aiMatrix3x3t<TReal>( nan,nan,nan,nan,nan,nan,nan,nan,nan);
+
+ return *this;
+ }
+
+ TReal invdet = static_cast<TReal>(1.0) / det;
+
+ aiMatrix3x3t<TReal> res;
+ res.a1 = invdet * (b2 * c3 - b3 * c2);
+ res.a2 = -invdet * (a2 * c3 - a3 * c2);
+ res.a3 = invdet * (a2 * b3 - a3 * b2);
+ res.b1 = -invdet * (b1 * c3 - b3 * c1);
+ res.b2 = invdet * (a1 * c3 - a3 * c1);
+ res.b3 = -invdet * (a1 * b3 - a3 * b1);
+ res.c1 = invdet * (b1 * c2 - b2 * c1);
+ res.c2 = -invdet * (a1 * c2 - a2 * c1);
+ res.c3 = invdet * (a1 * b2 - a2 * b1);
+ *this = res;
+
+ return *this;
}
// ------------------------------------------------------------------------------------------------
@@ -202,12 +202,12 @@ inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::RotationZ(TReal a, aiMatrix3x3t
{
out.a1 = out.b2 = std::cos(a);
out.b1 = std::sin(a);
- out.a2 = - out.b1;
+ out.a2 = - out.b1;
- out.a3 = out.b3 = out.c1 = out.c2 = 0.f;
- out.c3 = 1.f;
+ out.a3 = out.b3 = out.c1 = out.c2 = 0.f;
+ out.c3 = 1.f;
- return out;
+ return out;
}
// ------------------------------------------------------------------------------------------------
@@ -230,10 +230,10 @@ inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Rotation( TReal a, const aiVect
template <typename TReal>
inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Translation( const aiVector2t<TReal>& v, aiMatrix3x3t<TReal>& out)
{
- out = aiMatrix3x3t<TReal>();
- out.a3 = v.x;
- out.b3 = v.y;
- return out;
+ out = aiMatrix3x3t<TReal>();
+ out.a3 = v.x;
+ out.b3 = v.y;
+ return out;
}
// ----------------------------------------------------------------------------------------
@@ -241,90 +241,94 @@ inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Translation( const aiVector2t<T
* "from" into another vector called "to".
* Input : from[3], to[3] which both must be *normalized* non-zero vectors
* Output: mtx[3][3] -- a 3x3 matrix in colum-major form
- * Authors: Tomas Möller, John Hughes
+ * Authors: Tomas M�ller, John Hughes
* "Efficiently Building a Matrix to Rotate One Vector to Another"
* Journal of Graphics Tools, 4(4):1-4, 1999
*/
// ----------------------------------------------------------------------------------------
template <typename TReal>
-inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
- const aiVector3t<TReal>& to, aiMatrix3x3t<TReal>& mtx)
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix3x3t<TReal>& mtx)
{
- const TReal e = from * to;
- const TReal f = (e < 0)? -e:e;
-
- if (f > static_cast<TReal>(1.0) - static_cast<TReal>(0.00001)) /* "from" and "to"-vector almost parallel */
- {
- aiVector3D u,v; /* temporary storage vectors */
- aiVector3D x; /* vector most nearly orthogonal to "from" */
-
- x.x = (from.x > 0.0)? from.x : -from.x;
- x.y = (from.y > 0.0)? from.y : -from.y;
- x.z = (from.z > 0.0)? from.z : -from.z;
-
- if (x.x < x.y)
- {
- if (x.x < x.z)
- {
- x.x = static_cast<TReal>(1.0); x.y = x.z = static_cast<TReal>(0.0);
- }
- else
- {
- x.z = static_cast<TReal>(1.0); x.y = x.z = static_cast<TReal>(0.0);
- }
- }
- else
- {
- if (x.y < x.z)
- {
- x.y = static_cast<TReal>(1.0); x.x = x.z = static_cast<TReal>(0.0);
- }
- else
- {
- x.z = static_cast<TReal>(1.0); x.x = x.y = static_cast<TReal>(0.0);
- }
- }
-
- u.x = x.x - from.x; u.y = x.y - from.y; u.z = x.z - from.z;
- v.x = x.x - to.x; v.y = x.y - to.y; v.z = x.z - to.z;
-
- const TReal c1 = static_cast<TReal>(2.0) / (u * u);
- const TReal c2 = static_cast<TReal>(2.0) / (v * v);
- const TReal c3 = c1 * c2 * (u * v);
-
- for (unsigned int i = 0; i < 3; i++)
- {
- for (unsigned int j = 0; j < 3; j++)
- {
- mtx[i][j] = - c1 * u[i] * u[j] - c2 * v[i] * v[j]
- + c3 * v[i] * u[j];
- }
- mtx[i][i] += static_cast<TReal>(1.0);
- }
- }
- else /* the most common case, unless "from"="to", or "from"=-"to" */
- {
- const aiVector3D v = from ^ to;
- /* ... use this hand optimized version (9 mults less) */
- const TReal h = static_cast<TReal>(1.0)/(static_cast<TReal>(1.0) + e); /* optimization by Gottfried Chen */
- const TReal hvx = h * v.x;
- const TReal hvz = h * v.z;
- const TReal hvxy = hvx * v.y;
- const TReal hvxz = hvx * v.z;
- const TReal hvyz = hvz * v.y;
- mtx[0][0] = e + hvx * v.x;
- mtx[0][1] = hvxy - v.z;
- mtx[0][2] = hvxz + v.y;
-
- mtx[1][0] = hvxy + v.z;
- mtx[1][1] = e + h * v.y * v.y;
- mtx[1][2] = hvyz - v.x;
-
- mtx[2][0] = hvxz - v.y;
- mtx[2][1] = hvyz + v.x;
- mtx[2][2] = e + hvz * v.z;
- }
- return mtx;
+ const TReal e = from * to;
+ const TReal f = (e < 0)? -e:e;
+
+ if (f > static_cast<TReal>(1.0) - static_cast<TReal>(0.00001)) /* "from" and "to"-vector almost parallel */
+ {
+ aiVector3D u,v; /* temporary storage vectors */
+ aiVector3D x; /* vector most nearly orthogonal to "from" */
+
+ x.x = (from.x > 0.0)? from.x : -from.x;
+ x.y = (from.y > 0.0)? from.y : -from.y;
+ x.z = (from.z > 0.0)? from.z : -from.z;
+
+ if (x.x < x.y)
+ {
+ if (x.x < x.z)
+ {
+ x.x = static_cast<TReal>(1.0);
+ x.y = x.z = static_cast<TReal>(0.0);
+ }
+ else
+ {
+ x.z = static_cast<TReal>(1.0);
+ x.x = x.y = static_cast<TReal>(0.0);
+ }
+ }
+ else
+ {
+ if (x.y < x.z)
+ {
+ x.y = static_cast<TReal>(1.0);
+ x.x = x.z = static_cast<TReal>(0.0);
+ }
+ else
+ {
+ x.z = static_cast<TReal>(1.0);
+ x.x = x.y = static_cast<TReal>(0.0);
+ }
+ }
+
+ u.x = x.x - from.x; u.y = x.y - from.y; u.z = x.z - from.z;
+ v.x = x.x - to.x; v.y = x.y - to.y; v.z = x.z - to.z;
+
+ const TReal c1 = static_cast<TReal>(2.0) / (u * u);
+ const TReal c2 = static_cast<TReal>(2.0) / (v * v);
+ const TReal c3 = c1 * c2 * (u * v);
+
+ for (unsigned int i = 0; i < 3; i++)
+ {
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ mtx[i][j] = - c1 * u[i] * u[j] - c2 * v[i] * v[j]
+ + c3 * v[i] * u[j];
+ }
+ mtx[i][i] += static_cast<TReal>(1.0);
+ }
+ }
+ else /* the most common case, unless "from"="to", or "from"=-"to" */
+ {
+ const aiVector3D v = from ^ to;
+ /* ... use this hand optimized version (9 mults less) */
+ const TReal h = static_cast<TReal>(1.0)/(static_cast<TReal>(1.0) + e); /* optimization by Gottfried Chen */
+ const TReal hvx = h * v.x;
+ const TReal hvz = h * v.z;
+ const TReal hvxy = hvx * v.y;
+ const TReal hvxz = hvx * v.z;
+ const TReal hvyz = hvz * v.y;
+ mtx[0][0] = e + hvx * v.x;
+ mtx[0][1] = hvxy - v.z;
+ mtx[0][2] = hvxz + v.y;
+
+ mtx[1][0] = hvxy + v.z;
+ mtx[1][1] = e + h * v.y * v.y;
+ mtx[1][2] = hvyz - v.x;
+
+ mtx[2][0] = hvxz - v.y;
+ mtx[2][1] = hvyz + v.x;
+ mtx[2][2] = e + hvz * v.z;
+ }
+ return mtx;
}
diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.h b/src/3rdparty/assimp/include/assimp/matrix4x4.h
index 6ed550b7b..fc77b6964 100644
--- a/src/3rdparty/assimp/include/assimp/matrix4x4.h
+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.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,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MATRIX4X4_H_INC
#define AI_MATRIX4X4_H_INC
+#include "vector3.h"
#include "./Compiler/pushpack1.h"
#ifdef __cplusplus
@@ -55,7 +56,7 @@ template<typename TReal> class aiQuaterniont;
/** @brief Represents a row-major 4x4 matrix, use this for homogeneous
* coordinates.
*
- * There's much confusion about matrix layouts (column vs. row order).
+ * There's much confusion about matrix layouts (column vs. row order).
* This is *always* a row-major matrix. Not even with the
* #aiProcess_ConvertToLeftHanded flag, which absolutely does not affect
* matrix order - it just affects the handedness of the coordinate system
@@ -65,180 +66,178 @@ template<typename TReal>
class aiMatrix4x4t
{
public:
-
- /** set to identity */
- aiMatrix4x4t ();
-
- /** construction from single values */
- aiMatrix4x4t ( TReal _a1, TReal _a2, TReal _a3, TReal _a4,
- TReal _b1, TReal _b2, TReal _b3, TReal _b4,
- TReal _c1, TReal _c2, TReal _c3, TReal _c4,
- TReal _d1, TReal _d2, TReal _d3, TReal _d4);
-
-
- /** construction from 3x3 matrix, remaining elements are set to identity */
- explicit aiMatrix4x4t( const aiMatrix3x3t<TReal>& m);
-
- /** construction from position, rotation and scaling components
- * @param scaling The scaling for the x,y,z axes
- * @param rotation The rotation as a hamilton quaternion
- * @param position The position for the x,y,z axes
- */
- aiMatrix4x4t(const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation,
- const aiVector3t<TReal>& position);
+
+ /** set to identity */
+ aiMatrix4x4t ();
+
+ /** construction from single values */
+ aiMatrix4x4t ( TReal _a1, TReal _a2, TReal _a3, TReal _a4,
+ TReal _b1, TReal _b2, TReal _b3, TReal _b4,
+ TReal _c1, TReal _c2, TReal _c3, TReal _c4,
+ TReal _d1, TReal _d2, TReal _d3, TReal _d4);
+
+
+ /** construction from 3x3 matrix, remaining elements are set to identity */
+ explicit aiMatrix4x4t( const aiMatrix3x3t<TReal>& m);
+
+ /** construction from position, rotation and scaling components
+ * @param scaling The scaling for the x,y,z axes
+ * @param rotation The rotation as a hamilton quaternion
+ * @param position The position for the x,y,z axes
+ */
+ aiMatrix4x4t(const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation,
+ const aiVector3t<TReal>& position);
public:
- // array access operators
- TReal* operator[] (unsigned int p_iIndex);
- const TReal* operator[] (unsigned int p_iIndex) const;
+ // array access operators
+ TReal* operator[] (unsigned int p_iIndex);
+ const TReal* operator[] (unsigned int p_iIndex) const;
- // comparison operators
- bool operator== (const aiMatrix4x4t& m) const;
- bool operator!= (const aiMatrix4x4t& m) const;
+ // comparison operators
+ bool operator== (const aiMatrix4x4t& m) const;
+ bool operator!= (const aiMatrix4x4t& m) const;
- bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const;
+ bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const;
- // matrix multiplication.
- aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);
- aiMatrix4x4t operator * (const aiMatrix4x4t& m) const;
+ // matrix multiplication.
+ aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);
+ aiMatrix4x4t operator * (const aiMatrix4x4t& m) const;
- template <typename TOther>
- operator aiMatrix4x4t<TOther> () const;
+ template <typename TOther>
+ operator aiMatrix4x4t<TOther> () const;
public:
- // -------------------------------------------------------------------
- /** @brief Transpose the matrix */
- aiMatrix4x4t& Transpose();
-
- // -------------------------------------------------------------------
- /** @brief Invert the matrix.
- * If the matrix is not invertible all elements are set to qnan.
- * Beware, use (f != f) to check whether a TReal f is qnan.
- */
- aiMatrix4x4t& Inverse();
- TReal Determinant() const;
-
-
- // -------------------------------------------------------------------
- /** @brief Returns true of the matrix is the identity matrix.
- * The check is performed against a not so small epsilon.
- */
- inline bool IsIdentity() const;
-
- // -------------------------------------------------------------------
- /** @brief Decompose a trafo matrix into its original components
- * @param scaling Receives the output scaling for the x,y,z axes
- * @param rotation Receives the output rotation as a hamilton
- * quaternion
- * @param position Receives the output position for the x,y,z axes
- */
- void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
- aiVector3t<TReal>& position) const;
-
- // -------------------------------------------------------------------
- /** @brief Decompose a trafo matrix with no scaling into its
- * original components
- * @param rotation Receives the output rotation as a hamilton
- * quaternion
- * @param position Receives the output position for the x,y,z axes
- */
- void DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
- aiVector3t<TReal>& position) const;
-
-
- // -------------------------------------------------------------------
- /** @brief Creates a trafo matrix from a set of euler angles
- * @param x Rotation angle for the x-axis, in radians
- * @param y Rotation angle for the y-axis, in radians
- * @param z Rotation angle for the z-axis, in radians
- */
- aiMatrix4x4t& FromEulerAnglesXYZ(TReal x, TReal y, TReal z);
- aiMatrix4x4t& FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb);
+ // -------------------------------------------------------------------
+ /** @brief Transpose the matrix */
+ aiMatrix4x4t& Transpose();
+
+ // -------------------------------------------------------------------
+ /** @brief Invert the matrix.
+ * If the matrix is not invertible all elements are set to qnan.
+ * Beware, use (f != f) to check whether a TReal f is qnan.
+ */
+ aiMatrix4x4t& Inverse();
+ TReal Determinant() const;
+
+
+ // -------------------------------------------------------------------
+ /** @brief Returns true of the matrix is the identity matrix.
+ * The check is performed against a not so small epsilon.
+ */
+ inline bool IsIdentity() const;
+
+ // -------------------------------------------------------------------
+ /** @brief Decompose a trafo matrix into its original components
+ * @param scaling Receives the output scaling for the x,y,z axes
+ * @param rotation Receives the output rotation as a hamilton
+ * quaternion
+ * @param position Receives the output position for the x,y,z axes
+ */
+ void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
+ aiVector3t<TReal>& position) const;
+
+ // -------------------------------------------------------------------
+ /** @brief Decompose a trafo matrix with no scaling into its
+ * original components
+ * @param rotation Receives the output rotation as a hamilton
+ * quaternion
+ * @param position Receives the output position for the x,y,z axes
+ */
+ void DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
+ aiVector3t<TReal>& position) const;
+
+
+ // -------------------------------------------------------------------
+ /** @brief Creates a trafo matrix from a set of euler angles
+ * @param x Rotation angle for the x-axis, in radians
+ * @param y Rotation angle for the y-axis, in radians
+ * @param z Rotation angle for the z-axis, in radians
+ */
+ aiMatrix4x4t& FromEulerAnglesXYZ(TReal x, TReal y, TReal z);
+ aiMatrix4x4t& FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb);
public:
- // -------------------------------------------------------------------
- /** @brief Returns a rotation matrix for a rotation around the x axis
- * @param a Rotation angle, in radians
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix4x4t& RotationX(TReal a, aiMatrix4x4t& out);
-
- // -------------------------------------------------------------------
- /** @brief Returns a rotation matrix for a rotation around the y axis
- * @param a Rotation angle, in radians
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix4x4t& RotationY(TReal a, aiMatrix4x4t& out);
-
- // -------------------------------------------------------------------
- /** @brief Returns a rotation matrix for a rotation around the z axis
- * @param a Rotation angle, in radians
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix4x4t& RotationZ(TReal a, aiMatrix4x4t& out);
-
- // -------------------------------------------------------------------
- /** Returns a rotation matrix for a rotation around an arbitrary axis.
- * @param a Rotation angle, in radians
- * @param axis Rotation axis, should be a normalized vector.
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
- aiMatrix4x4t& out);
-
- // -------------------------------------------------------------------
- /** @brief Returns a translation matrix
- * @param v Translation vector
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
-
- // -------------------------------------------------------------------
- /** @brief Returns a scaling matrix
- * @param v Scaling vector
- * @param out Receives the output matrix
- * @return Reference to the output matrix
- */
- static aiMatrix4x4t& Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
-
- // -------------------------------------------------------------------
- /** @brief A function for creating a rotation matrix that rotates a
- * vector called "from" into another vector called "to".
- * Input : from[3], to[3] which both must be *normalized* non-zero vectors
- * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
- * Authors: Tomas Möller, John Hughes
- * "Efficiently Building a Matrix to Rotate One Vector to Another"
- * Journal of Graphics Tools, 4(4):1-4, 1999
- */
- static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
- const aiVector3t<TReal>& to, aiMatrix4x4t& out);
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around the x axis
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& RotationX(TReal a, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around the y axis
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& RotationY(TReal a, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a rotation matrix for a rotation around the z axis
+ * @param a Rotation angle, in radians
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& RotationZ(TReal a, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** Returns a rotation matrix for a rotation around an arbitrary axis.
+ * @param a Rotation angle, in radians
+ * @param axis Rotation axis, should be a normalized vector.
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
+ aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a translation matrix
+ * @param v Translation vector
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns a scaling matrix
+ * @param v Scaling vector
+ * @param out Receives the output matrix
+ * @return Reference to the output matrix
+ */
+ static aiMatrix4x4t& Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
+
+ // -------------------------------------------------------------------
+ /** @brief A function for creating a rotation matrix that rotates a
+ * vector called "from" into another vector called "to".
+ * Input : from[3], to[3] which both must be *normalized* non-zero vectors
+ * Output: mtx[3][3] -- a 3x3 matrix in column-major form
+ * Authors: Tomas Mueller, John Hughes
+ * "Efficiently Building a Matrix to Rotate One Vector to Another"
+ * Journal of Graphics Tools, 4(4):1-4, 1999
+ */
+ static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
+ const aiVector3t<TReal>& to, aiMatrix4x4t& out);
public:
-
- TReal a1, a2, a3, a4;
- TReal b1, b2, b3, b4;
- TReal c1, c2, c3, c4;
- TReal d1, d2, d3, d4;
-
-} PACK_STRUCT;
+ TReal a1, a2, a3, a4;
+ TReal b1, b2, b3, b4;
+ TReal c1, c2, c3, c4;
+ TReal d1, d2, d3, d4;
+} PACK_STRUCT;
typedef aiMatrix4x4t<float> aiMatrix4x4;
#else
struct aiMatrix4x4 {
- float a1, a2, a3, a4;
- float b1, b2, b3, b4;
- float c1, c2, c3, c4;
- float d1, d2, d3, d4;
-};
+ float a1, a2, a3, a4;
+ float b1, b2, b3, b4;
+ float c1, c2, c3, c4;
+ float d1, d2, d3, d4;
+} PACK_STRUCT;
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.inl b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
index 8fdabcf86..9ce794f0a 100644
--- a/src/3rdparty/assimp/include/assimp/matrix4x4.inl
+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, assimp team
All rights reserved.
@@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file aiMatrix4x4t<TReal>.inl
+/** @file matrix4x4.inl
* @brief Inline implementation of the 4x4 matrix operators
*/
#ifndef AI_MATRIX4x4_INL_INC
@@ -53,20 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <limits>
-
-#ifdef __cplusplus
-# include <cmath>
-#else
-# include <math.h>
-#endif
+#include <cmath>
// ----------------------------------------------------------------------------------------
template <typename TReal>
aiMatrix4x4t<TReal> ::aiMatrix4x4t () :
- a1(1.0f), a2(), a3(), a4(),
- b1(), b2(1.0f), b3(), b4(),
- c1(), c2(), c3(1.0f), c4(),
- d1(), d2(), d3(), d4(1.0f)
+ a1(1.0f), a2(), a3(), a4(),
+ b1(), b2(1.0f), b3(), b4(),
+ c1(), c2(), c3(1.0f), c4(),
+ d1(), d2(), d3(), d4(1.0f)
{
}
@@ -74,13 +69,13 @@ aiMatrix4x4t<TReal> ::aiMatrix4x4t () :
// ----------------------------------------------------------------------------------------
template <typename TReal>
aiMatrix4x4t<TReal> ::aiMatrix4x4t (TReal _a1, TReal _a2, TReal _a3, TReal _a4,
- TReal _b1, TReal _b2, TReal _b3, TReal _b4,
- TReal _c1, TReal _c2, TReal _c3, TReal _c4,
- TReal _d1, TReal _d2, TReal _d3, TReal _d4) :
- a1(_a1), a2(_a2), a3(_a3), a4(_a4),
- b1(_b1), b2(_b2), b3(_b3), b4(_b4),
- c1(_c1), c2(_c2), c3(_c3), c4(_c4),
- d1(_d1), d2(_d2), d3(_d3), d4(_d4)
+ TReal _b1, TReal _b2, TReal _b3, TReal _b4,
+ TReal _c1, TReal _c2, TReal _c3, TReal _c4,
+ TReal _d1, TReal _d2, TReal _d3, TReal _d4) :
+ a1(_a1), a2(_a2), a3(_a3), a4(_a4),
+ b1(_b1), b2(_b2), b3(_b3), b4(_b4),
+ c1(_c1), c2(_c2), c3(_c3), c4(_c4),
+ d1(_d1), d2(_d2), d3(_d3), d4(_d4)
{
}
@@ -90,10 +85,10 @@ template <typename TReal>
template <typename TOther>
aiMatrix4x4t<TReal>::operator aiMatrix4x4t<TOther> () const
{
- return aiMatrix4x4t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),static_cast<TOther>(a4),
- static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),static_cast<TOther>(b4),
- static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3),static_cast<TOther>(c4),
- static_cast<TOther>(d1),static_cast<TOther>(d2),static_cast<TOther>(d3),static_cast<TOther>(d4));
+ return aiMatrix4x4t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),static_cast<TOther>(a4),
+ static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),static_cast<TOther>(b4),
+ static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3),static_cast<TOther>(c4),
+ static_cast<TOther>(d1),static_cast<TOther>(d2),static_cast<TOther>(d3),static_cast<TOther>(d4));
}
@@ -101,71 +96,71 @@ aiMatrix4x4t<TReal>::operator aiMatrix4x4t<TOther> () const
template <typename TReal>
inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiMatrix3x3t<TReal>& m)
{
- a1 = m.a1; a2 = m.a2; a3 = m.a3; a4 = static_cast<TReal>(0.0);
- b1 = m.b1; b2 = m.b2; b3 = m.b3; b4 = static_cast<TReal>(0.0);
- c1 = m.c1; c2 = m.c2; c3 = m.c3; c4 = static_cast<TReal>(0.0);
- d1 = static_cast<TReal>(0.0); d2 = static_cast<TReal>(0.0); d3 = static_cast<TReal>(0.0); d4 = static_cast<TReal>(1.0);
+ a1 = m.a1; a2 = m.a2; a3 = m.a3; a4 = static_cast<TReal>(0.0);
+ b1 = m.b1; b2 = m.b2; b3 = m.b3; b4 = static_cast<TReal>(0.0);
+ c1 = m.c1; c2 = m.c2; c3 = m.c3; c4 = static_cast<TReal>(0.0);
+ d1 = static_cast<TReal>(0.0); d2 = static_cast<TReal>(0.0); d3 = static_cast<TReal>(0.0); d4 = static_cast<TReal>(1.0);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation, const aiVector3t<TReal>& position)
{
- // build a 3x3 rotation matrix
- aiMatrix3x3t<TReal> m = rotation.GetMatrix();
-
- a1 = m.a1 * scaling.x;
- a2 = m.a2 * scaling.x;
- a3 = m.a3 * scaling.x;
- a4 = position.x;
-
- b1 = m.b1 * scaling.y;
- b2 = m.b2 * scaling.y;
- b3 = m.b3 * scaling.y;
- b4 = position.y;
-
- c1 = m.c1 * scaling.z;
- c2 = m.c2 * scaling.z;
- c3 = m.c3 * scaling.z;
- c4= position.z;
-
- d1 = static_cast<TReal>(0.0);
- d2 = static_cast<TReal>(0.0);
- d3 = static_cast<TReal>(0.0);
- d4 = static_cast<TReal>(1.0);
+ // build a 3x3 rotation matrix
+ aiMatrix3x3t<TReal> m = rotation.GetMatrix();
+
+ a1 = m.a1 * scaling.x;
+ a2 = m.a2 * scaling.x;
+ a3 = m.a3 * scaling.x;
+ a4 = position.x;
+
+ b1 = m.b1 * scaling.y;
+ b2 = m.b2 * scaling.y;
+ b3 = m.b3 * scaling.y;
+ b4 = position.y;
+
+ c1 = m.c1 * scaling.z;
+ c2 = m.c2 * scaling.z;
+ c3 = m.c3 * scaling.z;
+ c4= position.z;
+
+ d1 = static_cast<TReal>(0.0);
+ d2 = static_cast<TReal>(0.0);
+ d3 = static_cast<TReal>(0.0);
+ d4 = static_cast<TReal>(1.0);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::operator *= (const aiMatrix4x4t<TReal>& m)
{
- *this = aiMatrix4x4t<TReal>(
- m.a1 * a1 + m.b1 * a2 + m.c1 * a3 + m.d1 * a4,
- m.a2 * a1 + m.b2 * a2 + m.c2 * a3 + m.d2 * a4,
- m.a3 * a1 + m.b3 * a2 + m.c3 * a3 + m.d3 * a4,
- m.a4 * a1 + m.b4 * a2 + m.c4 * a3 + m.d4 * a4,
- m.a1 * b1 + m.b1 * b2 + m.c1 * b3 + m.d1 * b4,
- m.a2 * b1 + m.b2 * b2 + m.c2 * b3 + m.d2 * b4,
- m.a3 * b1 + m.b3 * b2 + m.c3 * b3 + m.d3 * b4,
- m.a4 * b1 + m.b4 * b2 + m.c4 * b3 + m.d4 * b4,
- m.a1 * c1 + m.b1 * c2 + m.c1 * c3 + m.d1 * c4,
- m.a2 * c1 + m.b2 * c2 + m.c2 * c3 + m.d2 * c4,
- m.a3 * c1 + m.b3 * c2 + m.c3 * c3 + m.d3 * c4,
- m.a4 * c1 + m.b4 * c2 + m.c4 * c3 + m.d4 * c4,
- m.a1 * d1 + m.b1 * d2 + m.c1 * d3 + m.d1 * d4,
- m.a2 * d1 + m.b2 * d2 + m.c2 * d3 + m.d2 * d4,
- m.a3 * d1 + m.b3 * d2 + m.c3 * d3 + m.d3 * d4,
- m.a4 * d1 + m.b4 * d2 + m.c4 * d3 + m.d4 * d4);
- return *this;
+ *this = aiMatrix4x4t<TReal>(
+ m.a1 * a1 + m.b1 * a2 + m.c1 * a3 + m.d1 * a4,
+ m.a2 * a1 + m.b2 * a2 + m.c2 * a3 + m.d2 * a4,
+ m.a3 * a1 + m.b3 * a2 + m.c3 * a3 + m.d3 * a4,
+ m.a4 * a1 + m.b4 * a2 + m.c4 * a3 + m.d4 * a4,
+ m.a1 * b1 + m.b1 * b2 + m.c1 * b3 + m.d1 * b4,
+ m.a2 * b1 + m.b2 * b2 + m.c2 * b3 + m.d2 * b4,
+ m.a3 * b1 + m.b3 * b2 + m.c3 * b3 + m.d3 * b4,
+ m.a4 * b1 + m.b4 * b2 + m.c4 * b3 + m.d4 * b4,
+ m.a1 * c1 + m.b1 * c2 + m.c1 * c3 + m.d1 * c4,
+ m.a2 * c1 + m.b2 * c2 + m.c2 * c3 + m.d2 * c4,
+ m.a3 * c1 + m.b3 * c2 + m.c3 * c3 + m.d3 * c4,
+ m.a4 * c1 + m.b4 * c2 + m.c4 * c3 + m.d4 * c4,
+ m.a1 * d1 + m.b1 * d2 + m.c1 * d3 + m.d1 * d4,
+ m.a2 * d1 + m.b2 * d2 + m.c2 * d3 + m.d2 * d4,
+ m.a3 * d1 + m.b3 * d2 + m.c3 * d3 + m.d3 * d4,
+ m.a4 * d1 + m.b4 * d2 + m.c4 * d3 + m.d4 * d4);
+ return *this;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const aiMatrix4x4t<TReal>& m) const
{
- aiMatrix4x4t<TReal> temp( *this);
- temp *= m;
- return temp;
+ aiMatrix4x4t<TReal> temp( *this);
+ temp *= m;
+ return temp;
}
@@ -173,14 +168,14 @@ inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const aiMatrix4x4t<TR
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Transpose()
{
- // (TReal&) don't remove, GCC complains cause of packed fields
- std::swap( (TReal&)b1, (TReal&)a2);
- std::swap( (TReal&)c1, (TReal&)a3);
- std::swap( (TReal&)c2, (TReal&)b3);
- std::swap( (TReal&)d1, (TReal&)a4);
- std::swap( (TReal&)d2, (TReal&)b4);
- std::swap( (TReal&)d3, (TReal&)c4);
- return *this;
+ // (TReal&) don't remove, GCC complains cause of packed fields
+ std::swap( (TReal&)b1, (TReal&)a2);
+ std::swap( (TReal&)c1, (TReal&)a3);
+ std::swap( (TReal&)c2, (TReal&)b3);
+ std::swap( (TReal&)d1, (TReal&)a4);
+ std::swap( (TReal&)d2, (TReal&)b4);
+ std::swap( (TReal&)d3, (TReal&)c4);
+ return *this;
}
@@ -188,196 +183,202 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Transpose()
template <typename TReal>
inline TReal aiMatrix4x4t<TReal>::Determinant() const
{
- return a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4
- + a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4
- - a2*b4*c1*d3 + a2*b4*c3*d1 - a2*b1*c3*d4 + a2*b1*c4*d3
- + a3*b4*c1*d2 - a3*b4*c2*d1 + a3*b1*c2*d4 - a3*b1*c4*d2
- + a3*b2*c4*d1 - a3*b2*c1*d4 - a4*b1*c2*d3 + a4*b1*c3*d2
- - a4*b2*c3*d1 + a4*b2*c1*d3 - a4*b3*c1*d2 + a4*b3*c2*d1;
+ return a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4
+ + a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4
+ - a2*b4*c1*d3 + a2*b4*c3*d1 - a2*b1*c3*d4 + a2*b1*c4*d3
+ + a3*b4*c1*d2 - a3*b4*c2*d1 + a3*b1*c2*d4 - a3*b1*c4*d2
+ + a3*b2*c4*d1 - a3*b2*c1*d4 - a4*b1*c2*d3 + a4*b1*c3*d2
+ - a4*b2*c3*d1 + a4*b2*c1*d3 - a4*b3*c1*d2 + a4*b3*c2*d1;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Inverse()
{
- // Compute the reciprocal determinant
- const TReal det = Determinant();
- if(det == static_cast<TReal>(0.0))
- {
- // Matrix not invertible. Setting all elements to nan is not really
- // correct in a mathematical sense but it is easy to debug for the
- // programmer.
- const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
- *this = aiMatrix4x4t<TReal>(
- nan,nan,nan,nan,
- nan,nan,nan,nan,
- nan,nan,nan,nan,
- nan,nan,nan,nan);
-
- return *this;
- }
-
- const TReal invdet = static_cast<TReal>(1.0) / det;
-
- aiMatrix4x4t<TReal> res;
- res.a1 = invdet * (b2 * (c3 * d4 - c4 * d3) + b3 * (c4 * d2 - c2 * d4) + b4 * (c2 * d3 - c3 * d2));
- res.a2 = -invdet * (a2 * (c3 * d4 - c4 * d3) + a3 * (c4 * d2 - c2 * d4) + a4 * (c2 * d3 - c3 * d2));
- res.a3 = invdet * (a2 * (b3 * d4 - b4 * d3) + a3 * (b4 * d2 - b2 * d4) + a4 * (b2 * d3 - b3 * d2));
- res.a4 = -invdet * (a2 * (b3 * c4 - b4 * c3) + a3 * (b4 * c2 - b2 * c4) + a4 * (b2 * c3 - b3 * c2));
- res.b1 = -invdet * (b1 * (c3 * d4 - c4 * d3) + b3 * (c4 * d1 - c1 * d4) + b4 * (c1 * d3 - c3 * d1));
- res.b2 = invdet * (a1 * (c3 * d4 - c4 * d3) + a3 * (c4 * d1 - c1 * d4) + a4 * (c1 * d3 - c3 * d1));
- res.b3 = -invdet * (a1 * (b3 * d4 - b4 * d3) + a3 * (b4 * d1 - b1 * d4) + a4 * (b1 * d3 - b3 * d1));
- res.b4 = invdet * (a1 * (b3 * c4 - b4 * c3) + a3 * (b4 * c1 - b1 * c4) + a4 * (b1 * c3 - b3 * c1));
- res.c1 = invdet * (b1 * (c2 * d4 - c4 * d2) + b2 * (c4 * d1 - c1 * d4) + b4 * (c1 * d2 - c2 * d1));
- res.c2 = -invdet * (a1 * (c2 * d4 - c4 * d2) + a2 * (c4 * d1 - c1 * d4) + a4 * (c1 * d2 - c2 * d1));
- res.c3 = invdet * (a1 * (b2 * d4 - b4 * d2) + a2 * (b4 * d1 - b1 * d4) + a4 * (b1 * d2 - b2 * d1));
- res.c4 = -invdet * (a1 * (b2 * c4 - b4 * c2) + a2 * (b4 * c1 - b1 * c4) + a4 * (b1 * c2 - b2 * c1));
- res.d1 = -invdet * (b1 * (c2 * d3 - c3 * d2) + b2 * (c3 * d1 - c1 * d3) + b3 * (c1 * d2 - c2 * d1));
- res.d2 = invdet * (a1 * (c2 * d3 - c3 * d2) + a2 * (c3 * d1 - c1 * d3) + a3 * (c1 * d2 - c2 * d1));
- res.d3 = -invdet * (a1 * (b2 * d3 - b3 * d2) + a2 * (b3 * d1 - b1 * d3) + a3 * (b1 * d2 - b2 * d1));
- res.d4 = invdet * (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1));
- *this = res;
-
- return *this;
+ // Compute the reciprocal determinant
+ const TReal det = Determinant();
+ if(det == static_cast<TReal>(0.0))
+ {
+ // Matrix not invertible. Setting all elements to nan is not really
+ // correct in a mathematical sense but it is easy to debug for the
+ // programmer.
+ const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
+ *this = aiMatrix4x4t<TReal>(
+ nan,nan,nan,nan,
+ nan,nan,nan,nan,
+ nan,nan,nan,nan,
+ nan,nan,nan,nan);
+
+ return *this;
+ }
+
+ const TReal invdet = static_cast<TReal>(1.0) / det;
+
+ aiMatrix4x4t<TReal> res;
+ res.a1 = invdet * (b2 * (c3 * d4 - c4 * d3) + b3 * (c4 * d2 - c2 * d4) + b4 * (c2 * d3 - c3 * d2));
+ res.a2 = -invdet * (a2 * (c3 * d4 - c4 * d3) + a3 * (c4 * d2 - c2 * d4) + a4 * (c2 * d3 - c3 * d2));
+ res.a3 = invdet * (a2 * (b3 * d4 - b4 * d3) + a3 * (b4 * d2 - b2 * d4) + a4 * (b2 * d3 - b3 * d2));
+ res.a4 = -invdet * (a2 * (b3 * c4 - b4 * c3) + a3 * (b4 * c2 - b2 * c4) + a4 * (b2 * c3 - b3 * c2));
+ res.b1 = -invdet * (b1 * (c3 * d4 - c4 * d3) + b3 * (c4 * d1 - c1 * d4) + b4 * (c1 * d3 - c3 * d1));
+ res.b2 = invdet * (a1 * (c3 * d4 - c4 * d3) + a3 * (c4 * d1 - c1 * d4) + a4 * (c1 * d3 - c3 * d1));
+ res.b3 = -invdet * (a1 * (b3 * d4 - b4 * d3) + a3 * (b4 * d1 - b1 * d4) + a4 * (b1 * d3 - b3 * d1));
+ res.b4 = invdet * (a1 * (b3 * c4 - b4 * c3) + a3 * (b4 * c1 - b1 * c4) + a4 * (b1 * c3 - b3 * c1));
+ res.c1 = invdet * (b1 * (c2 * d4 - c4 * d2) + b2 * (c4 * d1 - c1 * d4) + b4 * (c1 * d2 - c2 * d1));
+ res.c2 = -invdet * (a1 * (c2 * d4 - c4 * d2) + a2 * (c4 * d1 - c1 * d4) + a4 * (c1 * d2 - c2 * d1));
+ res.c3 = invdet * (a1 * (b2 * d4 - b4 * d2) + a2 * (b4 * d1 - b1 * d4) + a4 * (b1 * d2 - b2 * d1));
+ res.c4 = -invdet * (a1 * (b2 * c4 - b4 * c2) + a2 * (b4 * c1 - b1 * c4) + a4 * (b1 * c2 - b2 * c1));
+ res.d1 = -invdet * (b1 * (c2 * d3 - c3 * d2) + b2 * (c3 * d1 - c1 * d3) + b3 * (c1 * d2 - c2 * d1));
+ res.d2 = invdet * (a1 * (c2 * d3 - c3 * d2) + a2 * (c3 * d1 - c1 * d3) + a3 * (c1 * d2 - c2 * d1));
+ res.d3 = -invdet * (a1 * (b2 * d3 - b3 * d2) + a2 * (b3 * d1 - b1 * d3) + a3 * (b1 * d2 - b2 * d1));
+ res.d4 = invdet * (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1));
+ *this = res;
+
+ return *this;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
-inline TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex)
-{
- // XXX this is UB. Has been for years. The fact that it works now does not make it better.
- return &this->a1 + p_iIndex * 4;
+inline TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) {
+ if (p_iIndex > 3) {
+ return NULL;
+ }
+
+ // XXX this is UB. Has been for years. The fact that it works now does not make it better.
+ return &this->a1 + p_iIndex * 4;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
-inline const TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) const
-{
- // XXX same
- return &this->a1 + p_iIndex * 4;
+inline const TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) const {
+ if (p_iIndex > 3) {
+ return NULL;
+ }
+
+ // XXX same
+ return &this->a1 + p_iIndex * 4;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix4x4t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const
{
- return (a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && a4 == m.a4 &&
- b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && b4 == m.b4 &&
- c1 == m.c1 && c2 == m.c2 && c3 == m.c3 && c4 == m.c4 &&
- d1 == m.d1 && d2 == m.d2 && d3 == m.d3 && d4 == m.d4);
+ return (a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && a4 == m.a4 &&
+ b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && b4 == m.b4 &&
+ c1 == m.c1 && c2 == m.c2 && c3 == m.c3 && c4 == m.c4 &&
+ d1 == m.d1 && d2 == m.d2 && d3 == m.d3 && d4 == m.d4);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix4x4t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const
{
- return !(*this == m);
+ return !(*this == m);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline bool aiMatrix4x4t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon) const {
- return
- std::abs(a1 - m.a1) <= epsilon &&
- std::abs(a2 - m.a2) <= epsilon &&
- std::abs(a3 - m.a3) <= epsilon &&
- std::abs(a4 - m.a4) <= epsilon &&
- std::abs(b1 - m.b1) <= epsilon &&
- std::abs(b2 - m.b2) <= epsilon &&
- std::abs(b3 - m.b3) <= epsilon &&
- std::abs(b4 - m.b4) <= epsilon &&
- std::abs(c1 - m.c1) <= epsilon &&
- std::abs(c2 - m.c2) <= epsilon &&
- std::abs(c3 - m.c3) <= epsilon &&
- std::abs(c4 - m.c4) <= epsilon &&
- std::abs(d1 - m.d1) <= epsilon &&
- std::abs(d2 - m.d2) <= epsilon &&
- std::abs(d3 - m.d3) <= epsilon &&
- std::abs(d4 - m.d4) <= epsilon;
+ return
+ std::abs(a1 - m.a1) <= epsilon &&
+ std::abs(a2 - m.a2) <= epsilon &&
+ std::abs(a3 - m.a3) <= epsilon &&
+ std::abs(a4 - m.a4) <= epsilon &&
+ std::abs(b1 - m.b1) <= epsilon &&
+ std::abs(b2 - m.b2) <= epsilon &&
+ std::abs(b3 - m.b3) <= epsilon &&
+ std::abs(b4 - m.b4) <= epsilon &&
+ std::abs(c1 - m.c1) <= epsilon &&
+ std::abs(c2 - m.c2) <= epsilon &&
+ std::abs(c3 - m.c3) <= epsilon &&
+ std::abs(c4 - m.c4) <= epsilon &&
+ std::abs(d1 - m.d1) <= epsilon &&
+ std::abs(d2 - m.d2) <= epsilon &&
+ std::abs(d3 - m.d3) <= epsilon &&
+ std::abs(d4 - m.d4) <= epsilon;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
- aiVector3t<TReal>& position) const
+ aiVector3t<TReal>& position) const
{
- const aiMatrix4x4t<TReal>& _this = *this;
-
- // extract translation
- position.x = _this[0][3];
- position.y = _this[1][3];
- position.z = _this[2][3];
-
- // extract the rows of the matrix
- aiVector3t<TReal> vRows[3] = {
- aiVector3t<TReal>(_this[0][0],_this[1][0],_this[2][0]),
- aiVector3t<TReal>(_this[0][1],_this[1][1],_this[2][1]),
- aiVector3t<TReal>(_this[0][2],_this[1][2],_this[2][2])
- };
-
- // extract the scaling factors
- scaling.x = vRows[0].Length();
- scaling.y = vRows[1].Length();
- scaling.z = vRows[2].Length();
-
- // and the sign of the scaling
- if (Determinant() < 0) {
- scaling.x = -scaling.x;
- scaling.y = -scaling.y;
- scaling.z = -scaling.z;
- }
-
- // and remove all scaling from the matrix
- if(scaling.x)
- {
- vRows[0] /= scaling.x;
- }
- if(scaling.y)
- {
- vRows[1] /= scaling.y;
- }
- if(scaling.z)
- {
- vRows[2] /= scaling.z;
- }
-
- // build a 3x3 rotation matrix
- aiMatrix3x3t<TReal> m(vRows[0].x,vRows[1].x,vRows[2].x,
- vRows[0].y,vRows[1].y,vRows[2].y,
- vRows[0].z,vRows[1].z,vRows[2].z);
-
- // and generate the rotation quaternion from it
- rotation = aiQuaterniont<TReal>(m);
+ const aiMatrix4x4t<TReal>& _this = *this;
+
+ // extract translation
+ position.x = _this[0][3];
+ position.y = _this[1][3];
+ position.z = _this[2][3];
+
+ // extract the rows of the matrix
+ aiVector3t<TReal> vRows[3] = {
+ aiVector3t<TReal>(_this[0][0],_this[1][0],_this[2][0]),
+ aiVector3t<TReal>(_this[0][1],_this[1][1],_this[2][1]),
+ aiVector3t<TReal>(_this[0][2],_this[1][2],_this[2][2])
+ };
+
+ // extract the scaling factors
+ scaling.x = vRows[0].Length();
+ scaling.y = vRows[1].Length();
+ scaling.z = vRows[2].Length();
+
+ // and the sign of the scaling
+ if (Determinant() < 0) {
+ scaling.x = -scaling.x;
+ scaling.y = -scaling.y;
+ scaling.z = -scaling.z;
+ }
+
+ // and remove all scaling from the matrix
+ if(scaling.x)
+ {
+ vRows[0] /= scaling.x;
+ }
+ if(scaling.y)
+ {
+ vRows[1] /= scaling.y;
+ }
+ if(scaling.z)
+ {
+ vRows[2] /= scaling.z;
+ }
+
+ // build a 3x3 rotation matrix
+ aiMatrix3x3t<TReal> m(vRows[0].x,vRows[1].x,vRows[2].x,
+ vRows[0].y,vRows[1].y,vRows[2].y,
+ vRows[0].z,vRows[1].z,vRows[2].z);
+
+ // and generate the rotation quaternion from it
+ rotation = aiQuaterniont<TReal>(m);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline void aiMatrix4x4t<TReal>::DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
- aiVector3t<TReal>& position) const
+ aiVector3t<TReal>& position) const
{
- const aiMatrix4x4t<TReal>& _this = *this;
+ const aiMatrix4x4t<TReal>& _this = *this;
- // extract translation
- position.x = _this[0][3];
- position.y = _this[1][3];
- position.z = _this[2][3];
+ // extract translation
+ position.x = _this[0][3];
+ position.y = _this[1][3];
+ position.z = _this[2][3];
- // extract rotation
- rotation = aiQuaterniont<TReal>((aiMatrix3x3t<TReal>)_this);
+ // extract rotation
+ rotation = aiQuaterniont<TReal>((aiMatrix3x3t<TReal>)_this);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb)
{
- return FromEulerAnglesXYZ(blubb.x,blubb.y,blubb.z);
+ return FromEulerAnglesXYZ(blubb.x,blubb.y,blubb.z);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(TReal x, TReal y, TReal z)
{
- aiMatrix4x4t<TReal>& _this = *this;
+ aiMatrix4x4t<TReal>& _this = *this;
TReal cr = std::cos( x );
TReal sr = std::sin( x );
@@ -386,93 +387,93 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(TReal x, TRe
TReal cy = std::cos( z );
TReal sy = std::sin( z );
- _this.a1 = cp*cy ;
- _this.a2 = cp*sy;
- _this.a3 = -sp ;
+ _this.a1 = cp*cy ;
+ _this.a2 = cp*sy;
+ _this.a3 = -sp ;
- TReal srsp = sr*sp;
- TReal crsp = cr*sp;
+ TReal srsp = sr*sp;
+ TReal crsp = cr*sp;
- _this.b1 = srsp*cy-cr*sy ;
- _this.b2 = srsp*sy+cr*cy ;
- _this.b3 = sr*cp ;
+ _this.b1 = srsp*cy-cr*sy ;
+ _this.b2 = srsp*sy+cr*cy ;
+ _this.b3 = sr*cp ;
- _this.c1 = crsp*cy+sr*sy ;
- _this.c2 = crsp*sy-sr*cy ;
- _this.c3 = cr*cp ;
+ _this.c1 = crsp*cy+sr*sy ;
+ _this.c2 = crsp*sy-sr*cy ;
+ _this.c3 = cr*cp ;
- return *this;
+ return *this;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix4x4t<TReal>::IsIdentity() const
{
- // Use a small epsilon to solve floating-point inaccuracies
- const static TReal epsilon = 10e-3f;
-
- return (a2 <= epsilon && a2 >= -epsilon &&
- a3 <= epsilon && a3 >= -epsilon &&
- a4 <= epsilon && a4 >= -epsilon &&
- b1 <= epsilon && b1 >= -epsilon &&
- b3 <= epsilon && b3 >= -epsilon &&
- b4 <= epsilon && b4 >= -epsilon &&
- c1 <= epsilon && c1 >= -epsilon &&
- c2 <= epsilon && c2 >= -epsilon &&
- c4 <= epsilon && c4 >= -epsilon &&
- d1 <= epsilon && d1 >= -epsilon &&
- d2 <= epsilon && d2 >= -epsilon &&
- d3 <= epsilon && d3 >= -epsilon &&
- a1 <= 1.f+epsilon && a1 >= 1.f-epsilon &&
- b2 <= 1.f+epsilon && b2 >= 1.f-epsilon &&
- c3 <= 1.f+epsilon && c3 >= 1.f-epsilon &&
- d4 <= 1.f+epsilon && d4 >= 1.f-epsilon);
+ // Use a small epsilon to solve floating-point inaccuracies
+ const static TReal epsilon = 10e-3f;
+
+ return (a2 <= epsilon && a2 >= -epsilon &&
+ a3 <= epsilon && a3 >= -epsilon &&
+ a4 <= epsilon && a4 >= -epsilon &&
+ b1 <= epsilon && b1 >= -epsilon &&
+ b3 <= epsilon && b3 >= -epsilon &&
+ b4 <= epsilon && b4 >= -epsilon &&
+ c1 <= epsilon && c1 >= -epsilon &&
+ c2 <= epsilon && c2 >= -epsilon &&
+ c4 <= epsilon && c4 >= -epsilon &&
+ d1 <= epsilon && d1 >= -epsilon &&
+ d2 <= epsilon && d2 >= -epsilon &&
+ d3 <= epsilon && d3 >= -epsilon &&
+ a1 <= 1.f+epsilon && a1 >= 1.f-epsilon &&
+ b2 <= 1.f+epsilon && b2 >= 1.f-epsilon &&
+ c3 <= 1.f+epsilon && c3 >= 1.f-epsilon &&
+ d4 <= 1.f+epsilon && d4 >= 1.f-epsilon);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationX(TReal a, aiMatrix4x4t<TReal>& out)
{
- /*
- | 1 0 0 0 |
- M = | 0 std::cos(A) -std::sin(A) 0 |
- | 0 std::sin(A) std::cos(A) 0 |
- | 0 0 0 1 | */
- out = aiMatrix4x4t<TReal>();
+ /*
+ | 1 0 0 0 |
+ M = | 0 cos(A) -sin(A) 0 |
+ | 0 sin(A) cos(A) 0 |
+ | 0 0 0 1 | */
+ out = aiMatrix4x4t<TReal>();
out.b2 = out.c3 = std::cos(a);
out.b3 = -(out.c2 = std::sin(a));
- return out;
+ return out;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationY(TReal a, aiMatrix4x4t<TReal>& out)
{
- /*
- | std::cos(A) 0 std::sin(A) 0 |
+ /*
+ | cos(A) 0 sin(A) 0 |
M = | 0 1 0 0 |
- | -std::sin(A) 0 std::cos(A) 0 |
+ | -sin(A) 0 cos(A) 0 |
| 0 0 0 1 |
- */
- out = aiMatrix4x4t<TReal>();
+ */
+ out = aiMatrix4x4t<TReal>();
out.a1 = out.c3 = std::cos(a);
out.c1 = -(out.a3 = std::sin(a));
- return out;
+ return out;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationZ(TReal a, aiMatrix4x4t<TReal>& out)
{
- /*
- | std::cos(A) -std::sin(A) 0 0 |
- M = | std::sin(A) std::cos(A) 0 0 |
+ /*
+ | cos(A) -sin(A) 0 0 |
+ M = | sin(A) cos(A) 0 0 |
| 0 0 1 0 |
- | 0 0 0 1 | */
- out = aiMatrix4x4t<TReal>();
+ | 0 0 0 1 | */
+ out = aiMatrix4x4t<TReal>();
out.a1 = out.b2 = std::cos(a);
out.a2 = -(out.b1 = std::sin(a));
- return out;
+ return out;
}
// ----------------------------------------------------------------------------------------
@@ -498,22 +499,22 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Rotation( TReal a, const aiVect
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Translation( const aiVector3t<TReal>& v, aiMatrix4x4t<TReal>& out)
{
- out = aiMatrix4x4t<TReal>();
- out.a4 = v.x;
- out.b4 = v.y;
- out.c4 = v.z;
- return out;
+ out = aiMatrix4x4t<TReal>();
+ out.a4 = v.x;
+ out.b4 = v.y;
+ out.c4 = v.z;
+ return out;
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t<TReal>& out)
{
- out = aiMatrix4x4t<TReal>();
- out.a1 = v.x;
- out.b2 = v.y;
- out.c3 = v.z;
- return out;
+ out = aiMatrix4x4t<TReal>();
+ out.a1 = v.x;
+ out.b2 = v.y;
+ out.c3 = v.z;
+ return out;
}
// ----------------------------------------------------------------------------------------
@@ -521,19 +522,19 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Scaling( const aiVector3t<TReal
* "from" into another vector called "to".
* Input : from[3], to[3] which both must be *normalized* non-zero vectors
* Output: mtx[3][3] -- a 3x3 matrix in colum-major form
- * Authors: Tomas Möller, John Hughes
+ * Authors: Tomas M�ller, John Hughes
* "Efficiently Building a Matrix to Rotate One Vector to Another"
* Journal of Graphics Tools, 4(4):1-4, 1999
*/
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
- const aiVector3t<TReal>& to, aiMatrix4x4t<TReal>& mtx)
+ const aiVector3t<TReal>& to, aiMatrix4x4t<TReal>& mtx)
{
- aiMatrix3x3t<TReal> m3;
- aiMatrix3x3t<TReal>::FromToMatrix(from,to,m3);
- mtx = aiMatrix4x4t<TReal>(m3);
- return mtx;
+ aiMatrix3x3t<TReal> m3;
+ aiMatrix3x3t<TReal>::FromToMatrix(from,to,m3);
+ mtx = aiMatrix4x4t<TReal>(m3);
+ return mtx;
}
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/mesh.h b/src/3rdparty/assimp/include/assimp/mesh.h
index 7e2ecc179..5fd30bb02 100644
--- a/src/3rdparty/assimp/include/assimp/mesh.h
+++ b/src/3rdparty/assimp/include/assimp/mesh.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,22 +25,22 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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 mesh.h
- * @brief Declares the data structures in which the imported geometry is
+ * @brief Declares the data structures in which the imported geometry is
returned by ASSIMP: aiMesh, aiFace and aiBone data structures.
*/
#ifndef INCLUDED_AI_MESH_H
@@ -53,144 +53,144 @@ extern "C" {
#endif
// ---------------------------------------------------------------------------
-// Limits. These values are required to match the settings Assimp was
-// compiled against. Therfore, do not redefine them unless you build the
+// Limits. These values are required to match the settings Assimp was
+// compiled against. Therfore, do not redefine them unless you build the
// library from source using the same definitions.
// ---------------------------------------------------------------------------
/** @def AI_MAX_FACE_INDICES
* Maximum number of indices per face (polygon). */
-#ifndef AI_MAX_FACE_INDICES
-# define AI_MAX_FACE_INDICES 0x7fff
+#ifndef AI_MAX_FACE_INDICES
+# define AI_MAX_FACE_INDICES 0x7fff
#endif
/** @def AI_MAX_BONE_WEIGHTS
* Maximum number of indices per face (polygon). */
#ifndef AI_MAX_BONE_WEIGHTS
-# define AI_MAX_BONE_WEIGHTS 0x7fffffff
+# define AI_MAX_BONE_WEIGHTS 0x7fffffff
#endif
/** @def AI_MAX_VERTICES
* Maximum number of vertices per mesh. */
#ifndef AI_MAX_VERTICES
-# define AI_MAX_VERTICES 0x7fffffff
+# define AI_MAX_VERTICES 0x7fffffff
#endif
/** @def AI_MAX_FACES
* Maximum number of faces per mesh. */
#ifndef AI_MAX_FACES
-# define AI_MAX_FACES 0x7fffffff
+# define AI_MAX_FACES 0x7fffffff
#endif
/** @def AI_MAX_NUMBER_OF_COLOR_SETS
* Supported number of vertex color sets per mesh. */
#ifndef AI_MAX_NUMBER_OF_COLOR_SETS
-# define AI_MAX_NUMBER_OF_COLOR_SETS 0x8
+# define AI_MAX_NUMBER_OF_COLOR_SETS 0x8
#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
/** @def AI_MAX_NUMBER_OF_TEXTURECOORDS
* Supported number of texture coord sets (UV(W) channels) per mesh */
#ifndef AI_MAX_NUMBER_OF_TEXTURECOORDS
-# define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x8
+# define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x8
#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
// ---------------------------------------------------------------------------
-/** @brief A single face in a mesh, referring to multiple vertices.
+/** @brief A single face in a mesh, referring to multiple vertices.
*
- * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3
+ * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3
* it's called 'polygon' (hey, that's just a definition!).
* <br>
* aiMesh::mPrimitiveTypes can be queried to quickly examine which types of
- * primitive are actually present in a mesh. The #aiProcess_SortByPType flag
+ * primitive are actually present in a mesh. The #aiProcess_SortByPType flag
* executes a special post-processing algorithm which splits meshes with
* *different* primitive types mixed up (e.g. lines and triangles) in several
* 'clean' submeshes. Furthermore there is a configuration option (
- * #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
+ * #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
* specific kinds of primitives from the imported scene, completely and forever.
- * In many cases you'll probably want to set this setting to
- * @code
+ * In many cases you'll probably want to set this setting to
+ * @code
* aiPrimitiveType_LINE|aiPrimitiveType_POINT
* @endcode
* Together with the #aiProcess_Triangulate flag you can then be sure that
- * #aiFace::mNumIndices is always 3.
+ * #aiFace::mNumIndices is always 3.
* @note Take a look at the @link data Data Structures page @endlink for
* more information on the layout and winding order of a face.
*/
struct aiFace
{
- //! Number of indices defining this face.
- //! The maximum value for this member is #AI_MAX_FACE_INDICES.
- unsigned int mNumIndices;
+ //! Number of indices defining this face.
+ //! The maximum value for this member is #AI_MAX_FACE_INDICES.
+ unsigned int mNumIndices;
- //! Pointer to the indices array. Size of the array is given in numIndices.
- unsigned int* mIndices;
+ //! Pointer to the indices array. Size of the array is given in numIndices.
+ unsigned int* mIndices;
#ifdef __cplusplus
- //! Default constructor
- aiFace()
+ //! Default constructor
+ aiFace()
: mNumIndices( 0 )
, mIndices( NULL )
- {
- }
+ {
+ }
- //! Default destructor. Delete the index array
- ~aiFace()
- {
- delete [] mIndices;
- }
+ //! Default destructor. Delete the index array
+ ~aiFace()
+ {
+ delete [] mIndices;
+ }
- //! Copy constructor. Copy the index array
- aiFace( const aiFace& o)
+ //! Copy constructor. Copy the index array
+ aiFace( const aiFace& o)
: mIndices( NULL )
- {
- *this = o;
- }
-
- //! Assignment operator. Copy the index array
- aiFace& operator = ( const aiFace& o)
- {
- if (&o == this)
- return *this;
-
- delete[] mIndices;
- mNumIndices = o.mNumIndices;
- if (mNumIndices) {
- mIndices = new unsigned int[mNumIndices];
- ::memcpy( mIndices, o.mIndices, mNumIndices * sizeof( unsigned int));
- }
- else {
- mIndices = NULL;
- }
- return *this;
- }
-
- //! Comparison operator. Checks whether the index array
- //! of two faces is identical
- bool operator== (const aiFace& o) const
- {
- if (mIndices == o.mIndices)return true;
- else if (mIndices && mNumIndices == o.mNumIndices)
- {
- for (unsigned int i = 0;i < this->mNumIndices;++i)
- if (mIndices[i] != o.mIndices[i])return false;
- return true;
- }
- return false;
- }
-
- //! Inverse comparison operator. Checks whether the index
- //! array of two faces is NOT identical
- bool operator != (const aiFace& o) const
- {
- return !(*this == o);
- }
+ {
+ *this = o;
+ }
+
+ //! Assignment operator. Copy the index array
+ aiFace& operator = ( const aiFace& o)
+ {
+ if (&o == this)
+ return *this;
+
+ delete[] mIndices;
+ mNumIndices = o.mNumIndices;
+ if (mNumIndices) {
+ mIndices = new unsigned int[mNumIndices];
+ ::memcpy( mIndices, o.mIndices, mNumIndices * sizeof( unsigned int));
+ }
+ else {
+ mIndices = NULL;
+ }
+ return *this;
+ }
+
+ //! Comparison operator. Checks whether the index array
+ //! of two faces is identical
+ bool operator== (const aiFace& o) const
+ {
+ if (mIndices == o.mIndices)return true;
+ else if (mIndices && mNumIndices == o.mNumIndices)
+ {
+ for (unsigned int i = 0;i < this->mNumIndices;++i)
+ if (mIndices[i] != o.mIndices[i])return false;
+ return true;
+ }
+ return false;
+ }
+
+ //! Inverse comparison operator. Checks whether the index
+ //! array of two faces is NOT identical
+ bool operator != (const aiFace& o) const
+ {
+ return !(*this == o);
+ }
#endif // __cplusplus
}; // struct aiFace
@@ -200,24 +200,24 @@ struct aiFace
*/
struct aiVertexWeight
{
- //! Index of the vertex which is influenced by the bone.
- unsigned int mVertexId;
+ //! Index of the vertex which is influenced by the bone.
+ unsigned int mVertexId;
- //! The strength of the influence in the range (0...1).
- //! The influence from all bones at one vertex amounts to 1.
- float mWeight;
+ //! The strength of the influence in the range (0...1).
+ //! The influence from all bones at one vertex amounts to 1.
+ float mWeight;
#ifdef __cplusplus
- //! Default constructor
- aiVertexWeight() { }
+ //! Default constructor
+ aiVertexWeight() { }
- //! Initialisation from a given index and vertex weight factor
- //! \param pID ID
- //! \param pWeight Vertex weight factor
- aiVertexWeight( unsigned int pID, float pWeight)
- : mVertexId( pID), mWeight( pWeight)
- { /* nothing to do here */ }
+ //! Initialisation from a given index and vertex weight factor
+ //! \param pID ID
+ //! \param pWeight Vertex weight factor
+ aiVertexWeight( unsigned int pID, float pWeight)
+ : mVertexId( pID), mWeight( pWeight)
+ { /* nothing to do here */ }
#endif // __cplusplus
};
@@ -227,58 +227,59 @@ struct aiVertexWeight
/** @brief A single bone of a mesh.
*
* A bone has a name by which it can be found in the frame hierarchy and by
- * which it can be addressed by animations. In addition it has a number of
+ * which it can be addressed by animations. In addition it has a number of
* influences on vertices.
*/
struct aiBone
{
- //! The name of the bone.
- C_STRUCT aiString mName;
+ //! The name of the bone.
+ C_STRUCT aiString mName;
- //! The number of vertices affected by this bone
- //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
- unsigned int mNumWeights;
+ //! The number of vertices affected by this bone
+ //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
+ unsigned int mNumWeights;
- //! The vertices affected by this bone
- C_STRUCT aiVertexWeight* mWeights;
+ //! The vertices affected by this bone
+ C_STRUCT aiVertexWeight* mWeights;
- //! Matrix that transforms from mesh space to bone space in bind pose
- C_STRUCT aiMatrix4x4 mOffsetMatrix;
+ //! Matrix that transforms from mesh space to bone space in bind pose
+ C_STRUCT aiMatrix4x4 mOffsetMatrix;
#ifdef __cplusplus
- //! Default constructor
- aiBone()
- : mNumWeights( 0 )
+ //! Default constructor
+ aiBone()
+ : mName()
+ , mNumWeights( 0 )
, mWeights( NULL )
- {
- }
+ {
+ }
- //! Copy constructor
- aiBone(const aiBone& other)
+ //! Copy constructor
+ aiBone(const aiBone& other)
: mName( other.mName )
, mNumWeights( other.mNumWeights )
, mOffsetMatrix( other.mOffsetMatrix )
- {
- if (other.mWeights && other.mNumWeights)
- {
- mWeights = new aiVertexWeight[mNumWeights];
- ::memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
- }
- }
-
- //! Destructor - deletes the array of vertex weights
- ~aiBone()
- {
- delete [] mWeights;
- }
+ {
+ if (other.mWeights && other.mNumWeights)
+ {
+ mWeights = new aiVertexWeight[mNumWeights];
+ ::memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
+ }
+ }
+
+ //! Destructor - deletes the array of vertex weights
+ ~aiBone()
+ {
+ delete [] mWeights;
+ }
#endif // __cplusplus
};
// ---------------------------------------------------------------------------
/** @brief Enumerates the types of geometric primitives supported by Assimp.
- *
+ *
* @see aiFace Face data structure
* @see aiProcess_SortByPType Per-primitive sorting of meshes
* @see aiProcess_Triangulate Automatic triangulation
@@ -286,163 +287,163 @@ struct aiBone
*/
enum aiPrimitiveType
{
- /** A point primitive.
- *
- * This is just a single vertex in the virtual world,
- * #aiFace contains just one index for such a primitive.
- */
- aiPrimitiveType_POINT = 0x1,
-
- /** A line primitive.
- *
- * This is a line defined through a start and an end position.
- * #aiFace contains exactly two indices for such a primitive.
- */
- aiPrimitiveType_LINE = 0x2,
-
- /** A triangular primitive.
- *
- * A triangle consists of three indices.
- */
- aiPrimitiveType_TRIANGLE = 0x4,
-
- /** A higher-level polygon with more than 3 edges.
- *
- * A triangle is a polygon, but polygon in this context means
- * "all polygons that are not triangles". The "Triangulate"-Step
- * is provided for your convenience, it splits all polygons in
- * triangles (which are much easier to handle).
- */
- aiPrimitiveType_POLYGON = 0x8,
-
-
- /** This value is not used. It is just here to force the
- * compiler to map this enum to a 32 Bit integer.
- */
+ /** A point primitive.
+ *
+ * This is just a single vertex in the virtual world,
+ * #aiFace contains just one index for such a primitive.
+ */
+ aiPrimitiveType_POINT = 0x1,
+
+ /** A line primitive.
+ *
+ * This is a line defined through a start and an end position.
+ * #aiFace contains exactly two indices for such a primitive.
+ */
+ aiPrimitiveType_LINE = 0x2,
+
+ /** A triangular primitive.
+ *
+ * A triangle consists of three indices.
+ */
+ aiPrimitiveType_TRIANGLE = 0x4,
+
+ /** A higher-level polygon with more than 3 edges.
+ *
+ * A triangle is a polygon, but polygon in this context means
+ * "all polygons that are not triangles". The "Triangulate"-Step
+ * is provided for your convenience, it splits all polygons in
+ * triangles (which are much easier to handle).
+ */
+ aiPrimitiveType_POLYGON = 0x8,
+
+
+ /** This value is not used. It is just here to force the
+ * compiler to map this enum to a 32 Bit integer.
+ */
#ifndef SWIG
- _aiPrimitiveType_Force32Bit = INT_MAX
+ _aiPrimitiveType_Force32Bit = INT_MAX
#endif
}; //! enum aiPrimitiveType
// Get the #aiPrimitiveType flag for a specific number of face indices
#define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
- ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
+ ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
// ---------------------------------------------------------------------------
-/** @brief NOT CURRENTLY IN USE. An AnimMesh is an attachment to an #aiMesh stores per-vertex
+/** @brief NOT CURRENTLY IN USE. An AnimMesh is an attachment to an #aiMesh stores per-vertex
* animations for a particular frame.
- *
+ *
* You may think of an #aiAnimMesh as a `patch` for the host mesh, which
- * replaces only certain vertex data streams at a particular time.
+ * replaces only certain vertex data streams at a particular time.
* Each mesh stores n attached attached meshes (#aiMesh::mAnimMeshes).
- * The actual relationship between the time line and anim meshes is
+ * The actual relationship between the time line and anim meshes is
* established by #aiMeshAnim, which references singular mesh attachments
* by their ID and binds them to a time offset.
*/
struct aiAnimMesh
{
- /** Replacement for aiMesh::mVertices. If this array is non-NULL,
- * it *must* contain mNumVertices entries. The corresponding
- * array in the host mesh must be non-NULL as well - animation
- * meshes may neither add or nor remove vertex components (if
- * a replacement array is NULL and the corresponding source
- * array is not, the source data is taken instead)*/
- C_STRUCT aiVector3D* mVertices;
-
- /** Replacement for aiMesh::mNormals. */
- C_STRUCT aiVector3D* mNormals;
-
- /** Replacement for aiMesh::mTangents. */
- C_STRUCT aiVector3D* mTangents;
-
- /** Replacement for aiMesh::mBitangents. */
- C_STRUCT aiVector3D* mBitangents;
-
- /** Replacement for aiMesh::mColors */
- C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
-
- /** Replacement for aiMesh::mTextureCoords */
- C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-
- /** The number of vertices in the aiAnimMesh, and thus the length of all
- * the member arrays.
- *
- * This has always the same value as the mNumVertices property in the
- * corresponding aiMesh. It is duplicated here merely to make the length
- * of the member arrays accessible even if the aiMesh is not known, e.g.
- * from language bindings.
- */
- unsigned int mNumVertices;
+ /** Replacement for aiMesh::mVertices. If this array is non-NULL,
+ * it *must* contain mNumVertices entries. The corresponding
+ * array in the host mesh must be non-NULL as well - animation
+ * meshes may neither add or nor remove vertex components (if
+ * a replacement array is NULL and the corresponding source
+ * array is not, the source data is taken instead)*/
+ C_STRUCT aiVector3D* mVertices;
+
+ /** Replacement for aiMesh::mNormals. */
+ C_STRUCT aiVector3D* mNormals;
+
+ /** Replacement for aiMesh::mTangents. */
+ C_STRUCT aiVector3D* mTangents;
+
+ /** Replacement for aiMesh::mBitangents. */
+ C_STRUCT aiVector3D* mBitangents;
+
+ /** Replacement for aiMesh::mColors */
+ C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ /** Replacement for aiMesh::mTextureCoords */
+ C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ /** The number of vertices in the aiAnimMesh, and thus the length of all
+ * the member arrays.
+ *
+ * This has always the same value as the mNumVertices property in the
+ * corresponding aiMesh. It is duplicated here merely to make the length
+ * of the member arrays accessible even if the aiMesh is not known, e.g.
+ * from language bindings.
+ */
+ unsigned int mNumVertices;
/** Weight of the AnimMesh. */
float mWeight;
#ifdef __cplusplus
- aiAnimMesh()
- : mVertices( NULL )
- , mNormals( NULL )
- , mTangents( NULL )
- , mBitangents( NULL )
- , mNumVertices( 0 )
- {
- // fixme consider moving this to the ctor initializer list as well
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
- mTextureCoords[a] = NULL;
- }
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
- mColors[a] = NULL;
- }
- }
-
- ~aiAnimMesh()
- {
- delete [] mVertices;
- delete [] mNormals;
- delete [] mTangents;
- delete [] mBitangents;
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
- delete [] mTextureCoords[a];
- }
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
- delete [] mColors[a];
- }
- }
-
- /** Check whether the anim mesh overrides the vertex positions
- * of its host mesh*/
- bool HasPositions() const {
- return mVertices != NULL;
- }
-
- /** Check whether the anim mesh overrides the vertex normals
- * of its host mesh*/
- bool HasNormals() const {
- return mNormals != NULL;
- }
-
- /** Check whether the anim mesh overrides the vertex tangents
- * and bitangents of its host mesh. As for aiMesh,
- * tangents and bitangents always go together. */
- bool HasTangentsAndBitangents() const {
- return mTangents != NULL;
- }
-
- /** Check whether the anim mesh overrides a particular
- * set of vertex colors on his host mesh.
- * @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS */
- bool HasVertexColors( unsigned int pIndex) const {
- return pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != NULL;
- }
-
- /** Check whether the anim mesh overrides a particular
- * set of texture coordinates on his host mesh.
- * @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS */
- bool HasTextureCoords( unsigned int pIndex) const {
- return pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != NULL;
- }
+ aiAnimMesh()
+ : mVertices( NULL )
+ , mNormals( NULL )
+ , mTangents( NULL )
+ , mBitangents( NULL )
+ , mNumVertices( 0 )
+ {
+ // fixme consider moving this to the ctor initializer list as well
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
+ mTextureCoords[a] = NULL;
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
+ mColors[a] = NULL;
+ }
+ }
+
+ ~aiAnimMesh()
+ {
+ delete [] mVertices;
+ delete [] mNormals;
+ delete [] mTangents;
+ delete [] mBitangents;
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
+ delete [] mTextureCoords[a];
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
+ delete [] mColors[a];
+ }
+ }
+
+ /** Check whether the anim mesh overrides the vertex positions
+ * of its host mesh*/
+ bool HasPositions() const {
+ return mVertices != NULL;
+ }
+
+ /** Check whether the anim mesh overrides the vertex normals
+ * of its host mesh*/
+ bool HasNormals() const {
+ return mNormals != NULL;
+ }
+
+ /** Check whether the anim mesh overrides the vertex tangents
+ * and bitangents of its host mesh. As for aiMesh,
+ * tangents and bitangents always go together. */
+ bool HasTangentsAndBitangents() const {
+ return mTangents != NULL;
+ }
+
+ /** Check whether the anim mesh overrides a particular
+ * set of vertex colors on his host mesh.
+ * @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS */
+ bool HasVertexColors( unsigned int pIndex) const {
+ return pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != NULL;
+ }
+
+ /** Check whether the anim mesh overrides a particular
+ * set of texture coordinates on his host mesh.
+ * @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS */
+ bool HasTextureCoords( unsigned int pIndex) const {
+ return pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != NULL;
+ }
#endif
};
@@ -470,291 +471,289 @@ enum aiMorphingMethod
}; //! enum aiMorphingMethod
// ---------------------------------------------------------------------------
-/** @brief A mesh represents a geometry or model with a single material.
+/** @brief A mesh represents a geometry or model with a single material.
*
-* It usually consists of a number of vertices and a series of primitives/faces
-* referencing the vertices. In addition there might be a series of bones, each
-* of them addressing a number of vertices with a certain weight. Vertex data
-* is presented in channels with each channel containing a single per-vertex
+* It usually consists of a number of vertices and a series of primitives/faces
+* referencing the vertices. In addition there might be a series of bones, each
+* of them addressing a number of vertices with a certain weight. Vertex data
+* is presented in channels with each channel containing a single per-vertex
* information such as a set of texture coords or a normal vector.
* If a data pointer is non-null, the corresponding data stream is present.
* From C++-programs you can also use the comfort functions Has*() to
* test for the presence of various data streams.
*
* A Mesh uses only a single material which is referenced by a material ID.
-* @note The mPositions member is usually not optional. However, vertex positions
-* *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in
+* @note The mPositions member is usually not optional. However, vertex positions
+* *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in
* @code
* aiScene::mFlags
* @endcode
*/
struct aiMesh
{
- /** Bitwise combination of the members of the #aiPrimitiveType enum.
- * This specifies which types of primitives are present in the mesh.
- * The "SortByPrimitiveType"-Step can be used to make sure the
- * output meshes consist of one primitive type each.
- */
- unsigned int mPrimitiveTypes;
-
- /** The number of vertices in this mesh.
- * This is also the size of all of the per-vertex data arrays.
- * The maximum value for this member is #AI_MAX_VERTICES.
- */
- unsigned int mNumVertices;
-
- /** The number of primitives (triangles, polygons, lines) in this mesh.
- * This is also the size of the mFaces array.
- * The maximum value for this member is #AI_MAX_FACES.
- */
- unsigned int mNumFaces;
-
- /** Vertex positions.
- * This array is always present in a mesh. The array is
- * mNumVertices in size.
- */
- C_STRUCT aiVector3D* mVertices;
-
- /** Vertex normals.
- * The array contains normalized vectors, NULL if not present.
- * The array is mNumVertices in size. Normals are undefined for
- * point and line primitives. A mesh consisting of points and
- * lines only may not have normal vectors. Meshes with mixed
- * primitive types (i.e. lines and triangles) may have normals,
- * but the normals for vertices that are only referenced by
- * point or line primitives are undefined and set to QNaN (WARN:
- * qNaN compares to inequal to *everything*, even to qNaN itself.
- * Using code like this to check whether a field is qnan is:
- * @code
- * #define IS_QNAN(f) (f != f)
- * @endcode
- * still dangerous because even 1.f == 1.f could evaluate to false! (
- * remember the subtleties of IEEE754 artithmetics). Use stuff like
- * @c fpclassify instead.
- * @note Normal vectors computed by Assimp are always unit-length.
- * However, this needn't apply for normals that have been taken
- * directly from the model file.
- */
- C_STRUCT aiVector3D* mNormals;
-
- /** Vertex tangents.
- * The tangent of a vertex points in the direction of the positive
- * X texture axis. The array contains normalized vectors, NULL if
- * not present. The array is mNumVertices in size. A mesh consisting
- * of points and lines only may not have normal vectors. Meshes with
- * mixed primitive types (i.e. lines and triangles) may have
- * normals, but the normals for vertices that are only referenced by
- * point or line primitives are undefined and set to qNaN. See
- * the #mNormals member for a detailled discussion of qNaNs.
- * @note If the mesh contains tangents, it automatically also
- * contains bitangents.
- */
- C_STRUCT aiVector3D* mTangents;
-
- /** Vertex bitangents.
- * The bitangent of a vertex points in the direction of the positive
- * Y texture axis. The array contains normalized vectors, NULL if not
- * present. The array is mNumVertices in size.
- * @note If the mesh contains tangents, it automatically also contains
- * bitangents.
- */
- C_STRUCT aiVector3D* mBitangents;
-
- /** Vertex color sets.
- * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex
- * colors per vertex. NULL if not present. Each array is
- * mNumVertices in size if present.
- */
- C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
-
- /** Vertex texture coords, also known as UV channels.
- * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
- * vertex. NULL if not present. The array is mNumVertices in size.
- */
- C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-
- /** Specifies the number of components for a given UV channel.
- * Up to three channels are supported (UVW, for accessing volume
- * or cube maps). If the value is 2 for a given channel n, the
- * component p.z of mTextureCoords[n][p] is set to 0.0f.
- * If the value is 1 for a given channel, p.y is set to 0.0f, too.
- * @note 4D coords are not supported
- */
- unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-
- /** The faces the mesh is constructed from.
- * Each face refers to a number of vertices by their indices.
- * This array is always present in a mesh, its size is given
- * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
- * is NOT set each face references an unique set of vertices.
- */
- C_STRUCT aiFace* mFaces;
-
- /** The number of bones this mesh contains.
- * Can be 0, in which case the mBones array is NULL.
- */
- unsigned int mNumBones;
-
- /** The bones of this mesh.
- * A bone consists of a name by which it can be found in the
- * frame hierarchy and a set of vertex weights.
- */
- C_STRUCT aiBone** mBones;
-
- /** The material used by this mesh.
- * A mesh does use only a single material. If an imported model uses
- * multiple materials, the import splits up the mesh. Use this value
- * as index into the scene's material list.
- */
- unsigned int mMaterialIndex;
-
- /** Name of the mesh. Meshes can be named, but this is not a
- * requirement and leaving this field empty is totally fine.
- * There are mainly three uses for mesh names:
- * - some formats name nodes and meshes independently.
- * - importers tend to split meshes up to meet the
- * one-material-per-mesh requirement. Assigning
- * the same (dummy) name to each of the result meshes
- * aids the caller at recovering the original mesh
- * partitioning.
- * - Vertex animations refer to meshes by their names.
- **/
- C_STRUCT aiString mName;
-
-
- /** The number of attachment meshes. Note! Currently only works with Collada loader. */
- unsigned int mNumAnimMeshes;
-
- /** Attachment meshes for this mesh, for vertex-based animation.
- * Attachment meshes carry replacement data for some of the
- * mesh'es vertex components (usually positions, normals).
- * Note! Currently only works with Collada loader.*/
- C_STRUCT aiAnimMesh** mAnimMeshes;
+ /** Bitwise combination of the members of the #aiPrimitiveType enum.
+ * This specifies which types of primitives are present in the mesh.
+ * The "SortByPrimitiveType"-Step can be used to make sure the
+ * output meshes consist of one primitive type each.
+ */
+ unsigned int mPrimitiveTypes;
+
+ /** The number of vertices in this mesh.
+ * This is also the size of all of the per-vertex data arrays.
+ * The maximum value for this member is #AI_MAX_VERTICES.
+ */
+ unsigned int mNumVertices;
+
+ /** The number of primitives (triangles, polygons, lines) in this mesh.
+ * This is also the size of the mFaces array.
+ * The maximum value for this member is #AI_MAX_FACES.
+ */
+ unsigned int mNumFaces;
+
+ /** Vertex positions.
+ * This array is always present in a mesh. The array is
+ * mNumVertices in size.
+ */
+ C_STRUCT aiVector3D* mVertices;
+
+ /** Vertex normals.
+ * The array contains normalized vectors, NULL if not present.
+ * The array is mNumVertices in size. Normals are undefined for
+ * point and line primitives. A mesh consisting of points and
+ * lines only may not have normal vectors. Meshes with mixed
+ * primitive types (i.e. lines and triangles) may have normals,
+ * but the normals for vertices that are only referenced by
+ * point or line primitives are undefined and set to QNaN (WARN:
+ * qNaN compares to inequal to *everything*, even to qNaN itself.
+ * Using code like this to check whether a field is qnan is:
+ * @code
+ * #define IS_QNAN(f) (f != f)
+ * @endcode
+ * still dangerous because even 1.f == 1.f could evaluate to false! (
+ * remember the subtleties of IEEE754 artithmetics). Use stuff like
+ * @c fpclassify instead.
+ * @note Normal vectors computed by Assimp are always unit-length.
+ * However, this needn't apply for normals that have been taken
+ * directly from the model file.
+ */
+ C_STRUCT aiVector3D* mNormals;
+
+ /** Vertex tangents.
+ * The tangent of a vertex points in the direction of the positive
+ * X texture axis. The array contains normalized vectors, NULL if
+ * not present. The array is mNumVertices in size. A mesh consisting
+ * of points and lines only may not have normal vectors. Meshes with
+ * mixed primitive types (i.e. lines and triangles) may have
+ * normals, but the normals for vertices that are only referenced by
+ * point or line primitives are undefined and set to qNaN. See
+ * the #mNormals member for a detailed discussion of qNaNs.
+ * @note If the mesh contains tangents, it automatically also
+ * contains bitangents.
+ */
+ C_STRUCT aiVector3D* mTangents;
+
+ /** Vertex bitangents.
+ * The bitangent of a vertex points in the direction of the positive
+ * Y texture axis. The array contains normalized vectors, NULL if not
+ * present. The array is mNumVertices in size.
+ * @note If the mesh contains tangents, it automatically also contains
+ * bitangents.
+ */
+ C_STRUCT aiVector3D* mBitangents;
+
+ /** Vertex color sets.
+ * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex
+ * colors per vertex. NULL if not present. Each array is
+ * mNumVertices in size if present.
+ */
+ C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ /** Vertex texture coords, also known as UV channels.
+ * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
+ * vertex. NULL if not present. The array is mNumVertices in size.
+ */
+ C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ /** Specifies the number of components for a given UV channel.
+ * Up to three channels are supported (UVW, for accessing volume
+ * or cube maps). If the value is 2 for a given channel n, the
+ * component p.z of mTextureCoords[n][p] is set to 0.0f.
+ * If the value is 1 for a given channel, p.y is set to 0.0f, too.
+ * @note 4D coords are not supported
+ */
+ unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ /** The faces the mesh is constructed from.
+ * Each face refers to a number of vertices by their indices.
+ * This array is always present in a mesh, its size is given
+ * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
+ * is NOT set each face references an unique set of vertices.
+ */
+ C_STRUCT aiFace* mFaces;
+
+ /** The number of bones this mesh contains.
+ * Can be 0, in which case the mBones array is NULL.
+ */
+ unsigned int mNumBones;
+
+ /** The bones of this mesh.
+ * A bone consists of a name by which it can be found in the
+ * frame hierarchy and a set of vertex weights.
+ */
+ C_STRUCT aiBone** mBones;
+
+ /** The material used by this mesh.
+ * A mesh uses only a single material. If an imported model uses
+ * multiple materials, the import splits up the mesh. Use this value
+ * as index into the scene's material list.
+ */
+ unsigned int mMaterialIndex;
+
+ /** Name of the mesh. Meshes can be named, but this is not a
+ * requirement and leaving this field empty is totally fine.
+ * There are mainly three uses for mesh names:
+ * - some formats name nodes and meshes independently.
+ * - importers tend to split meshes up to meet the
+ * one-material-per-mesh requirement. Assigning
+ * the same (dummy) name to each of the result meshes
+ * aids the caller at recovering the original mesh
+ * partitioning.
+ * - Vertex animations refer to meshes by their names.
+ **/
+ C_STRUCT aiString mName;
+
+
+ /** NOT CURRENTLY IN USE. The number of attachment meshes */
+ unsigned int mNumAnimMeshes;
+
+ /** NOT CURRENTLY IN USE. Attachment meshes for this mesh, for vertex-based animation.
+ * Attachment meshes carry replacement data for some of the
+ * mesh'es vertex components (usually positions, normals). */
+ C_STRUCT aiAnimMesh** mAnimMeshes;
/** Method of morphing when animeshes are specified. */
unsigned int mMethod;
#ifdef __cplusplus
- //! Default constructor. Initializes all members to 0
- aiMesh()
- : mPrimitiveTypes( 0 )
- , mNumVertices( 0 )
- , mNumFaces( 0 )
- , mVertices( NULL )
- , mNormals( NULL )
- , mTangents( NULL )
- , mBitangents( NULL )
- , mFaces( NULL )
- , mNumBones( 0 )
- , mBones( NULL )
- , mMaterialIndex( 0 )
- , mNumAnimMeshes( 0 )
- , mAnimMeshes( NULL )
- {
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
- {
- mNumUVComponents[a] = 0;
- mTextureCoords[a] = NULL;
- }
-
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
- mColors[a] = NULL;
- }
-
- //! Deletes all storage allocated for the mesh
- ~aiMesh()
- {
- delete [] mVertices;
- delete [] mNormals;
- delete [] mTangents;
- delete [] mBitangents;
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
- delete [] mTextureCoords[a];
- }
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
- delete [] mColors[a];
- }
-
- // DO NOT REMOVE THIS ADDITIONAL CHECK
- if (mNumBones && mBones) {
- for( unsigned int a = 0; a < mNumBones; a++) {
- delete mBones[a];
- }
- delete [] mBones;
- }
-
- if (mNumAnimMeshes && mAnimMeshes) {
- for( unsigned int a = 0; a < mNumAnimMeshes; a++) {
- delete mAnimMeshes[a];
- }
- delete [] mAnimMeshes;
- }
-
- delete [] mFaces;
- }
-
- //! Check whether the mesh contains positions. Provided no special
- //! scene flags are set (such as #AI_SCENE_FLAGS_ANIM_SKELETON_ONLY),
- //! this will always be true
- bool HasPositions() const
- { return mVertices != NULL && mNumVertices > 0; }
-
- //! Check whether the mesh contains faces. If no special scene flags
- //! are set this should always return true
- bool HasFaces() const
- { return mFaces != NULL && mNumFaces > 0; }
-
- //! Check whether the mesh contains normal vectors
- bool HasNormals() const
- { return mNormals != NULL && mNumVertices > 0; }
-
- //! Check whether the mesh contains tangent and bitangent vectors
- //! It is not possible that it contains tangents and no bitangents
- //! (or the other way round). The existence of one of them
- //! implies that the second is there, too.
- bool HasTangentsAndBitangents() const
- { return mTangents != NULL && mBitangents != NULL && mNumVertices > 0; }
-
- //! Check whether the mesh contains a vertex color set
- //! \param pIndex Index of the vertex color set
- bool HasVertexColors( unsigned int pIndex) const
- {
- if( pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS)
- return false;
- else
- return mColors[pIndex] != NULL && mNumVertices > 0;
- }
-
- //! Check whether the mesh contains a texture coordinate set
- //! \param pIndex Index of the texture coordinates set
- bool HasTextureCoords( unsigned int pIndex) const
- {
- if( pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS)
- return false;
- else
- return mTextureCoords[pIndex] != NULL && mNumVertices > 0;
- }
-
- //! Get the number of UV channels the mesh contains
- unsigned int GetNumUVChannels() const
- {
- unsigned int n = 0;
- while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mTextureCoords[n])++n;
- return n;
- }
-
- //! Get the number of vertex color channels the mesh contains
- unsigned int GetNumColorChannels() const
- {
- unsigned int n = 0;
- while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n])++n;
- return n;
- }
-
- //! Check whether the mesh contains bones
- inline bool HasBones() const
- { return mBones != NULL && mNumBones > 0; }
+ //! Default constructor. Initializes all members to 0
+ aiMesh()
+ : mPrimitiveTypes( 0 )
+ , mNumVertices( 0 )
+ , mNumFaces( 0 )
+ , mVertices( NULL )
+ , mNormals( NULL )
+ , mTangents( NULL )
+ , mBitangents( NULL )
+ , mFaces( NULL )
+ , mNumBones( 0 )
+ , mBones( NULL )
+ , mMaterialIndex( 0 )
+ , mNumAnimMeshes( 0 )
+ , mAnimMeshes( NULL )
+ {
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
+ {
+ mNumUVComponents[a] = 0;
+ mTextureCoords[a] = NULL;
+ }
+
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
+ mColors[a] = NULL;
+ }
+
+ //! Deletes all storage allocated for the mesh
+ ~aiMesh()
+ {
+ delete [] mVertices;
+ delete [] mNormals;
+ delete [] mTangents;
+ delete [] mBitangents;
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
+ delete [] mTextureCoords[a];
+ }
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
+ delete [] mColors[a];
+ }
+
+ // DO NOT REMOVE THIS ADDITIONAL CHECK
+ if (mNumBones && mBones) {
+ for( unsigned int a = 0; a < mNumBones; a++) {
+ delete mBones[a];
+ }
+ delete [] mBones;
+ }
+
+ if (mNumAnimMeshes && mAnimMeshes) {
+ for( unsigned int a = 0; a < mNumAnimMeshes; a++) {
+ delete mAnimMeshes[a];
+ }
+ delete [] mAnimMeshes;
+ }
+
+ delete [] mFaces;
+ }
+
+ //! Check whether the mesh contains positions. Provided no special
+ //! scene flags are set, this will always be true
+ bool HasPositions() const
+ { return mVertices != NULL && mNumVertices > 0; }
+
+ //! Check whether the mesh contains faces. If no special scene flags
+ //! are set this should always return true
+ bool HasFaces() const
+ { return mFaces != NULL && mNumFaces > 0; }
+
+ //! Check whether the mesh contains normal vectors
+ bool HasNormals() const
+ { return mNormals != NULL && mNumVertices > 0; }
+
+ //! Check whether the mesh contains tangent and bitangent vectors
+ //! It is not possible that it contains tangents and no bitangents
+ //! (or the other way round). The existence of one of them
+ //! implies that the second is there, too.
+ bool HasTangentsAndBitangents() const
+ { return mTangents != NULL && mBitangents != NULL && mNumVertices > 0; }
+
+ //! Check whether the mesh contains a vertex color set
+ //! \param pIndex Index of the vertex color set
+ bool HasVertexColors( unsigned int pIndex) const
+ {
+ if( pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS)
+ return false;
+ else
+ return mColors[pIndex] != NULL && mNumVertices > 0;
+ }
+
+ //! Check whether the mesh contains a texture coordinate set
+ //! \param pIndex Index of the texture coordinates set
+ bool HasTextureCoords( unsigned int pIndex) const
+ {
+ if( pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS)
+ return false;
+ else
+ return mTextureCoords[pIndex] != NULL && mNumVertices > 0;
+ }
+
+ //! Get the number of UV channels the mesh contains
+ unsigned int GetNumUVChannels() const
+ {
+ unsigned int n = 0;
+ while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mTextureCoords[n])++n;
+ return n;
+ }
+
+ //! Get the number of vertex color channels the mesh contains
+ unsigned int GetNumColorChannels() const
+ {
+ unsigned int n = 0;
+ while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n])++n;
+ return n;
+ }
+
+ //! Check whether the mesh contains bones
+ inline bool HasBones() const
+ { return mBones != NULL && mNumBones > 0; }
#endif // __cplusplus
};
diff --git a/src/3rdparty/assimp/include/assimp/metadata.h b/src/3rdparty/assimp/include/assimp/metadata.h
index 16809a511..579ccd446 100644
--- a/src/3rdparty/assimp/include/assimp/metadata.h
+++ b/src/3rdparty/assimp/include/assimp/metadata.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.
---------------------------------------------------------------------------
*/
@@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if defined(_MSC_VER) && (_MSC_VER <= 1500)
#include "Compiler/pstdint.h"
#else
+#include <limits.h>
#include <stdint.h>
#endif
@@ -62,15 +63,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -------------------------------------------------------------------------------
typedef enum aiMetadataType
{
- AI_BOOL = 0,
- AI_INT = 1,
- AI_UINT64 = 2,
- AI_FLOAT = 3,
- AI_AISTRING = 4,
- AI_AIVECTOR3D = 5,
+ AI_BOOL = 0,
+ AI_INT = 1,
+ AI_UINT64 = 2,
+ AI_FLOAT = 3,
+ AI_AISTRING = 4,
+ AI_AIVECTOR3D = 5,
#ifndef SWIG
- FORCE_32BIT = INT_MAX
+ FORCE_32BIT = INT_MAX
#endif
} aiMetadataType;
@@ -85,8 +86,8 @@ typedef enum aiMetadataType
// -------------------------------------------------------------------------------
struct aiMetadataEntry
{
- aiMetadataType mType;
- void* mData;
+ aiMetadataType mType;
+ void* mData;
};
@@ -106,8 +107,8 @@ inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
inline aiMetadataType GetAiType( int ) { return AI_INT; }
inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
-inline aiMetadataType GetAiType( aiString ) { return AI_AISTRING; }
-inline aiMetadataType GetAiType( aiVector3D ) { return AI_AIVECTOR3D; }
+inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; }
+inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
@@ -122,120 +123,123 @@ inline aiMetadataType GetAiType( aiVector3D ) { return AI_AIVECTOR3D; }
* Metadata is a key-value store using string keys and values.
*/
// -------------------------------------------------------------------------------
-struct aiMetadata
+struct aiMetadata
{
- /** Length of the mKeys and mValues arrays, respectively */
- unsigned int mNumProperties;
+ /** Length of the mKeys and mValues arrays, respectively */
+ unsigned int mNumProperties;
- /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
- C_STRUCT aiString* mKeys;
+ /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
+ C_STRUCT aiString* mKeys;
- /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
- * corresponding property key has no assigned value. */
- C_STRUCT aiMetadataEntry* mValues;
+ /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
+ * corresponding property key has no assigned value. */
+ C_STRUCT aiMetadataEntry* mValues;
#ifdef __cplusplus
- /** Constructor */
- aiMetadata()
- // set all members to zero by default
- : mNumProperties(0)
- , mKeys(NULL)
- , mValues(NULL)
- {}
+ /** Constructor */
+ aiMetadata()
+ // set all members to zero by default
+ : mNumProperties(0)
+ , mKeys(NULL)
+ , mValues(NULL)
+ {}
- /** Destructor */
- ~aiMetadata()
- {
+ /** Destructor */
+ ~aiMetadata()
+ {
delete[] mKeys;
mKeys = NULL;
- if (mValues)
- {
- // Delete each metadata entry
- for (unsigned i=0; i<mNumProperties; ++i)
- {
- void* data = mValues[i].mData;
- switch (mValues[i].mType)
- {
- case AI_BOOL:
- delete static_cast<bool*>(data);
- break;
- case AI_INT:
- delete static_cast<int*>(data);
- break;
- case AI_UINT64:
- delete static_cast<uint64_t*>(data);
- break;
- case AI_FLOAT:
- delete static_cast<float*>(data);
- break;
- case AI_AISTRING:
- delete static_cast<aiString*>(data);
- break;
- case AI_AIVECTOR3D:
- delete static_cast<aiVector3D*>(data);
- break;
- default:
- assert(false);
- break;
- }
- }
-
- // Delete the metadata array
- delete [] mValues;
+ if (mValues)
+ {
+ // Delete each metadata entry
+ for (unsigned i=0; i<mNumProperties; ++i)
+ {
+ void* data = mValues[i].mData;
+ switch (mValues[i].mType)
+ {
+ case AI_BOOL:
+ delete static_cast<bool*>(data);
+ break;
+ case AI_INT:
+ delete static_cast<int*>(data);
+ break;
+ case AI_UINT64:
+ delete static_cast<uint64_t*>(data);
+ break;
+ case AI_FLOAT:
+ delete static_cast<float*>(data);
+ break;
+ case AI_AISTRING:
+ delete static_cast<aiString*>(data);
+ break;
+ case AI_AIVECTOR3D:
+ delete static_cast<aiVector3D*>(data);
+ break;
+#ifndef SWIG
+ case FORCE_32BIT:
+#endif
+ default:
+ assert(false);
+ break;
+ }
+ }
+
+ // Delete the metadata array
+ delete [] mValues;
mValues = NULL;
- }
- }
+ }
+ }
- template<typename T>
- inline void Set( unsigned index, const std::string& key, const T& value )
- {
- // In range assertion
- assert(index < mNumProperties);
+ template<typename T>
+ inline void Set( unsigned index, const std::string& key, const T& value )
+ {
+ // In range assertion
+ assert(index < mNumProperties);
- // Set metadata key
- mKeys[index] = key;
+ // Set metadata key
+ mKeys[index] = key;
- // Set metadata type
- mValues[index].mType = GetAiType(value);
- // Copy the given value to the dynamic storage
- mValues[index].mData = new T(value);
- }
+ // Set metadata type
+ mValues[index].mType = GetAiType(value);
+ // Copy the given value to the dynamic storage
+ mValues[index].mData = new T(value);
+ }
- template<typename T>
- inline bool Get( unsigned index, T& value )
- {
- // In range assertion
- assert(index < mNumProperties);
+ template<typename T>
+ inline bool Get( unsigned index, T& value )
+ {
+ // In range assertion
+ assert(index < mNumProperties);
- // Return false if the output data type does
- // not match the found value's data type
+ // Return false if the output data type does
+ // not match the found value's data type
if ( GetAiType( value ) != mValues[ index ].mType ) {
return false;
}
- // Otherwise, output the found value and
- // return true
- value = *static_cast<T*>(mValues[index].mData);
- return true;
- }
-
- template<typename T>
- inline bool Get( const aiString& key, T& value )
- {
- // Search for the given key
- for (unsigned i=0; i<mNumProperties; ++i)
- if (mKeys[i]==key)
- return Get(i, value);
- return false;
- }
-
- template<typename T>
- inline bool Get( const std::string& key, T& value ) {
- return Get(aiString(key), value);
+ // Otherwise, output the found value and
+ // return true
+ value = *static_cast<T*>(mValues[index].mData);
+ return true;
+ }
+
+ template<typename T>
+ inline bool Get( const aiString& key, T& value )
+ {
+ // Search for the given key
+ for (unsigned i=0; i<mNumProperties; ++i)
+ if (mKeys[i]==key)
+ return Get(i, value);
+ return false;
+ }
+
+ template<typename T>
+ inline bool Get( const std::string& key, T& value ) {
+ return Get(aiString(key), value);
}
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
new file mode 100644
index 000000000..6f806f922
--- /dev/null
+++ b/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
@@ -0,0 +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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Android implementation of IOSystem using the standard C file functions.
+ * Aimed to ease the access to android assets */
+
+#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC
+#define AI_ANDROIDJNIIOSYSTEM_H_INC
+
+#include "../code/DefaultIOSystem.h"
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+#include <android/native_activity.h>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** Android extension to DefaultIOSystem using the standard C file functions */
+class ASSIMP_API AndroidJNIIOSystem : public DefaultIOSystem
+{
+public:
+
+ /** Initialize android activity data */
+ std::string mApkWorkspacePath;
+ AAssetManager* mApkAssetManager;
+
+ /** Constructor. */
+ AndroidJNIIOSystem(ANativeActivity* activity);
+
+ /** Destructor. */
+ ~AndroidJNIIOSystem();
+
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const;
+
+ // -------------------------------------------------------------------
+ /** Opens a file at the given path, with given mode */
+ IOStream* Open( const char* strFile, const char* strMode);
+
+ // ------------------------------------------------------------------------------------------------
+ // Inits Android extractor
+ void AndroidActivityInit(ANativeActivity* activity);
+
+ // ------------------------------------------------------------------------------------------------
+ // Extracts android asset
+ bool AndroidExtractAsset(std::string name);
+
+};
+
+} //!ns Assimp
+
+#endif //AI_ANDROIDJNIIOSYSTEM_H_INC
+#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
diff --git a/src/3rdparty/assimp/include/assimp/postprocess.h b/src/3rdparty/assimp/include/assimp/postprocess.h
index 0eb9abea9..04de7a275 100644
--- a/src/3rdparty/assimp/include/assimp/postprocess.h
+++ b/src/3rdparty/assimp/include/assimp/postprocess.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.
----------------------------------------------------------------------
@@ -65,512 +65,512 @@ extern "C" {
enum aiPostProcessSteps
{
- // -------------------------------------------------------------------------
- /** <hr>Calculates the tangents and bitangents for the imported meshes.
- *
- * Does nothing if a mesh does not have normals. You might want this post
- * processing step to be executed if you plan to use tangent space calculations
- * such as normal mapping applied to the meshes. There's an importer property,
- * <tt>#AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE</tt>, which allows you to specify
- * a maximum smoothing angle for the algorithm. However, usually you'll
- * want to leave it at the default value.
- */
- aiProcess_CalcTangentSpace = 0x1,
-
- // -------------------------------------------------------------------------
- /** <hr>Identifies and joins identical vertex data sets within all
- * imported meshes.
- *
- * After this step is run, each mesh contains unique vertices,
- * so a vertex may be used by multiple faces. You usually want
- * to use this post processing step. If your application deals with
- * indexed geometry, this step is compulsory or you'll just waste rendering
- * time. <b>If this flag is not specified</b>, no vertices are referenced by
- * more than one face and <b>no index buffer is required</b> for rendering.
- */
- aiProcess_JoinIdenticalVertices = 0x2,
-
- // -------------------------------------------------------------------------
- /** <hr>Converts all the imported data to a left-handed coordinate space.
- *
- * By default the data is returned in a right-handed coordinate space (which
- * OpenGL prefers). In this space, +X points to the right,
- * +Z points towards the viewer, and +Y points upwards. In the DirectX
- * coordinate space +X points to the right, +Y points upwards, and +Z points
+ // -------------------------------------------------------------------------
+ /** <hr>Calculates the tangents and bitangents for the imported meshes.
+ *
+ * Does nothing if a mesh does not have normals. You might want this post
+ * processing step to be executed if you plan to use tangent space calculations
+ * such as normal mapping applied to the meshes. There's an importer property,
+ * <tt>#AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE</tt>, which allows you to specify
+ * a maximum smoothing angle for the algorithm. However, usually you'll
+ * want to leave it at the default value.
+ */
+ aiProcess_CalcTangentSpace = 0x1,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Identifies and joins identical vertex data sets within all
+ * imported meshes.
+ *
+ * After this step is run, each mesh contains unique vertices,
+ * so a vertex may be used by multiple faces. You usually want
+ * to use this post processing step. If your application deals with
+ * indexed geometry, this step is compulsory or you'll just waste rendering
+ * time. <b>If this flag is not specified</b>, no vertices are referenced by
+ * more than one face and <b>no index buffer is required</b> for rendering.
+ */
+ aiProcess_JoinIdenticalVertices = 0x2,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Converts all the imported data to a left-handed coordinate space.
+ *
+ * By default the data is returned in a right-handed coordinate space (which
+ * OpenGL prefers). In this space, +X points to the right,
+ * +Z points towards the viewer, and +Y points upwards. In the DirectX
+ * coordinate space +X points to the right, +Y points upwards, and +Z points
* away from the viewer.
- *
- * You'll probably want to consider this flag if you use Direct3D for
- * rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
- * setting and bundles all conversions typically required for D3D-based
- * applications.
- */
- aiProcess_MakeLeftHanded = 0x4,
-
- // -------------------------------------------------------------------------
- /** <hr>Triangulates all faces of all meshes.
- *
- * By default the imported mesh data might contain faces with more than 3
- * indices. For rendering you'll usually want all faces to be triangles.
- * This post processing step splits up faces with more than 3 indices into
- * triangles. Line and point primitives are *not* modified! If you want
- * 'triangles only' with no other kinds of primitives, try the following
- * solution:
- * <ul>
- * <li>Specify both #aiProcess_Triangulate and #aiProcess_SortByPType </li>
- * <li>Ignore all point and line meshes when you process assimp's output</li>
- * </ul>
- */
- aiProcess_Triangulate = 0x8,
-
- // -------------------------------------------------------------------------
- /** <hr>Removes some parts of the data structure (animations, materials,
- * light sources, cameras, textures, vertex components).
- *
- * The components to be removed are specified in a separate
- * importer property, <tt>#AI_CONFIG_PP_RVC_FLAGS</tt>. This is quite useful
- * if you don't need all parts of the output structure. Vertex colors
- * are rarely used today for example... Calling this step to remove unneeded
- * data from the pipeline as early as possible results in increased
- * performance and a more optimized output data structure.
- * This step is also useful if you want to force Assimp to recompute
- * normals or tangents. The corresponding steps don't recompute them if
- * they're already there (loaded from the source asset). By using this
- * step you can make sure they are NOT there.
- *
- * This flag is a poor one, mainly because its purpose is usually
+ *
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
+ * setting and bundles all conversions typically required for D3D-based
+ * applications.
+ */
+ aiProcess_MakeLeftHanded = 0x4,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Triangulates all faces of all meshes.
+ *
+ * By default the imported mesh data might contain faces with more than 3
+ * indices. For rendering you'll usually want all faces to be triangles.
+ * This post processing step splits up faces with more than 3 indices into
+ * triangles. Line and point primitives are *not* modified! If you want
+ * 'triangles only' with no other kinds of primitives, try the following
+ * solution:
+ * <ul>
+ * <li>Specify both #aiProcess_Triangulate and #aiProcess_SortByPType </li>
+ * <li>Ignore all point and line meshes when you process assimp's output</li>
+ * </ul>
+ */
+ aiProcess_Triangulate = 0x8,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Removes some parts of the data structure (animations, materials,
+ * light sources, cameras, textures, vertex components).
+ *
+ * The components to be removed are specified in a separate
+ * importer property, <tt>#AI_CONFIG_PP_RVC_FLAGS</tt>. This is quite useful
+ * if you don't need all parts of the output structure. Vertex colors
+ * are rarely used today for example... Calling this step to remove unneeded
+ * data from the pipeline as early as possible results in increased
+ * performance and a more optimized output data structure.
+ * This step is also useful if you want to force Assimp to recompute
+ * normals or tangents. The corresponding steps don't recompute them if
+ * they're already there (loaded from the source asset). By using this
+ * step you can make sure they are NOT there.
+ *
+ * This flag is a poor one, mainly because its purpose is usually
* misunderstood. Consider the following case: a 3D model has been exported
- * from a CAD app, and it has per-face vertex colors. Vertex positions can't be
- * shared, thus the #aiProcess_JoinIdenticalVertices step fails to
- * optimize the data because of these nasty little vertex colors.
- * Most apps don't even process them, so it's all for nothing. By using
- * this step, unneeded components are excluded as early as possible
- * thus opening more room for internal optimizations.
- */
- aiProcess_RemoveComponent = 0x10,
-
- // -------------------------------------------------------------------------
- /** <hr>Generates normals for all faces of all meshes.
- *
- * This is ignored if normals are already there at the time this flag
- * is evaluated. Model importers try to load them from the source file, so
- * they're usually already there. Face normals are shared between all points
- * of a single face, so a single point can have multiple normals, which
- * forces the library to duplicate vertices in some cases.
- * #aiProcess_JoinIdenticalVertices is *senseless* then.
- *
- * This flag may not be specified together with #aiProcess_GenSmoothNormals.
- */
- aiProcess_GenNormals = 0x20,
-
- // -------------------------------------------------------------------------
- /** <hr>Generates smooth normals for all vertices in the mesh.
- *
- * This is ignored if normals are already there at the time this flag
- * is evaluated. Model importers try to load them from the source file, so
- * they're usually already there.
- *
- * This flag may not be specified together with
- * #aiProcess_GenNormals. There's a importer property,
- * <tt>#AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE</tt> which allows you to specify
- * an angle maximum for the normal smoothing algorithm. Normals exceeding
- * this limit are not smoothed, resulting in a 'hard' seam between two faces.
- * Using a decent angle here (e.g. 80 degrees) results in very good visual
- * appearance.
- */
- aiProcess_GenSmoothNormals = 0x40,
-
- // -------------------------------------------------------------------------
- /** <hr>Splits large meshes into smaller sub-meshes.
- *
- * This is quite useful for real-time rendering, where the number of triangles
- * which can be maximally processed in a single draw-call is limited
- * by the video driver/hardware. The maximum vertex buffer is usually limited
- * too. Both requirements can be met with this step: you may specify both a
- * triangle and vertex limit for a single mesh.
- *
- * The split limits can (and should!) be set through the
- * <tt>#AI_CONFIG_PP_SLM_VERTEX_LIMIT</tt> and <tt>#AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</tt>
- * importer properties. The default values are <tt>#AI_SLM_DEFAULT_MAX_VERTICES</tt> and
- * <tt>#AI_SLM_DEFAULT_MAX_TRIANGLES</tt>.
- *
- * Note that splitting is generally a time-consuming task, but only if there's
- * something to split. The use of this step is recommended for most users.
- */
- aiProcess_SplitLargeMeshes = 0x80,
-
- // -------------------------------------------------------------------------
- /** <hr>Removes the node graph and pre-transforms all vertices with
- * the local transformation matrices of their nodes.
- *
- * The output scene still contains nodes, however there is only a
- * root node with children, each one referencing only one mesh,
- * and each mesh referencing one material. For rendering, you can
- * simply render all meshes in order - you don't need to pay
- * attention to local transformations and the node hierarchy.
- * Animations are removed during this step.
- * This step is intended for applications without a scenegraph.
- * The step CAN cause some problems: if e.g. a mesh of the asset
- * contains normals and another, using the same material index, does not,
- * they will be brought together, but the first meshes's part of
- * the normal list is zeroed. However, these artifacts are rare.
- * @note The <tt>#AI_CONFIG_PP_PTV_NORMALIZE</tt> configuration property
- * can be set to normalize the scene's spatial dimension to the -1...1
- * range.
- */
- aiProcess_PreTransformVertices = 0x100,
-
- // -------------------------------------------------------------------------
- /** <hr>Limits the number of bones simultaneously affecting a single vertex
- * to a maximum value.
- *
- * If any vertex is affected by more than the maximum number of bones, the least
- * important vertex weights are removed and the remaining vertex weights are
- * renormalized so that the weights still sum up to 1.
- * The default bone weight limit is 4 (defined as <tt>#AI_LMW_MAX_WEIGHTS</tt> in
- * config.h), but you can use the <tt>#AI_CONFIG_PP_LBW_MAX_WEIGHTS</tt> importer
- * property to supply your own limit to the post processing step.
- *
- * If you intend to perform the skinning in hardware, this post processing
- * step might be of interest to you.
- */
- aiProcess_LimitBoneWeights = 0x200,
-
- // -------------------------------------------------------------------------
- /** <hr>Validates the imported scene data structure.
- * This makes sure that all indices are valid, all animations and
- * bones are linked correctly, all material references are correct .. etc.
- *
- * It is recommended that you capture Assimp's log output if you use this flag,
- * so you can easily find out what's wrong if a file fails the
- * validation. The validator is quite strict and will find *all*
- * inconsistencies in the data structure... It is recommended that plugin
- * developers use it to debug their loaders. There are two types of
- * validation failures:
- * <ul>
- * <li>Error: There's something wrong with the imported data. Further
- * postprocessing is not possible and the data is not usable at all.
- * The import fails. #Importer::GetErrorString() or #aiGetErrorString()
- * carry the error message around.</li>
- * <li>Warning: There are some minor issues (e.g. 1000000 animation
- * keyframes with the same time), but further postprocessing and use
- * of the data structure is still safe. Warning details are written
- * to the log file, <tt>#AI_SCENE_FLAGS_VALIDATION_WARNING</tt> is set
- * in #aiScene::mFlags</li>
- * </ul>
- *
- * This post-processing step is not time-consuming. Its use is not
- * compulsory, but recommended.
- */
- aiProcess_ValidateDataStructure = 0x400,
-
- // -------------------------------------------------------------------------
- /** <hr>Reorders triangles for better vertex cache locality.
- *
- * The step tries to improve the ACMR (average post-transform vertex cache
- * miss ratio) for all meshes. The implementation runs in O(n) and is
- * roughly based on the 'tipsify' algorithm (see <a href="
- * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf">this
- * paper</a>).
- *
- * If you intend to render huge models in hardware, this step might
- * be of interest to you. The <tt>#AI_CONFIG_PP_ICL_PTCACHE_SIZE</tt>
- * importer property can be used to fine-tune the cache optimization.
- */
- aiProcess_ImproveCacheLocality = 0x800,
-
- // -------------------------------------------------------------------------
- /** <hr>Searches for redundant/unreferenced materials and removes them.
- *
- * This is especially useful in combination with the
- * #aiProcess_PretransformVertices and #aiProcess_OptimizeMeshes flags.
- * Both join small meshes with equal characteristics, but they can't do
- * their work if two meshes have different materials. Because several
- * material settings are lost during Assimp's import filters,
- * (and because many exporters don't check for redundant materials), huge
- * models often have materials which are are defined several times with
- * exactly the same settings.
- *
- * Several material settings not contributing to the final appearance of
- * a surface are ignored in all comparisons (e.g. the material name).
- * So, if you're passing additional information through the
- * content pipeline (probably using *magic* material names), don't
- * specify this flag. Alternatively take a look at the
- * <tt>#AI_CONFIG_PP_RRM_EXCLUDE_LIST</tt> importer property.
- */
- aiProcess_RemoveRedundantMaterials = 0x1000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step tries to determine which meshes have normal vectors
- * that are facing inwards and inverts them.
- *
- * The algorithm is simple but effective:
- * the bounding box of all vertices + their normals is compared against
- * the volume of the bounding box of all vertices without their normals.
- * This works well for most objects, problems might occur with planar
- * surfaces. However, the step tries to filter such cases.
- * The step inverts all in-facing normals. Generally it is recommended
- * to enable this step, although the result is not always correct.
- */
- aiProcess_FixInfacingNormals = 0x2000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step splits meshes with more than one primitive type in
- * homogeneous sub-meshes.
- *
- * The step is executed after the triangulation step. After the step
- * returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
- * especially useful for real-time rendering where point and line
- * primitives are often ignored or rendered separately.
- * You can use the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
- * specify which primitive types you need. This can be used to easily
- * exclude lines and points, which are rarely used, from the import.
- */
- aiProcess_SortByPType = 0x8000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step searches all meshes for degenerate primitives and
- * converts them to proper lines or points.
- *
- * A face is 'degenerate' if one or more of its points are identical.
- * To have the degenerate stuff not only detected and collapsed but
- * removed, try one of the following procedures:
- * <br><b>1.</b> (if you support lines and points for rendering but don't
- * want the degenerates)</br>
- * <ul>
- * <li>Specify the #aiProcess_FindDegenerates flag.
- * </li>
- * <li>Set the <tt>#AI_CONFIG_PP_FD_REMOVE</tt> importer property to
- * 1. This will cause the step to remove degenerate triangles from the
- * import as soon as they're detected. They won't pass any further
- * pipeline steps.
- * </li>
- * </ul>
- * <br><b>2.</b>(if you don't support lines and points at all)</br>
- * <ul>
- * <li>Specify the #aiProcess_FindDegenerates flag.
- * </li>
- * <li>Specify the #aiProcess_SortByPType flag. This moves line and
- * point primitives to separate meshes.
- * </li>
- * <li>Set the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
- * @code aiPrimitiveType_POINTS | aiPrimitiveType_LINES
- * @endcode to cause SortByPType to reject point
- * and line meshes from the scene.
- * </li>
- * </ul>
- * @note Degenerate polygons are not necessarily evil and that's why
- * they're not removed by default. There are several file formats which
- * don't support lines or points, and some exporters bypass the
- * format specification and write them as degenerate triangles instead.
- */
- aiProcess_FindDegenerates = 0x10000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step searches all meshes for invalid data, such as zeroed
- * normal vectors or invalid UV coords and removes/fixes them. This is
- * intended to get rid of some common exporter errors.
- *
- * This is especially useful for normals. If they are invalid, and
- * the step recognizes this, they will be removed and can later
- * be recomputed, i.e. by the #aiProcess_GenSmoothNormals flag.<br>
- * The step will also remove meshes that are infinitely small and reduce
- * animation tracks consisting of hundreds if redundant keys to a single
- * key. The <tt>AI_CONFIG_PP_FID_ANIM_ACCURACY</tt> config property decides
- * the accuracy of the check for duplicate animation tracks.
- */
- aiProcess_FindInvalidData = 0x20000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step converts non-UV mappings (such as spherical or
- * cylindrical mapping) to proper texture coordinate channels.
- *
- * Most applications will support UV mapping only, so you will
- * probably want to specify this step in every case. Note that Assimp is not
- * always able to match the original mapping implementation of the
- * 3D app which produced a model perfectly. It's always better to let the
- * modelling app compute the UV channels - 3ds max, Maya, Blender,
- * LightWave, and Modo do this for example.
- *
- * @note If this step is not requested, you'll need to process the
- * <tt>#AI_MATKEY_MAPPING</tt> material property in order to display all assets
- * properly.
- */
- aiProcess_GenUVCoords = 0x40000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step applies per-texture UV transformations and bakes
- * them into stand-alone vtexture coordinate channels.
- *
- * UV transformations are specified per-texture - see the
- * <tt>#AI_MATKEY_UVTRANSFORM</tt> material key for more information.
- * This step processes all textures with
- * transformed input UV coordinates and generates a new (pre-transformed) UV channel
- * which replaces the old channel. Most applications won't support UV
- * transformations, so you will probably want to specify this step.
- *
- * @note UV transformations are usually implemented in real-time apps by
- * transforming texture coordinates at vertex shader stage with a 3x3
- * (homogenous) transformation matrix.
- */
- aiProcess_TransformUVCoords = 0x80000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step searches for duplicate meshes and replaces them
- * with references to the first mesh.
- *
- * This step takes a while, so don't use it if speed is a concern.
- * Its main purpose is to workaround the fact that many export
- * file formats don't support instanced meshes, so exporters need to
- * duplicate meshes. This step removes the duplicates again. Please
- * note that Assimp does not currently support per-node material
- * assignment to meshes, which means that identical meshes with
- * different materials are currently *not* joined, although this is
- * planned for future versions.
- */
- aiProcess_FindInstances = 0x100000,
-
- // -------------------------------------------------------------------------
- /** <hr>A postprocessing step to reduce the number of meshes.
- *
- * This will, in fact, reduce the number of draw calls.
- *
- * This is a very effective optimization and is recommended to be used
- * together with #aiProcess_OptimizeGraph, if possible. The flag is fully
- * compatible with both #aiProcess_SplitLargeMeshes and #aiProcess_SortByPType.
- */
- aiProcess_OptimizeMeshes = 0x200000,
-
-
- // -------------------------------------------------------------------------
- /** <hr>A postprocessing step to optimize the scene hierarchy.
- *
- * Nodes without animations, bones, lights or cameras assigned are
- * collapsed and joined.
- *
- * Node names can be lost during this step. If you use special 'tag nodes'
- * to pass additional information through your content pipeline, use the
- * <tt>#AI_CONFIG_PP_OG_EXCLUDE_LIST</tt> importer property to specify a
- * list of node names you want to be kept. Nodes matching one of the names
- * in this list won't be touched or modified.
- *
- * Use this flag with caution. Most simple files will be collapsed to a
- * single node, so complex hierarchies are usually completely lost. This is not
- * useful for editor environments, but probably a very effective
- * optimization if you just want to get the model data, convert it to your
- * own format, and render it as fast as possible.
- *
- * This flag is designed to be used with #aiProcess_OptimizeMeshes for best
- * results.
- *
- * @note 'Crappy' scenes with thousands of extremely small meshes packed
- * in deeply nested nodes exist for almost all file formats.
- * #aiProcess_OptimizeMeshes in combination with #aiProcess_OptimizeGraph
- * usually fixes them all and makes them renderable.
- */
- aiProcess_OptimizeGraph = 0x400000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step flips all UV coordinates along the y-axis and adjusts
- * material settings and bitangents accordingly.
- *
- * <b>Output UV coordinate system:</b>
- * @code
- * 0y|0y ---------- 1x|0y
+ * from a CAD app, and it has per-face vertex colors. Vertex positions can't be
+ * shared, thus the #aiProcess_JoinIdenticalVertices step fails to
+ * optimize the data because of these nasty little vertex colors.
+ * Most apps don't even process them, so it's all for nothing. By using
+ * this step, unneeded components are excluded as early as possible
+ * thus opening more room for internal optimizations.
+ */
+ aiProcess_RemoveComponent = 0x10,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Generates normals for all faces of all meshes.
+ *
+ * This is ignored if normals are already there at the time this flag
+ * is evaluated. Model importers try to load them from the source file, so
+ * they're usually already there. Face normals are shared between all points
+ * of a single face, so a single point can have multiple normals, which
+ * forces the library to duplicate vertices in some cases.
+ * #aiProcess_JoinIdenticalVertices is *senseless* then.
+ *
+ * This flag may not be specified together with #aiProcess_GenSmoothNormals.
+ */
+ aiProcess_GenNormals = 0x20,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Generates smooth normals for all vertices in the mesh.
+ *
+ * This is ignored if normals are already there at the time this flag
+ * is evaluated. Model importers try to load them from the source file, so
+ * they're usually already there.
+ *
+ * This flag may not be specified together with
+ * #aiProcess_GenNormals. There's a importer property,
+ * <tt>#AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE</tt> which allows you to specify
+ * an angle maximum for the normal smoothing algorithm. Normals exceeding
+ * this limit are not smoothed, resulting in a 'hard' seam between two faces.
+ * Using a decent angle here (e.g. 80 degrees) results in very good visual
+ * appearance.
+ */
+ aiProcess_GenSmoothNormals = 0x40,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Splits large meshes into smaller sub-meshes.
+ *
+ * This is quite useful for real-time rendering, where the number of triangles
+ * which can be maximally processed in a single draw-call is limited
+ * by the video driver/hardware. The maximum vertex buffer is usually limited
+ * too. Both requirements can be met with this step: you may specify both a
+ * triangle and vertex limit for a single mesh.
+ *
+ * The split limits can (and should!) be set through the
+ * <tt>#AI_CONFIG_PP_SLM_VERTEX_LIMIT</tt> and <tt>#AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</tt>
+ * importer properties. The default values are <tt>#AI_SLM_DEFAULT_MAX_VERTICES</tt> and
+ * <tt>#AI_SLM_DEFAULT_MAX_TRIANGLES</tt>.
+ *
+ * Note that splitting is generally a time-consuming task, but only if there's
+ * something to split. The use of this step is recommended for most users.
+ */
+ aiProcess_SplitLargeMeshes = 0x80,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Removes the node graph and pre-transforms all vertices with
+ * the local transformation matrices of their nodes.
+ *
+ * The output scene still contains nodes, however there is only a
+ * root node with children, each one referencing only one mesh,
+ * and each mesh referencing one material. For rendering, you can
+ * simply render all meshes in order - you don't need to pay
+ * attention to local transformations and the node hierarchy.
+ * Animations are removed during this step.
+ * This step is intended for applications without a scenegraph.
+ * The step CAN cause some problems: if e.g. a mesh of the asset
+ * contains normals and another, using the same material index, does not,
+ * they will be brought together, but the first meshes's part of
+ * the normal list is zeroed. However, these artifacts are rare.
+ * @note The <tt>#AI_CONFIG_PP_PTV_NORMALIZE</tt> configuration property
+ * can be set to normalize the scene's spatial dimension to the -1...1
+ * range.
+ */
+ aiProcess_PreTransformVertices = 0x100,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Limits the number of bones simultaneously affecting a single vertex
+ * to a maximum value.
+ *
+ * If any vertex is affected by more than the maximum number of bones, the least
+ * important vertex weights are removed and the remaining vertex weights are
+ * renormalized so that the weights still sum up to 1.
+ * The default bone weight limit is 4 (defined as <tt>#AI_LMW_MAX_WEIGHTS</tt> in
+ * config.h), but you can use the <tt>#AI_CONFIG_PP_LBW_MAX_WEIGHTS</tt> importer
+ * property to supply your own limit to the post processing step.
+ *
+ * If you intend to perform the skinning in hardware, this post processing
+ * step might be of interest to you.
+ */
+ aiProcess_LimitBoneWeights = 0x200,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Validates the imported scene data structure.
+ * This makes sure that all indices are valid, all animations and
+ * bones are linked correctly, all material references are correct .. etc.
+ *
+ * It is recommended that you capture Assimp's log output if you use this flag,
+ * so you can easily find out what's wrong if a file fails the
+ * validation. The validator is quite strict and will find *all*
+ * inconsistencies in the data structure... It is recommended that plugin
+ * developers use it to debug their loaders. There are two types of
+ * validation failures:
+ * <ul>
+ * <li>Error: There's something wrong with the imported data. Further
+ * postprocessing is not possible and the data is not usable at all.
+ * The import fails. #Importer::GetErrorString() or #aiGetErrorString()
+ * carry the error message around.</li>
+ * <li>Warning: There are some minor issues (e.g. 1000000 animation
+ * keyframes with the same time), but further postprocessing and use
+ * of the data structure is still safe. Warning details are written
+ * to the log file, <tt>#AI_SCENE_FLAGS_VALIDATION_WARNING</tt> is set
+ * in #aiScene::mFlags</li>
+ * </ul>
+ *
+ * This post-processing step is not time-consuming. Its use is not
+ * compulsory, but recommended.
+ */
+ aiProcess_ValidateDataStructure = 0x400,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Reorders triangles for better vertex cache locality.
+ *
+ * The step tries to improve the ACMR (average post-transform vertex cache
+ * miss ratio) for all meshes. The implementation runs in O(n) and is
+ * roughly based on the 'tipsify' algorithm (see <a href="
+ * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf">this
+ * paper</a>).
+ *
+ * If you intend to render huge models in hardware, this step might
+ * be of interest to you. The <tt>#AI_CONFIG_PP_ICL_PTCACHE_SIZE</tt>
+ * importer property can be used to fine-tune the cache optimization.
+ */
+ aiProcess_ImproveCacheLocality = 0x800,
+
+ // -------------------------------------------------------------------------
+ /** <hr>Searches for redundant/unreferenced materials and removes them.
+ *
+ * This is especially useful in combination with the
+ * #aiProcess_PreTransformVertices and #aiProcess_OptimizeMeshes flags.
+ * Both join small meshes with equal characteristics, but they can't do
+ * their work if two meshes have different materials. Because several
+ * material settings are lost during Assimp's import filters,
+ * (and because many exporters don't check for redundant materials), huge
+ * models often have materials which are are defined several times with
+ * exactly the same settings.
+ *
+ * Several material settings not contributing to the final appearance of
+ * a surface are ignored in all comparisons (e.g. the material name).
+ * So, if you're passing additional information through the
+ * content pipeline (probably using *magic* material names), don't
+ * specify this flag. Alternatively take a look at the
+ * <tt>#AI_CONFIG_PP_RRM_EXCLUDE_LIST</tt> importer property.
+ */
+ aiProcess_RemoveRedundantMaterials = 0x1000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step tries to determine which meshes have normal vectors
+ * that are facing inwards and inverts them.
+ *
+ * The algorithm is simple but effective:
+ * the bounding box of all vertices + their normals is compared against
+ * the volume of the bounding box of all vertices without their normals.
+ * This works well for most objects, problems might occur with planar
+ * surfaces. However, the step tries to filter such cases.
+ * The step inverts all in-facing normals. Generally it is recommended
+ * to enable this step, although the result is not always correct.
+ */
+ aiProcess_FixInfacingNormals = 0x2000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step splits meshes with more than one primitive type in
+ * homogeneous sub-meshes.
+ *
+ * The step is executed after the triangulation step. After the step
+ * returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
+ * especially useful for real-time rendering where point and line
+ * primitives are often ignored or rendered separately.
+ * You can use the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
+ * specify which primitive types you need. This can be used to easily
+ * exclude lines and points, which are rarely used, from the import.
+ */
+ aiProcess_SortByPType = 0x8000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step searches all meshes for degenerate primitives and
+ * converts them to proper lines or points.
+ *
+ * A face is 'degenerate' if one or more of its points are identical.
+ * To have the degenerate stuff not only detected and collapsed but
+ * removed, try one of the following procedures:
+ * <br><b>1.</b> (if you support lines and points for rendering but don't
+ * want the degenerates)<br>
+ * <ul>
+ * <li>Specify the #aiProcess_FindDegenerates flag.
+ * </li>
+ * <li>Set the <tt>#AI_CONFIG_PP_FD_REMOVE</tt> importer property to
+ * 1. This will cause the step to remove degenerate triangles from the
+ * import as soon as they're detected. They won't pass any further
+ * pipeline steps.
+ * </li>
+ * </ul>
+ * <br><b>2.</b>(if you don't support lines and points at all)<br>
+ * <ul>
+ * <li>Specify the #aiProcess_FindDegenerates flag.
+ * </li>
+ * <li>Specify the #aiProcess_SortByPType flag. This moves line and
+ * point primitives to separate meshes.
+ * </li>
+ * <li>Set the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
+ * @code aiPrimitiveType_POINTS | aiPrimitiveType_LINES
+ * @endcode to cause SortByPType to reject point
+ * and line meshes from the scene.
+ * </li>
+ * </ul>
+ * @note Degenerate polygons are not necessarily evil and that's why
+ * they're not removed by default. There are several file formats which
+ * don't support lines or points, and some exporters bypass the
+ * format specification and write them as degenerate triangles instead.
+ */
+ aiProcess_FindDegenerates = 0x10000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step searches all meshes for invalid data, such as zeroed
+ * normal vectors or invalid UV coords and removes/fixes them. This is
+ * intended to get rid of some common exporter errors.
+ *
+ * This is especially useful for normals. If they are invalid, and
+ * the step recognizes this, they will be removed and can later
+ * be recomputed, i.e. by the #aiProcess_GenSmoothNormals flag.<br>
+ * The step will also remove meshes that are infinitely small and reduce
+ * animation tracks consisting of hundreds if redundant keys to a single
+ * key. The <tt>AI_CONFIG_PP_FID_ANIM_ACCURACY</tt> config property decides
+ * the accuracy of the check for duplicate animation tracks.
+ */
+ aiProcess_FindInvalidData = 0x20000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step converts non-UV mappings (such as spherical or
+ * cylindrical mapping) to proper texture coordinate channels.
+ *
+ * Most applications will support UV mapping only, so you will
+ * probably want to specify this step in every case. Note that Assimp is not
+ * always able to match the original mapping implementation of the
+ * 3D app which produced a model perfectly. It's always better to let the
+ * modelling app compute the UV channels - 3ds max, Maya, Blender,
+ * LightWave, and Modo do this for example.
+ *
+ * @note If this step is not requested, you'll need to process the
+ * <tt>#AI_MATKEY_MAPPING</tt> material property in order to display all assets
+ * properly.
+ */
+ aiProcess_GenUVCoords = 0x40000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step applies per-texture UV transformations and bakes
+ * them into stand-alone vtexture coordinate channels.
+ *
+ * UV transformations are specified per-texture - see the
+ * <tt>#AI_MATKEY_UVTRANSFORM</tt> material key for more information.
+ * This step processes all textures with
+ * transformed input UV coordinates and generates a new (pre-transformed) UV channel
+ * which replaces the old channel. Most applications won't support UV
+ * transformations, so you will probably want to specify this step.
+ *
+ * @note UV transformations are usually implemented in real-time apps by
+ * transforming texture coordinates at vertex shader stage with a 3x3
+ * (homogenous) transformation matrix.
+ */
+ aiProcess_TransformUVCoords = 0x80000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step searches for duplicate meshes and replaces them
+ * with references to the first mesh.
+ *
+ * This step takes a while, so don't use it if speed is a concern.
+ * Its main purpose is to workaround the fact that many export
+ * file formats don't support instanced meshes, so exporters need to
+ * duplicate meshes. This step removes the duplicates again. Please
+ * note that Assimp does not currently support per-node material
+ * assignment to meshes, which means that identical meshes with
+ * different materials are currently *not* joined, although this is
+ * planned for future versions.
+ */
+ aiProcess_FindInstances = 0x100000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>A postprocessing step to reduce the number of meshes.
+ *
+ * This will, in fact, reduce the number of draw calls.
+ *
+ * This is a very effective optimization and is recommended to be used
+ * together with #aiProcess_OptimizeGraph, if possible. The flag is fully
+ * compatible with both #aiProcess_SplitLargeMeshes and #aiProcess_SortByPType.
+ */
+ aiProcess_OptimizeMeshes = 0x200000,
+
+
+ // -------------------------------------------------------------------------
+ /** <hr>A postprocessing step to optimize the scene hierarchy.
+ *
+ * Nodes without animations, bones, lights or cameras assigned are
+ * collapsed and joined.
+ *
+ * Node names can be lost during this step. If you use special 'tag nodes'
+ * to pass additional information through your content pipeline, use the
+ * <tt>#AI_CONFIG_PP_OG_EXCLUDE_LIST</tt> importer property to specify a
+ * list of node names you want to be kept. Nodes matching one of the names
+ * in this list won't be touched or modified.
+ *
+ * Use this flag with caution. Most simple files will be collapsed to a
+ * single node, so complex hierarchies are usually completely lost. This is not
+ * useful for editor environments, but probably a very effective
+ * optimization if you just want to get the model data, convert it to your
+ * own format, and render it as fast as possible.
+ *
+ * This flag is designed to be used with #aiProcess_OptimizeMeshes for best
+ * results.
+ *
+ * @note 'Crappy' scenes with thousands of extremely small meshes packed
+ * in deeply nested nodes exist for almost all file formats.
+ * #aiProcess_OptimizeMeshes in combination with #aiProcess_OptimizeGraph
+ * usually fixes them all and makes them renderable.
+ */
+ aiProcess_OptimizeGraph = 0x400000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step flips all UV coordinates along the y-axis and adjusts
+ * material settings and bitangents accordingly.
+ *
+ * <b>Output UV coordinate system:</b>
+ * @code
+ * 0y|0y ---------- 1x|0y
* | |
* | |
* | |
* 0x|1y ---------- 1x|1y
- * @endcode
- *
- * You'll probably want to consider this flag if you use Direct3D for
- * rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
- * setting and bundles all conversions typically required for D3D-based
- * applications.
- */
- aiProcess_FlipUVs = 0x800000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step adjusts the output face winding order to be CW.
- *
- * The default face winding order is counter clockwise (CCW).
- *
- * <b>Output face order:</b>
- * @code
- * x2
- *
- * x0
- * x1
- * @endcode
- */
- aiProcess_FlipWindingOrder = 0x1000000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step splits meshes with many bones into sub-meshes so that each
- * su-bmesh has fewer or as many bones as a given limit.
+ * @endcode
+ *
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
+ * setting and bundles all conversions typically required for D3D-based
+ * applications.
*/
- aiProcess_SplitByBoneCount = 0x2000000,
-
- // -------------------------------------------------------------------------
- /** <hr>This step removes bones losslessly or according to some threshold.
- *
- * In some cases (i.e. formats that require it) exporters are forced to
- * assign dummy bone weights to otherwise static meshes assigned to
- * animated meshes. Full, weight-based skinning is expensive while
- * animating nodes is extremely cheap, so this step is offered to clean up
- * the data in that regard.
- *
- * Use <tt>#AI_CONFIG_PP_DB_THRESHOLD</tt> to control this.
- * Use <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE</tt> if you want bones removed if and
- * only if all bones within the scene qualify for removal.
+ aiProcess_FlipUVs = 0x800000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step adjusts the output face winding order to be CW.
+ *
+ * The default face winding order is counter clockwise (CCW).
+ *
+ * <b>Output face order:</b>
+ * @code
+ * x2
+ *
+ * x0
+ * x1
+ * @endcode
*/
- aiProcess_Debone = 0x4000000
+ aiProcess_FlipWindingOrder = 0x1000000,
- // aiProcess_GenEntityMeshes = 0x100000,
- // aiProcess_OptimizeAnimations = 0x200000
- // aiProcess_FixTexturePaths = 0x200000
+ // -------------------------------------------------------------------------
+ /** <hr>This step splits meshes with many bones into sub-meshes so that each
+ * su-bmesh has fewer or as many bones as a given limit.
+ */
+ aiProcess_SplitByBoneCount = 0x2000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step removes bones losslessly or according to some threshold.
+ *
+ * In some cases (i.e. formats that require it) exporters are forced to
+ * assign dummy bone weights to otherwise static meshes assigned to
+ * animated meshes. Full, weight-based skinning is expensive while
+ * animating nodes is extremely cheap, so this step is offered to clean up
+ * the data in that regard.
+ *
+ * Use <tt>#AI_CONFIG_PP_DB_THRESHOLD</tt> to control this.
+ * Use <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE</tt> if you want bones removed if and
+ * only if all bones within the scene qualify for removal.
+ */
+ aiProcess_Debone = 0x4000000
+
+ // aiProcess_GenEntityMeshes = 0x100000,
+ // aiProcess_OptimizeAnimations = 0x200000
+ // aiProcess_FixTexturePaths = 0x200000
};
// ---------------------------------------------------------------------------------------
/** @def aiProcess_ConvertToLeftHanded
- * @brief Shortcut flag for Direct3D-based applications.
+ * @brief Shortcut flag for Direct3D-based applications.
*
* Supersedes the #aiProcess_MakeLeftHanded and #aiProcess_FlipUVs and
* #aiProcess_FlipWindingOrder flags.
* The output data matches Direct3D's conventions: left-handed geometry, upper-left
* origin for UV coordinates and finally clockwise face order, suitable for CCW culling.
*
- * @deprecated
+ * @deprecated
*/
#define aiProcess_ConvertToLeftHanded ( \
- aiProcess_MakeLeftHanded | \
- aiProcess_FlipUVs | \
- aiProcess_FlipWindingOrder | \
- 0 )
+ aiProcess_MakeLeftHanded | \
+ aiProcess_FlipUVs | \
+ aiProcess_FlipWindingOrder | \
+ 0 )
// ---------------------------------------------------------------------------------------
-/** @def aiProcessPreset_TargetRealtimeUse_Fast
+/** @def aiProcessPreset_TargetRealtime_Fast
* @brief Default postprocess configuration optimizing the data for real-time rendering.
- *
+ *
* Applications would want to use this preset to load models on end-user PCs,
* maybe for direct use in game.
*
* If you're using DirectX, don't forget to combine this value with
* the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
* in your application apply the #aiProcess_TransformUVCoords step, too.
- * @note Please take the time to read the docs for the steps enabled by this preset.
+ * @note Please take the time to read the docs for the steps enabled by this preset.
* Some of them offer further configurable properties, while some of them might not be of
* use for you so it might be better to not specify them.
*/
#define aiProcessPreset_TargetRealtime_Fast ( \
- aiProcess_CalcTangentSpace | \
- aiProcess_GenNormals | \
- aiProcess_JoinIdenticalVertices | \
- aiProcess_Triangulate | \
- aiProcess_GenUVCoords | \
- aiProcess_SortByPType | \
- 0 )
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ 0 )
// ---------------------------------------------------------------------------------------
/** @def aiProcessPreset_TargetRealtime_Quality
@@ -580,50 +580,50 @@ enum aiPostProcessSteps
* performs some extra optimizations to improve rendering speed and
* to minimize memory usage. It could be a good choice for a level editor
* environment where import speed is not so important.
- *
+ *
* If you're using DirectX, don't forget to combine this value with
* the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
* in your application apply the #aiProcess_TransformUVCoords step, too.
- * @note Please take the time to read the docs for the steps enabled by this preset.
+ * @note Please take the time to read the docs for the steps enabled by this preset.
* Some of them offer further configurable properties, while some of them might not be
* of use for you so it might be better to not specify them.
*/
#define aiProcessPreset_TargetRealtime_Quality ( \
- aiProcess_CalcTangentSpace | \
- aiProcess_GenSmoothNormals | \
- aiProcess_JoinIdenticalVertices | \
- aiProcess_ImproveCacheLocality | \
- aiProcess_LimitBoneWeights | \
- aiProcess_RemoveRedundantMaterials | \
- aiProcess_SplitLargeMeshes | \
- aiProcess_Triangulate | \
- aiProcess_GenUVCoords | \
- aiProcess_SortByPType | \
- aiProcess_FindDegenerates | \
- aiProcess_FindInvalidData | \
- 0 )
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenSmoothNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_ImproveCacheLocality | \
+ aiProcess_LimitBoneWeights | \
+ aiProcess_RemoveRedundantMaterials | \
+ aiProcess_SplitLargeMeshes | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ aiProcess_FindDegenerates | \
+ aiProcess_FindInvalidData | \
+ 0 )
// ---------------------------------------------------------------------------------------
/** @def aiProcessPreset_TargetRealtime_MaxQuality
* @brief Default postprocess configuration optimizing the data for real-time rendering.
*
* This preset enables almost every optimization step to achieve perfectly
- * optimized data. It's your choice for level editor environments where import speed
+ * optimized data. It's your choice for level editor environments where import speed
* is not important.
- *
+ *
* If you're using DirectX, don't forget to combine this value with
* the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
* in your application, apply the #aiProcess_TransformUVCoords step, too.
- * @note Please take the time to read the docs for the steps enabled by this preset.
+ * @note Please take the time to read the docs for the steps enabled by this preset.
* Some of them offer further configurable properties, while some of them might not be
* of use for you so it might be better to not specify them.
*/
#define aiProcessPreset_TargetRealtime_MaxQuality ( \
- aiProcessPreset_TargetRealtime_Quality | \
- aiProcess_FindInstances | \
- aiProcess_ValidateDataStructure | \
- aiProcess_OptimizeMeshes | \
- 0 )
+ aiProcessPreset_TargetRealtime_Quality | \
+ aiProcess_FindInstances | \
+ aiProcess_ValidateDataStructure | \
+ aiProcess_OptimizeMeshes | \
+ 0 )
#ifdef __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/quaternion.h b/src/3rdparty/assimp/include/assimp/quaternion.h
index ad64dd9d3..fe213f71e 100644
--- a/src/3rdparty/assimp/include/assimp/quaternion.h
+++ b/src/3rdparty/assimp/include/assimp/quaternion.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,61 +55,61 @@ template <typename TReal>
class aiQuaterniont
{
public:
- aiQuaterniont() : w(1.0), x(), y(), z() {}
- aiQuaterniont(TReal pw, TReal px, TReal py, TReal pz)
- : w(pw), x(px), y(py), z(pz) {}
+ aiQuaterniont() : w(1.0), x(), y(), z() {}
+ aiQuaterniont(TReal pw, TReal px, TReal py, TReal pz)
+ : w(pw), x(px), y(py), z(pz) {}
- /** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */
- aiQuaterniont( const aiMatrix3x3t<TReal>& pRotMatrix);
+ /** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */
+ explicit aiQuaterniont( const aiMatrix3x3t<TReal>& pRotMatrix);
- /** Construct from euler angles */
- aiQuaterniont( TReal rotx, TReal roty, TReal rotz);
+ /** Construct from euler angles */
+ aiQuaterniont( TReal rotx, TReal roty, TReal rotz);
- /** Construct from an axis-angle pair */
- aiQuaterniont( aiVector3t<TReal> axis, TReal angle);
+ /** Construct from an axis-angle pair */
+ aiQuaterniont( aiVector3t<TReal> axis, TReal angle);
- /** Construct from a normalized quaternion stored in a vec3 */
- aiQuaterniont( aiVector3t<TReal> normalized);
+ /** Construct from a normalized quaternion stored in a vec3 */
+ explicit aiQuaterniont( aiVector3t<TReal> normalized);
- /** Returns a matrix representation of the quaternion */
- aiMatrix3x3t<TReal> GetMatrix() const;
+ /** Returns a matrix representation of the quaternion */
+ aiMatrix3x3t<TReal> GetMatrix() const;
public:
- bool operator== (const aiQuaterniont& o) const;
- bool operator!= (const aiQuaterniont& o) const;
+ bool operator== (const aiQuaterniont& o) const;
+ bool operator!= (const aiQuaterniont& o) const;
- bool Equal(const aiQuaterniont& o, TReal epsilon = 1e-6) const;
+ bool Equal(const aiQuaterniont& o, TReal epsilon = 1e-6) const;
public:
- /** Normalize the quaternion */
- aiQuaterniont& Normalize();
+ /** Normalize the quaternion */
+ aiQuaterniont& Normalize();
- /** Compute quaternion conjugate */
- aiQuaterniont& Conjugate ();
+ /** Compute quaternion conjugate */
+ aiQuaterniont& Conjugate ();
- /** Rotate a point by this quaternion */
- aiVector3t<TReal> Rotate (const aiVector3t<TReal>& in);
+ /** Rotate a point by this quaternion */
+ aiVector3t<TReal> Rotate (const aiVector3t<TReal>& in);
- /** Multiply two quaternions */
- aiQuaterniont operator* (const aiQuaterniont& two) const;
+ /** Multiply two quaternions */
+ aiQuaterniont operator* (const aiQuaterniont& two) const;
public:
- /** Performs a spherical interpolation between two quaternions and writes the result into the third.
- * @param pOut Target object to received the interpolated rotation.
- * @param pStart Start rotation of the interpolation at factor == 0.
- * @param pEnd End rotation, factor == 1.
- * @param pFactor Interpolation factor between 0 and 1. Values outside of this range yield undefined results.
- */
- static void Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart,
- const aiQuaterniont& pEnd, TReal pFactor);
+ /** Performs a spherical interpolation between two quaternions and writes the result into the third.
+ * @param pOut Target object to received the interpolated rotation.
+ * @param pStart Start rotation of the interpolation at factor == 0.
+ * @param pEnd End rotation, factor == 1.
+ * @param pFactor Interpolation factor between 0 and 1. Values outside of this range yield undefined results.
+ */
+ static void Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart,
+ const aiQuaterniont& pEnd, TReal pFactor);
public:
- //! w,x,y,z components of the quaternion
- TReal w, x, y, z;
+ //! w,x,y,z components of the quaternion
+ TReal w, x, y, z;
} ;
typedef aiQuaterniont<float> aiQuaternion;
@@ -117,7 +117,7 @@ typedef aiQuaterniont<float> aiQuaternion;
#else
struct aiQuaternion {
- float w, x, y, z;
+ float w, x, y, z;
};
#endif
diff --git a/src/3rdparty/assimp/include/assimp/quaternion.inl b/src/3rdparty/assimp/include/assimp/quaternion.inl
index b966433d1..db27c25ff 100644
--- a/src/3rdparty/assimp/include/assimp/quaternion.inl
+++ b/src/3rdparty/assimp/include/assimp/quaternion.inl
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file aiQuaterniont.inl
+/** @file quaternion.inl
* @brief Inline implementation of aiQuaterniont<TReal> operators
*/
#ifndef AI_QUATERNION_INL_INC
@@ -54,24 +54,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template<typename TReal>
bool aiQuaterniont<TReal>::operator== (const aiQuaterniont& o) const
{
- return x == o.x && y == o.y && z == o.z && w == o.w;
+ return x == o.x && y == o.y && z == o.z && w == o.w;
}
// ---------------------------------------------------------------------------
template<typename TReal>
bool aiQuaterniont<TReal>::operator!= (const aiQuaterniont& o) const
{
- return !(*this == o);
+ return !(*this == o);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline bool aiQuaterniont<TReal>::Equal(const aiQuaterniont& o, TReal epsilon) const {
- return
- std::abs(x - o.x) <= epsilon &&
- std::abs(y - o.y) <= epsilon &&
- std::abs(z - o.z) <= epsilon &&
- std::abs(w - o.w) <= epsilon;
+ return
+ std::abs(x - o.x) <= epsilon &&
+ std::abs(y - o.y) <= epsilon &&
+ std::abs(z - o.z) <= epsilon &&
+ std::abs(w - o.w) <= epsilon;
}
// ---------------------------------------------------------------------------
@@ -79,43 +79,43 @@ inline bool aiQuaterniont<TReal>::Equal(const aiQuaterniont& o, TReal epsilon) c
template<typename TReal>
inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatrix)
{
- TReal t = pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
+ TReal t = pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
- // large enough
- if( t > static_cast<TReal>(0))
- {
+ // large enough
+ if( t > static_cast<TReal>(0))
+ {
TReal s = std::sqrt(1 + t) * static_cast<TReal>(2.0);
- x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
- y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
- z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
- w = static_cast<TReal>(0.25) * s;
- } // else we have to check several cases
- else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )
- {
- // Column 0:
+ x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
+ y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
+ z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
+ w = static_cast<TReal>(0.25) * s;
+ } // else we have to check several cases
+ else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )
+ {
+ // Column 0:
TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
- x = static_cast<TReal>(0.25) * s;
- y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
- z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
- w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
- }
- else if( pRotMatrix.b2 > pRotMatrix.c3)
- {
- // Column 1:
+ x = static_cast<TReal>(0.25) * s;
+ y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
+ z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
+ w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
+ }
+ else if( pRotMatrix.b2 > pRotMatrix.c3)
+ {
+ // Column 1:
TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
- x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
- y = static_cast<TReal>(0.25) * s;
- z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
- w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
- } else
- {
- // Column 2:
+ x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
+ y = static_cast<TReal>(0.25) * s;
+ z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
+ w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
+ } else
+ {
+ // Column 2:
TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
- x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
- y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
- z = static_cast<TReal>(0.25) * s;
- w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
- }
+ x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
+ y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
+ z = static_cast<TReal>(0.25) * s;
+ w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
+ }
}
// ---------------------------------------------------------------------------
@@ -129,12 +129,12 @@ inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRol
const TReal fCosYaw(std::cos(fYaw*static_cast<TReal>(0.5)));
const TReal fSinRoll(std::sin(fRoll*static_cast<TReal>(0.5)));
const TReal fCosRoll(std::cos(fRoll*static_cast<TReal>(0.5)));
- const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
- const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
- x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
- y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
- z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
- w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
+ const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
+ const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
+ x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
+ y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
+ z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
+ w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
}
// ---------------------------------------------------------------------------
@@ -142,18 +142,18 @@ inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRol
template<typename TReal>
inline aiMatrix3x3t<TReal> aiQuaterniont<TReal>::GetMatrix() const
{
- aiMatrix3x3t<TReal> resMatrix;
- resMatrix.a1 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (y * y + z * z);
- resMatrix.a2 = static_cast<TReal>(2.0) * (x * y - z * w);
- resMatrix.a3 = static_cast<TReal>(2.0) * (x * z + y * w);
- resMatrix.b1 = static_cast<TReal>(2.0) * (x * y + z * w);
- resMatrix.b2 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + z * z);
- resMatrix.b3 = static_cast<TReal>(2.0) * (y * z - x * w);
- resMatrix.c1 = static_cast<TReal>(2.0) * (x * z - y * w);
- resMatrix.c2 = static_cast<TReal>(2.0) * (y * z + x * w);
- resMatrix.c3 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + y * y);
-
- return resMatrix;
+ aiMatrix3x3t<TReal> resMatrix;
+ resMatrix.a1 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (y * y + z * z);
+ resMatrix.a2 = static_cast<TReal>(2.0) * (x * y - z * w);
+ resMatrix.a3 = static_cast<TReal>(2.0) * (x * z + y * w);
+ resMatrix.b1 = static_cast<TReal>(2.0) * (x * y + z * w);
+ resMatrix.b2 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + z * z);
+ resMatrix.b3 = static_cast<TReal>(2.0) * (y * z - x * w);
+ resMatrix.c1 = static_cast<TReal>(2.0) * (x * z - y * w);
+ resMatrix.c2 = static_cast<TReal>(2.0) * (y * z + x * w);
+ resMatrix.c3 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + y * y);
+
+ return resMatrix;
}
// ---------------------------------------------------------------------------
@@ -161,123 +161,122 @@ inline aiMatrix3x3t<TReal> aiQuaterniont<TReal>::GetMatrix() const
template<typename TReal>
inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> axis, TReal angle)
{
- axis.Normalize();
+ axis.Normalize();
const TReal sin_a = std::sin( angle / 2 );
const TReal cos_a = std::cos( angle / 2 );
- x = axis.x * sin_a;
- y = axis.y * sin_a;
- z = axis.z * sin_a;
- w = cos_a;
+ x = axis.x * sin_a;
+ y = axis.y * sin_a;
+ z = axis.z * sin_a;
+ w = cos_a;
}
// ---------------------------------------------------------------------------
// Construction from am existing, normalized quaternion
template<typename TReal>
inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> normalized)
{
- x = normalized.x;
- y = normalized.y;
- z = normalized.z;
+ x = normalized.x;
+ y = normalized.y;
+ z = normalized.z;
- const TReal t = static_cast<TReal>(1.0) - (x*x) - (y*y) - (z*z);
+ const TReal t = static_cast<TReal>(1.0) - (x*x) - (y*y) - (z*z);
- if (t < static_cast<TReal>(0.0)) {
- w = static_cast<TReal>(0.0);
- }
+ if (t < static_cast<TReal>(0.0)) {
+ w = static_cast<TReal>(0.0);
+ }
else w = std::sqrt (t);
}
// ---------------------------------------------------------------------------
-// Performs a spherical interpolation between two quaternions
+// Performs a spherical interpolation between two quaternions
// Implementation adopted from the gmtl project. All others I found on the net fail in some cases.
// Congrats, gmtl!
template<typename TReal>
inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart, const aiQuaterniont& pEnd, TReal pFactor)
{
- // calc cosine theta
- TReal cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
-
- // adjust signs (if necessary)
- aiQuaterniont end = pEnd;
- if( cosom < static_cast<TReal>(0.0))
- {
- cosom = -cosom;
- end.x = -end.x; // Reverse all signs
- end.y = -end.y;
- end.z = -end.z;
- end.w = -end.w;
- }
-
- // Calculate coefficients
- TReal sclp, sclq;
- if( (static_cast<TReal>(1.0) - cosom) > static_cast<TReal>(0.0001)) // 0.0001 -> some epsillon
- {
- // Standard case (slerp)
- TReal omega, sinom;
- omega = std::acos( cosom); // extract theta from dot product's cos theta
+ // calc cosine theta
+ TReal cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
+
+ // adjust signs (if necessary)
+ aiQuaterniont end = pEnd;
+ if( cosom < static_cast<TReal>(0.0))
+ {
+ cosom = -cosom;
+ end.x = -end.x; // Reverse all signs
+ end.y = -end.y;
+ end.z = -end.z;
+ end.w = -end.w;
+ }
+
+ // Calculate coefficients
+ TReal sclp, sclq;
+ if( (static_cast<TReal>(1.0) - cosom) > static_cast<TReal>(0.0001)) // 0.0001 -> some epsillon
+ {
+ // Standard case (slerp)
+ TReal omega, sinom;
+ omega = std::acos( cosom); // extract theta from dot product's cos theta
sinom = std::sin( omega);
sclp = std::sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
sclq = std::sin( pFactor * omega) / sinom;
- } else
- {
- // Very close, do linear interp (because it's faster)
- sclp = static_cast<TReal>(1.0) - pFactor;
- sclq = pFactor;
- }
-
- pOut.x = sclp * pStart.x + sclq * end.x;
- pOut.y = sclp * pStart.y + sclq * end.y;
- pOut.z = sclp * pStart.z + sclq * end.z;
- pOut.w = sclp * pStart.w + sclq * end.w;
+ } else
+ {
+ // Very close, do linear interp (because it's faster)
+ sclp = static_cast<TReal>(1.0) - pFactor;
+ sclq = pFactor;
+ }
+
+ pOut.x = sclp * pStart.x + sclq * end.x;
+ pOut.y = sclp * pStart.y + sclq * end.y;
+ pOut.z = sclp * pStart.z + sclq * end.z;
+ pOut.w = sclp * pStart.w + sclq * end.w;
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Normalize()
{
- // compute the magnitude and divide through it
+ // compute the magnitude and divide through it
const TReal mag = std::sqrt(x*x + y*y + z*z + w*w);
- if (mag)
- {
- const TReal invMag = static_cast<TReal>(1.0)/mag;
- x *= invMag;
- y *= invMag;
- z *= invMag;
- w *= invMag;
- }
- return *this;
+ if (mag)
+ {
+ const TReal invMag = static_cast<TReal>(1.0)/mag;
+ x *= invMag;
+ y *= invMag;
+ z *= invMag;
+ w *= invMag;
+ }
+ return *this;
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline aiQuaterniont<TReal> aiQuaterniont<TReal>::operator* (const aiQuaterniont& t) const
{
- return aiQuaterniont(w*t.w - x*t.x - y*t.y - z*t.z,
- w*t.x + x*t.w + y*t.z - z*t.y,
- w*t.y + y*t.w + z*t.x - x*t.z,
- w*t.z + z*t.w + x*t.y - y*t.x);
+ return aiQuaterniont(w*t.w - x*t.x - y*t.y - z*t.z,
+ w*t.x + x*t.w + y*t.z - z*t.y,
+ w*t.y + y*t.w + z*t.x - x*t.z,
+ w*t.z + z*t.w + x*t.y - y*t.x);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Conjugate ()
{
- x = -x;
- y = -y;
- z = -z;
- return *this;
+ x = -x;
+ y = -y;
+ z = -z;
+ return *this;
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline aiVector3t<TReal> aiQuaterniont<TReal>::Rotate (const aiVector3t<TReal>& v)
{
- aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
- q.Conjugate();
-
- q = q*q2*qinv;
- return aiVector3t<TReal>(q.x,q.y,q.z);
+ aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
+ qinv.Conjugate();
+ q = q*q2*qinv;
+ return aiVector3t<TReal>(q.x,q.y,q.z);
}
#endif
diff --git a/src/3rdparty/assimp/include/assimp/scene.h b/src/3rdparty/assimp/include/assimp/scene.h
index 9196d1835..8987ac6a3 100644
--- a/src/3rdparty/assimp/include/assimp/scene.h
+++ b/src/3rdparty/assimp/include/assimp/scene.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,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.
---------------------------------------------------------------------------
*/
-/** @file aiScene.h
+/** @file scene.h
* @brief Defines the data structures in which the imported scene is returned.
*/
#ifndef __AI_SCENE_H_INC__
@@ -60,199 +60,199 @@ extern "C" {
// -------------------------------------------------------------------------------
-/** A node in the imported hierarchy.
+/** A node in the imported hierarchy.
*
- * Each node has name, a parent node (except for the root node),
+ * Each node has name, a parent node (except for the root node),
* a transformation relative to its parent and possibly several child nodes.
- * Simple file formats don't support hierarchical structures - for these formats
+ * Simple file formats don't support hierarchical structures - for these formats
* the imported scene does consist of only a single root node without children.
*/
// -------------------------------------------------------------------------------
struct aiNode
{
- /** The name of the node.
- *
- * The name might be empty (length of zero) but all nodes which
- * need to be referenced by either bones or animations are named.
- * Multiple nodes may have the same name, except for nodes which are referenced
- * by bones (see #aiBone and #aiMesh::mBones). Their names *must* be unique.
- *
- * Cameras and lights reference a specific node by name - if there
- * are multiple nodes with this name, they are assigned to each of them.
- * <br>
- * There are no limitations with regard to the characters contained in
- * the name string as it is usually taken directly from the source file.
- *
- * Implementations should be able to handle tokens such as whitespace, tabs,
- * line feeds, quotation marks, ampersands etc.
- *
- * Sometimes assimp introduces new nodes not present in the source file
- * into the hierarchy (usually out of necessity because sometimes the
- * source hierarchy format is simply not compatible). Their names are
- * surrounded by @verbatim <> @endverbatim e.g.
- * @verbatim<DummyRootNode> @endverbatim.
- */
- C_STRUCT aiString mName;
-
- /** The transformation relative to the node's parent. */
- C_STRUCT aiMatrix4x4 mTransformation;
-
- /** Parent node. NULL if this node is the root node. */
- C_STRUCT aiNode* mParent;
-
- /** The number of child nodes of this node. */
- unsigned int mNumChildren;
-
- /** The child nodes of this node. NULL if mNumChildren is 0. */
- C_STRUCT aiNode** mChildren;
-
- /** The number of meshes of this node. */
- unsigned int mNumMeshes;
-
- /** The meshes of this node. Each entry is an index into the mesh */
- unsigned int* mMeshes;
-
- /** Metadata associated with this node or NULL if there is no metadata.
- * Whether any metadata is generated depends on the source file format. See the
- * @link importer_notes @endlink page for more information on every source file
- * format. Importers that don't document any metadata don't write any.
- */
- C_STRUCT aiMetadata* mMetaData;
+ /** The name of the node.
+ *
+ * The name might be empty (length of zero) but all nodes which
+ * need to be referenced by either bones or animations are named.
+ * Multiple nodes may have the same name, except for nodes which are referenced
+ * by bones (see #aiBone and #aiMesh::mBones). Their names *must* be unique.
+ *
+ * Cameras and lights reference a specific node by name - if there
+ * are multiple nodes with this name, they are assigned to each of them.
+ * <br>
+ * There are no limitations with regard to the characters contained in
+ * the name string as it is usually taken directly from the source file.
+ *
+ * Implementations should be able to handle tokens such as whitespace, tabs,
+ * line feeds, quotation marks, ampersands etc.
+ *
+ * Sometimes assimp introduces new nodes not present in the source file
+ * into the hierarchy (usually out of necessity because sometimes the
+ * source hierarchy format is simply not compatible). Their names are
+ * surrounded by @verbatim <> @endverbatim e.g.
+ * @verbatim<DummyRootNode> @endverbatim.
+ */
+ C_STRUCT aiString mName;
+
+ /** The transformation relative to the node's parent. */
+ C_STRUCT aiMatrix4x4 mTransformation;
+
+ /** Parent node. NULL if this node is the root node. */
+ C_STRUCT aiNode* mParent;
+
+ /** The number of child nodes of this node. */
+ unsigned int mNumChildren;
+
+ /** The child nodes of this node. NULL if mNumChildren is 0. */
+ C_STRUCT aiNode** mChildren;
+
+ /** The number of meshes of this node. */
+ unsigned int mNumMeshes;
+
+ /** The meshes of this node. Each entry is an index into the
+ * mesh list of the #aiScene.
+ */
+ unsigned int* mMeshes;
+
+ /** Metadata associated with this node or NULL if there is no metadata.
+ * Whether any metadata is generated depends on the source file format. See the
+ * @link importer_notes @endlink page for more information on every source file
+ * format. Importers that don't document any metadata don't write any.
+ */
+ C_STRUCT aiMetadata* mMetaData;
#ifdef __cplusplus
- /** Constructor */
- aiNode()
- // set all members to zero by default
- : mName("")
- , mParent(NULL)
- , mNumChildren(0)
- , mChildren(NULL)
- , mNumMeshes(0)
- , mMeshes(NULL)
- , mMetaData(NULL)
- {
- }
-
-
- /** Construction from a specific name */
- aiNode(const std::string& name)
- // set all members to zero by default
- : mName(name)
- , mParent(NULL)
- , mNumChildren(0)
- , mChildren(NULL)
- , mNumMeshes(0)
- , mMeshes(NULL)
- , mMetaData(NULL)
- {
- }
-
- /** Destructor */
- ~aiNode()
- {
- // delete all children recursively
- // to make sure we won't crash if the data is invalid ...
- if (mChildren && mNumChildren)
- {
- for( unsigned int a = 0; a < mNumChildren; a++)
- delete mChildren[a];
- }
- delete [] mChildren;
- delete [] mMeshes;
- delete mMetaData;
- }
-
-
- /** Searches for a node with a specific name, beginning at this
- * nodes. Normally you will call this method on the root node
- * of the scene.
- *
- * @param name Name to search for
- * @return NULL or a valid Node if the search was successful.
- */
- inline const aiNode* FindNode(const aiString& name) const
- {
- return FindNode(name.data);
- }
-
-
- inline aiNode* FindNode(const aiString& name)
- {
- return FindNode(name.data);
- }
-
-
- /** @override
- */
- inline const aiNode* FindNode(const char* name) const
- {
- if (!::strcmp( mName.data,name))return this;
- for (unsigned int i = 0; i < mNumChildren;++i)
- {
- const aiNode* const p = mChildren[i]->FindNode(name);
- if (p) {
- return p;
- }
- }
- // there is definitely no sub-node with this name
- return NULL;
- }
-
- inline aiNode* FindNode(const char* name)
- {
- if (!::strcmp( mName.data,name))return this;
- for (unsigned int i = 0; i < mNumChildren;++i)
- {
- aiNode* const p = mChildren[i]->FindNode(name);
- if (p) {
- return p;
- }
- }
- // there is definitely no sub-node with this name
- return NULL;
- }
+ /** Constructor */
+ aiNode()
+ // set all members to zero by default
+ : mName("")
+ , mParent(NULL)
+ , mNumChildren(0)
+ , mChildren(NULL)
+ , mNumMeshes(0)
+ , mMeshes(NULL)
+ , mMetaData(NULL)
+ {
+ }
+
+
+ /** Construction from a specific name */
+ explicit aiNode(const std::string& name)
+ // set all members to zero by default
+ : mName(name)
+ , mParent(NULL)
+ , mNumChildren(0)
+ , mChildren(NULL)
+ , mNumMeshes(0)
+ , mMeshes(NULL)
+ , mMetaData(NULL)
+ {
+ }
+
+ /** Destructor */
+ ~aiNode()
+ {
+ // delete all children recursively
+ // to make sure we won't crash if the data is invalid ...
+ if (mChildren && mNumChildren)
+ {
+ for( unsigned int a = 0; a < mNumChildren; a++)
+ delete mChildren[a];
+ }
+ delete [] mChildren;
+ delete [] mMeshes;
+ delete mMetaData;
+ }
+
+
+ /** Searches for a node with a specific name, beginning at this
+ * nodes. Normally you will call this method on the root node
+ * of the scene.
+ *
+ * @param name Name to search for
+ * @return NULL or a valid Node if the search was successful.
+ */
+ inline const aiNode* FindNode(const aiString& name) const
+ {
+ return FindNode(name.data);
+ }
+
+
+ inline aiNode* FindNode(const aiString& name)
+ {
+ return FindNode(name.data);
+ }
+
+
+ inline const aiNode* FindNode(const char* name) const
+ {
+ if (!::strcmp( mName.data,name))return this;
+ for (unsigned int i = 0; i < mNumChildren;++i)
+ {
+ const aiNode* const p = mChildren[i]->FindNode(name);
+ if (p) {
+ return p;
+ }
+ }
+ // there is definitely no sub-node with this name
+ return NULL;
+ }
+
+ inline aiNode* FindNode(const char* name)
+ {
+ if (!::strcmp( mName.data,name))return this;
+ for (unsigned int i = 0; i < mNumChildren;++i)
+ {
+ aiNode* const p = mChildren[i]->FindNode(name);
+ if (p) {
+ return p;
+ }
+ }
+ // there is definitely no sub-node with this name
+ return NULL;
+ }
#endif // __cplusplus
};
// -------------------------------------------------------------------------------
-/** @def AI_SCENE_FLAGS_INCOMPLETE
+/**
* Specifies that the scene data structure that was imported is not complete.
- * This flag bypasses some internal validations and allows the import
- * of animation skeletons, material libraries or camera animation paths
- * using Assimp. Most applications won't support such data.
+ * This flag bypasses some internal validations and allows the import
+ * of animation skeletons, material libraries or camera animation paths
+ * using Assimp. Most applications won't support such data.
*/
-#define AI_SCENE_FLAGS_INCOMPLETE 0x1
+#define AI_SCENE_FLAGS_INCOMPLETE 0x1
-/** @def AI_SCENE_FLAGS_VALIDATED
+/**
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
* if the validation is successful. In a validated scene you can be sure that
* any cross references in the data structure (e.g. vertex indices) are valid.
*/
-#define AI_SCENE_FLAGS_VALIDATED 0x2
+#define AI_SCENE_FLAGS_VALIDATED 0x2
-/** @def AI_SCENE_FLAGS_VALIDATION_WARNING
+/**
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
* if the validation is successful but some issues have been found.
- * This can for example mean that a texture that does not exist is referenced
+ * This can for example mean that a texture that does not exist is referenced
* by a material or that the bone weights for a vertex don't sum to 1.0 ... .
* In most cases you should still be able to use the import. This flag could
* be useful for applications which don't capture Assimp's log output.
*/
-#define AI_SCENE_FLAGS_VALIDATION_WARNING 0x4
+#define AI_SCENE_FLAGS_VALIDATION_WARNING 0x4
-/** @def AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
+/**
* This flag is currently only set by the aiProcess_JoinIdenticalVertices step.
* It indicates that the vertices of the output meshes aren't in the internal
* verbose format anymore. In the verbose format all vertices are unique,
* no vertex is ever referenced by more than one face.
*/
-#define AI_SCENE_FLAGS_NON_VERBOSE_FORMAT 0x8
+#define AI_SCENE_FLAGS_NON_VERBOSE_FORMAT 0x8
- /** @def AI_SCENE_FLAGS_TERRAIN
- * Denotes pure height-map terrain data. Pure terrains usually consist of quads,
- * sometimes triangles, in a regular grid. The x,y coordinates of all vertex
+ /**
+ * Denotes pure height-map terrain data. Pure terrains usually consist of quads,
+ * sometimes triangles, in a regular grid. The x,y coordinates of all vertex
* positions refer to the x,y coordinates on the terrain height map, the z-axis
* stores the elevation at a specific point.
*
@@ -266,8 +266,8 @@ struct aiNode
// -------------------------------------------------------------------------------
-/** The root structure of the imported data.
- *
+/** The root structure of the imported data.
+ *
* Everything that was imported from the given file can be accessed from here.
* Objects of this class are generally maintained and owned by Assimp, not
* by the caller. You shouldn't want to instance it, nor should you ever try to
@@ -277,146 +277,146 @@ struct aiNode
struct aiScene
{
- /** Any combination of the AI_SCENE_FLAGS_XXX flags. By default
- * this value is 0, no flags are set. Most applications will
- * want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
- * bit set.
- */
- unsigned int mFlags;
+ /** Any combination of the AI_SCENE_FLAGS_XXX flags. By default
+ * this value is 0, no flags are set. Most applications will
+ * want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
+ * bit set.
+ */
+ unsigned int mFlags;
- /** The root node of the hierarchy.
- *
- * There will always be at least the root node if the import
- * was successful (and no special flags have been set).
- * Presence of further nodes depends on the format and content
- * of the imported file.
- */
- C_STRUCT aiNode* mRootNode;
+ /** The root node of the hierarchy.
+ *
+ * There will always be at least the root node if the import
+ * was successful (and no special flags have been set).
+ * Presence of further nodes depends on the format and content
+ * of the imported file.
+ */
+ C_STRUCT aiNode* mRootNode;
- /** The number of meshes in the scene. */
- unsigned int mNumMeshes;
+ /** The number of meshes in the scene. */
+ unsigned int mNumMeshes;
- /** The array of meshes.
- *
- * Use the indices given in the aiNode structure to access
- * this array. The array is mNumMeshes in size. If the
- * AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
- * be at least ONE material.
- */
- C_STRUCT aiMesh** mMeshes;
+ /** The array of meshes.
+ *
+ * Use the indices given in the aiNode structure to access
+ * this array. The array is mNumMeshes in size. If the
+ * AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+ * be at least ONE material.
+ */
+ C_STRUCT aiMesh** mMeshes;
- /** The number of materials in the scene. */
- unsigned int mNumMaterials;
+ /** The number of materials in the scene. */
+ unsigned int mNumMaterials;
- /** The array of materials.
- *
- * Use the index given in each aiMesh structure to access this
- * array. The array is mNumMaterials in size. If the
- * AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
- * be at least ONE material.
- */
- C_STRUCT aiMaterial** mMaterials;
+ /** The array of materials.
+ *
+ * Use the index given in each aiMesh structure to access this
+ * array. The array is mNumMaterials in size. If the
+ * AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+ * be at least ONE material.
+ */
+ C_STRUCT aiMaterial** mMaterials;
- /** The number of animations in the scene. */
- unsigned int mNumAnimations;
+ /** The number of animations in the scene. */
+ unsigned int mNumAnimations;
- /** The array of animations.
- *
- * All animations imported from the given file are listed here.
- * The array is mNumAnimations in size.
- */
- C_STRUCT aiAnimation** mAnimations;
+ /** The array of animations.
+ *
+ * All animations imported from the given file are listed here.
+ * The array is mNumAnimations in size.
+ */
+ C_STRUCT aiAnimation** mAnimations;
- /** The number of textures embedded into the file */
- unsigned int mNumTextures;
+ /** The number of textures embedded into the file */
+ unsigned int mNumTextures;
- /** The array of embedded textures.
- *
- * Not many file formats embed their textures into the file.
- * An example is Quake's MDL format (which is also used by
- * some GameStudio versions)
- */
- C_STRUCT aiTexture** mTextures;
+ /** The array of embedded textures.
+ *
+ * Not many file formats embed their textures into the file.
+ * An example is Quake's MDL format (which is also used by
+ * some GameStudio versions)
+ */
+ C_STRUCT aiTexture** mTextures;
- /** The number of light sources in the scene. Light sources
- * are fully optional, in most cases this attribute will be 0
+ /** The number of light sources in the scene. Light sources
+ * are fully optional, in most cases this attribute will be 0
*/
- unsigned int mNumLights;
+ unsigned int mNumLights;
- /** The array of light sources.
- *
- * All light sources imported from the given file are
- * listed here. The array is mNumLights in size.
- */
- C_STRUCT aiLight** mLights;
+ /** The array of light sources.
+ *
+ * All light sources imported from the given file are
+ * listed here. The array is mNumLights in size.
+ */
+ C_STRUCT aiLight** mLights;
- /** The number of cameras in the scene. Cameras
- * are fully optional, in most cases this attribute will be 0
+ /** The number of cameras in the scene. Cameras
+ * are fully optional, in most cases this attribute will be 0
*/
- unsigned int mNumCameras;
+ unsigned int mNumCameras;
- /** The array of cameras.
- *
- * All cameras imported from the given file are listed here.
- * The array is mNumCameras in size. The first camera in the
- * array (if existing) is the default camera view into
- * the scene.
- */
- C_STRUCT aiCamera** mCameras;
+ /** The array of cameras.
+ *
+ * All cameras imported from the given file are listed here.
+ * The array is mNumCameras in size. The first camera in the
+ * array (if existing) is the default camera view into
+ * the scene.
+ */
+ C_STRUCT aiCamera** mCameras;
#ifdef __cplusplus
- //! Default constructor - set everything to 0/NULL
- ASSIMP_API aiScene();
+ //! Default constructor - set everything to 0/NULL
+ ASSIMP_API aiScene();
- //! Destructor
- ASSIMP_API ~aiScene();
+ //! Destructor
+ ASSIMP_API ~aiScene();
- //! Check whether the scene contains meshes
- //! Unless no special scene flags are set this will always be true.
- inline bool HasMeshes() const
- { return mMeshes != NULL && mNumMeshes > 0; }
+ //! Check whether the scene contains meshes
+ //! Unless no special scene flags are set this will always be true.
+ inline bool HasMeshes() const
+ { return mMeshes != NULL && mNumMeshes > 0; }
- //! Check whether the scene contains materials
- //! Unless no special scene flags are set this will always be true.
- inline bool HasMaterials() const
- { return mMaterials != NULL && mNumMaterials > 0; }
+ //! Check whether the scene contains materials
+ //! Unless no special scene flags are set this will always be true.
+ inline bool HasMaterials() const
+ { return mMaterials != NULL && mNumMaterials > 0; }
- //! Check whether the scene contains lights
- inline bool HasLights() const
- { return mLights != NULL && mNumLights > 0; }
+ //! Check whether the scene contains lights
+ inline bool HasLights() const
+ { return mLights != NULL && mNumLights > 0; }
- //! Check whether the scene contains textures
- inline bool HasTextures() const
- { return mTextures != NULL && mNumTextures > 0; }
+ //! Check whether the scene contains textures
+ inline bool HasTextures() const
+ { return mTextures != NULL && mNumTextures > 0; }
- //! Check whether the scene contains cameras
- inline bool HasCameras() const
- { return mCameras != NULL && mNumCameras > 0; }
+ //! Check whether the scene contains cameras
+ inline bool HasCameras() const
+ { return mCameras != NULL && mNumCameras > 0; }
- //! Check whether the scene contains animations
- inline bool HasAnimations() const
- { return mAnimations != NULL && mNumAnimations > 0; }
+ //! Check whether the scene contains animations
+ inline bool HasAnimations() const
+ { return mAnimations != NULL && mNumAnimations > 0; }
#endif // __cplusplus
- /** Internal data, do not touch */
+ /** Internal data, do not touch */
#ifdef __cplusplus
- void* mPrivate;
+ void* mPrivate;
#else
- char* mPrivate;
+ char* mPrivate;
#endif
};
diff --git a/src/3rdparty/assimp/include/assimp/texture.h b/src/3rdparty/assimp/include/assimp/texture.h
index 27b93187b..ee3ee3149 100644
--- a/src/3rdparty/assimp/include/assimp/texture.h
+++ b/src/3rdparty/assimp/include/assimp/texture.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.
---------------------------------------------------------------------------
*/
@@ -60,13 +60,13 @@ extern "C" {
// --------------------------------------------------------------------------------
/** @def AI_MAKE_EMBEDDED_TEXNAME
- * Used to build the reserved path name used by the material system to
+ * Used to build the reserved path name used by the material system to
* reference textures that are embedded into their corresponding
* model files. The parameter specifies the index of the texture
* (zero-based, in the aiScene::mTextures array)
*/
#if (!defined AI_MAKE_EMBEDDED_TEXNAME)
-# define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_
+# define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_
#endif
@@ -74,33 +74,33 @@ extern "C" {
// --------------------------------------------------------------------------------
/** @brief Helper structure to represent a texel in a ARGB8888 format
-*
+*
* Used by aiTexture.
*/
struct aiTexel
{
- unsigned char b,g,r,a;
+ unsigned char b,g,r,a;
#ifdef __cplusplus
- //! Comparison operator
- bool operator== (const aiTexel& other) const
- {
- return b == other.b && r == other.r &&
- g == other.g && a == other.a;
- }
-
- //! Inverse comparison operator
- bool operator!= (const aiTexel& other) const
- {
- return b != other.b || r != other.r ||
- g != other.g || a != other.a;
- }
-
- //! Conversion to a floating-point 4d color
- operator aiColor4D() const
- {
- return aiColor4D(r/255.f,g/255.f,b/255.f,a/255.f);
- }
+ //! Comparison operator
+ bool operator== (const aiTexel& other) const
+ {
+ return b == other.b && r == other.r &&
+ g == other.g && a == other.a;
+ }
+
+ //! Inverse comparison operator
+ bool operator!= (const aiTexel& other) const
+ {
+ return b != other.b || r != other.r ||
+ g != other.g || a != other.a;
+ }
+
+ //! Conversion to a floating-point 4d color
+ operator aiColor4D() const
+ {
+ return aiColor4D(r/255.f,g/255.f,b/255.f,a/255.f);
+ }
#endif // __cplusplus
} PACK_STRUCT;
@@ -109,83 +109,87 @@ struct aiTexel
// --------------------------------------------------------------------------------
/** Helper structure to describe an embedded texture
- *
+ *
* Normally textures are contained in external files but some file formats embed
- * them directly in the model file. There are two types of embedded textures:
- * 1. Uncompressed textures. The color data is given in an uncompressed format.
- * 2. Compressed textures stored in a file format like png or jpg. The raw file
+ * them directly in the model file. There are two types of embedded textures:
+ * 1. Uncompressed textures. The color data is given in an uncompressed format.
+ * 2. Compressed textures stored in a file format like png or jpg. The raw file
* bytes are given so the application must utilize an image decoder (e.g. DevIL) to
* get access to the actual color data.
+ *
+ * Embedded textures are referenced from materials using strings like "*0", "*1", etc.
+ * as the texture paths (a single asterisk character followed by the
+ * zero-based index of the texture in the aiScene::mTextures array).
*/
struct aiTexture
{
- /** Width of the texture, in pixels
- *
- * If mHeight is zero the texture is compressed in a format
- * like JPEG. In this case mWidth specifies the size of the
- * memory area pcData is pointing to, in bytes.
- */
- unsigned int mWidth;
-
- /** Height of the texture, in pixels
- *
- * If this value is zero, pcData points to an compressed texture
- * in any format (e.g. JPEG).
- */
- unsigned int mHeight;
-
- /** A hint from the loader to make it easier for applications
- * to determine the type of embedded compressed textures.
- *
- * If mHeight != 0 this member is undefined. Otherwise it
- * is set set to '\\0\\0\\0\\0' if the loader has no additional
- * information about the texture file format used OR the
- * file extension of the format without a trailing dot. If there
- * are multiple file extensions for a format, the shortest
- * extension is chosen (JPEG maps to 'jpg', not to 'jpeg').
- * E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case.
- * The fourth character will always be '\\0'.
- */
- char achFormatHint[4];
-
- /** Data of the texture.
- *
- * Points to an array of mWidth * mHeight aiTexel's.
- * The format of the texture data is always ARGB8888 to
- * make the implementation for user of the library as easy
- * as possible. If mHeight = 0 this is a pointer to a memory
- * buffer of size mWidth containing the compressed texture
- * data. Good luck, have fun!
- */
- C_STRUCT aiTexel* pcData;
+ /** Width of the texture, in pixels
+ *
+ * If mHeight is zero the texture is compressed in a format
+ * like JPEG. In this case mWidth specifies the size of the
+ * memory area pcData is pointing to, in bytes.
+ */
+ unsigned int mWidth;
+
+ /** Height of the texture, in pixels
+ *
+ * If this value is zero, pcData points to an compressed texture
+ * in any format (e.g. JPEG).
+ */
+ unsigned int mHeight;
+
+ /** A hint from the loader to make it easier for applications
+ * to determine the type of embedded compressed textures.
+ *
+ * If mHeight != 0 this member is undefined. Otherwise it
+ * is set set to '\\0\\0\\0\\0' if the loader has no additional
+ * information about the texture file format used OR the
+ * file extension of the format without a trailing dot. If there
+ * are multiple file extensions for a format, the shortest
+ * extension is chosen (JPEG maps to 'jpg', not to 'jpeg').
+ * E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case.
+ * The fourth character will always be '\\0'.
+ */
+ char achFormatHint[4];
+
+ /** Data of the texture.
+ *
+ * Points to an array of mWidth * mHeight aiTexel's.
+ * The format of the texture data is always ARGB8888 to
+ * make the implementation for user of the library as easy
+ * as possible. If mHeight = 0 this is a pointer to a memory
+ * buffer of size mWidth containing the compressed texture
+ * data. Good luck, have fun!
+ */
+ C_STRUCT aiTexel* pcData;
#ifdef __cplusplus
- //! For compressed textures (mHeight == 0): compare the
- //! format hint against a given string.
- //! @param s Input string. 3 characters are maximally processed.
- //! Example values: "jpg", "png"
- //! @return true if the given string matches the format hint
- bool CheckFormat(const char* s) const
- {
- return (0 == ::strncmp(achFormatHint,s,3));
- }
-
- // Construction
- aiTexture ()
- : mWidth (0)
- , mHeight (0)
- , pcData (NULL)
- {
- achFormatHint[0] = achFormatHint[1] = 0;
- achFormatHint[2] = achFormatHint[3] = 0;
- }
-
- // Destruction
- ~aiTexture ()
- {
- delete[] pcData;
- }
+ //! For compressed textures (mHeight == 0): compare the
+ //! format hint against a given string.
+ //! @param s Input string. 3 characters are maximally processed.
+ //! Example values: "jpg", "png"
+ //! @return true if the given string matches the format hint
+ bool CheckFormat(const char* s) const
+ {
+ return (0 == ::strncmp(achFormatHint,s,3));
+ }
+
+ // Construction
+ aiTexture ()
+ : mWidth (0)
+ , mHeight (0)
+ , pcData (NULL)
+ {
+ achFormatHint[0] = achFormatHint[1] = 0;
+ achFormatHint[2] = achFormatHint[3] = 0;
+ }
+
+ // Destruction
+ ~aiTexture ()
+ {
+ delete[] pcData;
+ }
#endif
};
diff --git a/src/3rdparty/assimp/include/assimp/types.h b/src/3rdparty/assimp/include/assimp/types.h
index a8200a765..592d5c64d 100644
--- a/src/3rdparty/assimp/include/assimp/types.h
+++ b/src/3rdparty/assimp/include/assimp/types.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,29 +25,28 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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 types.h
- * Basic data types and primitives, such as vectors or colors.
+ * Basic data types and primitives, such as vectors or colors.
*/
#ifndef AI_TYPES_H_INC
#define AI_TYPES_H_INC
// Some runtime headers
#include <sys/types.h>
-#include <memory.h>
#include <math.h>
#include <stddef.h>
#include <string.h>
@@ -66,43 +65,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
#include <cstring>
-#include <new> // for std::nothrow_t
-#include <string> // for aiString::Set(const std::string&)
-
-namespace Assimp {
- //! @cond never
-namespace Intern {
- // --------------------------------------------------------------------
- /** @brief Internal helper class to utilize our internal new/delete
- * routines for allocating object of this and derived classes.
- *
- * By doing this you can safely share class objects between Assimp
- * and the application - it works even over DLL boundaries. A good
- * example is the #IOSystem where the application allocates its custom
- * #IOSystem, then calls #Importer::SetIOSystem(). When the Importer
- * destructs, Assimp calls operator delete on the stored #IOSystem.
- * If it lies on a different heap than Assimp is working with,
- * the application is determined to crash.
- */
- // --------------------------------------------------------------------
+#include <new> // for std::nothrow_t
+#include <string> // for aiString::Set(const std::string&)
+
+namespace Assimp {
+ //! @cond never
+namespace Intern {
+ // --------------------------------------------------------------------
+ /** @brief Internal helper class to utilize our internal new/delete
+ * routines for allocating object of this and derived classes.
+ *
+ * By doing this you can safely share class objects between Assimp
+ * and the application - it works even over DLL boundaries. A good
+ * example is the #IOSystem where the application allocates its custom
+ * #IOSystem, then calls #Importer::SetIOSystem(). When the Importer
+ * destructs, Assimp calls operator delete on the stored #IOSystem.
+ * If it lies on a different heap than Assimp is working with,
+ * the application is determined to crash.
+ */
+ // --------------------------------------------------------------------
#ifndef SWIG
- struct ASSIMP_API AllocateFromAssimpHeap {
- // http://www.gotw.ca/publications/mill15.htm
+ struct ASSIMP_API AllocateFromAssimpHeap {
+ // http://www.gotw.ca/publications/mill15.htm
- // new/delete overload
- void *operator new ( size_t num_bytes) /* throw( std::bad_alloc ) */;
- void *operator new ( size_t num_bytes, const std::nothrow_t& ) throw();
- void operator delete ( void* data);
+ // new/delete overload
+ void *operator new ( size_t num_bytes) /* throw( std::bad_alloc ) */;
+ void *operator new ( size_t num_bytes, const std::nothrow_t& ) throw();
+ void operator delete ( void* data);
- // array new/delete overload
- void *operator new[] ( size_t num_bytes) /* throw( std::bad_alloc ) */;
- void *operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw();
- void operator delete[] ( void* data);
+ // array new/delete overload
+ void *operator new[] ( size_t num_bytes) /* throw( std::bad_alloc ) */;
+ void *operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw();
+ void operator delete[] ( void* data);
- }; // struct AllocateFromAssimpHeap
+ }; // struct AllocateFromAssimpHeap
#endif
} // namespace Intern
- //! @endcond
+ //! @endcond
} // namespace Assimp
extern "C" {
@@ -112,7 +111,7 @@ extern "C" {
#ifdef __cplusplus
const size_t MAXLEN = 1024;
#else
-# define MAXLEN 1024
+# define MAXLEN 1024
#endif
#include "./Compiler/pushpack1.h"
@@ -123,16 +122,16 @@ const size_t MAXLEN = 1024;
struct aiPlane
{
#ifdef __cplusplus
- aiPlane () : a(0.f), b(0.f), c(0.f), d(0.f) {}
- aiPlane (float _a, float _b, float _c, float _d)
- : a(_a), b(_b), c(_c), d(_d) {}
+ aiPlane () : a(0.f), b(0.f), c(0.f), d(0.f) {}
+ aiPlane (float _a, float _b, float _c, float _d)
+ : a(_a), b(_b), c(_c), d(_d) {}
- aiPlane (const aiPlane& o) : a(o.a), b(o.b), c(o.c), d(o.d) {}
+ aiPlane (const aiPlane& o) : a(o.a), b(o.b), c(o.c), d(o.d) {}
#endif // !__cplusplus
- //! Plane equation
- float a,b,c,d;
+ //! Plane equation
+ float a,b,c,d;
} PACK_STRUCT; // !struct aiPlane
// ----------------------------------------------------------------------------------
@@ -141,89 +140,89 @@ struct aiPlane
struct aiRay
{
#ifdef __cplusplus
- aiRay () {}
- aiRay (const aiVector3D& _pos, const aiVector3D& _dir)
- : pos(_pos), dir(_dir) {}
+ aiRay () {}
+ aiRay (const aiVector3D& _pos, const aiVector3D& _dir)
+ : pos(_pos), dir(_dir) {}
- aiRay (const aiRay& o) : pos (o.pos), dir (o.dir) {}
+ aiRay (const aiRay& o) : pos (o.pos), dir (o.dir) {}
#endif // !__cplusplus
- //! Position and direction of the ray
- C_STRUCT aiVector3D pos, dir;
+ //! Position and direction of the ray
+ C_STRUCT aiVector3D pos, dir;
} PACK_STRUCT; // !struct aiRay
// ----------------------------------------------------------------------------------
-/** Represents a color in Red-Green-Blue space.
+/** Represents a color in Red-Green-Blue space.
*/
struct aiColor3D
{
#ifdef __cplusplus
- aiColor3D () : r(0.0f), g(0.0f), b(0.0f) {}
- aiColor3D (float _r, float _g, float _b) : r(_r), g(_g), b(_b) {}
- aiColor3D (float _r) : r(_r), g(_r), b(_r) {}
- aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {}
-
- /** Component-wise comparison */
- // TODO: add epsilon?
- bool operator == (const aiColor3D& other) const
- {return r == other.r && g == other.g && b == other.b;}
-
- /** Component-wise inverse comparison */
- // TODO: add epsilon?
- bool operator != (const aiColor3D& other) const
- {return r != other.r || g != other.g || b != other.b;}
-
- /** Component-wise comparison */
- // TODO: add epsilon?
- bool operator < (const aiColor3D& other) const {
- return r < other.r || (
- r == other.r && (g < other.g ||
- (g == other.g && b < other.b)
- )
- );
- }
-
- /** Component-wise addition */
- aiColor3D operator+(const aiColor3D& c) const {
- return aiColor3D(r+c.r,g+c.g,b+c.b);
- }
-
- /** Component-wise subtraction */
- aiColor3D operator-(const aiColor3D& c) const {
- return aiColor3D(r-c.r,g-c.g,b-c.b);
- }
-
- /** Component-wise multiplication */
- aiColor3D operator*(const aiColor3D& c) const {
- return aiColor3D(r*c.r,g*c.g,b*c.b);
- }
-
- /** Multiply with a scalar */
- aiColor3D operator*(float f) const {
- return aiColor3D(r*f,g*f,b*f);
- }
-
- /** Access a specific color component */
- float operator[](unsigned int i) const {
- return *(&r + i);
- }
-
- /** Access a specific color component */
- float& operator[](unsigned int i) {
- return *(&r + i);
- }
-
- /** Check whether a color is black */
- bool IsBlack() const {
- static const float epsilon = 10e-3f;
- return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
- }
+ aiColor3D () : r(0.0f), g(0.0f), b(0.0f) {}
+ aiColor3D (float _r, float _g, float _b) : r(_r), g(_g), b(_b) {}
+ explicit aiColor3D (float _r) : r(_r), g(_r), b(_r) {}
+ aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {}
+
+ /** Component-wise comparison */
+ // TODO: add epsilon?
+ bool operator == (const aiColor3D& other) const
+ {return r == other.r && g == other.g && b == other.b;}
+
+ /** Component-wise inverse comparison */
+ // TODO: add epsilon?
+ bool operator != (const aiColor3D& other) const
+ {return r != other.r || g != other.g || b != other.b;}
+
+ /** Component-wise comparison */
+ // TODO: add epsilon?
+ bool operator < (const aiColor3D& other) const {
+ return r < other.r || (
+ r == other.r && (g < other.g ||
+ (g == other.g && b < other.b)
+ )
+ );
+ }
+
+ /** Component-wise addition */
+ aiColor3D operator+(const aiColor3D& c) const {
+ return aiColor3D(r+c.r,g+c.g,b+c.b);
+ }
+
+ /** Component-wise subtraction */
+ aiColor3D operator-(const aiColor3D& c) const {
+ return aiColor3D(r-c.r,g-c.g,b-c.b);
+ }
+
+ /** Component-wise multiplication */
+ aiColor3D operator*(const aiColor3D& c) const {
+ return aiColor3D(r*c.r,g*c.g,b*c.b);
+ }
+
+ /** Multiply with a scalar */
+ aiColor3D operator*(float f) const {
+ return aiColor3D(r*f,g*f,b*f);
+ }
+
+ /** Access a specific color component */
+ float operator[](unsigned int i) const {
+ return *(&r + i);
+ }
+
+ /** Access a specific color component */
+ float& operator[](unsigned int i) {
+ return *(&r + i);
+ }
+
+ /** Check whether a color is black */
+ bool IsBlack() const {
+ static const float epsilon = 10e-3f;
+ return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
+ }
#endif // !__cplusplus
- //! Red, green and blue color values
- float r, g, b;
+ //! Red, green and blue color values
+ float r, g, b;
} PACK_STRUCT; // !struct aiColor3D
#include "./Compiler/poppack1.h"
@@ -233,161 +232,163 @@ struct aiColor3D
* The character set of an aiString is explicitly defined to be UTF-8. This Unicode
* transformation was chosen in the belief that most strings in 3d files are limited
* to ASCII, thus the character set needed to be strictly ASCII compatible.
- *
+ *
* Most text file loaders provide proper Unicode input file handling, special unicode
* characters are correctly transcoded to UTF8 and are kept throughout the libraries'
- * import pipeline.
+ * import pipeline.
*
* For most applications, it will be absolutely sufficient to interpret the
- * aiString as ASCII data and work with it as one would work with a plain char*.
+ * aiString as ASCII data and work with it as one would work with a plain char*.
* Windows users in need of proper support for i.e asian characters can use the
- * #MultiByteToWideChar(), #WideCharToMultiByte() WinAPI functionality to convert the
+ * MultiByteToWideChar(), WideCharToMultiByte() WinAPI functionality to convert the
* UTF-8 strings to their working character set (i.e. MBCS, WideChar).
*
- * We use this representation instead of std::string to be C-compatible. The
+ * We use this representation instead of std::string to be C-compatible. The
* (binary) length of such a string is limited to MAXLEN characters (including the
* the terminating zero).
*/
struct aiString
{
#ifdef __cplusplus
- /** Default constructor, the string is set to have zero length */
- aiString() :
- length(0)
- {
- data[0] = '\0';
+ /** Default constructor, the string is set to have zero length */
+ aiString() :
+ length(0)
+ {
+ data[0] = '\0';
#ifdef ASSIMP_BUILD_DEBUG
- // Debug build: overwrite the string on its full length with ESC (27)
- memset(data+1,27,MAXLEN-1);
+ // Debug build: overwrite the string on its full length with ESC (27)
+ memset(data+1,27,MAXLEN-1);
#endif
- }
-
- /** Copy constructor */
- aiString(const aiString& rOther) :
- length(rOther.length)
- {
- // Crop the string to the maximum length
- length = length>=MAXLEN?MAXLEN-1:length;
- memcpy( data, rOther.data, length);
- data[length] = '\0';
- }
-
- /** Constructor from std::string */
- explicit aiString(const std::string& pString) :
- length(pString.length())
- {
- length = length>=MAXLEN?MAXLEN-1:length;
- memcpy( data, pString.c_str(), length);
- data[length] = '\0';
- }
-
- /** Copy a std::string to the aiString */
- void Set( const std::string& pString) {
- if( pString.length() > MAXLEN - 1) {
- return;
- }
- length = pString.length();
- memcpy( data, pString.c_str(), length);
- data[length] = 0;
- }
-
- /** Copy a const char* to the aiString */
- void Set( const char* sz) {
- const size_t len = ::strlen(sz);
- if( len > MAXLEN - 1) {
- return;
- }
- length = len;
- memcpy( data, sz, len);
- data[len] = 0;
- }
-
- /** Assign a const char* to the string */
- aiString& operator = (const char* sz) {
- Set(sz);
- return *this;
- }
-
- /** Assign a cstd::string to the string */
- aiString& operator = ( const std::string& pString) {
- Set(pString);
- return *this;
- }
-
- /** Comparison operator */
- bool operator==(const aiString& other) const {
- return (length == other.length && 0 == memcmp(data,other.data,length));
- }
-
- /** Inverse comparison operator */
- bool operator!=(const aiString& other) const {
- return (length != other.length || 0 != memcmp(data,other.data,length));
- }
-
- /** Append a string to the string */
- void Append (const char* app) {
- const size_t len = ::strlen(app);
- if (!len) {
- return;
- }
- if (length + len >= MAXLEN) {
- return;
- }
-
- memcpy(&data[length],app,len+1);
- length += len;
- }
-
- /** Clear the string - reset its length to zero */
- void Clear () {
- length = 0;
- data[0] = '\0';
+ }
+
+ /** Copy constructor */
+ aiString(const aiString& rOther) :
+ length(rOther.length)
+ {
+ // Crop the string to the maximum length
+ length = length>=MAXLEN?MAXLEN-1:length;
+ memcpy( data, rOther.data, length);
+ data[length] = '\0';
+ }
+
+ /** Constructor from std::string */
+ explicit aiString(const std::string& pString) :
+ length(pString.length())
+ {
+ length = length>=MAXLEN?MAXLEN-1:length;
+ memcpy( data, pString.c_str(), length);
+ data[length] = '\0';
+ }
+
+ /** Copy a std::string to the aiString */
+ void Set( const std::string& pString) {
+ if( pString.length() > MAXLEN - 1) {
+ return;
+ }
+ length = pString.length();
+ memcpy( data, pString.c_str(), length);
+ data[length] = 0;
+ }
+
+ /** Copy a const char* to the aiString */
+ void Set( const char* sz) {
+ const size_t len = ::strlen(sz);
+ if( len > MAXLEN - 1) {
+ return;
+ }
+ length = len;
+ memcpy( data, sz, len);
+ data[len] = 0;
+ }
+
+ /** Assign a const char* to the string */
+ aiString& operator = (const char* sz) {
+ Set(sz);
+ return *this;
+ }
+
+ /** Assign a cstd::string to the string */
+ aiString& operator = ( const std::string& pString) {
+ Set(pString);
+ return *this;
+ }
+
+ /** Comparison operator */
+ bool operator==(const aiString& other) const {
+ return (length == other.length && 0 == memcmp(data,other.data,length));
+ }
+
+ /** Inverse comparison operator */
+ bool operator!=(const aiString& other) const {
+ return (length != other.length || 0 != memcmp(data,other.data,length));
+ }
+
+ /** Append a string to the string */
+ void Append (const char* app) {
+ const size_t len = ::strlen(app);
+ if (!len) {
+ return;
+ }
+ if (length + len >= MAXLEN) {
+ return;
+ }
+
+ memcpy(&data[length],app,len+1);
+ length += len;
+ }
+
+ /** Clear the string - reset its length to zero */
+ void Clear () {
+ length = 0;
+ data[0] = '\0';
#ifdef ASSIMP_BUILD_DEBUG
- // Debug build: overwrite the string on its full length with ESC (27)
- memset(data+1,27,MAXLEN-1);
+ // Debug build: overwrite the string on its full length with ESC (27)
+ memset(data+1,27,MAXLEN-1);
#endif
- }
+ }
- /** Returns a pointer to the underlying zero-terminated array of characters */
- const char* C_Str() const {
- return data;
- }
+ /** Returns a pointer to the underlying zero-terminated array of characters */
+ const char* C_Str() const {
+ return data;
+ }
#endif // !__cplusplus
- /** Binary length of the string excluding the terminal 0. This is NOT the
- * logical length of strings containing UTF-8 multibyte sequences! It's
- * the number of bytes from the beginning of the string to its end.*/
- size_t length;
+ /** Binary length of the string excluding the terminal 0. This is NOT the
+ * logical length of strings containing UTF-8 multibyte sequences! It's
+ * the number of bytes from the beginning of the string to its end.*/
+ size_t length;
- /** String buffer. Size limit is MAXLEN */
- char data[MAXLEN];
+ /** String buffer. Size limit is MAXLEN */
+ char data[MAXLEN];
} ; // !struct aiString
// ----------------------------------------------------------------------------------
-/** Standard return type for some library functions.
+/** Standard return type for some library functions.
* Rarely used, and if, mostly in the C API.
*/
typedef enum aiReturn
{
- /** Indicates that a function was successful */
- aiReturn_SUCCESS = 0x0,
+ /** Indicates that a function was successful */
+ aiReturn_SUCCESS = 0x0,
+
+ /** Indicates that a function failed */
+ aiReturn_FAILURE = -0x1,
- /** Indicates that a function failed */
- aiReturn_FAILURE = -0x1,
+ /** Indicates that not enough memory was available
+ * to perform the requested operation
+ */
+ aiReturn_OUTOFMEMORY = -0x3,
- /** Indicates that not enough memory was available
- * to perform the requested operation
- */
- aiReturn_OUTOFMEMORY = -0x3,
+ /** @cond never
+ * Force 32-bit size enum
+ */
+ _AI_ENFORCE_ENUM_SIZE = 0x7fffffff
- /** @cond never
- * Force 32-bit size enum
- */
- _AI_ENFORCE_ENUM_SIZE = 0x7fffffff
+ /// @endcond
} aiReturn; // !enum aiReturn
// just for backwards compatibility, don't use these constants anymore
@@ -401,47 +402,49 @@ typedef enum aiReturn
*/
enum aiOrigin
{
- /** Beginning of the file */
- aiOrigin_SET = 0x0,
+ /** Beginning of the file */
+ aiOrigin_SET = 0x0,
- /** Current position of the file pointer */
- aiOrigin_CUR = 0x1,
+ /** Current position of the file pointer */
+ aiOrigin_CUR = 0x1,
- /** End of the file, offsets must be negative */
- aiOrigin_END = 0x2,
+ /** End of the file, offsets must be negative */
+ aiOrigin_END = 0x2,
- /** @cond never
- * Force 32-bit size enum
- */
- _AI_ORIGIN_ENFORCE_ENUM_SIZE = 0x7fffffff
+ /** @cond never
+ * Force 32-bit size enum
+ */
+ _AI_ORIGIN_ENFORCE_ENUM_SIZE = 0x7fffffff
+
+ /// @endcond
}; // !enum aiOrigin
// ----------------------------------------------------------------------------------
-/** @brief Enumerates predefined log streaming destinations.
- * Logging to these streams can be enabled with a single call to
- * #LogStream::createDefaultStream or #aiAttachPredefinedLogStream(),
- * respectively.
+/** @brief Enumerates predefined log streaming destinations.
+ * Logging to these streams can be enabled with a single call to
+ * #LogStream::createDefaultStream.
*/
-enum aiDefaultLogStream
+enum aiDefaultLogStream
{
- /** Stream the log to a file */
- aiDefaultLogStream_FILE = 0x1,
+ /** Stream the log to a file */
+ aiDefaultLogStream_FILE = 0x1,
- /** Stream the log to std::cout */
- aiDefaultLogStream_STDOUT = 0x2,
+ /** Stream the log to std::cout */
+ aiDefaultLogStream_STDOUT = 0x2,
- /** Stream the log to std::cerr */
- aiDefaultLogStream_STDERR = 0x4,
+ /** Stream the log to std::cerr */
+ aiDefaultLogStream_STDERR = 0x4,
- /** MSVC only: Stream the log the the debugger
- * (this relies on OutputDebugString from the Win32 SDK)
- */
- aiDefaultLogStream_DEBUGGER = 0x8,
+ /** MSVC only: Stream the log the the debugger
+ * (this relies on OutputDebugString from the Win32 SDK)
+ */
+ aiDefaultLogStream_DEBUGGER = 0x8,
- /** @cond never
- * Force 32-bit size enum
- */
- _AI_DLS_ENFORCE_ENUM_SIZE = 0x7fffffff
+ /** @cond never
+ * Force 32-bit size enum
+ */
+ _AI_DLS_ENFORCE_ENUM_SIZE = 0x7fffffff
+ /// @endcond
}; // !enum aiDefaultLogStream
// just for backwards compatibility, don't use these constants anymore
@@ -459,44 +462,44 @@ struct aiMemoryInfo
{
#ifdef __cplusplus
- /** Default constructor */
- aiMemoryInfo()
- : textures (0)
- , materials (0)
- , meshes (0)
- , nodes (0)
- , animations (0)
- , cameras (0)
- , lights (0)
- , total (0)
- {}
+ /** Default constructor */
+ aiMemoryInfo()
+ : textures (0)
+ , materials (0)
+ , meshes (0)
+ , nodes (0)
+ , animations (0)
+ , cameras (0)
+ , lights (0)
+ , total (0)
+ {}
#endif
- /** Storage allocated for texture data */
- unsigned int textures;
+ /** Storage allocated for texture data */
+ unsigned int textures;
- /** Storage allocated for material data */
- unsigned int materials;
+ /** Storage allocated for material data */
+ unsigned int materials;
- /** Storage allocated for mesh data */
- unsigned int meshes;
+ /** Storage allocated for mesh data */
+ unsigned int meshes;
- /** Storage allocated for node data */
- unsigned int nodes;
+ /** Storage allocated for node data */
+ unsigned int nodes;
- /** Storage allocated for animation data */
- unsigned int animations;
+ /** Storage allocated for animation data */
+ unsigned int animations;
- /** Storage allocated for camera data */
- unsigned int cameras;
+ /** Storage allocated for camera data */
+ unsigned int cameras;
- /** Storage allocated for light data */
- unsigned int lights;
+ /** Storage allocated for light data */
+ unsigned int lights;
- /** Total storage allocated for the full import. */
- unsigned int total;
-}; // !struct aiMemoryInfo
+ /** Total storage allocated for the full import. */
+ unsigned int total;
+}; // !struct aiMemoryInfo
#ifdef __cplusplus
}
@@ -509,4 +512,4 @@ struct aiMemoryInfo
#include "quaternion.inl"
#include "matrix3x3.inl"
#include "matrix4x4.inl"
-#endif
+#endif
diff --git a/src/3rdparty/assimp/include/assimp/vector2.h b/src/3rdparty/assimp/include/assimp/vector2.h
index 5ec98f4eb..199743e26 100644
--- a/src/3rdparty/assimp/include/assimp/vector2.h
+++ b/src/3rdparty/assimp/include/assimp/vector2.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,20 +25,20 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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 aiVector2t.h
+/** @file vector2.h
* @brief 2D vector structure, including operators when compiling in C++
*/
#ifndef AI_VECTOR2D_H_INC
@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "./Compiler/pushpack1.h"
// ----------------------------------------------------------------------------------
-/** Represents a two-dimensional vector.
+/** Represents a two-dimensional vector.
*/
#ifdef __cplusplus
@@ -62,40 +62,40 @@ class aiVector2t
{
public:
- aiVector2t () : x(), y() {}
- aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {}
- explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {}
- aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {}
+ aiVector2t () : x(), y() {}
+ aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {}
+ explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {}
+ aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {}
public:
- void Set( TReal pX, TReal pY);
- TReal SquareLength() const ;
- TReal Length() const ;
- aiVector2t& Normalize();
+ void Set( TReal pX, TReal pY);
+ TReal SquareLength() const ;
+ TReal Length() const ;
+ aiVector2t& Normalize();
public:
- const aiVector2t& operator += (const aiVector2t& o);
- const aiVector2t& operator -= (const aiVector2t& o);
- const aiVector2t& operator *= (TReal f);
- const aiVector2t& operator /= (TReal f);
+ const aiVector2t& operator += (const aiVector2t& o);
+ const aiVector2t& operator -= (const aiVector2t& o);
+ const aiVector2t& operator *= (TReal f);
+ const aiVector2t& operator /= (TReal f);
- TReal operator[](unsigned int i) const;
- TReal& operator[](unsigned int i);
+ TReal operator[](unsigned int i) const;
+ TReal& operator[](unsigned int i);
- bool operator== (const aiVector2t& other) const;
- bool operator!= (const aiVector2t& other) const;
+ bool operator== (const aiVector2t& other) const;
+ bool operator!= (const aiVector2t& other) const;
- bool Equal(const aiVector2t& other, TReal epsilon = 1e-6) const;
+ bool Equal(const aiVector2t& other, TReal epsilon = 1e-6) const;
- aiVector2t& operator= (TReal f);
- const aiVector2t SymMul(const aiVector2t& o);
+ aiVector2t& operator= (TReal f);
+ const aiVector2t SymMul(const aiVector2t& o);
- template <typename TOther>
- operator aiVector2t<TOther> () const;
+ template <typename TOther>
+ operator aiVector2t<TOther> () const;
- TReal x, y;
+ TReal x, y;
} PACK_STRUCT;
typedef aiVector2t<float> aiVector2D;
@@ -103,7 +103,7 @@ typedef aiVector2t<float> aiVector2D;
#else
struct aiVector2D {
- float x,y;
+ float x, y;
};
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/vector2.inl b/src/3rdparty/assimp/include/assimp/vector2.inl
index da085ea6f..ae823fc1a 100644
--- a/src/3rdparty/assimp/include/assimp/vector2.inl
+++ b/src/3rdparty/assimp/include/assimp/vector2.inl
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file aiVector2D.inl
+/** @file vector2.inl
* @brief Inline implementation of aiVector2t<TReal> operators
*/
#ifndef AI_VECTOR2D_INL_INC
@@ -54,18 +54,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template <typename TReal>
template <typename TOther>
aiVector2t<TReal>::operator aiVector2t<TOther> () const {
- return aiVector2t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y));
+ return aiVector2t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y));
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-void aiVector2t<TReal>::Set( TReal pX, TReal pY) {
- x = pX; y = pY;
+void aiVector2t<TReal>::Set( TReal pX, TReal pY) {
+ x = pX; y = pY;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
TReal aiVector2t<TReal>::SquareLength() const {
- return x*x + y*y;
+ return x*x + y*y;
}
// ------------------------------------------------------------------------------------------------
@@ -76,82 +76,82 @@ TReal aiVector2t<TReal>::Length() const {
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-aiVector2t<TReal>& aiVector2t<TReal>::Normalize() {
- *this /= Length();
- return *this;
+aiVector2t<TReal>& aiVector2t<TReal>::Normalize() {
+ *this /= Length();
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
const aiVector2t<TReal>& aiVector2t<TReal>::operator += (const aiVector2t& o) {
- x += o.x; y += o.y;
- return *this;
+ x += o.x; y += o.y;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
const aiVector2t<TReal>& aiVector2t<TReal>::operator -= (const aiVector2t& o) {
- x -= o.x; y -= o.y;
- return *this;
+ x -= o.x; y -= o.y;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) {
- x *= f; y *= f;
- return *this;
+const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) {
+ x *= f; y *= f;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
const aiVector2t<TReal>& aiVector2t<TReal>::operator /= (TReal f) {
- x /= f; y /= f;
- return *this;
+ x /= f; y /= f;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
TReal aiVector2t<TReal>::operator[](unsigned int i) const {
- return *(&x + i);
+ return *(&x + i);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
TReal& aiVector2t<TReal>::operator[](unsigned int i) {
- return *(&x + i);
+ return *(&x + i);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
bool aiVector2t<TReal>::operator== (const aiVector2t& other) const {
- return x == other.x && y == other.y;
+ return x == other.x && y == other.y;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
bool aiVector2t<TReal>::operator!= (const aiVector2t& other) const {
- return x != other.x || y != other.y;
+ return x != other.x || y != other.y;
}
// ---------------------------------------------------------------------------
template<typename TReal>
bool aiVector2t<TReal>::Equal(const aiVector2t& other, TReal epsilon) const {
- return
- std::abs(x - other.x) <= epsilon &&
- std::abs(y - other.y) <= epsilon;
+ return
+ std::abs(x - other.x) <= epsilon &&
+ std::abs(y - other.y) <= epsilon;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f) {
- x = y = f;
- return *this;
+aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f) {
+ x = y = f;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
- return aiVector2t(x*o.x,y*o.y);
+ return aiVector2t(x*o.x,y*o.y);
}
@@ -160,7 +160,7 @@ const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
template <typename TReal>
inline aiVector2t<TReal> operator + (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
{
- return aiVector2t<TReal>( v1.x + v2.x, v1.y + v2.y);
+ return aiVector2t<TReal>( v1.x + v2.x, v1.y + v2.y);
}
// ------------------------------------------------------------------------------------------------
@@ -168,7 +168,7 @@ inline aiVector2t<TReal> operator + (const aiVector2t<TReal>& v1, const aiVector
template <typename TReal>
inline aiVector2t<TReal> operator - (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
{
- return aiVector2t<TReal>( v1.x - v2.x, v1.y - v2.y);
+ return aiVector2t<TReal>( v1.x - v2.x, v1.y - v2.y);
}
// ------------------------------------------------------------------------------------------------
@@ -176,7 +176,7 @@ inline aiVector2t<TReal> operator - (const aiVector2t<TReal>& v1, const aiVector
template <typename TReal>
inline TReal operator * (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
{
- return v1.x*v2.x + v1.y*v2.y;
+ return v1.x*v2.x + v1.y*v2.y;
}
// ------------------------------------------------------------------------------------------------
@@ -184,7 +184,7 @@ inline TReal operator * (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v
template <typename TReal>
inline aiVector2t<TReal> operator * ( TReal f, const aiVector2t<TReal>& v)
{
- return aiVector2t<TReal>( f*v.x, f*v.y);
+ return aiVector2t<TReal>( f*v.x, f*v.y);
}
// ------------------------------------------------------------------------------------------------
@@ -192,7 +192,7 @@ inline aiVector2t<TReal> operator * ( TReal f, const aiVector2t<TReal>& v)
template <typename TReal>
inline aiVector2t<TReal> operator * ( const aiVector2t<TReal>& v, TReal f)
{
- return aiVector2t<TReal>( f*v.x, f*v.y);
+ return aiVector2t<TReal>( f*v.x, f*v.y);
}
// ------------------------------------------------------------------------------------------------
@@ -201,7 +201,7 @@ template <typename TReal>
inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, TReal f)
{
- return v * (1/f);
+ return v * (1/f);
}
// ------------------------------------------------------------------------------------------------
@@ -209,7 +209,7 @@ inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, TReal f)
template <typename TReal>
inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, const aiVector2t<TReal>& v2)
{
- return aiVector2t<TReal>(v.x / v2.x,v.y / v2.y);
+ return aiVector2t<TReal>(v.x / v2.x,v.y / v2.y);
}
// ------------------------------------------------------------------------------------------------
@@ -217,8 +217,8 @@ inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, const aiVector
template <typename TReal>
inline aiVector2t<TReal> operator - ( const aiVector2t<TReal>& v)
{
- return aiVector2t<TReal>( -v.x, -v.y);
+ return aiVector2t<TReal>( -v.x, -v.y);
}
-#endif
+#endif
#endif
diff --git a/src/3rdparty/assimp/include/assimp/vector3.h b/src/3rdparty/assimp/include/assimp/vector3.h
index 8176f98a7..84f785f8f 100644
--- a/src/3rdparty/assimp/include/assimp/vector3.h
+++ b/src/3rdparty/assimp/include/assimp/vector3.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,20 +25,20 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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 aiVector3D.h
+/** @file vector3.h
* @brief 3D vector structure, including operators when compiling in C++
*/
#ifndef AI_VECTOR3D_H_INC
@@ -60,70 +60,72 @@ template<typename TReal> class aiMatrix4x4t;
// ---------------------------------------------------------------------------
/** Represents a three-dimensional vector. */
template <typename TReal>
-class aiVector3t
+class aiVector3t
{
public:
- aiVector3t () : x(), y(), z() {}
- aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
- explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {}
- aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {}
+ aiVector3t () : x(), y(), z() {}
+ aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
+ explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {}
+ aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {}
public:
- // combined operators
- const aiVector3t& operator += (const aiVector3t& o);
- const aiVector3t& operator -= (const aiVector3t& o);
- const aiVector3t& operator *= (TReal f);
- const aiVector3t& operator /= (TReal f);
+ // combined operators
+ const aiVector3t& operator += (const aiVector3t& o);
+ const aiVector3t& operator -= (const aiVector3t& o);
+ const aiVector3t& operator *= (TReal f);
+ const aiVector3t& operator /= (TReal f);
- // transform vector by matrix
- aiVector3t& operator *= (const aiMatrix3x3t<TReal>& mat);
- aiVector3t& operator *= (const aiMatrix4x4t<TReal>& mat);
+ // transform vector by matrix
+ aiVector3t& operator *= (const aiMatrix3x3t<TReal>& mat);
+ aiVector3t& operator *= (const aiMatrix4x4t<TReal>& mat);
- // access a single element
- TReal operator[](unsigned int i) const;
- TReal& operator[](unsigned int i);
+ // access a single element
+ TReal operator[](unsigned int i) const;
+ TReal& operator[](unsigned int i);
- // comparison
- bool operator== (const aiVector3t& other) const;
- bool operator!= (const aiVector3t& other) const;
- bool operator < (const aiVector3t& other) const;
+ // comparison
+ bool operator== (const aiVector3t& other) const;
+ bool operator!= (const aiVector3t& other) const;
+ bool operator < (const aiVector3t& other) const;
- bool Equal(const aiVector3t& other, TReal epsilon = 1e-6) const;
+ bool Equal(const aiVector3t& other, TReal epsilon = 1e-6) const;
- template <typename TOther>
- operator aiVector3t<TOther> () const;
+ template <typename TOther>
+ operator aiVector3t<TOther> () const;
public:
- /** @brief Set the components of a vector
- * @param pX X component
- * @param pY Y component
- * @param pZ Z component */
- void Set( TReal pX, TReal pY, TReal pZ);
+ /** @brief Set the components of a vector
+ * @param pX X component
+ * @param pY Y component
+ * @param pZ Z component */
+ void Set( TReal pX, TReal pY, TReal pZ);
- /** @brief Get the squared length of the vector
- * @return Square length */
- TReal SquareLength() const;
+ /** @brief Get the squared length of the vector
+ * @return Square length */
+ TReal SquareLength() const;
- /** @brief Get the length of the vector
- * @return length */
- TReal Length() const;
+ /** @brief Get the length of the vector
+ * @return length */
+ TReal Length() const;
- /** @brief Normalize the vector */
- aiVector3t& Normalize();
+ /** @brief Normalize the vector */
+ aiVector3t& Normalize();
-
- /** @brief Componentwise multiplication of two vectors
- *
- * Note that vec*vec yields the dot product.
- * @param o Second factor */
- const aiVector3t SymMul(const aiVector3t& o);
+ /** @brief Normalize the vector with extra check for zero vectors */
+ aiVector3t& NormalizeSafe();
- TReal x, y, z;
+ /** @brief Componentwise multiplication of two vectors
+ *
+ * Note that vec*vec yields the dot product.
+ * @param o Second factor */
+ const aiVector3t SymMul(const aiVector3t& o);
+
+ TReal x, y, z;
} PACK_STRUCT;
@@ -132,8 +134,7 @@ typedef aiVector3t<float> aiVector3D;
#else
struct aiVector3D {
-
- float x,y,z;
+ float x, y, z;
} PACK_STRUCT;
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/vector3.inl b/src/3rdparty/assimp/include/assimp/vector3.inl
index 4892f62fb..0d0d62968 100644
--- a/src/3rdparty/assimp/include/assimp/vector3.inl
+++ b/src/3rdparty/assimp/include/assimp/vector3.inl
@@ -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.
---------------------------------------------------------------------------
*/
-/** @file aiVector3D.inl
+/** @file vector3.inl
* @brief Inline implementation of aiVector3t<TReal> operators
*/
#ifndef AI_VECTOR3D_INL_INC
@@ -55,11 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template <typename TReal>
inline aiVector3t<TReal> operator * (const aiMatrix3x3t<TReal>& pMatrix, const aiVector3t<TReal>& pVector)
{
- aiVector3t<TReal> res;
- res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z;
- res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z;
- res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z;
- return res;
+ aiVector3t<TReal> res;
+ res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z;
+ res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z;
+ res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z;
+ return res;
}
// ------------------------------------------------------------------------------------------------
@@ -67,27 +67,27 @@ inline aiVector3t<TReal> operator * (const aiMatrix3x3t<TReal>& pMatrix, const a
template <typename TReal>
inline aiVector3t<TReal> operator * (const aiMatrix4x4t<TReal>& pMatrix, const aiVector3t<TReal>& pVector)
{
- aiVector3t<TReal> res;
- res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z + pMatrix.a4;
- res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z + pMatrix.b4;
- res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z + pMatrix.c4;
- return res;
+ aiVector3t<TReal> res;
+ res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z + pMatrix.a4;
+ res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z + pMatrix.b4;
+ res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z + pMatrix.c4;
+ return res;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
template <typename TOther>
aiVector3t<TReal>::operator aiVector3t<TOther> () const {
- return aiVector3t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y),static_cast<TOther>(z));
+ return aiVector3t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y),static_cast<TOther>(z));
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE void aiVector3t<TReal>::Set( TReal pX, TReal pY, TReal pZ) {
- x = pX; y = pY; z = pZ;
+AI_FORCE_INLINE void aiVector3t<TReal>::Set( TReal pX, TReal pY, TReal pZ) {
+ x = pX; y = pY; z = pZ;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal aiVector3t<TReal>::SquareLength() const {
- return x*x + y*y + z*z;
+ return x*x + y*y + z*z;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
@@ -96,130 +96,138 @@ AI_FORCE_INLINE TReal aiVector3t<TReal>::Length() const {
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::Normalize() {
- *this /= Length(); return *this;
+AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::Normalize() {
+ *this /= Length(); return *this;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::NormalizeSafe() {
+ TReal len = Length();
+ if (len > static_cast<TReal>(0))
+ *this /= len;
+ return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator += (const aiVector3t<TReal>& o) {
- x += o.x; y += o.y; z += o.z; return *this;
+ x += o.x; y += o.y; z += o.z; return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator -= (const aiVector3t<TReal>& o) {
- x -= o.x; y -= o.y; z -= o.z; return *this;
+ x -= o.x; y -= o.y; z -= o.z; return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator *= (TReal f) {
- x *= f; y *= f; z *= f; return *this;
+ x *= f; y *= f; z *= f; return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator /= (TReal f) {
- x /= f; y /= f; z /= f; return *this;
+ x /= f; y /= f; z /= f; return *this;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& mat){
- return(*this = mat * (*this));
+ return(*this = mat * (*this));
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatrix4x4t<TReal>& mat){
- return(*this = mat * (*this));
+ return(*this = mat * (*this));
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal aiVector3t<TReal>::operator[](unsigned int i) const {
- return *(&x + i);
+ return *(&x + i);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal& aiVector3t<TReal>::operator[](unsigned int i) {
- return *(&x + i);
+ return *(&x + i);
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiVector3t<TReal>::operator== (const aiVector3t<TReal>& other) const {
- return x == other.x && y == other.y && z == other.z;
+ return x == other.x && y == other.y && z == other.z;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiVector3t<TReal>::operator!= (const aiVector3t<TReal>& other) const {
- return x != other.x || y != other.y || z != other.z;
+ return x != other.x || y != other.y || z != other.z;
}
// ---------------------------------------------------------------------------
template<typename TReal>
AI_FORCE_INLINE bool aiVector3t<TReal>::Equal(const aiVector3t<TReal>& other, TReal epsilon) const {
- return
- std::abs(x - other.x) <= epsilon &&
- std::abs(y - other.y) <= epsilon &&
- std::abs(z - other.z) <= epsilon;
+ return
+ std::abs(x - other.x) <= epsilon &&
+ std::abs(y - other.y) <= epsilon &&
+ std::abs(z - other.z) <= epsilon;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiVector3t<TReal>::operator < (const aiVector3t<TReal>& other) const {
- return x != other.x ? x < other.x : y != other.y ? y < other.y : z < other.z;
+ return x != other.x ? x < other.x : y != other.y ? y < other.y : z < other.z;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal> aiVector3t<TReal>::SymMul(const aiVector3t<TReal>& o) {
- return aiVector3t<TReal>(x*o.x,y*o.y,z*o.z);
+ return aiVector3t<TReal>(x*o.x,y*o.y,z*o.z);
}
// ------------------------------------------------------------------------------------------------
// symmetric addition
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator + (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
- return aiVector3t<TReal>( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
+AI_FORCE_INLINE aiVector3t<TReal> operator + (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
// ------------------------------------------------------------------------------------------------
// symmetric subtraction
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator - (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
- return aiVector3t<TReal>( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
+AI_FORCE_INLINE aiVector3t<TReal> operator - (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
// ------------------------------------------------------------------------------------------------
// scalar product
template <typename TReal>
-AI_FORCE_INLINE TReal operator * (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
- return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
+AI_FORCE_INLINE TReal operator * (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
}
// ------------------------------------------------------------------------------------------------
// scalar multiplication
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator * ( TReal f, const aiVector3t<TReal>& v) {
- return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
+AI_FORCE_INLINE aiVector3t<TReal> operator * ( TReal f, const aiVector3t<TReal>& v) {
+ return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
}
// ------------------------------------------------------------------------------------------------
// and the other way around
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator * ( const aiVector3t<TReal>& v, TReal f) {
- return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
+AI_FORCE_INLINE aiVector3t<TReal> operator * ( const aiVector3t<TReal>& v, TReal f) {
+ return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
}
// ------------------------------------------------------------------------------------------------
// scalar division
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, TReal f) {
- return v * (1/f);
+AI_FORCE_INLINE aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, TReal f) {
+ return v * (1/f);
}
// ------------------------------------------------------------------------------------------------
// vector division
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, const aiVector3t<TReal>& v2) {
- return aiVector3t<TReal>(v.x / v2.x,v.y / v2.y,v.z / v2.z);
+AI_FORCE_INLINE aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>(v.x / v2.x,v.y / v2.y,v.z / v2.z);
}
// ------------------------------------------------------------------------------------------------
// cross product
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator ^ ( const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
- return aiVector3t<TReal>( v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
+AI_FORCE_INLINE aiVector3t<TReal> operator ^ ( const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2) {
+ return aiVector3t<TReal>( v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
}
// ------------------------------------------------------------------------------------------------
// vector negation
template <typename TReal>
-AI_FORCE_INLINE aiVector3t<TReal> operator - ( const aiVector3t<TReal>& v) {
- return aiVector3t<TReal>( -v.x, -v.y, -v.z);
+AI_FORCE_INLINE aiVector3t<TReal> operator - ( const aiVector3t<TReal>& v) {
+ return aiVector3t<TReal>( -v.x, -v.y, -v.z);
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/include/assimp/version.h b/src/3rdparty/assimp/include/assimp/version.h
index db914eb83..403798c1b 100644
--- a/src/3rdparty/assimp/include/assimp/version.h
+++ b/src/3rdparty/assimp/include/assimp/version.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,33 +25,35 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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 aiVersion.h
+/** @file version.h
* @brief Functions to query the version of the Assimp runtime, check
* compile flags, ...
*/
#ifndef INCLUDED_AI_VERSION_H
#define INCLUDED_AI_VERSION_H
+#include "defs.h"
+
#ifdef __cplusplus
extern "C" {
#endif
// ---------------------------------------------------------------------------
-/** @brief Returns a string with legal copyright and licensing information
+/** @brief Returns a string with legal copyright and licensing information
* about Assimp. The string may include multiple lines.
* @return Pointer to static string.
*/
@@ -73,13 +75,13 @@ ASSIMP_API unsigned int aiGetVersionMajor (void);
// ---------------------------------------------------------------------------
/** @brief Returns the repository revision of the Assimp runtime.
- * @return SVN Repository revision number of the Assimp runtime the
+ * @return SVN Repository revision number of the Assimp runtime the
* application was linked/built against.
*/
ASSIMP_API unsigned int aiGetVersionRevision (void);
//! Assimp was compiled as a shared object (Windows: DLL)
-#define ASSIMP_CFLAGS_SHARED 0x1
+#define ASSIMP_CFLAGS_SHARED 0x1
//! Assimp was compiled against STLport
#define ASSIMP_CFLAGS_STLPORT 0x2
//! Assimp was compiled as a debug build
diff --git a/src/3rdparty/assimp/qt_attribution.json b/src/3rdparty/assimp/qt_attribution.json
index 703836456..564058dc4 100644
--- a/src/3rdparty/assimp/qt_attribution.json
+++ b/src/3rdparty/assimp/qt_attribution.json
@@ -6,8 +6,9 @@
"QtUsage": "Used in Qt 3D.",
"Homepage": "http://www.assimp.org/",
+ "Version": "3.3.1",
"License": "BSD 3-clause \"New\" or \"Revised\" Licensee",
"LicenseId": "BSD-3-Clause",
"LicenseFile": "LICENSE",
- "Copyright": "Copyright (c) 2006-2012, assimp team"
+ "Copyright": "Copyright (c) 2006-2016, assimp team"
}
diff --git a/src/3rdparty/assimp/revision.h b/src/3rdparty/assimp/revision.h
index b265fb08f..05fde9ff4 100644
--- a/src/3rdparty/assimp/revision.h
+++ b/src/3rdparty/assimp/revision.h
@@ -1,7 +1,7 @@
#ifndef ASSIMP_REVISION_H_INC
#define ASSIMP_REVISION_H_INC
-#define GitVersion 0x1c4a8e9
+#define GitVersion 0xa8673d4
#define GitBranch "master"
#endif // ASSIMP_REVISION_H_INC
diff --git a/src/3rdparty/patches/0001-Fix-ambiguous-if-else-in-assimp.patch b/src/3rdparty/patches/0001-Fix-ambiguous-if-else-in-assimp.patch
deleted file mode 100644
index 893336d5e..000000000
--- a/src/3rdparty/patches/0001-Fix-ambiguous-if-else-in-assimp.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 3647801a7673f1e843bd64a0ac38d60dd4ae7495 Mon Sep 17 00:00:00 2001
-From: Sean Harmer <sean.harmer@kdab.com>
-Date: Sun, 13 Sep 2015 19:17:45 +0100
-Subject: [PATCH] Fix ambiguous if else in assimp
-
-Change-Id: I17516fc8f34dad7a99f536dc4b3cba47e7779d4b
----
- src/3rdparty/assimp/contrib/clipper/clipper.cpp | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/src/3rdparty/assimp/contrib/clipper/clipper.cpp b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
-index 2b209da..b2316cc 100644
---- a/src/3rdparty/assimp/contrib/clipper/clipper.cpp
-+++ b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
-@@ -2124,11 +2124,13 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
- {
- //check for 'rounding' artefacts ...
- if (outRec->sides == esNeither && pt.Y == op->pt.Y)
-+ {
- if (ToFront)
- {
- if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt
- }
- else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
-+ }
-
- outRec->sides = (EdgeSide)(outRec->sides | e->side);
- if (outRec->sides == esBoth)
---
-2.5.1
-
diff --git a/src/3rdparty/patches/0001-assimp-Fix-type-warnings.patch b/src/3rdparty/patches/0001-assimp-Fix-type-warnings.patch
new file mode 100644
index 000000000..1d97a64b4
--- /dev/null
+++ b/src/3rdparty/patches/0001-assimp-Fix-type-warnings.patch
@@ -0,0 +1,48 @@
+diff -ur assimpGIT/code/AssxmlExporter.cpp assimp/code/AssxmlExporter.cpp
+--- assimpGIT/code/AssxmlExporter.cpp 2016-12-08 14:13:07.000000000 -0500
++++ assimp/code/AssxmlExporter.cpp 2016-12-08 09:23:22.000000000 -0500
+@@ -72,7 +72,7 @@
+ return -1;
+ }
+
+- static const size_t Size = 4096;
++ static const int Size = 4096;
+ char sz[ Size ];
+ size_t len( strlen( format ) );
+ ::memset( sz, '\0', Size );
+diff -ur assimpGIT/code/glTFAssetWriter.inl assimp/code/glTFAssetWriter.inl
+--- assimpGIT/code/glTFAssetWriter.inl 2016-12-08 14:13:07.000000000 -0500
++++ assimp/code/glTFAssetWriter.inl 2016-12-08 10:14:27.000000000 -0500
+@@ -56,7 +56,7 @@
+ inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
+ val.SetArray();
+ val.Reserve(N, al);
+- for (int i = 0; i < N; ++i) {
++ for (decltype(N) i = 0; i < N; ++i) {
+ val.PushBack(r[i], al);
+ }
+ return val;
+diff -ur assimpGIT/contrib/openddlparser/code/OpenDDLExport.cpp assimp/contrib/openddlparser/code/OpenDDLExport.cpp
+--- assimpGIT/contrib/openddlparser/code/OpenDDLExport.cpp 2016-12-08 14:13:07.000000000 -0500
++++ assimp/contrib/openddlparser/code/OpenDDLExport.cpp 2016-12-08 09:23:22.000000000 -0500
+@@ -280,7 +280,7 @@
+ statement += "[";
+ char buffer[ 256 ];
+ ::memset( buffer, '\0', 256 * sizeof( char ) );
+- sprintf( buffer, "%d", numItems );
++ sprintf( buffer, "%d", int(numItems) );
+ statement += buffer;
+ statement += "]";
+ }
+diff -ur assimpGIT/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
+--- assimpGIT/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h 2016-12-08 14:13:07.000000000 -0500
++++ assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h 2016-12-08 09:23:22.000000000 -0500
+@@ -84,7 +84,7 @@
+ template<class T>
+ inline
+ bool isNumeric( const T in ) {
+- return ( chartype_table[ in ] == 1 );
++ return ( chartype_table[ static_cast<int>( in ) ] == 1 );
+ }
+
+ template<class T>
diff --git a/src/3rdparty/patches/0002-assimp-Add-license-header.patch b/src/3rdparty/patches/0002-assimp-Add-license-header.patch
new file mode 100644
index 000000000..a8385601e
--- /dev/null
+++ b/src/3rdparty/patches/0002-assimp-Add-license-header.patch
@@ -0,0 +1,39 @@
+--- assimpGIT/code/Version.cpp 2016-12-08 14:13:07.000000000 -0500
++++ assimp/code/Version.cpp 2016-12-08 14:10:08.000000000 -0500
+@@ -1,3 +1,36 @@
++/*
++---------------------------------------------------------------------------
++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.
+
diff --git a/src/3rdparty/patches/0002-assimp-Fix-building-with-mingw-older-than-4.9.patch b/src/3rdparty/patches/0002-assimp-Fix-building-with-mingw-older-than-4.9.patch
deleted file mode 100644
index e4b97d444..000000000
--- a/src/3rdparty/patches/0002-assimp-Fix-building-with-mingw-older-than-4.9.patch
+++ /dev/null
@@ -1,10174 +0,0 @@
-From 98e76a717acd6474062c4d31ba3ffce84855d227 Mon Sep 17 00:00:00 2001
-From: Andy Nichols <andy.nichols@theqtcompany.com>
-Date: Wed, 28 Oct 2015 12:12:23 +0100
-Subject: [PATCH] assimp: Fix building with mingw older than 4.9
-
-On Windows when building with mingw versions older than 4.9 the assembly
-of IFCReaderGen.o fails because it reaches the section limit. Normally
-we would use the -mbig-objj flag to the assembler, but older versions of
-GNU as don't have support for this. So to work around this
-IFCReaderGen.cpp is split into two separate files, which keeps the
-sections below the limit for each object file.
-
-Change-Id: If0cae29c10a50e3a5edf85fe21b8d2528971eb83
----
- src/3rdparty/assimp/assimp.pri | 3 +-
- src/3rdparty/assimp/code/IFCReaderGen.cpp | 5030 ----------------------------
- src/3rdparty/assimp/code/IFCReaderGen1.cpp | 3168 ++++++++++++++++++
- src/3rdparty/assimp/code/IFCReaderGen2.cpp | 1917 +++++++++++
- 4 files changed, 5087 insertions(+), 5031 deletions(-)
- delete mode 100644 src/3rdparty/assimp/code/IFCReaderGen.cpp
- create mode 100644 src/3rdparty/assimp/code/IFCReaderGen1.cpp
- create mode 100644 src/3rdparty/assimp/code/IFCReaderGen2.cpp
-
-diff --git a/src/3rdparty/assimp/assimp.pri b/src/3rdparty/assimp/assimp.pri
-index 0b63fd5..d171fbc 100644
---- a/src/3rdparty/assimp/assimp.pri
-+++ b/src/3rdparty/assimp/assimp.pri
-@@ -352,7 +352,8 @@ SOURCES += code/3DSConverter.cpp \
- code/IFCLoader.cpp \
- code/IFCMaterial.cpp \
- code/IFCProfile.cpp \
-- code/IFCReaderGen.cpp \
-+ code/IFCReaderGen1.cpp \
-+ code/IFCReaderGen2.cpp \
- code/IFCUtil.cpp \
- code/Importer.cpp \
- code/ImporterRegistry.cpp \
-diff --git a/src/3rdparty/assimp/code/IFCReaderGen.cpp b/src/3rdparty/assimp/code/IFCReaderGen.cpp
-deleted file mode 100644
-index c178051..0000000
---- a/src/3rdparty/assimp/code/IFCReaderGen.cpp
-+++ /dev/null
-@@ -1,5030 +0,0 @@
--/*
--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
--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 Development 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.
--
------------------------------------------------------------------------
--*/
--
--/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
--
--#include "AssimpPCH.h"
--#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
--
--#include "IFCReaderGen.h"
--
--namespace Assimp {
--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 )
--
-- };
--}
--
--// -----------------------------------------------------------------------------------------------------------
--void IFC::GetSchema(EXPRESS::ConversionSchema& out)
--{
-- out = EXPRESS::ConversionSchema(schema_raw);
--}
--
--namespace STEP {
--
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
--{
-- return 0;
--}
--
--
--
--// -----------------------------------------------------------------------------------------------------------
--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++];
-- 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; }
-- 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++];
-- 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; }
-- 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++];
-- 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; }
-- 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++];
-- 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; }
-- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRoot to be a `IfcText`")); }
-- } while(0);
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTypeObject>(const DB& db, const LIST& params, IfcTypeObject* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTypeProduct>(const DB& db, const LIST& params, IfcTypeProduct* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElementType>(const DB& db, const LIST& params, IfcElementType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDistributionElementType>(const DB& db, const LIST& params, IfcDistributionElementType* 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<IfcDistributionFlowElementType>(const DB& db, const LIST& params, IfcDistributionFlowElementType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowControllerType>(const DB& db, const LIST& params, IfcFlowControllerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricTimeControlType>(const DB& db, const LIST& params, IfcElectricTimeControlType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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)
--{
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTopologyRepresentation>(const DB& db, const LIST& params, IfcTopologyRepresentation* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelationship>(const DB& db, const LIST& params, IfcRelationship* 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));
--// this data structure is not used yet, so there is no code generated to fill its members
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCableCarrierFittingType>(const DB& db, const LIST& params, IfcCableCarrierFittingType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEnergyConversionDeviceType>(const DB& db, const LIST& params, 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCoilType>(const DB& db, const LIST& params, IfcCoilType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcObject>(const DB& db, const LIST& params, IfcObject* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcControl>(const DB& db, const LIST& params, IfcControl* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST& params, IfcPerformanceHistory* 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<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<IfcTextLiteral>(const DB& db, const LIST& params, IfcTextLiteral* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTextLiteralWithExtent>(const DB& db, const LIST& params, IfcTextLiteralWithExtent* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProductRepresentation>(const DB& db, const LIST& params, IfcProductRepresentation* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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++];
-- 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; }
-- 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++];
-- 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; }
-- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProduct to be a `IfcProductRepresentation`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, IfcElement* 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; }
-- 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<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDistributionFlowElement>(const DB& db, const LIST& params, IfcDistributionFlowElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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<IfcCartesianTransformationOperator>(const DB& db, const LIST& params, IfcCartesianTransformationOperator* 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`")); }
-- } 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; }
-- 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<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
-- 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProperty>(const DB& db, const LIST& params, IfcProperty* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSimpleProperty>(const DB& db, const LIST& params, IfcSimpleProperty* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPropertyEnumeratedValue>(const DB& db, const LIST& params, IfcPropertyEnumeratedValue* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuildingElementType>(const DB& db, const LIST& params, IfcBuildingElementType* 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<IfcStairFlightType>(const DB& db, const LIST& params, IfcStairFlightType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSurface>(const DB& db, const LIST& params, IfcSurface* in)
--{
-- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& params, IfcElementarySurface* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPlane>(const DB& db, const LIST& params, IfcPlane* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBooleanResult>(const DB& db, const LIST& params, IfcBooleanResult* 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`")); }
-- } 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBooleanClippingResult>(const DB& db, const LIST& params, IfcBooleanClippingResult* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSolidModel>(const DB& db, const LIST& params, IfcSolidModel* in)
--{
-- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcManifoldSolidBrep>(const DB& db, const LIST& params, IfcManifoldSolidBrep* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowTerminalType>(const DB& db, const LIST& params, 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStackTerminalType>(const DB& db, const LIST& params, IfcStackTerminalType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralItem>(const DB& db, const LIST& params, IfcStructuralItem* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralConnection>(const DB& db, const LIST& params, IfcStructuralConnection* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralCurveConnection>(const DB& db, const LIST& params, IfcStructuralCurveConnection* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcJunctionBoxType>(const DB& db, const LIST& params, IfcJunctionBoxType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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<IfcProcess>(const DB& db, const LIST& params, IfcProcess* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTask>(const DB& db, const LIST& params, IfcTask* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelFillsElement>(const DB& db, const LIST& params, IfcRelFillsElement* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProcedure>(const DB& db, const LIST& params, IfcProcedure* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProxy>(const DB& db, const LIST& params, IfcProxy* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcResource>(const DB& db, const LIST& params, IfcResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConstructionResource>(const DB& db, const LIST& params, IfcConstructionResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSubContractResource>(const DB& db, const LIST& params, IfcSubContractResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelContainedInSpatialStructure>(const DB& db, const LIST& params, IfcRelContainedInSpatialStructure* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTopologicalRepresentationItem>(const DB& db, const LIST& params, IfcTopologicalRepresentationItem* in)
--{
-- size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEdge>(const DB& db, const LIST& params, IfcEdge* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEdgeCurve>(const DB& db, const LIST& params, IfcEdgeCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, IfcPlateType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
--{
-- size_t base = 0;
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcGridPlacement>(const DB& db, const LIST& params, IfcGridPlacement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFireSuppressionTerminalType>(const DB& db, const LIST& params, IfcFireSuppressionTerminalType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& params, IfcFlowStorageDevice* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSweptSurface>(const DB& db, const LIST& params, IfcSweptSurface* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSurfaceOfRevolution>(const DB& db, const LIST& params, IfcSurfaceOfRevolution* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcOrientedEdge>(const DB& db, const LIST& params, IfcOrientedEdge* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDirection>(const DB& db, const LIST& params, IfcDirection* 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`")); }
-- } while(0);
-- 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
-- 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; }
-- 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`")); }
-- } while(0);
-- 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
-- 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCShapeProfileDef>(const DB& db, const LIST& params, IfcCShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEdgeFeature>(const DB& db, const LIST& params, IfcEdgeFeature* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcChamferEdgeFeature>(const DB& db, const LIST& params, IfcChamferEdgeFeature* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuildingElement>(const DB& db, const LIST& params, IfcBuildingElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcColumn>(const DB& db, const LIST& params, IfcColumn* 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<IfcPropertyReferenceValue>(const DB& db, const LIST& params, IfcPropertyReferenceValue* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricMotorType>(const DB& db, const LIST& params, IfcElectricMotorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSpatialStructureElementType>(const DB& db, const LIST& params, IfcSpatialStructureElementType* 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<IfcSpaceType>(const DB& db, const LIST& params, IfcSpaceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcColumnType>(const DB& db, const LIST& params, IfcColumnType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCraneRailAShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailAShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCondenserType>(const DB& db, const LIST& params, IfcCondenserType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPlacement>(const DB& db, const LIST& params, IfcPlacement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAxis2Placement3D>(const DB& db, const LIST& params, IfcAxis2Placement3D* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPresentationStyle>(const DB& db, const LIST& params, IfcPresentationStyle* 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; }
-- 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<IfcEquipmentElement>(const DB& db, const LIST& params, IfcEquipmentElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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; }
-- 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; }
-- 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; }
-- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCompositeCurveSegment to be a `IfcCurve`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRectangleProfileDef>(const DB& db, const LIST& params, IfcRectangleProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuildingElementProxy>(const DB& db, const LIST& params, IfcBuildingElementProxy* 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<IfcDistributionControlElementType>(const DB& db, const LIST& params, IfcDistributionControlElementType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowInstrumentType>(const DB& db, const LIST& params, IfcFlowInstrumentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDraughtingCallout>(const DB& db, const LIST& params, IfcDraughtingCallout* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDimensionCurveDirectedCallout>(const DB& db, const LIST& params, IfcDimensionCurveDirectedCallout* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLinearDimension>(const DB& db, const LIST& params, IfcLinearDimension* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElementAssembly>(const DB& db, const LIST& params, IfcElementAssembly* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCsgPrimitive3D>(const DB& db, const LIST& params, IfcCsgPrimitive3D* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRightCircularCone>(const DB& db, const LIST& params, IfcRightCircularCone* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProjectOrder>(const DB& db, const LIST& params, IfcProjectOrder* 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<IfcLShapeProfileDef>(const DB& db, const LIST& params, IfcLShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAngularDimension>(const DB& db, const LIST& params, IfcAngularDimension* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLocalPlacement>(const DB& db, const LIST& params, IfcLocalPlacement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSweptAreaSolid>(const DB& db, const LIST& params, IfcSweptAreaSolid* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralSurfaceConnection>(const DB& db, const LIST& params, IfcStructuralSurfaceConnection* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRadiusDimension>(const DB& db, const LIST& params, IfcRadiusDimension* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSweptDiskSolid>(const DB& db, const LIST& params, IfcSweptDiskSolid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcHalfSpaceSolid>(const DB& db, const LIST& params, IfcHalfSpaceSolid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const LIST& params, IfcPolygonalBoundedHalfSpace* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTimeSeriesSchedule>(const DB& db, const LIST& params, IfcTimeSeriesSchedule* 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<IfcCooledBeamType>(const DB& db, const LIST& params, IfcCooledBeamType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProject>(const DB& db, const LIST& params, IfcProject* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEvaporatorType>(const DB& db, const LIST& params, IfcEvaporatorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLaborResource>(const DB& db, const LIST& params, IfcLaborResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPropertyBoundedValue>(const DB& db, const LIST& params, IfcPropertyBoundedValue* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRampFlightType>(const DB& db, const LIST& params, IfcRampFlightType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMember>(const DB& db, const LIST& params, IfcMember* 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<IfcTubeBundleType>(const DB& db, const LIST& params, IfcTubeBundleType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcValveType>(const DB& db, const LIST& params, IfcValveType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTrimmedCurve>(const DB& db, const LIST& params, IfcTrimmedCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelDefines>(const DB& db, const LIST& params, IfcRelDefines* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelDefinesByProperties>(const DB& db, const LIST& params, IfcRelDefinesByProperties* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcActor>(const DB& db, const LIST& params, IfcActor* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcOccupant>(const DB& db, const LIST& params, IfcOccupant* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcHumidifierType>(const DB& db, const LIST& params, IfcHumidifierType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcArbitraryOpenProfileDef>(const DB& db, const LIST& params, IfcArbitraryOpenProfileDef* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPermit>(const DB& db, const LIST& params, IfcPermit* 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<IfcOffsetCurve3D>(const DB& db, const LIST& params, IfcOffsetCurve3D* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLightSource>(const DB& db, const LIST& params, 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLightSourcePositional>(const DB& db, const LIST& params, IfcLightSourcePositional* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCompositeProfileDef>(const DB& db, const LIST& params, IfcCompositeProfileDef* in)
--{
-- 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<IfcRamp>(const DB& db, const LIST& params, IfcRamp* 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<IfcFlowMovingDevice>(const DB& db, const LIST& params, IfcFlowMovingDevice* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSpaceHeaterType>(const DB& db, const LIST& params, IfcSpaceHeaterType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLampType>(const DB& db, const LIST& params, IfcLampType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuildingElementComponent>(const DB& db, const LIST& params, IfcBuildingElementComponent* 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<IfcReinforcingElement>(const DB& db, const LIST& params, IfcReinforcingElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcReinforcingBar>(const DB& db, const LIST& params, IfcReinforcingBar* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricHeaterType>(const DB& db, const LIST& params, IfcElectricHeaterType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTShapeProfileDef>(const DB& db, const LIST& params, IfcTShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralActivity>(const DB& db, const LIST& params, 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralAction>(const DB& db, const LIST& params, IfcStructuralAction* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDuctFittingType>(const DB& db, const LIST& params, IfcDuctFittingType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCartesianTransformationOperator2D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2D* in)
--{
-- 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<IfcVirtualElement>(const DB& db, const LIST& params, IfcVirtualElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRightCircularCylinder>(const DB& db, const LIST& params, IfcRightCircularCylinder* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcOutletType>(const DB& db, const LIST& params, IfcOutletType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelDecomposes>(const DB& db, const LIST& params, IfcRelDecomposes* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCovering>(const DB& db, const LIST& params, IfcCovering* 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<IfcPolyline>(const DB& db, const LIST& params, IfcPolyline* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPath>(const DB& db, const LIST& params, IfcPath* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElementComponent>(const DB& db, const LIST& params, IfcElementComponent* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFastener>(const DB& db, const LIST& params, IfcFastener* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMappedItem>(const DB& db, const LIST& params, IfcMappedItem* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRectangularPyramid>(const DB& db, const LIST& params, IfcRectangularPyramid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCrewResource>(const DB& db, const LIST& params, IfcCrewResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, IfcNamedUnit* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcContextDependentUnit>(const DB& db, const LIST& params, IfcContextDependentUnit* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcUnitaryEquipmentType>(const DB& db, const LIST& params, IfcUnitaryEquipmentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRoof>(const DB& db, const LIST& params, IfcRoof* 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<IfcStructuralMember>(const DB& db, const LIST& params, IfcStructuralMember* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStyleModel>(const DB& db, const LIST& params, IfcStyleModel* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStyledRepresentation>(const DB& db, const LIST& params, IfcStyledRepresentation* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSpatialStructureElement>(const DB& db, const LIST& params, IfcSpatialStructureElement* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuilding>(const DB& db, const LIST& params, IfcBuilding* 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`")); }
-- } 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConnectedFaceSet>(const DB& db, const LIST& params, IfcConnectedFaceSet* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcOpenShell>(const DB& db, const LIST& params, IfcOpenShell* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFacetedBrep>(const DB& db, const LIST& params, IfcFacetedBrep* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcConic* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCoveringType>(const DB& db, const LIST& params, IfcCoveringType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRoundedRectangleProfileDef>(const DB& db, const LIST& params, IfcRoundedRectangleProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAirTerminalType>(const DB& db, const LIST& params, IfcAirTerminalType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowMovingDeviceType>(const DB& db, const LIST& params, IfcFlowMovingDeviceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCompressorType>(const DB& db, const LIST& params, IfcCompressorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAsymmetricIShapeProfileDef>(const DB& db, const LIST& params, IfcAsymmetricIShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcControllerType>(const DB& db, const LIST& params, IfcControllerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRailing>(const DB& db, const LIST& params, IfcRailing* 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<IfcGroup>(const DB& db, const LIST& params, IfcGroup* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAsset>(const DB& db, const LIST& params, IfcAsset* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMaterialDefinitionRepresentation>(const DB& db, const LIST& params, IfcMaterialDefinitionRepresentation* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRailingType>(const DB& db, const LIST& params, IfcRailingType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWall>(const DB& db, const LIST& params, IfcWall* 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<IfcStructuralPointConnection>(const DB& db, const LIST& params, IfcStructuralPointConnection* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPropertyListValue>(const DB& db, const LIST& params, IfcPropertyListValue* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFurnitureStandard>(const DB& db, const LIST& params, IfcFurnitureStandard* 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<IfcElectricGeneratorType>(const DB& db, const LIST& params, IfcElectricGeneratorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAnnotationOccurrence>(const DB& db, const LIST& params, IfcAnnotationOccurrence* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAnnotationSymbolOccurrence>(const DB& db, const LIST& params, IfcAnnotationSymbolOccurrence* 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<IfcArbitraryClosedProfileDef>(const DB& db, const LIST& params, IfcArbitraryClosedProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcArbitraryProfileDefWithVoids>(const DB& db, const LIST& params, IfcArbitraryProfileDefWithVoids* in)
--{
-- size_t base = GenericFill(db,params,static_cast<IfcArbitraryClosedProfileDef*>(in));
--// this data structure is not used yet, so there is no code generated to fill its members
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLine>(const DB& db, const LIST& params, IfcLine* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowSegmentType>(const DB& db, const LIST& params, IfcFlowSegmentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAirTerminalBoxType>(const DB& db, const LIST& params, IfcAirTerminalBoxType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPropertySingleValue>(const DB& db, const LIST& params, IfcPropertySingleValue* 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++];
-- 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`")); }
-- } 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 IfcPropertySingleValue to be a `IfcUnit`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAlarmType>(const DB& db, const LIST& params, IfcAlarmType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStair>(const DB& db, const LIST& params, IfcStair* 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<IfcSurfaceStyleShading>(const DB& db, const LIST& params, IfcSurfaceStyleShading* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPumpType>(const DB& db, const LIST& params, IfcPumpType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDefinedSymbol>(const DB& db, const LIST& params, IfcDefinedSymbol* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElementComponentType>(const DB& db, const LIST& params, IfcElementComponentType* 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<IfcFastenerType>(const DB& db, const LIST& params, IfcFastenerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMechanicalFastenerType>(const DB& db, const LIST& params, IfcMechanicalFastenerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowFitting>(const DB& db, const LIST& params, IfcFlowFitting* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLightSourceDirectional>(const DB& db, const LIST& params, IfcLightSourceDirectional* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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)
--{
-- 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<IfcFlowController>(const DB& db, const LIST& params, IfcFlowController* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuildingStorey>(const DB& db, const LIST& params, IfcBuildingStorey* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWorkControl>(const DB& db, const LIST& params, IfcWorkControl* 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<IfcWorkSchedule>(const DB& db, const LIST& params, IfcWorkSchedule* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDuctSegmentType>(const DB& db, const LIST& params, IfcDuctSegmentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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`")); }
-- } 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCostSchedule>(const DB& db, const LIST& params, IfcCostSchedule* 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<IfcPlanarExtent>(const DB& db, const LIST& params, IfcPlanarExtent* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPlanarBox>(const DB& db, const LIST& params, IfcPlanarBox* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcColourSpecification>(const DB& db, const LIST& params, IfcColourSpecification* 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; }
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBeam>(const DB& db, const LIST& params, IfcBeam* 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<IfcColourRgb>(const DB& db, const LIST& params, IfcColourRgb* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralPlanarAction>(const DB& db, const LIST& params, IfcStructuralPlanarAction* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralPlanarActionVarying>(const DB& db, const LIST& params, IfcStructuralPlanarActionVarying* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSite>(const DB& db, const LIST& params, IfcSite* 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));
--// this data structure is not used yet, so there is no code generated to fill its members
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcVibrationIsolatorType>(const DB& db, const LIST& params, IfcVibrationIsolatorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEvaporativeCoolerType>(const DB& db, const LIST& params, IfcEvaporativeCoolerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDistributionChamberElementType>(const DB& db, const LIST& params, IfcDistributionChamberElementType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFeatureElementAddition>(const DB& db, const LIST& params, IfcFeatureElementAddition* in)
--{
-- 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<IfcStructuredDimensionCallout>(const DB& db, const LIST& params, IfcStructuredDimensionCallout* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCoolingTowerType>(const DB& db, const LIST& params, IfcCoolingTowerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCenterLineProfileDef>(const DB& db, const LIST& params, IfcCenterLineProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWindowStyle>(const DB& db, const LIST& params, IfcWindowStyle* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLightSourceGoniometric>(const DB& db, const LIST& params, IfcLightSourceGoniometric* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTransformerType>(const DB& db, const LIST& params, IfcTransformerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMemberType>(const DB& db, const LIST& params, IfcMemberType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSurfaceOfLinearExtrusion>(const DB& db, const LIST& params, IfcSurfaceOfLinearExtrusion* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMotorConnectionType>(const DB& db, const LIST& params, IfcMotorConnectionType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowTreatmentDeviceType>(const DB& db, const LIST& params, IfcFlowTreatmentDeviceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDuctSilencerType>(const DB& db, const LIST& params, IfcDuctSilencerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFurnishingElementType>(const DB& db, const LIST& params, IfcFurnishingElementType* 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<IfcSystemFurnitureElementType>(const DB& db, const LIST& params, IfcSystemFurnitureElementType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWasteTerminalType>(const DB& db, const LIST& params, IfcWasteTerminalType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBezierCurve>(const DB& db, const LIST& params, IfcBezierCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcActuatorType>(const DB& db, const LIST& params, IfcActuatorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDistributionControlElement>(const DB& db, const LIST& params, IfcDistributionControlElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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() < 7) { throw STEP::TypeError("expected 7 arguments to IfcAnnotation"); } return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--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 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcActionRequest>(const DB& db, const LIST& params, IfcActionRequest* 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<IfcExtrudedAreaSolid>(const DB& db, const LIST& params, IfcExtrudedAreaSolid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSystem>(const DB& db, const LIST& params, IfcSystem* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFillAreaStyleHatching>(const DB& db, const LIST& params, IfcFillAreaStyleHatching* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelVoidsElement>(const DB& db, const LIST& params, IfcRelVoidsElement* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSurfaceCurveSweptAreaSolid>(const DB& db, const LIST& params, IfcSurfaceCurveSweptAreaSolid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCartesianTransformationOperator3DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3DnonUniform* 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCurtainWallType>(const DB& db, const LIST& params, IfcCurtainWallType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEquipmentStandard>(const DB& db, const LIST& params, IfcEquipmentStandard* 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<IfcFlowStorageDeviceType>(const DB& db, const LIST& params, IfcFlowStorageDeviceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDiameterDimension>(const DB& db, const LIST& params, IfcDiameterDimension* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSwitchingDeviceType>(const DB& db, const LIST& params, IfcSwitchingDeviceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWindow>(const DB& db, const LIST& params, IfcWindow* 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<IfcFlowTreatmentDevice>(const DB& db, const LIST& params, IfcFlowTreatmentDevice* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcChillerType>(const DB& db, const LIST& params, IfcChillerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRectangleHollowProfileDef>(const DB& db, const LIST& params, IfcRectangleHollowProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBoxedHalfSpace>(const DB& db, const LIST& params, IfcBoxedHalfSpace* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAxis2Placement2D>(const DB& db, const LIST& params, IfcAxis2Placement2D* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBoundedSurface>(const DB& db, const LIST& params, IfcBoundedSurface* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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)
--{
-- 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`")); }
-- } 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRepresentationContext>(const DB& db, const LIST& params, IfcRepresentationContext* 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; }
-- 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`")); }
-- } 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; }
-- 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCurveBoundedPlane>(const DB& db, const LIST& params, IfcCurveBoundedPlane* 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<IfcSIUnit>(const DB& db, const LIST& params, IfcSIUnit* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralReaction>(const DB& db, const LIST& params, IfcStructuralReaction* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralPointReaction>(const DB& db, const LIST& params, IfcStructuralPointReaction* in)
--{
-- 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<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricApplianceType>(const DB& db, const LIST& params, IfcElectricApplianceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSensorType>(const DB& db, const LIST& params, IfcSensorType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFurnishingElement>(const DB& db, const LIST& params, IfcFurnishingElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProtectiveDeviceType>(const DB& db, const LIST& params, IfcProtectiveDeviceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcZShapeProfileDef>(const DB& db, const LIST& params, IfcZShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcScheduleTimeControl>(const DB& db, const LIST& params, IfcScheduleTimeControl* 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<IfcRepresentationMap>(const DB& db, const LIST& params, IfcRepresentationMap* 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`")); }
-- } 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`")); }
-- } while(0);
-- 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)
--{
-- 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<IfcBlock>(const DB& db, const LIST& params, IfcBlock* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLightFixtureType>(const DB& db, const LIST& params, IfcLightFixtureType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcLightSourceSpot>(const DB& db, const LIST& params, IfcLightSourceSpot* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTendonAnchor>(const DB& db, const LIST& params, IfcTendonAnchor* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricFlowStorageDeviceType>(const DB& db, const LIST& params, IfcElectricFlowStorageDeviceType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSphere>(const DB& db, const LIST& params, IfcSphere* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDamperType>(const DB& db, const LIST& params, IfcDamperType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProjectOrderRecord>(const DB& db, const LIST& params, IfcProjectOrderRecord* 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<IfcDistributionChamberElement>(const DB& db, const LIST& params, IfcDistributionChamberElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMechanicalFastener>(const DB& db, const LIST& params, IfcMechanicalFastener* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRectangularTrimmedSurface>(const DB& db, const LIST& params, IfcRectangularTrimmedSurface* 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<IfcZone>(const DB& db, const LIST& params, IfcZone* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFanType>(const DB& db, const LIST& params, IfcFanType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcGeometricSet>(const DB& db, const LIST& params, IfcGeometricSet* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFillAreaStyleTiles>(const DB& db, const LIST& params, IfcFillAreaStyleTiles* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCableSegmentType>(const DB& db, const LIST& params, IfcCableSegmentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRelOverridesProperties>(const DB& db, const LIST& params, IfcRelOverridesProperties* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSlabType>(const DB& db, const LIST& params, IfcSlabType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcServiceLife>(const DB& db, const LIST& params, IfcServiceLife* 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<IfcFurnitureType>(const DB& db, const LIST& params, IfcFurnitureType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCostItem>(const DB& db, const LIST& params, IfcCostItem* 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<IfcReinforcingMesh>(const DB& db, const LIST& params, IfcReinforcingMesh* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFacetedBrepWithVoids>(const DB& db, const LIST& params, IfcFacetedBrepWithVoids* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcGasTerminalType>(const DB& db, const LIST& params, IfcGasTerminalType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPile>(const DB& db, const LIST& params, IfcPile* 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<IfcFillAreaStyleTileSymbolWithStyle>(const DB& db, const LIST& params, IfcFillAreaStyleTileSymbolWithStyle* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConstructionMaterialResource>(const DB& db, const LIST& params, IfcConstructionMaterialResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAnnotationCurveOccurrence>(const DB& db, const LIST& params, IfcAnnotationCurveOccurrence* 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<IfcDimensionCurve>(const DB& db, const LIST& params, IfcDimensionCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcGeometricCurveSet>(const DB& db, const LIST& params, IfcGeometricCurveSet* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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)
--{
-- 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`")); }
-- } 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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)
--{
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPlate>(const DB& db, const LIST& params, IfcPlate* 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<IfcUShapeProfileDef>(const DB& db, const LIST& params, IfcUShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, IfcFaceBound* 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`")); }
-- } 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`")); }
-- } while(0);
-- 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)
--{
-- 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<IfcBoilerType>(const DB& db, const LIST& params, IfcBoilerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConstructionEquipmentResource>(const DB& db, const LIST& params, IfcConstructionEquipmentResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFooting>(const DB& db, const LIST& params, IfcFooting* 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<IfcConstructionProductResource>(const DB& db, const LIST& params, IfcConstructionProductResource* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDerivedProfileDef>(const DB& db, const LIST& params, IfcDerivedProfileDef* in)
--{
-- 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<IfcPropertyTableValue>(const DB& db, const LIST& params, IfcPropertyTableValue* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowMeterType>(const DB& db, const LIST& params, IfcFlowMeterType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDoorStyle>(const DB& db, const LIST& params, IfcDoorStyle* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcUnitAssignment>(const DB& db, const LIST& params, IfcUnitAssignment* 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));
--// this data structure is not used yet, so there is no code generated to fill its members
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCraneRailFShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailFShapeProfileDef* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFlowSegment>(const DB& db, const LIST& params, IfcFlowSegment* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCurtainWall>(const DB& db, const LIST& params, IfcCurtainWall* 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<IfcDiscreteAccessory>(const DB& db, const LIST& params, IfcDiscreteAccessory* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcGrid>(const DB& db, const LIST& params, IfcGrid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSanitaryTerminalType>(const DB& db, const LIST& params, IfcSanitaryTerminalType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSubedge>(const DB& db, const LIST& params, IfcSubedge* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcFilterType>(const DB& db, const LIST& params, IfcFilterType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTendon>(const DB& db, const LIST& params, IfcTendon* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralLoadGroup>(const DB& db, const LIST& params, IfcStructuralLoadGroup* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPresentationStyleAssignment>(const DB& db, const LIST& params, IfcPresentationStyleAssignment* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralCurveMember>(const DB& db, const LIST& params, IfcStructuralCurveMember* 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<IfcLightSourceAmbient>(const DB& db, const LIST& params, IfcLightSourceAmbient* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCondition>(const DB& db, const LIST& params, IfcCondition* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPort>(const DB& db, const LIST& params, IfcPort* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSpace>(const DB& db, const LIST& params, IfcSpace* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTankType>(const DB& db, const LIST& params, IfcTankType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcInventory>(const DB& db, const LIST& params, IfcInventory* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTransportElementType>(const DB& db, const LIST& params, IfcTransportElementType* 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<IfcAirToAirHeatRecoveryType>(const DB& db, const LIST& params, IfcAirToAirHeatRecoveryType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStairFlight>(const DB& db, const LIST& params, IfcStairFlight* 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<IfcElectricalElement>(const DB& db, const LIST& params, IfcElectricalElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSurfaceStyleWithTextures>(const DB& db, const LIST& params, IfcSurfaceStyleWithTextures* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBoundingBox>(const DB& db, const LIST& params, IfcBoundingBox* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWallType>(const DB& db, const LIST& params, IfcWallType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcMove>(const DB& db, const LIST& params, IfcMove* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCircle>(const DB& db, const LIST& params, IfcCircle* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcOffsetCurve2D>(const DB& db, const LIST& params, IfcOffsetCurve2D* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPointOnCurve>(const DB& db, const LIST& params, IfcPointOnCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralResultGroup>(const DB& db, const LIST& params, IfcStructuralResultGroup* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSectionedSpine>(const DB& db, const LIST& params, IfcSectionedSpine* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSlab>(const DB& db, const LIST& params, IfcSlab* 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<IfcVertex>(const DB& db, const LIST& params, IfcVertex* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcVertexPoint>(const DB& db, const LIST& params, IfcVertexPoint* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralLinearAction>(const DB& db, const LIST& params, IfcStructuralLinearAction* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralLinearActionVarying>(const DB& db, const LIST& params, IfcStructuralLinearActionVarying* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBuildingElementProxyType>(const DB& db, const LIST& params, IfcBuildingElementProxyType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProjectionElement>(const DB& db, const LIST& params, IfcProjectionElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAnnotationSurfaceOccurrence>(const DB& db, const LIST& params, IfcAnnotationSurfaceOccurrence* 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<IfcRoundedEdgeFeature>(const DB& db, const LIST& params, IfcRoundedEdgeFeature* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricDistributionPoint>(const DB& db, const LIST& params, IfcElectricDistributionPoint* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCableCarrierSegmentType>(const DB& db, const LIST& params, IfcCableCarrierSegmentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcWallStandardCase>(const DB& db, const LIST& params, IfcWallStandardCase* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcCsgSolid>(const DB& db, const LIST& params, IfcCsgSolid* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcBeamType>(const DB& db, const LIST& params, IfcBeamType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAnnotationFillArea>(const DB& db, const LIST& params, IfcAnnotationFillArea* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralCurveMemberVarying>(const DB& db, const LIST& params, IfcStructuralCurveMemberVarying* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPointOnSurface>(const DB& db, const LIST& params, IfcPointOnSurface* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcOrderAction>(const DB& db, const LIST& params, IfcOrderAction* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcEdgeLoop>(const DB& db, const LIST& params, IfcEdgeLoop* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcAnnotationFillAreaOccurrence>(const DB& db, const LIST& params, IfcAnnotationFillAreaOccurrence* 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<IfcWorkPlan>(const DB& db, const LIST& params, IfcWorkPlan* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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
-- 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`")); }
-- } 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`")); }
-- } while(0);
-- return base;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProductDefinitionShape>(const DB& db, const LIST& params, IfcProductDefinitionShape* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcProjectionCurve>(const DB& db, const LIST& params, IfcProjectionCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcElectricalCircuit>(const DB& db, const LIST& params, IfcElectricalCircuit* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcRationalBezierCurve>(const DB& db, const LIST& params, IfcRationalBezierCurve* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcStructuralPointAction>(const DB& db, const LIST& params, IfcStructuralPointAction* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPipeSegmentType>(const DB& db, const LIST& params, IfcPipeSegmentType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTwoDirectionRepeatFactor>(const DB& db, const LIST& params, IfcTwoDirectionRepeatFactor* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcShapeRepresentation>(const DB& db, const LIST& params, IfcShapeRepresentation* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPropertySet>(const DB& db, const LIST& params, IfcPropertySet* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIST& params, IfcSurfaceStyleRendering* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcDistributionPort>(const DB& db, const LIST& params, IfcDistributionPort* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcPipeFittingType>(const DB& db, const LIST& params, IfcPipeFittingType* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcTransportElement>(const DB& db, const LIST& params, IfcTransportElement* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--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<IfcStructuralAnalysisModel>(const DB& db, const LIST& params, IfcStructuralAnalysisModel* 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;
--}
--// -----------------------------------------------------------------------------------------------------------
--template <> size_t GenericFill<IfcConditionCriterion>(const DB& db, const LIST& params, IfcConditionCriterion* 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;
--}
--
--} // ! STEP
--} // ! Assimp
--
--#endif
-diff --git a/src/3rdparty/assimp/code/IFCReaderGen1.cpp b/src/3rdparty/assimp/code/IFCReaderGen1.cpp
-new file mode 100644
-index 0000000..bbf25c2
---- /dev/null
-+++ b/src/3rdparty/assimp/code/IFCReaderGen1.cpp
-@@ -0,0 +1,3168 @@
-+/*
-+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
-+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 Development 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.
-+
-+----------------------------------------------------------------------
-+*/
-+
-+/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
-+
-+#include "AssimpPCH.h"
-+#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
-+
-+#include "IFCReaderGen.h"
-+
-+namespace Assimp {
-+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 )
-+
-+ };
-+}
-+
-+// -----------------------------------------------------------------------------------------------------------
-+void IFC::GetSchema(EXPRESS::ConversionSchema& out)
-+{
-+ out = EXPRESS::ConversionSchema(schema_raw);
-+}
-+
-+namespace STEP {
-+
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
-+{
-+ return 0;
-+}
-+
-+
-+
-+// -----------------------------------------------------------------------------------------------------------
-+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++];
-+ 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; }
-+ 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++];
-+ 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; }
-+ 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++];
-+ 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; }
-+ 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++];
-+ 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; }
-+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRoot to be a `IfcText`")); }
-+ } while(0);
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTypeObject>(const DB& db, const LIST& params, IfcTypeObject* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTypeProduct>(const DB& db, const LIST& params, IfcTypeProduct* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElementType>(const DB& db, const LIST& params, IfcElementType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDistributionElementType>(const DB& db, const LIST& params, IfcDistributionElementType* 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<IfcDistributionFlowElementType>(const DB& db, const LIST& params, IfcDistributionFlowElementType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowControllerType>(const DB& db, const LIST& params, IfcFlowControllerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricTimeControlType>(const DB& db, const LIST& params, IfcElectricTimeControlType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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)
-+{
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTopologyRepresentation>(const DB& db, const LIST& params, IfcTopologyRepresentation* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelationship>(const DB& db, const LIST& params, IfcRelationship* 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));
-+// this data structure is not used yet, so there is no code generated to fill its members
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCableCarrierFittingType>(const DB& db, const LIST& params, IfcCableCarrierFittingType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEnergyConversionDeviceType>(const DB& db, const LIST& params, 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCoilType>(const DB& db, const LIST& params, IfcCoilType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcObject>(const DB& db, const LIST& params, IfcObject* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcControl>(const DB& db, const LIST& params, IfcControl* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST& params, IfcPerformanceHistory* 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<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<IfcTextLiteral>(const DB& db, const LIST& params, IfcTextLiteral* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTextLiteralWithExtent>(const DB& db, const LIST& params, IfcTextLiteralWithExtent* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProductRepresentation>(const DB& db, const LIST& params, IfcProductRepresentation* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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++];
-+ 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; }
-+ 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++];
-+ 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; }
-+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProduct to be a `IfcProductRepresentation`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, IfcElement* 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; }
-+ 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<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDistributionFlowElement>(const DB& db, const LIST& params, IfcDistributionFlowElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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<IfcCartesianTransformationOperator>(const DB& db, const LIST& params, IfcCartesianTransformationOperator* 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`")); }
-+ } 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; }
-+ 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<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
-+ 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProperty>(const DB& db, const LIST& params, IfcProperty* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSimpleProperty>(const DB& db, const LIST& params, IfcSimpleProperty* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPropertyEnumeratedValue>(const DB& db, const LIST& params, IfcPropertyEnumeratedValue* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuildingElementType>(const DB& db, const LIST& params, IfcBuildingElementType* 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<IfcStairFlightType>(const DB& db, const LIST& params, IfcStairFlightType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSurface>(const DB& db, const LIST& params, IfcSurface* in)
-+{
-+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& params, IfcElementarySurface* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPlane>(const DB& db, const LIST& params, IfcPlane* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBooleanResult>(const DB& db, const LIST& params, IfcBooleanResult* 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`")); }
-+ } 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBooleanClippingResult>(const DB& db, const LIST& params, IfcBooleanClippingResult* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSolidModel>(const DB& db, const LIST& params, IfcSolidModel* in)
-+{
-+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcManifoldSolidBrep>(const DB& db, const LIST& params, IfcManifoldSolidBrep* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowTerminalType>(const DB& db, const LIST& params, 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStackTerminalType>(const DB& db, const LIST& params, IfcStackTerminalType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralItem>(const DB& db, const LIST& params, IfcStructuralItem* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralConnection>(const DB& db, const LIST& params, IfcStructuralConnection* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralCurveConnection>(const DB& db, const LIST& params, IfcStructuralCurveConnection* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcJunctionBoxType>(const DB& db, const LIST& params, IfcJunctionBoxType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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<IfcProcess>(const DB& db, const LIST& params, IfcProcess* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTask>(const DB& db, const LIST& params, IfcTask* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelFillsElement>(const DB& db, const LIST& params, IfcRelFillsElement* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProcedure>(const DB& db, const LIST& params, IfcProcedure* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProxy>(const DB& db, const LIST& params, IfcProxy* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcResource>(const DB& db, const LIST& params, IfcResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConstructionResource>(const DB& db, const LIST& params, IfcConstructionResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSubContractResource>(const DB& db, const LIST& params, IfcSubContractResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelContainedInSpatialStructure>(const DB& db, const LIST& params, IfcRelContainedInSpatialStructure* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTopologicalRepresentationItem>(const DB& db, const LIST& params, IfcTopologicalRepresentationItem* in)
-+{
-+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEdge>(const DB& db, const LIST& params, IfcEdge* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEdgeCurve>(const DB& db, const LIST& params, IfcEdgeCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, IfcPlateType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
-+{
-+ size_t base = 0;
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcGridPlacement>(const DB& db, const LIST& params, IfcGridPlacement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFireSuppressionTerminalType>(const DB& db, const LIST& params, IfcFireSuppressionTerminalType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& params, IfcFlowStorageDevice* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSweptSurface>(const DB& db, const LIST& params, IfcSweptSurface* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSurfaceOfRevolution>(const DB& db, const LIST& params, IfcSurfaceOfRevolution* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcOrientedEdge>(const DB& db, const LIST& params, IfcOrientedEdge* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDirection>(const DB& db, const LIST& params, IfcDirection* 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`")); }
-+ } while(0);
-+ 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
-+ 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; }
-+ 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`")); }
-+ } while(0);
-+ 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
-+ 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCShapeProfileDef>(const DB& db, const LIST& params, IfcCShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEdgeFeature>(const DB& db, const LIST& params, IfcEdgeFeature* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcChamferEdgeFeature>(const DB& db, const LIST& params, IfcChamferEdgeFeature* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuildingElement>(const DB& db, const LIST& params, IfcBuildingElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcColumn>(const DB& db, const LIST& params, IfcColumn* 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<IfcPropertyReferenceValue>(const DB& db, const LIST& params, IfcPropertyReferenceValue* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricMotorType>(const DB& db, const LIST& params, IfcElectricMotorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSpatialStructureElementType>(const DB& db, const LIST& params, IfcSpatialStructureElementType* 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<IfcSpaceType>(const DB& db, const LIST& params, IfcSpaceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcColumnType>(const DB& db, const LIST& params, IfcColumnType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCraneRailAShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailAShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCondenserType>(const DB& db, const LIST& params, IfcCondenserType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPlacement>(const DB& db, const LIST& params, IfcPlacement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAxis2Placement3D>(const DB& db, const LIST& params, IfcAxis2Placement3D* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPresentationStyle>(const DB& db, const LIST& params, IfcPresentationStyle* 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; }
-+ 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<IfcEquipmentElement>(const DB& db, const LIST& params, IfcEquipmentElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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; }
-+ 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; }
-+ 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; }
-+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCompositeCurveSegment to be a `IfcCurve`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRectangleProfileDef>(const DB& db, const LIST& params, IfcRectangleProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuildingElementProxy>(const DB& db, const LIST& params, IfcBuildingElementProxy* 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<IfcDistributionControlElementType>(const DB& db, const LIST& params, IfcDistributionControlElementType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowInstrumentType>(const DB& db, const LIST& params, IfcFlowInstrumentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDraughtingCallout>(const DB& db, const LIST& params, IfcDraughtingCallout* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDimensionCurveDirectedCallout>(const DB& db, const LIST& params, IfcDimensionCurveDirectedCallout* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLinearDimension>(const DB& db, const LIST& params, IfcLinearDimension* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElementAssembly>(const DB& db, const LIST& params, IfcElementAssembly* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCsgPrimitive3D>(const DB& db, const LIST& params, IfcCsgPrimitive3D* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRightCircularCone>(const DB& db, const LIST& params, IfcRightCircularCone* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProjectOrder>(const DB& db, const LIST& params, IfcProjectOrder* 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<IfcLShapeProfileDef>(const DB& db, const LIST& params, IfcLShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAngularDimension>(const DB& db, const LIST& params, IfcAngularDimension* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLocalPlacement>(const DB& db, const LIST& params, IfcLocalPlacement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSweptAreaSolid>(const DB& db, const LIST& params, IfcSweptAreaSolid* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralSurfaceConnection>(const DB& db, const LIST& params, IfcStructuralSurfaceConnection* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRadiusDimension>(const DB& db, const LIST& params, IfcRadiusDimension* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSweptDiskSolid>(const DB& db, const LIST& params, IfcSweptDiskSolid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcHalfSpaceSolid>(const DB& db, const LIST& params, IfcHalfSpaceSolid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const LIST& params, IfcPolygonalBoundedHalfSpace* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTimeSeriesSchedule>(const DB& db, const LIST& params, IfcTimeSeriesSchedule* 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<IfcCooledBeamType>(const DB& db, const LIST& params, IfcCooledBeamType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProject>(const DB& db, const LIST& params, IfcProject* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEvaporatorType>(const DB& db, const LIST& params, IfcEvaporatorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLaborResource>(const DB& db, const LIST& params, IfcLaborResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPropertyBoundedValue>(const DB& db, const LIST& params, IfcPropertyBoundedValue* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRampFlightType>(const DB& db, const LIST& params, IfcRampFlightType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMember>(const DB& db, const LIST& params, IfcMember* 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<IfcTubeBundleType>(const DB& db, const LIST& params, IfcTubeBundleType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcValveType>(const DB& db, const LIST& params, IfcValveType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTrimmedCurve>(const DB& db, const LIST& params, IfcTrimmedCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelDefines>(const DB& db, const LIST& params, IfcRelDefines* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelDefinesByProperties>(const DB& db, const LIST& params, IfcRelDefinesByProperties* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcActor>(const DB& db, const LIST& params, IfcActor* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcOccupant>(const DB& db, const LIST& params, IfcOccupant* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcHumidifierType>(const DB& db, const LIST& params, IfcHumidifierType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcArbitraryOpenProfileDef>(const DB& db, const LIST& params, IfcArbitraryOpenProfileDef* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPermit>(const DB& db, const LIST& params, IfcPermit* 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<IfcOffsetCurve3D>(const DB& db, const LIST& params, IfcOffsetCurve3D* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLightSource>(const DB& db, const LIST& params, 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLightSourcePositional>(const DB& db, const LIST& params, IfcLightSourcePositional* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCompositeProfileDef>(const DB& db, const LIST& params, IfcCompositeProfileDef* in)
-+{
-+ 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<IfcRamp>(const DB& db, const LIST& params, IfcRamp* 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<IfcFlowMovingDevice>(const DB& db, const LIST& params, IfcFlowMovingDevice* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSpaceHeaterType>(const DB& db, const LIST& params, IfcSpaceHeaterType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLampType>(const DB& db, const LIST& params, IfcLampType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuildingElementComponent>(const DB& db, const LIST& params, IfcBuildingElementComponent* 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<IfcReinforcingElement>(const DB& db, const LIST& params, IfcReinforcingElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcReinforcingBar>(const DB& db, const LIST& params, IfcReinforcingBar* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricHeaterType>(const DB& db, const LIST& params, IfcElectricHeaterType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTShapeProfileDef>(const DB& db, const LIST& params, IfcTShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralActivity>(const DB& db, const LIST& params, 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralAction>(const DB& db, const LIST& params, IfcStructuralAction* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDuctFittingType>(const DB& db, const LIST& params, IfcDuctFittingType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCartesianTransformationOperator2D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2D* in)
-+{
-+ 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<IfcVirtualElement>(const DB& db, const LIST& params, IfcVirtualElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRightCircularCylinder>(const DB& db, const LIST& params, IfcRightCircularCylinder* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcOutletType>(const DB& db, const LIST& params, IfcOutletType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelDecomposes>(const DB& db, const LIST& params, IfcRelDecomposes* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCovering>(const DB& db, const LIST& params, IfcCovering* 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<IfcPolyline>(const DB& db, const LIST& params, IfcPolyline* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPath>(const DB& db, const LIST& params, IfcPath* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElementComponent>(const DB& db, const LIST& params, IfcElementComponent* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFastener>(const DB& db, const LIST& params, IfcFastener* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMappedItem>(const DB& db, const LIST& params, IfcMappedItem* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRectangularPyramid>(const DB& db, const LIST& params, IfcRectangularPyramid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCrewResource>(const DB& db, const LIST& params, IfcCrewResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, IfcNamedUnit* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcContextDependentUnit>(const DB& db, const LIST& params, IfcContextDependentUnit* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcUnitaryEquipmentType>(const DB& db, const LIST& params, IfcUnitaryEquipmentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRoof>(const DB& db, const LIST& params, IfcRoof* 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<IfcStructuralMember>(const DB& db, const LIST& params, IfcStructuralMember* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStyleModel>(const DB& db, const LIST& params, IfcStyleModel* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStyledRepresentation>(const DB& db, const LIST& params, IfcStyledRepresentation* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSpatialStructureElement>(const DB& db, const LIST& params, IfcSpatialStructureElement* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuilding>(const DB& db, const LIST& params, IfcBuilding* 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`")); }
-+ } 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConnectedFaceSet>(const DB& db, const LIST& params, IfcConnectedFaceSet* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcOpenShell>(const DB& db, const LIST& params, IfcOpenShell* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFacetedBrep>(const DB& db, const LIST& params, IfcFacetedBrep* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcConic* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCoveringType>(const DB& db, const LIST& params, IfcCoveringType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRoundedRectangleProfileDef>(const DB& db, const LIST& params, IfcRoundedRectangleProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAirTerminalType>(const DB& db, const LIST& params, IfcAirTerminalType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowMovingDeviceType>(const DB& db, const LIST& params, IfcFlowMovingDeviceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCompressorType>(const DB& db, const LIST& params, IfcCompressorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAsymmetricIShapeProfileDef>(const DB& db, const LIST& params, IfcAsymmetricIShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcControllerType>(const DB& db, const LIST& params, IfcControllerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRailing>(const DB& db, const LIST& params, IfcRailing* 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<IfcGroup>(const DB& db, const LIST& params, IfcGroup* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAsset>(const DB& db, const LIST& params, IfcAsset* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMaterialDefinitionRepresentation>(const DB& db, const LIST& params, IfcMaterialDefinitionRepresentation* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRailingType>(const DB& db, const LIST& params, IfcRailingType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWall>(const DB& db, const LIST& params, IfcWall* 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<IfcStructuralPointConnection>(const DB& db, const LIST& params, IfcStructuralPointConnection* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPropertyListValue>(const DB& db, const LIST& params, IfcPropertyListValue* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFurnitureStandard>(const DB& db, const LIST& params, IfcFurnitureStandard* 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<IfcElectricGeneratorType>(const DB& db, const LIST& params, IfcElectricGeneratorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAnnotationOccurrence>(const DB& db, const LIST& params, IfcAnnotationOccurrence* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAnnotationSymbolOccurrence>(const DB& db, const LIST& params, IfcAnnotationSymbolOccurrence* 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<IfcArbitraryClosedProfileDef>(const DB& db, const LIST& params, IfcArbitraryClosedProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcArbitraryProfileDefWithVoids>(const DB& db, const LIST& params, IfcArbitraryProfileDefWithVoids* in)
-+{
-+ size_t base = GenericFill(db,params,static_cast<IfcArbitraryClosedProfileDef*>(in));
-+// this data structure is not used yet, so there is no code generated to fill its members
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLine>(const DB& db, const LIST& params, IfcLine* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowSegmentType>(const DB& db, const LIST& params, IfcFlowSegmentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAirTerminalBoxType>(const DB& db, const LIST& params, IfcAirTerminalBoxType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPropertySingleValue>(const DB& db, const LIST& params, IfcPropertySingleValue* 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++];
-+ 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`")); }
-+ } 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 IfcPropertySingleValue to be a `IfcUnit`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAlarmType>(const DB& db, const LIST& params, IfcAlarmType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStair>(const DB& db, const LIST& params, IfcStair* 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<IfcSurfaceStyleShading>(const DB& db, const LIST& params, IfcSurfaceStyleShading* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPumpType>(const DB& db, const LIST& params, IfcPumpType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDefinedSymbol>(const DB& db, const LIST& params, IfcDefinedSymbol* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElementComponentType>(const DB& db, const LIST& params, IfcElementComponentType* 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<IfcFastenerType>(const DB& db, const LIST& params, IfcFastenerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMechanicalFastenerType>(const DB& db, const LIST& params, IfcMechanicalFastenerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowFitting>(const DB& db, const LIST& params, IfcFlowFitting* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLightSourceDirectional>(const DB& db, const LIST& params, IfcLightSourceDirectional* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+
-+} // ! STEP
-+} // ! Assimp
-+
-+#endif
-diff --git a/src/3rdparty/assimp/code/IFCReaderGen2.cpp b/src/3rdparty/assimp/code/IFCReaderGen2.cpp
-new file mode 100644
-index 0000000..c8d0800
---- /dev/null
-+++ b/src/3rdparty/assimp/code/IFCReaderGen2.cpp
-@@ -0,0 +1,1917 @@
-+/*
-+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
-+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 Development Team.
-+
-+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+
-+----------------------------------------------------------------------
-+*/
-+
-+#include "AssimpPCH.h"
-+#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
-+
-+#include "IFCReaderGen.h"
-+
-+namespace Assimp {
-+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)
-+{
-+ 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<IfcFlowController>(const DB& db, const LIST& params, IfcFlowController* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuildingStorey>(const DB& db, const LIST& params, IfcBuildingStorey* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWorkControl>(const DB& db, const LIST& params, IfcWorkControl* 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<IfcWorkSchedule>(const DB& db, const LIST& params, IfcWorkSchedule* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDuctSegmentType>(const DB& db, const LIST& params, IfcDuctSegmentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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`")); }
-+ } 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCostSchedule>(const DB& db, const LIST& params, IfcCostSchedule* 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<IfcPlanarExtent>(const DB& db, const LIST& params, IfcPlanarExtent* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPlanarBox>(const DB& db, const LIST& params, IfcPlanarBox* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcColourSpecification>(const DB& db, const LIST& params, IfcColourSpecification* 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; }
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBeam>(const DB& db, const LIST& params, IfcBeam* 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<IfcColourRgb>(const DB& db, const LIST& params, IfcColourRgb* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralPlanarAction>(const DB& db, const LIST& params, IfcStructuralPlanarAction* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralPlanarActionVarying>(const DB& db, const LIST& params, IfcStructuralPlanarActionVarying* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSite>(const DB& db, const LIST& params, IfcSite* 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));
-+// this data structure is not used yet, so there is no code generated to fill its members
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcVibrationIsolatorType>(const DB& db, const LIST& params, IfcVibrationIsolatorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEvaporativeCoolerType>(const DB& db, const LIST& params, IfcEvaporativeCoolerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDistributionChamberElementType>(const DB& db, const LIST& params, IfcDistributionChamberElementType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFeatureElementAddition>(const DB& db, const LIST& params, IfcFeatureElementAddition* in)
-+{
-+ 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<IfcStructuredDimensionCallout>(const DB& db, const LIST& params, IfcStructuredDimensionCallout* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCoolingTowerType>(const DB& db, const LIST& params, IfcCoolingTowerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCenterLineProfileDef>(const DB& db, const LIST& params, IfcCenterLineProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWindowStyle>(const DB& db, const LIST& params, IfcWindowStyle* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLightSourceGoniometric>(const DB& db, const LIST& params, IfcLightSourceGoniometric* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTransformerType>(const DB& db, const LIST& params, IfcTransformerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMemberType>(const DB& db, const LIST& params, IfcMemberType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSurfaceOfLinearExtrusion>(const DB& db, const LIST& params, IfcSurfaceOfLinearExtrusion* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMotorConnectionType>(const DB& db, const LIST& params, IfcMotorConnectionType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowTreatmentDeviceType>(const DB& db, const LIST& params, IfcFlowTreatmentDeviceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDuctSilencerType>(const DB& db, const LIST& params, IfcDuctSilencerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFurnishingElementType>(const DB& db, const LIST& params, IfcFurnishingElementType* 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<IfcSystemFurnitureElementType>(const DB& db, const LIST& params, IfcSystemFurnitureElementType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWasteTerminalType>(const DB& db, const LIST& params, IfcWasteTerminalType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBezierCurve>(const DB& db, const LIST& params, IfcBezierCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcActuatorType>(const DB& db, const LIST& params, IfcActuatorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDistributionControlElement>(const DB& db, const LIST& params, IfcDistributionControlElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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() < 7) { throw STEP::TypeError("expected 7 arguments to IfcAnnotation"); } return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcActionRequest>(const DB& db, const LIST& params, IfcActionRequest* 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<IfcExtrudedAreaSolid>(const DB& db, const LIST& params, IfcExtrudedAreaSolid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSystem>(const DB& db, const LIST& params, IfcSystem* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFillAreaStyleHatching>(const DB& db, const LIST& params, IfcFillAreaStyleHatching* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelVoidsElement>(const DB& db, const LIST& params, IfcRelVoidsElement* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSurfaceCurveSweptAreaSolid>(const DB& db, const LIST& params, IfcSurfaceCurveSweptAreaSolid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCartesianTransformationOperator3DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3DnonUniform* 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCurtainWallType>(const DB& db, const LIST& params, IfcCurtainWallType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEquipmentStandard>(const DB& db, const LIST& params, IfcEquipmentStandard* 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<IfcFlowStorageDeviceType>(const DB& db, const LIST& params, IfcFlowStorageDeviceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDiameterDimension>(const DB& db, const LIST& params, IfcDiameterDimension* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSwitchingDeviceType>(const DB& db, const LIST& params, IfcSwitchingDeviceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWindow>(const DB& db, const LIST& params, IfcWindow* 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<IfcFlowTreatmentDevice>(const DB& db, const LIST& params, IfcFlowTreatmentDevice* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcChillerType>(const DB& db, const LIST& params, IfcChillerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRectangleHollowProfileDef>(const DB& db, const LIST& params, IfcRectangleHollowProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBoxedHalfSpace>(const DB& db, const LIST& params, IfcBoxedHalfSpace* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAxis2Placement2D>(const DB& db, const LIST& params, IfcAxis2Placement2D* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBoundedSurface>(const DB& db, const LIST& params, IfcBoundedSurface* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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)
-+{
-+ 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`")); }
-+ } 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRepresentationContext>(const DB& db, const LIST& params, IfcRepresentationContext* 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; }
-+ 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`")); }
-+ } 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; }
-+ 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCurveBoundedPlane>(const DB& db, const LIST& params, IfcCurveBoundedPlane* 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<IfcSIUnit>(const DB& db, const LIST& params, IfcSIUnit* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralReaction>(const DB& db, const LIST& params, IfcStructuralReaction* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralPointReaction>(const DB& db, const LIST& params, IfcStructuralPointReaction* in)
-+{
-+ 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<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricApplianceType>(const DB& db, const LIST& params, IfcElectricApplianceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSensorType>(const DB& db, const LIST& params, IfcSensorType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFurnishingElement>(const DB& db, const LIST& params, IfcFurnishingElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProtectiveDeviceType>(const DB& db, const LIST& params, IfcProtectiveDeviceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcZShapeProfileDef>(const DB& db, const LIST& params, IfcZShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcScheduleTimeControl>(const DB& db, const LIST& params, IfcScheduleTimeControl* 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<IfcRepresentationMap>(const DB& db, const LIST& params, IfcRepresentationMap* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ 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)
-+{
-+ 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<IfcBlock>(const DB& db, const LIST& params, IfcBlock* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLightFixtureType>(const DB& db, const LIST& params, IfcLightFixtureType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcLightSourceSpot>(const DB& db, const LIST& params, IfcLightSourceSpot* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTendonAnchor>(const DB& db, const LIST& params, IfcTendonAnchor* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricFlowStorageDeviceType>(const DB& db, const LIST& params, IfcElectricFlowStorageDeviceType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSphere>(const DB& db, const LIST& params, IfcSphere* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDamperType>(const DB& db, const LIST& params, IfcDamperType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProjectOrderRecord>(const DB& db, const LIST& params, IfcProjectOrderRecord* 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<IfcDistributionChamberElement>(const DB& db, const LIST& params, IfcDistributionChamberElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMechanicalFastener>(const DB& db, const LIST& params, IfcMechanicalFastener* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRectangularTrimmedSurface>(const DB& db, const LIST& params, IfcRectangularTrimmedSurface* 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<IfcZone>(const DB& db, const LIST& params, IfcZone* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFanType>(const DB& db, const LIST& params, IfcFanType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcGeometricSet>(const DB& db, const LIST& params, IfcGeometricSet* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFillAreaStyleTiles>(const DB& db, const LIST& params, IfcFillAreaStyleTiles* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCableSegmentType>(const DB& db, const LIST& params, IfcCableSegmentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRelOverridesProperties>(const DB& db, const LIST& params, IfcRelOverridesProperties* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSlabType>(const DB& db, const LIST& params, IfcSlabType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcServiceLife>(const DB& db, const LIST& params, IfcServiceLife* 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<IfcFurnitureType>(const DB& db, const LIST& params, IfcFurnitureType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCostItem>(const DB& db, const LIST& params, IfcCostItem* 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<IfcReinforcingMesh>(const DB& db, const LIST& params, IfcReinforcingMesh* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFacetedBrepWithVoids>(const DB& db, const LIST& params, IfcFacetedBrepWithVoids* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcGasTerminalType>(const DB& db, const LIST& params, IfcGasTerminalType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPile>(const DB& db, const LIST& params, IfcPile* 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<IfcFillAreaStyleTileSymbolWithStyle>(const DB& db, const LIST& params, IfcFillAreaStyleTileSymbolWithStyle* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConstructionMaterialResource>(const DB& db, const LIST& params, IfcConstructionMaterialResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAnnotationCurveOccurrence>(const DB& db, const LIST& params, IfcAnnotationCurveOccurrence* 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<IfcDimensionCurve>(const DB& db, const LIST& params, IfcDimensionCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcGeometricCurveSet>(const DB& db, const LIST& params, IfcGeometricCurveSet* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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)
-+{
-+ 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`")); }
-+ } 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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)
-+{
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPlate>(const DB& db, const LIST& params, IfcPlate* 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<IfcUShapeProfileDef>(const DB& db, const LIST& params, IfcUShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, IfcFaceBound* 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ 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)
-+{
-+ 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<IfcBoilerType>(const DB& db, const LIST& params, IfcBoilerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConstructionEquipmentResource>(const DB& db, const LIST& params, IfcConstructionEquipmentResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFooting>(const DB& db, const LIST& params, IfcFooting* 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<IfcConstructionProductResource>(const DB& db, const LIST& params, IfcConstructionProductResource* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDerivedProfileDef>(const DB& db, const LIST& params, IfcDerivedProfileDef* in)
-+{
-+ 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<IfcPropertyTableValue>(const DB& db, const LIST& params, IfcPropertyTableValue* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowMeterType>(const DB& db, const LIST& params, IfcFlowMeterType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDoorStyle>(const DB& db, const LIST& params, IfcDoorStyle* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcUnitAssignment>(const DB& db, const LIST& params, IfcUnitAssignment* 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));
-+// this data structure is not used yet, so there is no code generated to fill its members
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCraneRailFShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailFShapeProfileDef* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFlowSegment>(const DB& db, const LIST& params, IfcFlowSegment* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCurtainWall>(const DB& db, const LIST& params, IfcCurtainWall* 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<IfcDiscreteAccessory>(const DB& db, const LIST& params, IfcDiscreteAccessory* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcGrid>(const DB& db, const LIST& params, IfcGrid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSanitaryTerminalType>(const DB& db, const LIST& params, IfcSanitaryTerminalType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSubedge>(const DB& db, const LIST& params, IfcSubedge* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcFilterType>(const DB& db, const LIST& params, IfcFilterType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTendon>(const DB& db, const LIST& params, IfcTendon* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralLoadGroup>(const DB& db, const LIST& params, IfcStructuralLoadGroup* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPresentationStyleAssignment>(const DB& db, const LIST& params, IfcPresentationStyleAssignment* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralCurveMember>(const DB& db, const LIST& params, IfcStructuralCurveMember* 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<IfcLightSourceAmbient>(const DB& db, const LIST& params, IfcLightSourceAmbient* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCondition>(const DB& db, const LIST& params, IfcCondition* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPort>(const DB& db, const LIST& params, IfcPort* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSpace>(const DB& db, const LIST& params, IfcSpace* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTankType>(const DB& db, const LIST& params, IfcTankType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcInventory>(const DB& db, const LIST& params, IfcInventory* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTransportElementType>(const DB& db, const LIST& params, IfcTransportElementType* 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<IfcAirToAirHeatRecoveryType>(const DB& db, const LIST& params, IfcAirToAirHeatRecoveryType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStairFlight>(const DB& db, const LIST& params, IfcStairFlight* 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<IfcElectricalElement>(const DB& db, const LIST& params, IfcElectricalElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSurfaceStyleWithTextures>(const DB& db, const LIST& params, IfcSurfaceStyleWithTextures* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBoundingBox>(const DB& db, const LIST& params, IfcBoundingBox* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWallType>(const DB& db, const LIST& params, IfcWallType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcMove>(const DB& db, const LIST& params, IfcMove* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCircle>(const DB& db, const LIST& params, IfcCircle* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcOffsetCurve2D>(const DB& db, const LIST& params, IfcOffsetCurve2D* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPointOnCurve>(const DB& db, const LIST& params, IfcPointOnCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralResultGroup>(const DB& db, const LIST& params, IfcStructuralResultGroup* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSectionedSpine>(const DB& db, const LIST& params, IfcSectionedSpine* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSlab>(const DB& db, const LIST& params, IfcSlab* 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<IfcVertex>(const DB& db, const LIST& params, IfcVertex* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcVertexPoint>(const DB& db, const LIST& params, IfcVertexPoint* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralLinearAction>(const DB& db, const LIST& params, IfcStructuralLinearAction* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralLinearActionVarying>(const DB& db, const LIST& params, IfcStructuralLinearActionVarying* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBuildingElementProxyType>(const DB& db, const LIST& params, IfcBuildingElementProxyType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProjectionElement>(const DB& db, const LIST& params, IfcProjectionElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAnnotationSurfaceOccurrence>(const DB& db, const LIST& params, IfcAnnotationSurfaceOccurrence* 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<IfcRoundedEdgeFeature>(const DB& db, const LIST& params, IfcRoundedEdgeFeature* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricDistributionPoint>(const DB& db, const LIST& params, IfcElectricDistributionPoint* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCableCarrierSegmentType>(const DB& db, const LIST& params, IfcCableCarrierSegmentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcWallStandardCase>(const DB& db, const LIST& params, IfcWallStandardCase* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcCsgSolid>(const DB& db, const LIST& params, IfcCsgSolid* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcBeamType>(const DB& db, const LIST& params, IfcBeamType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAnnotationFillArea>(const DB& db, const LIST& params, IfcAnnotationFillArea* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralCurveMemberVarying>(const DB& db, const LIST& params, IfcStructuralCurveMemberVarying* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPointOnSurface>(const DB& db, const LIST& params, IfcPointOnSurface* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcOrderAction>(const DB& db, const LIST& params, IfcOrderAction* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcEdgeLoop>(const DB& db, const LIST& params, IfcEdgeLoop* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcAnnotationFillAreaOccurrence>(const DB& db, const LIST& params, IfcAnnotationFillAreaOccurrence* 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<IfcWorkPlan>(const DB& db, const LIST& params, IfcWorkPlan* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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
-+ 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`")); }
-+ } 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`")); }
-+ } while(0);
-+ return base;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProductDefinitionShape>(const DB& db, const LIST& params, IfcProductDefinitionShape* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcProjectionCurve>(const DB& db, const LIST& params, IfcProjectionCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcElectricalCircuit>(const DB& db, const LIST& params, IfcElectricalCircuit* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcRationalBezierCurve>(const DB& db, const LIST& params, IfcRationalBezierCurve* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcStructuralPointAction>(const DB& db, const LIST& params, IfcStructuralPointAction* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPipeSegmentType>(const DB& db, const LIST& params, IfcPipeSegmentType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTwoDirectionRepeatFactor>(const DB& db, const LIST& params, IfcTwoDirectionRepeatFactor* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcShapeRepresentation>(const DB& db, const LIST& params, IfcShapeRepresentation* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPropertySet>(const DB& db, const LIST& params, IfcPropertySet* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIST& params, IfcSurfaceStyleRendering* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcDistributionPort>(const DB& db, const LIST& params, IfcDistributionPort* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcPipeFittingType>(const DB& db, const LIST& params, IfcPipeFittingType* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcTransportElement>(const DB& db, const LIST& params, IfcTransportElement* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+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<IfcStructuralAnalysisModel>(const DB& db, const LIST& params, IfcStructuralAnalysisModel* 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;
-+}
-+// -----------------------------------------------------------------------------------------------------------
-+template <> size_t GenericFill<IfcConditionCriterion>(const DB& db, const LIST& params, IfcConditionCriterion* 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;
-+}
-+
-+} // ! STEP
-+} // ! Assimp
-+
-+#endif
-\ No newline at end of file
---
-1.8.1.msysgit.1
-
diff --git a/src/3rdparty/patches/0003-assimp-Add-missing-case-option.patch b/src/3rdparty/patches/0003-assimp-Add-missing-case-option.patch
new file mode 100644
index 000000000..1b62209ad
--- /dev/null
+++ b/src/3rdparty/patches/0003-assimp-Add-missing-case-option.patch
@@ -0,0 +1,11 @@
+diff -ur assimpGIT/code/ColladaExporter.cpp assimp/code/ColladaExporter.cpp
+--- assimpGIT/code/ColladaExporter.cpp 2016-12-08 14:13:07.000000000 -0500
++++ assimp/code/ColladaExporter.cpp 2016-12-08 09:23:22.000000000 -0500
+@@ -383,6 +383,7 @@
+ case aiLightSource_SPOT:
+ WriteSpotLight(light);
+ break;
++ case aiLightSource_AREA:
+ case aiLightSource_UNDEFINED:
+ case _aiLightSource_Force32Bit:
+ break;
diff --git a/src/3rdparty/patches/0003-assimp-Remove-usage-of-deprecated-keyword-register.patch b/src/3rdparty/patches/0003-assimp-Remove-usage-of-deprecated-keyword-register.patch
deleted file mode 100644
index f469831c8..000000000
--- a/src/3rdparty/patches/0003-assimp-Remove-usage-of-deprecated-keyword-register.patch
+++ /dev/null
@@ -1,382 +0,0 @@
-From 662d2cabc5b5546c61f8596887c3a9a5cfc0f87b Mon Sep 17 00:00:00 2001
-From: Andy Nichols <andy.nichols@theqtcompany.com>
-Date: Tue, 3 Nov 2015 12:32:50 +0100
-Subject: [PATCH] assimp: Remove usage of deprecated keyword register
-
-Change-Id: I1a85b0602c9e2729bab9582dc5325213f3598988
----
- src/3rdparty/assimp/code/3DSConverter.cpp | 2 +-
- src/3rdparty/assimp/code/ACLoader.cpp | 4 ++--
- src/3rdparty/assimp/code/CalcTangentsProcess.cpp | 2 +-
- src/3rdparty/assimp/code/FindDegenerates.cpp | 4 ++--
- src/3rdparty/assimp/code/FindInvalidDataProcess.cpp | 2 +-
- src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp | 2 +-
- src/3rdparty/assimp/code/ImproveCacheLocality.cpp | 2 +-
- src/3rdparty/assimp/code/LWOFileData.h | 2 +-
- src/3rdparty/assimp/code/LWOLoader.cpp | 10 +++++-----
- src/3rdparty/assimp/code/MD2Loader.cpp | 2 +-
- src/3rdparty/assimp/code/NFFLoader.cpp | 2 +-
- src/3rdparty/assimp/code/OptimizeMeshes.cpp | 2 +-
- src/3rdparty/assimp/code/PlyParser.cpp | 4 ++--
- src/3rdparty/assimp/code/Q3DLoader.cpp | 2 +-
- src/3rdparty/assimp/code/RemoveVCProcess.cpp | 4 ++--
- src/3rdparty/assimp/code/SmoothingGroups.inl | 2 +-
- src/3rdparty/assimp/code/SortByPTypeProcess.cpp | 2 +-
- src/3rdparty/assimp/code/StringComparison.h | 6 +++---
- src/3rdparty/assimp/code/TerragenLoader.cpp | 2 +-
- src/3rdparty/assimp/contrib/unzip/crypt.h | 2 +-
- 20 files changed, 30 insertions(+), 30 deletions(-)
-
-diff --git a/src/3rdparty/assimp/code/3DSConverter.cpp b/src/3rdparty/assimp/code/3DSConverter.cpp
-index 7bff38f..3498a4b 100644
---- a/src/3rdparty/assimp/code/3DSConverter.cpp
-+++ b/src/3rdparty/assimp/code/3DSConverter.cpp
-@@ -396,7 +396,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
- }
- for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
- {
-- register unsigned int index = aiSplit[p][q];
-+ unsigned int index = aiSplit[p][q];
- aiFace& face = meshOut->mFaces[q];
-
- face.mIndices = new unsigned int[3];
-diff --git a/src/3rdparty/assimp/code/ACLoader.cpp b/src/3rdparty/assimp/code/ACLoader.cpp
-index 93e739b..687e9ac 100644
---- a/src/3rdparty/assimp/code/ACLoader.cpp
-+++ b/src/3rdparty/assimp/code/ACLoader.cpp
-@@ -489,7 +489,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
-
- for (it = object.surfaces.begin(); it != end; ++it)
- {
-- register unsigned int idx = (*it).mat;
-+ unsigned int idx = (*it).mat;
- if (idx >= needMat.size())
- {
- DefaultLogger::get()->error("AC3D: material index is out of range");
-@@ -617,7 +617,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
- it2 = (*it).entries.begin();
-
- // either a closed or an unclosed line
-- register unsigned int tmp = (unsigned int)(*it).entries.size();
-+ unsigned int tmp = (unsigned int)(*it).entries.size();
- if (0x2 == type)--tmp;
- for (unsigned int m = 0; m < tmp;++m)
- {
-diff --git a/src/3rdparty/assimp/code/CalcTangentsProcess.cpp b/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
-index 20ed3ea..1d5e1bd 100644
---- a/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
-+++ b/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
-@@ -167,7 +167,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
- // their tangent vectors are set to qnan.
- for (unsigned int i = 0; i < face.mNumIndices;++i)
- {
-- register unsigned int idx = face.mIndices[i];
-+ unsigned int idx = face.mIndices[i];
- vertexDone [idx] = true;
- meshTang [idx] = aiVector3D(qnan);
- meshBitang [idx] = aiVector3D(qnan);
-diff --git a/src/3rdparty/assimp/code/FindDegenerates.cpp b/src/3rdparty/assimp/code/FindDegenerates.cpp
-index 3870e04..04ca925 100644
---- a/src/3rdparty/assimp/code/FindDegenerates.cpp
-+++ b/src/3rdparty/assimp/code/FindDegenerates.cpp
-@@ -107,7 +107,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
- bool first = true;
-
- // check whether the face contains degenerated entries
-- for (register unsigned int i = 0; i < face.mNumIndices; ++i)
-+ 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,
-@@ -116,7 +116,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
- if (face.mNumIndices > 4)
- limit = std::min(limit,i+2);
-
-- for (register unsigned int t = i+1; t < limit; ++t)
-+ for (unsigned int t = i+1; t < limit; ++t)
- {
- if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
- {
-diff --git a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
-index 6b7659a..618e7d3 100644
---- a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
-+++ b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
-@@ -89,7 +89,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMap
- unsigned int out = 0;
- for (unsigned int a = 0; a < node->mNumMeshes;++a) {
-
-- register unsigned int ref = node->mMeshes[a];
-+ unsigned int ref = node->mMeshes[a];
- if (UINT_MAX != (ref = meshMapping[ref])) {
- node->mMeshes[out++] = ref;
- }
-diff --git a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
-index e4f96b6..643dc8f 100644
---- a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
-+++ b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
-@@ -195,7 +195,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
- // Write the smoothed normal back to all affected normals
- for (unsigned int a = 0; a < verticesFound.size(); ++a)
- {
-- register unsigned int vidx = verticesFound[a];
-+ unsigned int vidx = verticesFound[a];
- pcNew[vidx] = pcNor;
- abHad[vidx] = true;
- }
-diff --git a/src/3rdparty/assimp/code/ImproveCacheLocality.cpp b/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
-index 8cd4ee6..b6aa338 100644
---- a/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
-+++ b/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
-@@ -303,7 +303,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
- ivdx = -1;
- int max_priority = -1;
- for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) {
-- register const unsigned int dp = *piCur;
-+ const unsigned int dp = *piCur;
-
- // must have live triangles
- if (piNumTriPtr[dp] > 0) {
-diff --git a/src/3rdparty/assimp/code/LWOFileData.h b/src/3rdparty/assimp/code/LWOFileData.h
-index d8f4b8d..88ca9c5 100644
---- a/src/3rdparty/assimp/code/LWOFileData.h
-+++ b/src/3rdparty/assimp/code/LWOFileData.h
-@@ -346,7 +346,7 @@ struct VColorChannel : public VMapEntry
- if (!rawData.empty())
- return; // return if already allocated
-
-- register unsigned int m = num*dims;
-+ unsigned int m = num*dims;
- rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
- rawData.resize(m);
-
-diff --git a/src/3rdparty/assimp/code/LWOLoader.cpp b/src/3rdparty/assimp/code/LWOLoader.cpp
-index 5e5aa83..e0891b7 100644
---- a/src/3rdparty/assimp/code/LWOLoader.cpp
-+++ b/src/3rdparty/assimp/code/LWOLoader.cpp
-@@ -344,7 +344,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
-
- // copy all vertices
- for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) {
-- register unsigned int idx = face.mIndices[q];
-+ unsigned int idx = face.mIndices[q];
- *pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/;
-
- // process UV coordinates
-@@ -491,7 +491,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
- aiFace& face = *begin;
- for (unsigned int i = 0; i < face.mNumIndices;++i)
- {
-- register unsigned int tt = face.mIndices[i];
-+ unsigned int tt = face.mIndices[i];
- sSort.Add(mesh->mVertices[tt],tt,*it);
- }
- }
-@@ -510,7 +510,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
- unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
- for (; beginIdx != endIdx; ++beginIdx)
- {
-- register unsigned int idx = *beginIdx;
-+ unsigned int idx = *beginIdx;
- sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
- std::vector<unsigned int>::const_iterator a, end = poResult.end();
-
-@@ -533,7 +533,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
- unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
- for (; beginIdx != endIdx; ++beginIdx)
- {
-- register unsigned int idx = *beginIdx;
-+ unsigned int idx = *beginIdx;
- if (vertexDone[idx])
- continue;
- sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
-@@ -730,7 +730,7 @@ 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.
-- register unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
-+ unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
- if (mIsLWO2)
- {
- mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) );
-diff --git a/src/3rdparty/assimp/code/MD2Loader.cpp b/src/3rdparty/assimp/code/MD2Loader.cpp
-index e27ea4b..050555b 100644
---- a/src/3rdparty/assimp/code/MD2Loader.cpp
-+++ b/src/3rdparty/assimp/code/MD2Loader.cpp
-@@ -377,7 +377,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
-
- // validate vertex indices
-- register unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
-+ 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;
-diff --git a/src/3rdparty/assimp/code/NFFLoader.cpp b/src/3rdparty/assimp/code/NFFLoader.cpp
-index b3cbef3..b81698a 100644
---- a/src/3rdparty/assimp/code/NFFLoader.cpp
-+++ b/src/3rdparty/assimp/code/NFFLoader.cpp
-@@ -400,7 +400,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
- if (TokenMatch(sz,"0x",2))
- {
- hasColor = true;
-- register unsigned int numIdx = ::strtoul16(sz,&sz);
-+ unsigned int numIdx = ::strtoul16(sz,&sz);
- aiColor4D clr;
- clr.a = 1.f;
-
-diff --git a/src/3rdparty/assimp/code/OptimizeMeshes.cpp b/src/3rdparty/assimp/code/OptimizeMeshes.cpp
-index dce0ebd..85961de 100644
---- a/src/3rdparty/assimp/code/OptimizeMeshes.cpp
-+++ b/src/3rdparty/assimp/code/OptimizeMeshes.cpp
-@@ -162,7 +162,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
-
- // Find meshes to merge with us
- for (unsigned int a = i+1; a < pNode->mNumMeshes;++a) {
-- register unsigned int am = pNode->mMeshes[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]);
-diff --git a/src/3rdparty/assimp/code/PlyParser.cpp b/src/3rdparty/assimp/code/PlyParser.cpp
-index 048fd5e..a168535 100644
---- a/src/3rdparty/assimp/code/PlyParser.cpp
-+++ b/src/3rdparty/assimp/code/PlyParser.cpp
-@@ -794,7 +794,7 @@ bool PLY::PropertyInstance::ParseValue(
- {
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
-
-- register bool ret = true;
-+ bool ret = true;
- *pCurOut = pCur;
- switch (eType)
- {
-@@ -841,7 +841,7 @@ bool PLY::PropertyInstance::ParseValueBinary(
- {
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
-
-- register bool ret = true;
-+ bool ret = true;
- switch (eType)
- {
- case EDT_UInt:
-diff --git a/src/3rdparty/assimp/code/Q3DLoader.cpp b/src/3rdparty/assimp/code/Q3DLoader.cpp
-index 54b5456..0e436e3 100644
---- a/src/3rdparty/assimp/code/Q3DLoader.cpp
-+++ b/src/3rdparty/assimp/code/Q3DLoader.cpp
-@@ -314,7 +314,7 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
- if (!tex->mWidth || !tex->mHeight)
- throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
-
-- register unsigned int mul = tex->mWidth * tex->mHeight;
-+ unsigned int mul = tex->mWidth * tex->mHeight;
- aiTexel* begin = tex->pcData = new aiTexel[mul];
- aiTexel* const end = & begin [mul];
-
-diff --git a/src/3rdparty/assimp/code/RemoveVCProcess.cpp b/src/3rdparty/assimp/code/RemoveVCProcess.cpp
-index 346d84a..7c4908f 100644
---- a/src/3rdparty/assimp/code/RemoveVCProcess.cpp
-+++ b/src/3rdparty/assimp/code/RemoveVCProcess.cpp
-@@ -84,7 +84,7 @@ inline void ArrayDelete(T**& in, unsigned int& num)
- // "don't remove" flag not set. Nodes with meshes are never deleted.
- bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
- {
-- register bool b = false;
-+ bool b = false;
-
- std::list<aiNode*> mine;
- for (unsigned int i = 0; i < node->mNumChildren;++i)
-@@ -271,7 +271,7 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
- }
-
- // handle texture coordinates
-- register bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
-+ 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;
-diff --git a/src/3rdparty/assimp/code/SmoothingGroups.inl b/src/3rdparty/assimp/code/SmoothingGroups.inl
-index 55a9394..156ebf7 100644
---- a/src/3rdparty/assimp/code/SmoothingGroups.inl
-+++ b/src/3rdparty/assimp/code/SmoothingGroups.inl
-@@ -106,7 +106,7 @@ void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh)
- std::vector<unsigned int> poResult;
- for (unsigned int c = 0; c < 3;++c)
- {
-- register unsigned int idx = (*i).mIndices[c];
-+ unsigned int idx = (*i).mIndices[c];
- if (vertexDone[idx])continue;
-
- sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup,
-diff --git a/src/3rdparty/assimp/code/SortByPTypeProcess.cpp b/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
-index 2b3c9d5..7165f44 100644
---- a/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
-+++ b/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
-@@ -289,7 +289,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
-
- for (unsigned int q = 0; q < in.mNumIndices; ++q)
- {
-- register unsigned int idx = in.mIndices[q];
-+ unsigned int idx = in.mIndices[q];
-
- // process all bones of this index
- if (avw)
-diff --git a/src/3rdparty/assimp/code/StringComparison.h b/src/3rdparty/assimp/code/StringComparison.h
-index 72dee86..d38fc86 100644
---- a/src/3rdparty/assimp/code/StringComparison.h
-+++ b/src/3rdparty/assimp/code/StringComparison.h
-@@ -137,7 +137,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
- return ::strcasecmp(s1,s2);
- #else
-
-- register char c1, c2;
-+ char c1, c2;
- do {
- c1 = tolower(*s1++);
- c2 = tolower(*s2++);
-@@ -156,7 +156,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
- */
- inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
- {
-- register int i = (int)b.length()-(int)a.length();
-+ int i = (int)b.length()-(int)a.length();
- return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
- }
-
-@@ -186,7 +186,7 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
- return ::strncasecmp(s1,s2, n);
-
- #else
-- register char c1, c2;
-+ char c1, c2;
- unsigned int p = 0;
- do
- {
-diff --git a/src/3rdparty/assimp/code/TerragenLoader.cpp b/src/3rdparty/assimp/code/TerragenLoader.cpp
-index 8c0ab1c..27775dd 100644
---- a/src/3rdparty/assimp/code/TerragenLoader.cpp
-+++ b/src/3rdparty/assimp/code/TerragenLoader.cpp
-@@ -225,7 +225,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
-
- // make verts
- const float fy = (float)yy, fx = (float)xx;
-- register unsigned tmp,tmp2;
-+ 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);
-diff --git a/src/3rdparty/assimp/contrib/unzip/crypt.h b/src/3rdparty/assimp/contrib/unzip/crypt.h
-index 622f4bc..1362cfc 100644
---- a/src/3rdparty/assimp/contrib/unzip/crypt.h
-+++ b/src/3rdparty/assimp/contrib/unzip/crypt.h
-@@ -51,7 +51,7 @@ static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int
- (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
- (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
- {
-- register int keyshift = (int)((*(pkeys+1)) >> 24);
-+ int keyshift = (int)((*(pkeys+1)) >> 24);
- (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
- }
- return c;
---
-2.4.9 (Apple Git-60)
-
diff --git a/src/3rdparty/patches/0004-assimp-Remove-register-keyword.patch b/src/3rdparty/patches/0004-assimp-Remove-register-keyword.patch
new file mode 100644
index 000000000..a50248d7b
--- /dev/null
+++ b/src/3rdparty/patches/0004-assimp-Remove-register-keyword.patch
@@ -0,0 +1,12 @@
+diff -ur assimpGIT/contrib/unzip/crypt.h assimp/contrib/unzip/crypt.h
+--- assimpGIT/contrib/unzip/crypt.h 2016-12-07 20:20:54.000000000 -0500
++++ assimp/contrib/unzip/crypt.h 2016-12-07 17:00:44.000000000 -0500
+@@ -51,7 +51,7 @@
+ (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+ (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+ {
+- register int keyshift = (int)((*(pkeys+1)) >> 24);
++ int keyshift = (int)((*(pkeys+1)) >> 24);
+ (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+ }
+ return c;
diff --git a/src/3rdparty/patches/0004-assimp-Use-std-namespace-for-most-cmath-functions.patch b/src/3rdparty/patches/0004-assimp-Use-std-namespace-for-most-cmath-functions.patch
deleted file mode 100644
index c50dac07e..000000000
--- a/src/3rdparty/patches/0004-assimp-Use-std-namespace-for-most-cmath-functions.patch
+++ /dev/null
@@ -1,1281 +0,0 @@
-From f58bcc1100afc3f5df5e7c6c2796f211ee1824cb Mon Sep 17 00:00:00 2001
-From: Andy Nichols <andy.nichols@theqtcompany.com>
-Date: Tue, 3 Nov 2015 13:09:13 +0100
-Subject: [PATCH] assimp: Use std namespace for most cmath functions
-
-This also fixes a couple of cases where the int version of abs was used
-when it should be the float version.
-
-Change-Id: Id5063545e5a6e659e95262177217be98766794b0
----
- src/3rdparty/assimp/code/BlenderTessellator.cpp | 4 +-
- src/3rdparty/assimp/code/ColladaLoader.cpp | 2 +-
- .../assimp/code/ComputeUVMappingProcess.cpp | 14 ++--
- src/3rdparty/assimp/code/FBXConverter.cpp | 10 +--
- .../assimp/code/FindInvalidDataProcess.cpp | 2 +-
- src/3rdparty/assimp/code/FixNormalsStep.cpp | 6 +-
- .../assimp/code/GenVertexNormalsProcess.cpp | 2 +-
- src/3rdparty/assimp/code/IFCBoolean.cpp | 10 +--
- src/3rdparty/assimp/code/IFCCurve.cpp | 30 ++++-----
- src/3rdparty/assimp/code/IFCGeometry.cpp | 14 ++--
- src/3rdparty/assimp/code/IFCOpenings.cpp | 78 +++++++++++-----------
- src/3rdparty/assimp/code/IFCProfile.cpp | 2 +-
- src/3rdparty/assimp/code/IFCUtil.cpp | 2 +-
- src/3rdparty/assimp/code/IFCUtil.h | 2 +-
- src/3rdparty/assimp/code/IRRLoader.cpp | 4 +-
- src/3rdparty/assimp/code/LWOAnimation.cpp | 2 +-
- src/3rdparty/assimp/code/LWOBLoader.cpp | 2 +-
- src/3rdparty/assimp/code/LWOLoader.cpp | 2 +-
- src/3rdparty/assimp/code/MD5Parser.h | 2 +-
- src/3rdparty/assimp/code/PolyTools.h | 12 ++--
- src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp | 2 +-
- src/3rdparty/assimp/code/StandardShapes.cpp | 20 +++---
- src/3rdparty/assimp/code/TextureTransform.h | 14 ++--
- src/3rdparty/assimp/code/TriangulateProcess.cpp | 4 +-
- src/3rdparty/assimp/code/XGLLoader.cpp | 2 +-
- src/3rdparty/assimp/code/fast_atof.h | 2 +-
- .../contrib/poly2tri/poly2tri/common/shapes.h | 2 +-
- src/3rdparty/assimp/include/assimp/color4.inl | 2 +-
- src/3rdparty/assimp/include/assimp/matrix3x3.inl | 6 +-
- src/3rdparty/assimp/include/assimp/matrix4x4.inl | 38 +++++------
- src/3rdparty/assimp/include/assimp/quaternion.inl | 36 +++++-----
- src/3rdparty/assimp/include/assimp/types.h | 2 +-
- src/3rdparty/assimp/include/assimp/vector2.inl | 2 +-
- src/3rdparty/assimp/include/assimp/vector3.inl | 2 +-
- 34 files changed, 168 insertions(+), 168 deletions(-)
-
-diff --git a/src/3rdparty/assimp/code/BlenderTessellator.cpp b/src/3rdparty/assimp/code/BlenderTessellator.cpp
-index ffe7949..98ccbad 100644
---- a/src/3rdparty/assimp/code/BlenderTessellator.cpp
-+++ b/src/3rdparty/assimp/code/BlenderTessellator.cpp
-@@ -324,7 +324,7 @@ void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCou
- aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
- {
- aiVector3D sideA( 1.0f, 0.0f, 0.0f );
-- if ( fabs( plane.normal * sideA ) > 0.999f )
-+ if ( std::fabs( plane.normal * sideA ) > 0.999f )
- {
- sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
- }
-@@ -420,7 +420,7 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
- {
- for ( int y = 0; y < 3; ++y )
- {
-- result = p2tMax( fabs( mtx[ x ][ y ] ), result );
-+ result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
- }
- }
-
-diff --git a/src/3rdparty/assimp/code/ColladaLoader.cpp b/src/3rdparty/assimp/code/ColladaLoader.cpp
-index 058baf9..2096e95 100644
---- a/src/3rdparty/assimp/code/ColladaLoader.cpp
-+++ b/src/3rdparty/assimp/code/ColladaLoader.cpp
-@@ -341,7 +341,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
- {
- // 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 (acos(pow(0.1f,1.f/srcLight->mFalloffExponent))+
-+ out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
- srcLight->mFalloffAngle);
- }
- else {
-diff --git a/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp b/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
-index 091f6a0..c25a17c 100644
---- a/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
-+++ b/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
-@@ -197,9 +197,9 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
- // 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)
-+ // 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)
-@@ -207,7 +207,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
- 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,
-- (asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
-+ (std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
- }
- }
- else if (axis * base_axis_y >= angle_epsilon) {
-@@ -215,7 +215,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
- 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,
-- (asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
-+ (std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
- }
- }
- else if (axis * base_axis_z >= angle_epsilon) {
-@@ -223,7 +223,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
- 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,
-- (asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.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
-@@ -235,7 +235,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
- 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);
-+ (std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
- }
- }
-
-diff --git a/src/3rdparty/assimp/code/FBXConverter.cpp b/src/3rdparty/assimp/code/FBXConverter.cpp
-index 89854fc..56643bc 100644
---- a/src/3rdparty/assimp/code/FBXConverter.cpp
-+++ b/src/3rdparty/assimp/code/FBXConverter.cpp
-@@ -499,15 +499,15 @@ private:
- bool is_id[3] = { true, true, true };
-
- aiMatrix4x4 temp[3];
-- if(fabs(rotation.z) > angle_epsilon) {
-+ if(std::fabs(rotation.z) > angle_epsilon) {
- aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z),temp[2]);
- is_id[2] = false;
- }
-- if(fabs(rotation.y) > angle_epsilon) {
-+ if(std::fabs(rotation.y) > angle_epsilon) {
- aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y),temp[1]);
- is_id[1] = false;
- }
-- if(fabs(rotation.x) > angle_epsilon) {
-+ if(std::fabs(rotation.x) > angle_epsilon) {
- aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x),temp[0]);
- is_id[0] = false;
- }
-@@ -676,7 +676,7 @@ private:
- }
-
- const aiVector3D& Scaling = PropertyGet<aiVector3D>(props,"Lcl Scaling",ok);
-- if(ok && fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) {
-+ if(ok && std::fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) {
- aiMatrix4x4::Scaling(Scaling,chain[TransformationComp_Scaling]);
- }
-
-@@ -686,7 +686,7 @@ private:
- }
-
- const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
-- if (ok && fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) {
-+ if (ok && std::fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) {
- aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
- }
-
-diff --git a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
-index 618e7d3..ba47810 100644
---- a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
-+++ b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
-@@ -221,7 +221,7 @@ 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 fabs(n-s)>epsilon;
-+ return std::fabs(n-s)>epsilon;
- }
-
- // ------------------------------------------------------------------------------------------------
-diff --git a/src/3rdparty/assimp/code/FixNormalsStep.cpp b/src/3rdparty/assimp/code/FixNormalsStep.cpp
-index f95dfbc..9b85222 100644
---- a/src/3rdparty/assimp/code/FixNormalsStep.cpp
-+++ b/src/3rdparty/assimp/code/FixNormalsStep.cpp
-@@ -144,9 +144,9 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
- // 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;
-+ 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) <
-diff --git a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
-index 643dc8f..231b655 100644
---- a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
-+++ b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
-@@ -204,7 +204,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
- // 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 = ::cos(configMaxAngle);
-+ 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);
-diff --git a/src/3rdparty/assimp/code/IFCBoolean.cpp b/src/3rdparty/assimp/code/IFCBoolean.cpp
-index 8573e4d..3581d2a 100644
---- a/src/3rdparty/assimp/code/IFCBoolean.cpp
-+++ b/src/3rdparty/assimp/code/IFCBoolean.cpp
-@@ -69,8 +69,8 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
- const IfcVector3 pdelta = e0 - p, seg = e1-e0;
- const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
-
-- if (fabs(dotOne) < 1e-6) {
-- return fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
-+ if (std::fabs(dotOne) < 1e-6) {
-+ return std::fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
- }
-
- const IfcFloat t = dotTwo/dotOne;
-@@ -210,7 +210,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
- // 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(fabs(det) < 1e-6) {
-+ if(std::fabs(det) < 1e-6) {
- // no solutions (parallel lines)
- continue;
- }
-@@ -234,7 +234,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
- if (t >= -epsilon && (t <= 1.0+epsilon || half_open) && s >= -epsilon && s <= 1.0) {
-
- if (e0_hits_border && !*e0_hits_border) {
-- *e0_hits_border = fabs(t) < 1e-5f;
-+ *e0_hits_border = std::fabs(t) < 1e-5f;
- }
-
- const IfcVector3& p = e0 + e*t;
-@@ -419,7 +419,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
-
- #ifdef ASSIMP_BUILD_DEBUG
- if (isect == Intersect_Yes) {
-- const IfcFloat f = fabs((isectpos - p)*n);
-+ const IfcFloat f = std::fabs((isectpos - p)*n);
- ai_assert(f < 1e-5);
- }
- #endif
-diff --git a/src/3rdparty/assimp/code/IFCCurve.cpp b/src/3rdparty/assimp/code/IFCCurve.cpp
-index 4919b52..1079c1e 100644
---- a/src/3rdparty/assimp/code/IFCCurve.cpp
-+++ b/src/3rdparty/assimp/code/IFCCurve.cpp
-@@ -88,10 +88,10 @@ public:
- a *= conv.angle_scale;
- b *= conv.angle_scale;
-
-- a = fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
-- b = fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
-+ 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 );
-- return static_cast<size_t>( ceil(abs( b-a)) / setting);
-+ return static_cast<size_t>( std::ceil(std::abs( b-a)) / setting);
- }
-
- // --------------------------------------------------
-@@ -124,8 +124,8 @@ public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat u) const {
- u = -conv.angle_scale * u;
-- return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(::cos(u))*p[0] +
-- static_cast<IfcFloat>(::sin(u))*p[1]);
-+ return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
-+ static_cast<IfcFloat>(std::sin(u))*p[1]);
- }
-
- private:
-@@ -153,8 +153,8 @@ public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat u) const {
- u = -conv.angle_scale * u;
-- return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(::cos(u))*p[0] +
-- static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(::sin(u))*p[1];
-+ 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:
-@@ -276,7 +276,7 @@ public:
- IfcFloat acc = 0;
- BOOST_FOREACH(const CurveEntry& entry, curves) {
- const ParamRange& range = entry.first->GetParametricRange();
-- const IfcFloat delta = abs(range.second-range.first);
-+ 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));
- }
-@@ -295,7 +295,7 @@ public:
- IfcFloat acc = 0;
- BOOST_FOREACH(const CurveEntry& entry, curves) {
- const ParamRange& range = entry.first->GetParametricRange();
-- const IfcFloat delta = abs(range.second-range.first);
-+ 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 );
-@@ -486,7 +486,7 @@ public:
- IfcVector3 Eval(IfcFloat p) const {
- ai_assert(InRange(p));
-
-- const size_t b = static_cast<size_t>(floor(p));
-+ const size_t b = static_cast<size_t>(std::floor(p));
- if (b == points.size()-1) {
- return points.back();
- }
-@@ -498,7 +498,7 @@ public:
- // --------------------------------------------------
- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
-- return static_cast<size_t>( ceil(b) - floor(a) );
-+ return static_cast<size_t>( std::ceil(b) - std::floor(a) );
- }
-
- // --------------------------------------------------
-@@ -558,7 +558,7 @@ bool Curve :: InRange(IfcFloat u) const
- if (IsClosed()) {
- return true;
- //ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
-- //u = range.first + fmod(u-range.first,range.second-range.first);
-+ //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;
-@@ -569,7 +569,7 @@ bool Curve :: InRange(IfcFloat u) const
- IfcFloat Curve :: GetParametricRangeDelta() const
- {
- const ParamRange& range = GetParametricRange();
-- return abs(range.second - range.first);
-+ return std::abs(range.second - range.first);
- }
-
- // ------------------------------------------------------------------------------------------------
-@@ -606,12 +606,12 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
- }
-
- ai_assert(min_diff[0] != inf && min_diff[1] != inf);
-- if ( fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
-+ if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
- return min_point[0];
- }
-
- // fix for closed curves to take their wrap-over into account
-- if (cv->IsClosed() && fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) {
-+ 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();
-
-diff --git a/src/3rdparty/assimp/code/IFCGeometry.cpp b/src/3rdparty/assimp/code/IFCGeometry.cpp
-index a3c6711..96ccf29 100644
---- a/src/3rdparty/assimp/code/IFCGeometry.cpp
-+++ b/src/3rdparty/assimp/code/IFCGeometry.cpp
-@@ -250,17 +250,17 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
-
- bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
- const IfcFloat max_angle = solid.Angle*conv.angle_scale;
-- if(fabs(max_angle) < 1e-3) {
-+ 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 * fabs(max_angle)/AI_MATH_HALF_PI_F));
-+ 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 && fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
-+ 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);
-@@ -375,21 +375,21 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
- bool take_any = false;
-
- for (unsigned int i = 0; i < 2; ++i, take_any = true) {
-- if ((last_dir == 0 || take_any) && abs(d.x) > 1e-6) {
-+ 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;
- }
-- else if ((last_dir == 1 || take_any) && abs(d.y) > 1e-6) {
-+ 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;
- }
-- else if ((last_dir == 2 && abs(d.z) > 1e-6) || take_any) {
-+ 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;
-@@ -480,7 +480,7 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
- 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(fabs(nor.Length()) > 1e-8f) {
-+ if(std::fabs(nor.Length()) > 1e-8f) {
- done = true;
- break;
- }
-diff --git a/src/3rdparty/assimp/code/IFCOpenings.cpp b/src/3rdparty/assimp/code/IFCOpenings.cpp
-index c26574c..850403d 100644
---- a/src/3rdparty/assimp/code/IFCOpenings.cpp
-+++ b/src/3rdparty/assimp/code/IFCOpenings.cpp
-@@ -303,20 +303,20 @@ void InsertWindowContours(const ContourVector& contours,
- const IfcVector2& v = contour[n];
-
- bool hit = false;
-- if (fabs(v.x-bb.first.x)<epsilon) {
-+ if (std::fabs(v.x-bb.first.x)<epsilon) {
- edge.x = bb.first.x;
- hit = true;
- }
-- else if (fabs(v.x-bb.second.x)<epsilon) {
-+ else if (std::fabs(v.x-bb.second.x)<epsilon) {
- edge.x = bb.second.x;
- hit = true;
- }
-
-- if (fabs(v.y-bb.first.y)<epsilon) {
-+ if (std::fabs(v.y-bb.first.y)<epsilon) {
- edge.y = bb.first.y;
- hit = true;
- }
-- else if (fabs(v.y-bb.second.y)<epsilon) {
-+ else if (std::fabs(v.y-bb.second.y)<epsilon) {
- edge.y = bb.second.y;
- hit = true;
- }
-@@ -343,17 +343,17 @@ void InsertWindowContours(const ContourVector& contours,
-
- IfcVector2 corner = edge;
-
-- if (fabs(contour[last_hit].x-bb.first.x)<epsilon) {
-+ if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) {
- corner.x = bb.first.x;
- }
-- else if (fabs(contour[last_hit].x-bb.second.x)<epsilon) {
-+ else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
- corner.x = bb.second.x;
- }
-
-- if (fabs(contour[last_hit].y-bb.first.y)<epsilon) {
-+ if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) {
- corner.y = bb.first.y;
- }
-- else if (fabs(contour[last_hit].y-bb.second.y)<epsilon) {
-+ else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
- corner.y = bb.second.y;
- }
-
-@@ -590,10 +590,10 @@ 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 (fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
-- (fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
-- (fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
-- (fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
-+ 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);
- }
-
- // ------------------------------------------------------------------------------------------------
-@@ -615,11 +615,11 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
-
- static const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
-
-- if (!(n0_to_m0.SquareLength() < e*e || fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
-+ 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 || fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
-+ 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;
- }
-
-@@ -631,14 +631,14 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
- // the higher absolute difference is big enough as to avoid
- // divisions by zero, the case 0/0 ~ infinity is detected and
- // handled separately.
-- if(fabs(n0_to_n1.x) > fabs(n0_to_n1.y)) {
-+ 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 (fabs(s0) == inf && fabs(n0_to_m0.x) < smalle) {
-+ if (std::fabs(s0) == inf && std::fabs(n0_to_m0.x) < smalle) {
- s0 = 0.;
- }
-- if (fabs(s1) == inf && fabs(n0_to_m1.x) < smalle) {
-+ if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
- s1 = 0.;
- }
- }
-@@ -646,10 +646,10 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
- s0 = n0_to_m0.y / n0_to_n1.y;
- s1 = n0_to_m1.y / n0_to_n1.y;
-
-- if (fabs(s0) == inf && fabs(n0_to_m0.y) < smalle) {
-+ if (std::fabs(s0) == inf && std::fabs(n0_to_m0.y) < smalle) {
- s0 = 0.;
- }
-- if (fabs(s1) == inf && fabs(n0_to_m1.y) < smalle) {
-+ if (std::fabs(s1) == inf && std::fabs(n0_to_m1.y) < smalle) {
- s1 = 0.;
- }
- }
-@@ -664,7 +664,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
- s0 = std::min(1.0,s0);
- s1 = std::min(1.0,s1);
-
-- if (fabs(s1-s0) < e) {
-+ if (std::fabs(s1-s0) < e) {
- return false;
- }
-
-@@ -755,7 +755,7 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
- AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
- {
- const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5);
-- return fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
-+ return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
- }
-
- // ------------------------------------------------------------------------------------------------
-@@ -812,9 +812,9 @@ void FindBorderContours(ContourVector::iterator current)
- // ------------------------------------------------------------------------------------------------
- AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta)
- {
-- vdelta.x = fabs(vdelta.x);
-- vdelta.y = fabs(vdelta.y);
-- return (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));
- }
-
- // ------------------------------------------------------------------------------------------------
-@@ -926,7 +926,7 @@ size_t CloseWindows(ContourVector& contours,
- /* debug code to check for unwanted diagonal lines in window contours
- if (cit != cbegin) {
- const IfcVector2& vdelta = proj_point - last_proj;
-- if (fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
-+ if (std::fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
- //continue;
- }
- } */
-@@ -1065,7 +1065,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
- }
- #ifdef ASSIMP_BUILD_DEBUG
- const IfcFloat det = m.Determinant();
-- ai_assert(fabs(det-1) < 1e-5);
-+ ai_assert(std::fabs(det-1) < 1e-5);
- #endif
-
- IfcFloat zcoord = 0;
-@@ -1085,7 +1085,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
- // XXX this should be guarded, but we somehow need to pick a suitable
- // epsilon
- // if(coord != -1.0f) {
-- // assert(fabs(coord - vv.z) < 1e-3f);
-+ // assert(std::fabs(coord - vv.z) < 1e-3f);
- // }
- zcoord += vv.z;
- vmin = std::min(vv, vmin);
-@@ -1125,7 +1125,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
- const IfcVector3& vv = m * x;
-
- out_contour2.push_back(IfcVector2(vv.x,vv.y));
-- ai_assert(fabs(vv.z) < vmax.z + 1e-8);
-+ ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
- }
-
- for(size_t i = 0; i < out_contour.size(); ++i) {
-@@ -1188,9 +1188,9 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
- bool is_2d_source = false;
- if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) {
-
-- if(fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
-+ if(std::fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
- // horizontal extrusion
-- if (fabs(norm_extrusion_dir * nor) > 0.9) {
-+ if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
- profile_data = opening.profileMesh2D.get();
- is_2d_source = true;
- }
-@@ -1200,7 +1200,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
- }
- else {
- // vertical extrusion
-- if (fabs(norm_extrusion_dir * nor) > 0.9) {
-+ if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
- continue;
- }
- continue;
-@@ -1244,7 +1244,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
- 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 = abs(nor * face_nor);
-+ const IfcFloat abs_dot_face_nor = std::abs(nor * face_nor);
- if (abs_dot_face_nor < 0.9) {
- vi_total += profile_vertcnts[f];
- continue;
-@@ -1289,7 +1289,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
- ai_assert(!is_2d_source);
- const IfcVector2 area = vpmax-vpmin;
- const IfcVector2 area2 = vpmax2-vpmin2;
-- if (temp_contour.size() <= 2 || fabs(area2.x * area2.y) > fabs(area.x * area.y)) {
-+ if (temp_contour.size() <= 2 || std::fabs(area2.x * area2.y) > std::fabs(area.x * area.y)) {
- temp_contour.swap(temp_contour2);
-
- vpmax = vpmax2;
-@@ -1301,7 +1301,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
- }
-
- // TODO: This epsilon may be too large
-- const IfcFloat epsilon = fabs(dmax-dmin) * 0.0001;
-+ const IfcFloat epsilon = std::fabs(dmax-dmin) * 0.0001;
- if (!is_2d_source && check_intersection && (0 < dmin-epsilon || 0 > dmax+epsilon)) {
- continue;
- }
-@@ -1310,7 +1310,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
-
- // Skip over very small openings - these are likely projection errors
- // (i.e. they don't belong to this side of the wall)
-- if(fabs(vpmax.x - vpmin.x) * fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) {
-+ 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);
-@@ -1480,7 +1480,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
- // XXX this should be guarded, but we somehow need to pick a suitable
- // epsilon
- // if(coord != -1.0f) {
-- // assert(fabs(coord - vv.z) < 1e-3f);
-+ // assert(std::fabs(coord - vv.z) < 1e-3f);
- // }
-
- coord = vv.z;
-@@ -1515,7 +1515,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
- BOOST_FOREACH(const TempOpening& t,openings) {
- const IfcVector3& outernor = nors[c++];
- const IfcFloat dot = nor * outernor;
-- if (fabs(dot)<1.f-1e-6f) {
-+ if (std::fabs(dot)<1.f-1e-6f) {
- continue;
- }
-
-@@ -1529,7 +1529,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
- BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) {
- IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir);
-
-- const bool is_extruded_side = fabs(vv.z - coord) > fabs(vv_extr.z - coord);
-+ const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord);
- if (first) {
- first = false;
- if (dot > 0.f) {
-@@ -1741,4 +1741,4 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
- #undef from_int64
- #undef one_vec
-
--#endif
-\ No newline at end of file
-+#endif
-diff --git a/src/3rdparty/assimp/code/IFCProfile.cpp b/src/3rdparty/assimp/code/IFCProfile.cpp
-index 48ccd56..78f0381 100644
---- a/src/3rdparty/assimp/code/IFCProfile.cpp
-+++ b/src/3rdparty/assimp/code/IFCProfile.cpp
-@@ -124,7 +124,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
-
- IfcFloat angle = 0.f;
- for(size_t i = 0; i < segments; ++i, angle += delta) {
-- meshout.verts.push_back( IfcVector3( cos(angle)*radius, sin(angle)*radius, 0.f ));
-+ meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
- }
-
- meshout.vertcnt.push_back(segments);
-diff --git a/src/3rdparty/assimp/code/IFCUtil.cpp b/src/3rdparty/assimp/code/IFCUtil.cpp
-index 92e55c9..d28f91a 100644
---- a/src/3rdparty/assimp/code/IFCUtil.cpp
-+++ b/src/3rdparty/assimp/code/IFCUtil.cpp
-@@ -278,7 +278,7 @@ void TempMesh::RemoveAdjacentDuplicates()
- // continue;
- // }
-
-- // const IfcFloat d = (d0/sqrt(l0))*(d1/sqrt(l1));
-+ // const IfcFloat d = (d0/std::sqrt(l0))*(d1/std::sqrt(l1));
-
- // if ( d >= 1.f-dotepsilon ) {
- // v1 = v0;
-diff --git a/src/3rdparty/assimp/code/IFCUtil.h b/src/3rdparty/assimp/code/IFCUtil.h
-index e78d779..81b8f11 100644
---- a/src/3rdparty/assimp/code/IFCUtil.h
-+++ b/src/3rdparty/assimp/code/IFCUtil.h
-@@ -220,7 +220,7 @@ struct FuzzyVectorCompare {
-
- FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
- bool operator()(const IfcVector3& a, const IfcVector3& b) {
-- return fabs((a-b).SquareLength()) < epsilon;
-+ return std::fabs((a-b).SquareLength()) < epsilon;
- }
-
- const IfcFloat epsilon;
-diff --git a/src/3rdparty/assimp/code/IRRLoader.cpp b/src/3rdparty/assimp/code/IRRLoader.cpp
-index 4e1296d..03393f4 100644
---- a/src/3rdparty/assimp/code/IRRLoader.cpp
-+++ b/src/3rdparty/assimp/code/IRRLoader.cpp
-@@ -533,8 +533,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
- aiVectorKey& key = anim->mPositionKeys[i];
-
- const float dt = (i * in.speed * 0.001f );
-- const float u = dt - floor(dt);
-- const int idx = (int)floor(dt) % size;
-+ 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;
-diff --git a/src/3rdparty/assimp/code/LWOAnimation.cpp b/src/3rdparty/assimp/code/LWOAnimation.cpp
-index e1ef576..68efa17 100644
---- a/src/3rdparty/assimp/code/LWOAnimation.cpp
-+++ b/src/3rdparty/assimp/code/LWOAnimation.cpp
-@@ -156,7 +156,7 @@ void AnimResolver::UpdateAnimRangeSetup()
- case LWO::PrePostBehaviour_Repeat:
- case LWO::PrePostBehaviour_Oscillate:
- {
-- const double start_time = delta - fmod(my_first-first,delta);
-+ 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;
-
-diff --git a/src/3rdparty/assimp/code/LWOBLoader.cpp b/src/3rdparty/assimp/code/LWOBLoader.cpp
-index 5d874c5..9776b89 100644
---- a/src/3rdparty/assimp/code/LWOBLoader.cpp
-+++ b/src/3rdparty/assimp/code/LWOBLoader.cpp
-@@ -303,7 +303,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
- case AI_LWO_SMAN:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
-- surf.mMaximumSmoothAngle = fabs( GetF4() );
-+ surf.mMaximumSmoothAngle = std::fabs( GetF4() );
- break;
- }
- // glossiness
-diff --git a/src/3rdparty/assimp/code/LWOLoader.cpp b/src/3rdparty/assimp/code/LWOLoader.cpp
-index e0891b7..b23a9fe 100644
---- a/src/3rdparty/assimp/code/LWOLoader.cpp
-+++ b/src/3rdparty/assimp/code/LWOLoader.cpp
-@@ -503,7 +503,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
- // 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 = cos(surface.mMaximumSmoothAngle);
-+ const float fLimit = std::cos(surface.mMaximumSmoothAngle);
-
- for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
- const aiFace& face = *begin;
-diff --git a/src/3rdparty/assimp/code/MD5Parser.h b/src/3rdparty/assimp/code/MD5Parser.h
-index eecf354..4fd147d 100644
---- a/src/3rdparty/assimp/code/MD5Parser.h
-+++ b/src/3rdparty/assimp/code/MD5Parser.h
-@@ -259,7 +259,7 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
-
- if (t < 0.0f)
- out.w = 0.0f;
-- else out.w = sqrt (t);
-+ else out.w = std::sqrt (t);
- }
-
- // ---------------------------------------------------------------------------
-diff --git a/src/3rdparty/assimp/code/PolyTools.h b/src/3rdparty/assimp/code/PolyTools.h
-index d8040f6..7975959 100644
---- a/src/3rdparty/assimp/code/PolyTools.h
-+++ b/src/3rdparty/assimp/code/PolyTools.h
-@@ -118,9 +118,9 @@ inline bool IsCCW(T* in, size_t npoints) {
- ((-in[i+2].y + in[i+1].y) *
- (-in[i+2].y + in[i+1].y));
-
-- b = sqrt(bb);
-- c = sqrt(cc);
-- theta = acos((bb + cc - aa) / (2 * b * c));
-+ 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,
-@@ -146,9 +146,9 @@ inline bool IsCCW(T* in, size_t npoints) {
- 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 = sqrt(bb);
-- c = sqrt(cc);
-- theta = acos((bb + cc - aa) / (2 * b * c));
-+ 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,
-diff --git a/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp b/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
-index 242c596..7e0d68a 100644
---- a/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
-+++ b/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
-@@ -101,7 +101,7 @@ void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
- aiVector3D up = aiVector3D( childpos).Normalize();
-
- aiVector3D orth( 1.0f, 0.0f, 0.0f);
-- if( fabs( orth * up) > 0.99f)
-+ if( std::fabs( orth * up) > 0.99f)
- orth.Set( 0.0f, 1.0f, 0.0f);
-
- aiVector3D front = (up ^ orth).Normalize();
-diff --git a/src/3rdparty/assimp/code/StandardShapes.cpp b/src/3rdparty/assimp/code/StandardShapes.cpp
-index ef3f66c..5924a20 100644
---- a/src/3rdparty/assimp/code/StandardShapes.cpp
-+++ b/src/3rdparty/assimp/code/StandardShapes.cpp
-@@ -192,7 +192,7 @@ unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
- positions.reserve(positions.size()+60);
-
- const float t = (1.f + 2.236067977f)/2.f;
-- const float s = sqrt(1.f + t*t);
-+ 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;
-@@ -242,8 +242,8 @@ unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions
- positions.reserve(positions.size()+108);
-
- const float a = 1.f / 1.7320508f;
-- const float b = sqrt((3.f-2.23606797f)/6.f);
-- const float c = sqrt((3.f+2.23606797f)/6.f);
-+ 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);
-@@ -390,8 +390,8 @@ void StandardShapes::MakeCone(float height,float radius1,
- size_t old = positions.size();
-
- // No negative radii
-- radius1 = ::fabs(radius1);
-- radius2 = ::fabs(radius2);
-+ radius1 = std::fabs(radius1);
-+ radius2 = std::fabs(radius2);
-
- float halfHeight = height / 2;
-
-@@ -424,8 +424,8 @@ void StandardShapes::MakeCone(float height,float radius1,
- const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
-
- const float next = angle + angle_delta;
-- float s2 = ::cos(next);
-- float t2 = ::sin(next);
-+ 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 );
-@@ -476,7 +476,7 @@ void StandardShapes::MakeCircle(float radius, unsigned int tess,
- if (tess < 3 || !radius)
- return;
-
-- radius = ::fabs(radius);
-+ radius = std::fabs(radius);
-
- // We will need 3 vertices per segment
- positions.reserve(positions.size()+tess*3);
-@@ -491,8 +491,8 @@ void StandardShapes::MakeCircle(float radius, unsigned int tess,
- {
- positions.push_back(aiVector3D(s * radius,0.f,t * radius));
- angle += angle_delta;
-- s = ::cos(angle);
-- t = ::sin(angle);
-+ s = std::cos(angle);
-+ t = std::sin(angle);
- positions.push_back(aiVector3D(s * radius,0.f,t * radius));
-
- positions.push_back(aiVector3D(0.f,0.f,0.f));
-diff --git a/src/3rdparty/assimp/code/TextureTransform.h b/src/3rdparty/assimp/code/TextureTransform.h
-index 4826527..1f8580f 100644
---- a/src/3rdparty/assimp/code/TextureTransform.h
-+++ b/src/3rdparty/assimp/code/TextureTransform.h
-@@ -116,19 +116,19 @@ struct STransformVecInfo : public aiUVTransform
- // We use a small epsilon here
- const static float epsilon = 0.05f;
-
-- if (fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
-- fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
-+ if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
-+ std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
- {
- return false;
- }
-
-- if (fabs( mScaling.x - other.mScaling.x ) > epsilon ||
-- fabs( mScaling.y - other.mScaling.y ) > epsilon)
-+ if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
-+ std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
- {
- return false;
- }
-
-- if (fabs( mRotation - other.mRotation) > epsilon)
-+ if (std::fabs( mRotation - other.mRotation) > epsilon)
- {
- return false;
- }
-@@ -168,8 +168,8 @@ struct STransformVecInfo : public aiUVTransform
- if (mRotation)
- {
- aiMatrix3x3 mRot;
-- mRot.a1 = mRot.b2 = cos(mRotation);
-- mRot.a2 = mRot.b1 = sin(mRotation);
-+ mRot.a1 = mRot.b2 = std::cos(mRotation);
-+ mRot.a2 = mRot.b1 = std::sin(mRotation);
- mRot.a2 = -mRot.a2;
- mOut *= mRot;
- }
-diff --git a/src/3rdparty/assimp/code/TriangulateProcess.cpp b/src/3rdparty/assimp/code/TriangulateProcess.cpp
-index 1e3b96c..147e38e 100644
---- a/src/3rdparty/assimp/code/TriangulateProcess.cpp
-+++ b/src/3rdparty/assimp/code/TriangulateProcess.cpp
-@@ -241,7 +241,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
- diag.Normalize();
- right.Normalize();
-
-- const float angle = acos(left*diag) + acos(right*diag);
-+ 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;
-@@ -486,7 +486,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
- unsigned int* i = f->mIndices;
-
- // drop dumb 0-area triangles
-- if (fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
-+ 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;
-
-diff --git a/src/3rdparty/assimp/code/XGLLoader.cpp b/src/3rdparty/assimp/code/XGLLoader.cpp
-index 49ff686..963407b 100644
---- a/src/3rdparty/assimp/code/XGLLoader.cpp
-+++ b/src/3rdparty/assimp/code/XGLLoader.cpp
-@@ -489,7 +489,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
- up.Normalize();
-
- right = forward ^ up;
-- if (fabs(up * forward) > 1e-4) {
-+ 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");
-diff --git a/src/3rdparty/assimp/code/fast_atof.h b/src/3rdparty/assimp/code/fast_atof.h
-index 580447b..3cdb1e8 100644
---- a/src/3rdparty/assimp/code/fast_atof.h
-+++ b/src/3rdparty/assimp/code/fast_atof.h
-@@ -273,7 +273,7 @@ inline const char* fast_atoreal_move( const char* c, Real& out, bool check_comma
- if (einv) {
- exp = -exp;
- }
-- f *= pow(static_cast<Real>(10.0), exp);
-+ f *= std::pow(static_cast<Real>(10.0), exp);
- }
-
- if (inv) {
-diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
-index 4f69183..f3b3c65 100644
---- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
-+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
-@@ -107,7 +107,7 @@ struct Point {
- /// Get the length of this point (the norm).
- double Length() const
- {
-- return sqrt(x * x + y * y);
-+ return std::sqrt(x * x + y * y);
- }
-
- /// Convert this point into a unit point. Returns the Length.
-diff --git a/src/3rdparty/assimp/include/assimp/color4.inl b/src/3rdparty/assimp/include/assimp/color4.inl
-index 9a92e14..b0791fa 100644
---- a/src/3rdparty/assimp/include/assimp/color4.inl
-+++ b/src/3rdparty/assimp/include/assimp/color4.inl
-@@ -175,7 +175,7 @@ template <typename TReal>
- inline bool aiColor4t<TReal> :: IsBlack() const {
- // The alpha component doesn't care here. black is black.
- static const TReal epsilon = 10e-3f;
-- return fabs( r ) < epsilon && fabs( g ) < epsilon && fabs( b ) < epsilon;
-+ return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
- }
-
- #endif // __cplusplus
-diff --git a/src/3rdparty/assimp/include/assimp/matrix3x3.inl b/src/3rdparty/assimp/include/assimp/matrix3x3.inl
-index 56cac6c..dcced7b 100644
---- a/src/3rdparty/assimp/include/assimp/matrix3x3.inl
-+++ b/src/3rdparty/assimp/include/assimp/matrix3x3.inl
-@@ -200,8 +200,8 @@ inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Inverse()
- template <typename TReal>
- inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::RotationZ(TReal a, aiMatrix3x3t<TReal>& out)
- {
-- out.a1 = out.b2 = ::cos(a);
-- out.b1 = ::sin(a);
-+ out.a1 = out.b2 = std::cos(a);
-+ out.b1 = std::sin(a);
- out.a2 = - out.b1;
-
- out.a3 = out.b3 = out.c1 = out.c2 = 0.f;
-@@ -215,7 +215,7 @@ inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::RotationZ(TReal a, aiMatrix3x3t
- template <typename TReal>
- inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix3x3t<TReal>& out)
- {
-- TReal c = cos( a), s = sin( a), t = 1 - c;
-+ TReal c = std::cos( a), s = std::sin( a), t = 1 - c;
- TReal x = axis.x, y = axis.y, z = axis.z;
-
- // Many thanks to MathWorld and Wikipedia
-diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.inl b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
-index 4fb86b1..8fdabcf 100644
---- a/src/3rdparty/assimp/include/assimp/matrix4x4.inl
-+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
-@@ -379,12 +379,12 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(TReal x, TRe
- {
- aiMatrix4x4t<TReal>& _this = *this;
-
-- TReal cr = cos( x );
-- TReal sr = sin( x );
-- TReal cp = cos( y );
-- TReal sp = sin( y );
-- TReal cy = cos( z );
-- TReal sy = sin( z );
-+ TReal cr = std::cos( x );
-+ TReal sr = std::sin( x );
-+ TReal cp = std::cos( y );
-+ TReal sp = std::sin( y );
-+ TReal cy = std::cos( z );
-+ TReal sy = std::sin( z );
-
- _this.a1 = cp*cy ;
- _this.a2 = cp*sy;
-@@ -435,12 +435,12 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationX(TReal a, aiMatrix4x4t
- {
- /*
- | 1 0 0 0 |
-- M = | 0 cos(A) -sin(A) 0 |
-- | 0 sin(A) cos(A) 0 |
-+ M = | 0 std::cos(A) -std::sin(A) 0 |
-+ | 0 std::sin(A) std::cos(A) 0 |
- | 0 0 0 1 | */
- out = aiMatrix4x4t<TReal>();
-- out.b2 = out.c3 = cos(a);
-- out.b3 = -(out.c2 = sin(a));
-+ out.b2 = out.c3 = std::cos(a);
-+ out.b3 = -(out.c2 = std::sin(a));
- return out;
- }
-
-@@ -449,14 +449,14 @@ template <typename TReal>
- inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationY(TReal a, aiMatrix4x4t<TReal>& out)
- {
- /*
-- | cos(A) 0 sin(A) 0 |
-+ | std::cos(A) 0 std::sin(A) 0 |
- M = | 0 1 0 0 |
-- | -sin(A) 0 cos(A) 0 |
-+ | -std::sin(A) 0 std::cos(A) 0 |
- | 0 0 0 1 |
- */
- out = aiMatrix4x4t<TReal>();
-- out.a1 = out.c3 = cos(a);
-- out.c1 = -(out.a3 = sin(a));
-+ out.a1 = out.c3 = std::cos(a);
-+ out.c1 = -(out.a3 = std::sin(a));
- return out;
- }
-
-@@ -465,13 +465,13 @@ template <typename TReal>
- inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationZ(TReal a, aiMatrix4x4t<TReal>& out)
- {
- /*
-- | cos(A) -sin(A) 0 0 |
-- M = | sin(A) cos(A) 0 0 |
-+ | std::cos(A) -std::sin(A) 0 0 |
-+ M = | std::sin(A) std::cos(A) 0 0 |
- | 0 0 1 0 |
- | 0 0 0 1 | */
- out = aiMatrix4x4t<TReal>();
-- out.a1 = out.b2 = cos(a);
-- out.a2 = -(out.b1 = sin(a));
-+ out.a1 = out.b2 = std::cos(a);
-+ out.a2 = -(out.b1 = std::sin(a));
- return out;
- }
-
-@@ -480,7 +480,7 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationZ(TReal a, aiMatrix4x4t
- template <typename TReal>
- inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix4x4t<TReal>& out)
- {
-- TReal c = cos( a), s = sin( a), t = 1 - c;
-+ TReal c = std::cos( a), s = std::sin( a), t = 1 - c;
- TReal x = axis.x, y = axis.y, z = axis.z;
-
- // Many thanks to MathWorld and Wikipedia
-diff --git a/src/3rdparty/assimp/include/assimp/quaternion.inl b/src/3rdparty/assimp/include/assimp/quaternion.inl
-index 0230d21..b966433 100644
---- a/src/3rdparty/assimp/include/assimp/quaternion.inl
-+++ b/src/3rdparty/assimp/include/assimp/quaternion.inl
-@@ -84,7 +84,7 @@ inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatri
- // large enough
- if( t > static_cast<TReal>(0))
- {
-- TReal s = sqrt(1 + t) * static_cast<TReal>(2.0);
-+ TReal s = std::sqrt(1 + t) * static_cast<TReal>(2.0);
- x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
- y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
- z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
-@@ -93,7 +93,7 @@ inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatri
- else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )
- {
- // Column 0:
-- TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
-+ TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
- x = static_cast<TReal>(0.25) * s;
- y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
- z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
-@@ -102,7 +102,7 @@ inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatri
- else if( pRotMatrix.b2 > pRotMatrix.c3)
- {
- // Column 1:
-- TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
-+ TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
- x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
- y = static_cast<TReal>(0.25) * s;
- z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
-@@ -110,7 +110,7 @@ inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatri
- } else
- {
- // Column 2:
-- TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
-+ TReal s = std::sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
- x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
- y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
- z = static_cast<TReal>(0.25) * s;
-@@ -123,12 +123,12 @@ inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatri
- template<typename TReal>
- inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRoll )
- {
-- const TReal fSinPitch(sin(fPitch*static_cast<TReal>(0.5)));
-- const TReal fCosPitch(cos(fPitch*static_cast<TReal>(0.5)));
-- const TReal fSinYaw(sin(fYaw*static_cast<TReal>(0.5)));
-- const TReal fCosYaw(cos(fYaw*static_cast<TReal>(0.5)));
-- const TReal fSinRoll(sin(fRoll*static_cast<TReal>(0.5)));
-- const TReal fCosRoll(cos(fRoll*static_cast<TReal>(0.5)));
-+ const TReal fSinPitch(std::sin(fPitch*static_cast<TReal>(0.5)));
-+ const TReal fCosPitch(std::cos(fPitch*static_cast<TReal>(0.5)));
-+ const TReal fSinYaw(std::sin(fYaw*static_cast<TReal>(0.5)));
-+ const TReal fCosYaw(std::cos(fYaw*static_cast<TReal>(0.5)));
-+ const TReal fSinRoll(std::sin(fRoll*static_cast<TReal>(0.5)));
-+ const TReal fCosRoll(std::cos(fRoll*static_cast<TReal>(0.5)));
- const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
- const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
- x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
-@@ -163,8 +163,8 @@ inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> axis, TReal angle)
- {
- axis.Normalize();
-
-- const TReal sin_a = sin( angle / 2 );
-- const TReal cos_a = cos( angle / 2 );
-+ const TReal sin_a = std::sin( angle / 2 );
-+ const TReal cos_a = std::cos( angle / 2 );
- x = axis.x * sin_a;
- y = axis.y * sin_a;
- z = axis.z * sin_a;
-@@ -184,7 +184,7 @@ inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> normalized)
- if (t < static_cast<TReal>(0.0)) {
- w = static_cast<TReal>(0.0);
- }
-- else w = sqrt (t);
-+ else w = std::sqrt (t);
- }
-
- // ---------------------------------------------------------------------------
-@@ -214,10 +214,10 @@ inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuat
- {
- // Standard case (slerp)
- TReal omega, sinom;
-- omega = acos( cosom); // extract theta from dot product's cos theta
-- sinom = sin( omega);
-- sclp = sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
-- sclq = sin( pFactor * omega) / sinom;
-+ omega = std::acos( cosom); // extract theta from dot product's cos theta
-+ sinom = std::sin( omega);
-+ sclp = std::sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
-+ sclq = std::sin( pFactor * omega) / sinom;
- } else
- {
- // Very close, do linear interp (because it's faster)
-@@ -236,7 +236,7 @@ template<typename TReal>
- inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Normalize()
- {
- // compute the magnitude and divide through it
-- const TReal mag = sqrt(x*x + y*y + z*z + w*w);
-+ const TReal mag = std::sqrt(x*x + y*y + z*z + w*w);
- if (mag)
- {
- const TReal invMag = static_cast<TReal>(1.0)/mag;
-diff --git a/src/3rdparty/assimp/include/assimp/types.h b/src/3rdparty/assimp/include/assimp/types.h
-index 8b35bd3..a8200a7 100644
---- a/src/3rdparty/assimp/include/assimp/types.h
-+++ b/src/3rdparty/assimp/include/assimp/types.h
-@@ -217,7 +217,7 @@ struct aiColor3D
- /** Check whether a color is black */
- bool IsBlack() const {
- static const float epsilon = 10e-3f;
-- return fabs( r ) < epsilon && fabs( g ) < epsilon && fabs( b ) < epsilon;
-+ return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
- }
-
- #endif // !__cplusplus
-diff --git a/src/3rdparty/assimp/include/assimp/vector2.inl b/src/3rdparty/assimp/include/assimp/vector2.inl
-index eb1b986..da085ea 100644
---- a/src/3rdparty/assimp/include/assimp/vector2.inl
-+++ b/src/3rdparty/assimp/include/assimp/vector2.inl
-@@ -71,7 +71,7 @@ TReal aiVector2t<TReal>::SquareLength() const {
- // ------------------------------------------------------------------------------------------------
- template <typename TReal>
- TReal aiVector2t<TReal>::Length() const {
-- return ::sqrt( SquareLength());
-+ return std::sqrt( SquareLength());
- }
-
- // ------------------------------------------------------------------------------------------------
-diff --git a/src/3rdparty/assimp/include/assimp/vector3.inl b/src/3rdparty/assimp/include/assimp/vector3.inl
-index 01e0b6f..4892f62 100644
---- a/src/3rdparty/assimp/include/assimp/vector3.inl
-+++ b/src/3rdparty/assimp/include/assimp/vector3.inl
-@@ -92,7 +92,7 @@ AI_FORCE_INLINE TReal aiVector3t<TReal>::SquareLength() const {
- // ------------------------------------------------------------------------------------------------
- template <typename TReal>
- AI_FORCE_INLINE TReal aiVector3t<TReal>::Length() const {
-- return ::sqrt( SquareLength());
-+ return std::sqrt( SquareLength());
- }
- // ------------------------------------------------------------------------------------------------
- template <typename TReal>
---
-2.4.9 (Apple Git-60)
-
diff --git a/src/3rdparty/patches/0005-assimp-Avoid-unneeded-copy-ctor-calls-when-calling-getAiType.patch b/src/3rdparty/patches/0005-assimp-Avoid-unneeded-copy-ctor-calls-when-calling-getAiType.patch
new file mode 100644
index 000000000..df716b065
--- /dev/null
+++ b/src/3rdparty/patches/0005-assimp-Avoid-unneeded-copy-ctor-calls-when-calling-getAiType.patch
@@ -0,0 +1,31 @@
+From 2794f2041c8c7616c91e443ea74564e4a5d07a2e Mon Sep 17 00:00:00 2001
+From: Sergio Martins <sergio.martins@kdab.com>
+Date: Sun, 29 Jan 2017 17:37:53 +0000
+Subject: [PATCH] Avoid unneeded copy-ctor calls when calling getAiType
+
+Specially for aiString, which does a memcpy.
+Patch already committed upstream.
+
+Change-Id: I9497e4fcc11a60a4bf434fcac4b76f1467867186
+---
+ src/3rdparty/assimp/include/assimp/metadata.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/3rdparty/assimp/include/assimp/metadata.h b/src/3rdparty/assimp/include/assimp/metadata.h
+index 16809a511..db2f1873f 100644
+--- a/src/3rdparty/assimp/include/assimp/metadata.h
++++ b/src/3rdparty/assimp/include/assimp/metadata.h
+@@ -106,8 +106,8 @@ inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
+ inline aiMetadataType GetAiType( int ) { return AI_INT; }
+ inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
+ inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
+-inline aiMetadataType GetAiType( aiString ) { return AI_AISTRING; }
+-inline aiMetadataType GetAiType( aiVector3D ) { return AI_AIVECTOR3D; }
++inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; }
++inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
+
+
+
+--
+2.11.0
+
diff --git a/src/3rdparty/patches/0005-assimp-Fix-build-FBXConverter.patch b/src/3rdparty/patches/0005-assimp-Fix-build-FBXConverter.patch
deleted file mode 100644
index 9290b30aa..000000000
--- a/src/3rdparty/patches/0005-assimp-Fix-build-FBXConverter.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 1e39e6b296b94852e73adea1cb652adda435529e Mon Sep 17 00:00:00 2001
-From: Anton Kudryavtsev <a.kudryavtsev@netris.ru>
-Date: Mon, 21 Mar 2016 16:43:43 +0300
-Subject: [PATCH] assimp: Fix build FBXConverter.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-If you compile according to https://wiki.qt.io/Qt5ForAndroidBuilding
-with NDK v11.b, you get such warning and the compilation stops:
-
-FBXConverter.cpp:1262:19: warning: ‘count’ may be used uninitialized in this function [-Wmaybe-uninitialized]
- unsigned int count;
-
-Change-Id: Ieff61e6302800a22080f837267982fd2ea3129e6
----
- src/3rdparty/assimp/code/FBXConverter.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/assimp/code/FBXConverter.cpp b/src/3rdparty/assimp/code/FBXConverter.cpp
-index 56643bc..c6ef8c9 100644
---- a/src/3rdparty/assimp/code/FBXConverter.cpp
-+++ b/src/3rdparty/assimp/code/FBXConverter.cpp
-@@ -1259,7 +1259,7 @@ private:
- // taking notes so we don't need to do it twice.
- BOOST_FOREACH(WeightIndexArray::value_type index, indices) {
-
-- unsigned int count;
-+ unsigned int count = 0;
- const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count);
-
- index_out_indices.push_back(no_index_sentinel);
---
-1.9.1
-
diff --git a/src/animation/animation.pro b/src/animation/animation.pro
index 4443e3193..b7d08416c 100644
--- a/src/animation/animation.pro
+++ b/src/animation/animation.pro
@@ -15,7 +15,8 @@ include(backend/backend.pri)
HEADERS += \
qt3danimation_global.h \
qt3danimation_global_p.h \
- animationlogging_p.h
+ animationlogging_p.h \
+ job_common_p.h
SOURCES += \
animationlogging.cpp
diff --git a/src/animation/animationlogging.cpp b/src/animation/animationlogging.cpp
index a822f0346..11bd47a23 100644
--- a/src/animation/animationlogging.cpp
+++ b/src/animation/animationlogging.cpp
@@ -44,10 +44,10 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
-Q_LOGGING_CATEGORY(Backend, "Qt3D.Animation.Backend")
-Q_LOGGING_CATEGORY(Frontend, "Qt3D.Animation.Frontend")
-Q_LOGGING_CATEGORY(Jobs, "Qt3D.Animation.Jobs")
-Q_LOGGING_CATEGORY(HandlerLogic, "Qt3D.Animation.Handler")
+Q_LOGGING_CATEGORY(Backend, "Qt3D.Animation.Backend", QtWarningMsg)
+Q_LOGGING_CATEGORY(Frontend, "Qt3D.Animation.Frontend", QtWarningMsg)
+Q_LOGGING_CATEGORY(Jobs, "Qt3D.Animation.Jobs", QtWarningMsg)
+Q_LOGGING_CATEGORY(HandlerLogic, "Qt3D.Animation.Handler", QtWarningMsg)
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/additiveclipblend.cpp b/src/animation/backend/additiveclipblend.cpp
new file mode 100644
index 000000000..ac8b849e2
--- /dev/null
+++ b/src/animation/backend/additiveclipblend.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "additiveclipblend_p.h"
+#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
+#include <Qt3DAnimation/qadditiveclipblend.h>
+#include <Qt3DAnimation/private/qadditiveclipblend_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+namespace Animation {
+
+AdditiveClipBlend::AdditiveClipBlend()
+ : ClipBlendNode(ClipBlendNode::AdditiveBlendType)
+ , m_baseClipId()
+ , m_additiveClipId()
+ , m_additiveFactor(0.0f)
+{
+}
+
+AdditiveClipBlend::~AdditiveClipBlend()
+{
+}
+
+void AdditiveClipBlend::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+{
+ if (e->type() == Qt3DCore::PropertyUpdated) {
+ Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("additiveFactor"))
+ m_additiveFactor = change->value().toFloat();
+ else if (change->propertyName() == QByteArrayLiteral("baseClip"))
+ m_baseClipId = change->value().value<Qt3DCore::QNodeId>();
+ else if (change->propertyName() == QByteArrayLiteral("additiveClip"))
+ m_additiveClipId = change->value().value<Qt3DCore::QNodeId>();
+ }
+}
+
+ClipResults AdditiveClipBlend::doBlend(const QVector<ClipResults> &blendData) const
+{
+ Q_ASSERT(blendData.size() == 2);
+ Q_ASSERT(blendData[0].size() == blendData[1].size());
+ const int elementCount = blendData.first().size();
+ ClipResults blendResults(elementCount);
+
+ for (int i = 0; i < elementCount; ++i)
+ blendResults[i] = blendData[0][i] + m_additiveFactor * blendData[1][i];
+
+ return blendResults;
+}
+
+void AdditiveClipBlend::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+{
+ ClipBlendNode::initializeFromPeer(change);
+ const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QAdditiveClipBlendData>>(change);
+ const Qt3DAnimation::QAdditiveClipBlendData cloneData = creationChangeData->data;
+ m_baseClipId = cloneData.baseClipId;
+ m_additiveClipId = cloneData.additiveClipId;
+ m_additiveFactor = cloneData.additiveFactor;
+}
+
+} // Animation
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/backend/additiveclipblend_p.h b/src/animation/backend/additiveclipblend_p.h
new file mode 100644
index 000000000..b3fe240ed
--- /dev/null
+++ b/src/animation/backend/additiveclipblend_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_ANIMATION_ADDITIVECLIPBLEND_P_H
+#define QT3DANIMATION_ANIMATION_ADDITIVECLIPBLEND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DAnimation/private/clipblendnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+namespace Animation {
+
+class Q_AUTOTEST_EXPORT AdditiveClipBlend : public ClipBlendNode
+{
+public:
+ AdditiveClipBlend();
+ ~AdditiveClipBlend();
+
+ inline Qt3DCore::QNodeId baseClipId() const { return m_baseClipId; }
+ void setBaseClipId(Qt3DCore::QNodeId baseClipId) { m_baseClipId = baseClipId; } // For unit tests
+
+ inline Qt3DCore::QNodeId additiveClipId() const { return m_additiveClipId; }
+ void setAdditiveClipId(Qt3DCore::QNodeId additiveClipId) { m_additiveClipId = additiveClipId; } // For unit tests
+
+ inline float additiveFactor() const { return m_additiveFactor; }
+ void setAdditiveFactor(float additiveFactor) { m_additiveFactor = additiveFactor; } // For unit tests
+
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_FINAL;
+
+ inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE
+ {
+ return currentDependencyIds();
+ }
+
+ inline QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_OVERRIDE
+ {
+ return { m_baseClipId, m_additiveClipId };
+ }
+
+ inline double duration() const Q_DECL_OVERRIDE
+ {
+ ClipBlendNode *node = clipBlendNodeManager()->lookupNode(m_baseClipId);
+ Q_ASSERT(node);
+ return node->duration();
+ }
+
+protected:
+ ClipResults doBlend(const QVector<ClipResults> &blendData) const Q_DECL_FINAL;
+
+private:
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+
+ Qt3DCore::QNodeId m_baseClipId;
+ Qt3DCore::QNodeId m_additiveClipId;
+ float m_additiveFactor;
+};
+
+} // Animation
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_ADDITIVECLIPBLEND_P_H
diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp
index 3265a8fc5..6a3c3c15b 100644
--- a/src/animation/backend/animationclip.cpp
+++ b/src/animation/backend/animationclip.cpp
@@ -36,11 +36,12 @@
#include "animationclip_p.h"
#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qanimationclip_p.h>
+#include <Qt3DAnimation/private/qanimationcliploader_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qfile.h>
@@ -56,20 +57,36 @@ namespace Animation {
AnimationClip::AnimationClip()
: BackendNode(ReadWrite)
, m_source()
+ , m_status(QAnimationClipLoader::NotReady)
+ , m_clipData()
+ , m_dataType(Unknown)
, m_name()
- , m_objectName()
- , m_channelGroups()
+ , m_channels()
, m_duration(0.0f)
{
}
void AnimationClip::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAnimationClipData>>(change);
- const auto &data = typedChange->data;
- m_source = data.source;
- if (!m_source.isEmpty())
- setDirty(Handler::AnimationClipDirty);
+ const auto loaderTypedChange = qSharedPointerDynamicCast<Qt3DCore::QNodeCreatedChange<QAnimationClipLoaderData>>(change);
+ if (loaderTypedChange) {
+ const auto &data = loaderTypedChange->data;
+ m_dataType = File;
+ m_source = data.source;
+ if (!m_source.isEmpty())
+ setDirty(Handler::AnimationClipDirty);
+ return;
+ }
+
+ const auto clipTypedChange = qSharedPointerDynamicCast<Qt3DCore::QNodeCreatedChange<QAnimationClipChangeData>>(change);
+ if (clipTypedChange) {
+ const auto &data = clipTypedChange->data;
+ m_dataType = Data;
+ m_clipData = data.clipData;
+ if (m_clipData.isValid())
+ setDirty(Handler::AnimationClipDirty);
+ return;
+ }
}
void AnimationClip::cleanup()
@@ -77,20 +94,41 @@ void AnimationClip::cleanup()
setEnabled(false);
m_handler = nullptr;
m_source.clear();
- m_channelGroups.clear();
+ m_clipData.clearChannels();
+ m_status = QAnimationClipLoader::NotReady;
+ m_dataType = Unknown;
+ m_channels.clear();
m_duration = 0.0f;
clearData();
}
+void AnimationClip::setStatus(QAnimationClipLoader::Status status)
+{
+ if (status != m_status) {
+ m_status = status;
+ Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("status");
+ e->setValue(QVariant::fromValue(m_status));
+ notifyObservers(e);
+ }
+}
+
void AnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
switch (e->type()) {
case Qt3DCore::PropertyUpdated: {
const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
if (change->propertyName() == QByteArrayLiteral("source")) {
+ Q_ASSERT(m_dataType == File);
m_source = change->value().toUrl();
setDirty(Handler::AnimationClipDirty);
+ } else if (change->propertyName() == QByteArrayLiteral("clipData")) {
+ Q_ASSERT(m_dataType == Data);
+ m_clipData = change->value().value<Qt3DAnimation::QAnimationClipData>();
+ if (m_clipData.isValid())
+ setDirty(Handler::AnimationClipDirty);
}
break;
}
@@ -110,11 +148,45 @@ void AnimationClip::loadAnimation()
qCDebug(Jobs) << Q_FUNC_INFO << m_source;
clearData();
+ // Load the data
+ switch (m_dataType) {
+ case File:
+ loadAnimationFromUrl();
+ break;
+
+ case Data:
+ loadAnimationFromData();
+ break;
+
+ default:
+ Q_UNREACHABLE();
+ }
+
+ // Update the duration
+ const float t = findDuration();
+ setDuration(t);
+
+ m_channelComponentCount = findChannelComponentCount();
+
+ // If using a loader inform the frontend of the status change
+ if (m_source.isEmpty()) {
+ if (qFuzzyIsNull(t) || m_channelComponentCount == 0)
+ setStatus(QAnimationClipLoader::Error);
+ else
+ setStatus(QAnimationClipLoader::Ready);
+ }
+
+ qCDebug(Jobs) << "Loaded animation data:" << *this;
+}
+
+void AnimationClip::loadAnimationFromUrl()
+{
// TODO: Handle remote files
QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source);
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Could not find animation clip:" << filePath;
+ setStatus(QAnimationClipLoader::Error);
return;
}
@@ -127,28 +199,29 @@ void AnimationClip::loadAnimation()
qCDebug(Jobs) << "Found" << animationsArray.size() << "animations:";
for (int i = 0; i < animationsArray.size(); ++i) {
QJsonObject animation = animationsArray.at(i).toObject();
- qCDebug(Jobs) << "\tName:" << animation[QLatin1String("action")].toString()
- << "Object:" << animation[QLatin1String("object")].toString();
+ qCDebug(Jobs) << "Animation Name:" << animation[QLatin1String("animationName")].toString();
}
// For now just load the first animation
+ // TODO: Allow loading a named animation from within the file analogous to QMesh
QJsonObject animation = animationsArray.at(0).toObject();
- m_name = animation[QLatin1String("action")].toString();
- m_objectName = animation[QLatin1String("object")].toString();
- QJsonArray groupsArray = animation[QLatin1String("groups")].toArray();
- const int groupCount = groupsArray.size();
- m_channelGroups.resize(groupCount);
- for (int i = 0; i < groupCount; ++i) {
- const QJsonObject group = groupsArray.at(i).toObject();
- m_channelGroups[i].read(group);
+ m_name = animation[QLatin1String("animationName")].toString();
+ QJsonArray channelsArray = animation[QLatin1String("channels")].toArray();
+ const int channelCount = channelsArray.size();
+ m_channels.resize(channelCount);
+ for (int i = 0; i < channelCount; ++i) {
+ const QJsonObject group = channelsArray.at(i).toObject();
+ m_channels[i].read(group);
}
+}
- const float t = findDuration();
- setDuration(t);
-
- m_channelCount = findChannelCount();
-
- qCDebug(Jobs) << "Loaded animation data:" << *this;
+void AnimationClip::loadAnimationFromData()
+{
+ // Reformat data from QAnimationClipData to backend format
+ m_channels.resize(m_clipData.channelCount());
+ int i = 0;
+ for (const auto &frontendChannel : qAsConst(m_clipData))
+ m_channels[i++].setFromQChannel(frontendChannel);
}
void AnimationClip::setDuration(float duration)
@@ -161,44 +234,52 @@ void AnimationClip::setDuration(float duration)
// Send a change to the frontend
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
e->setPropertyName("duration");
e->setValue(m_duration);
notifyObservers(e);
}
+int AnimationClip::channelIndex(const QString &channelName) const
+{
+ const int channelCount = m_channels.size();
+ for (int i = 0; i < channelCount; ++i) {
+ if (m_channels[i].name == channelName)
+ return i;
+ }
+ return -1;
+}
+
/*!
\internal
- Given the index of a channel group, \a channelGroupIndex, calculates
- the base index of the first channel in this group. For example, if
+ Given the index of a channel, \a channelIndex, calculates
+ the base index of the first channelComponent in this group. For example, if
there are two channel groups each with 3 channels and you request
the channelBaseIndex(1), the return value will be 3. Indices 0-2 are
for the first group, so the first channel of the second group occurs
at index 3.
*/
-int AnimationClip::channelBaseIndex(int channelGroupIndex) const
+int AnimationClip::channelComponentBaseIndex(int channelIndex) const
{
int index = 0;
- for (int i = 0; i < channelGroupIndex; ++i)
- index += m_channelGroups[i].channels.size();
+ for (int i = 0; i < channelIndex; ++i)
+ index += m_channels[i].channelComponents.size();
return index;
}
void AnimationClip::clearData()
{
m_name.clear();
- m_objectName.clear();
- m_channelGroups.clear();
+ m_channels.clear();
}
float AnimationClip::findDuration()
{
// Iterate over the contained fcurves and find the longest one
double tMax = 0.0;
- for (const ChannelGroup &channelGroup : qAsConst(m_channelGroups)) {
- for (const Channel &channel : qAsConst(channelGroup.channels)) {
- const float t = channel.fcurve.endTime();
+ for (const Channel &channel : qAsConst(m_channels)) {
+ for (const ChannelComponent &channelComponent : qAsConst(channel.channelComponents)) {
+ const float t = channelComponent.fcurve.endTime();
if (t > tMax)
tMax = t;
}
@@ -206,11 +287,11 @@ float AnimationClip::findDuration()
return tMax;
}
-int AnimationClip::findChannelCount()
+int AnimationClip::findChannelComponentCount()
{
int channelCount = 0;
- for (const ChannelGroup &channelGroup : qAsConst(m_channelGroups))
- channelCount += channelGroup.channels.size();
+ for (const Channel &channel : qAsConst(m_channels))
+ channelCount += channel.channelComponents.size();
return channelCount;
}
diff --git a/src/animation/backend/animationclip_p.h b/src/animation/backend/animationclip_p.h
index cfd8558c7..7ff79c01a 100644
--- a/src/animation/backend/animationclip_p.h
+++ b/src/animation/backend/animationclip_p.h
@@ -49,6 +49,8 @@
//
#include <Qt3DAnimation/private/backendnode_p.h>
+#include <Qt3DAnimation/qanimationclipdata.h>
+#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/fcurve_p.h>
#include <QtCore/qurl.h>
@@ -67,32 +69,52 @@ public:
void cleanup();
void setSource(const QUrl &source) { m_source = source; }
QUrl source() const { return m_source; }
+ void setStatus(QAnimationClipLoader::Status status);
+ QAnimationClipLoader::Status status() const { return m_status; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
QString name() const { return m_name; }
- QString objectName() const { return m_objectName; }
- const QVector<ChannelGroup> &channelGroups() const { return m_channelGroups; }
+ const QVector<Channel> &channels() const { return m_channels; }
// Called from jobs
void loadAnimation();
void setDuration(float duration);
float duration() const { return m_duration; }
- int channelCount() const { return m_channelCount; }
- int channelBaseIndex(int channelGroupIndex) const;
+ int channelIndex(const QString &channelName) const;
+ int channelCount() const { return m_channelComponentCount; }
+ int channelComponentBaseIndex(int channelGroupIndex) const;
+
+ // Allow unit tests to set the data type
+#if !defined(QT_BUILD_INTERNAL)
+private:
+#endif
+ enum ClipDataType {
+ Unknown,
+ File,
+ Data
+ };
+#if defined(QT_BUILD_INTERNAL)
+public:
+ void setDataType(ClipDataType dataType) { m_dataType = dataType; }
+#endif
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void loadAnimationFromUrl();
+ void loadAnimationFromData();
void clearData();
float findDuration();
- int findChannelCount();
+ int findChannelComponentCount();
QUrl m_source;
+ QAnimationClipLoader::Status m_status;
+ QAnimationClipData m_clipData;
+ ClipDataType m_dataType;
QString m_name;
- QString m_objectName;
- QVector<ChannelGroup> m_channelGroups;
+ QVector<Channel> m_channels;
float m_duration;
- int m_channelCount;
+ int m_channelComponentCount;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -101,12 +123,12 @@ inline QDebug operator<<(QDebug dbg, const AnimationClip &animationClip)
QDebugStateSaver saver(dbg);
dbg << "QNodeId =" << animationClip.peerId() << endl
<< "Name =" << animationClip.name() << endl
- << "Object Name =" << animationClip.objectName() << endl
- << "Channel Groups:" << endl;
+ << "Duration: " << animationClip.duration() << endl
+ << "Channels:" << endl;
- const QVector<ChannelGroup> channelGroups = animationClip.channelGroups();
- for (const auto channelGroup : channelGroups) {
- dbg << channelGroup;
+ const QVector<Channel> channels = animationClip.channels();
+ for (const auto &channel : channels) {
+ dbg << channel;
}
return dbg;
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp
index 65a455144..1f675f271 100644
--- a/src/animation/backend/animationutils.cpp
+++ b/src/animation/backend/animationutils.cpp
@@ -37,6 +37,9 @@
#include "animationutils_p.h"
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DAnimation/private/managers_p.h>
+#include <Qt3DAnimation/private/clipblendnode_p.h>
+#include <Qt3DAnimation/private/clipblendnodevisitor_p.h>
+#include <Qt3DAnimation/private/clipblendvalue_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <QtGui/qvector2d.h>
@@ -46,17 +49,60 @@
#include <QtCore/qvariant.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
+#include <numeric>
+
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
-double AnimationUtils::localTimeFromGlobalTime(double t_global,
- double t_start_global,
- double playbackRate,
- double duration,
- int loopCount,
- int &currentLoop)
+int componentsForType(int type)
+{
+ int componentCount = 1;
+ switch (type) {
+ case QVariant::Double:
+ componentCount = 1;
+ break;
+
+ case QVariant::Vector2D:
+ componentCount = 2;
+ break;
+
+ case QVariant::Vector3D:
+ componentCount = 3;
+ break;
+
+ case QVariant::Vector4D:
+ case QVariant::Quaternion:
+ componentCount = 4;
+ break;
+
+ default:
+ qWarning() << "Unhandled animation type";
+ }
+
+ return componentCount;
+}
+
+ClipEvaluationData evaluationDataForClip(AnimationClip *clip,
+ const AnimatorEvaluationData &animatorData)
+{
+ // global time values expected in seconds
+ ClipEvaluationData result;
+ result.localTime = localTimeFromGlobalTime(animatorData.globalTime, animatorData.startTime,
+ animatorData.playbackRate, clip->duration(),
+ animatorData.loopCount, result.currentLoop);
+ result.isFinalFrame = isFinalFrame(result.localTime, clip->duration(),
+ result.currentLoop, animatorData.loopCount);
+ return result;
+}
+
+double localTimeFromGlobalTime(double t_global,
+ double t_start_global,
+ double playbackRate,
+ double duration,
+ int loopCount,
+ int &currentLoop)
{
double t_local = playbackRate * (t_global - t_start_global);
double loopNumber = 0;
@@ -89,60 +135,48 @@ double AnimationUtils::localTimeFromGlobalTime(double t_global,
return t_local;
}
-QVector<int> AnimationUtils::channelsToIndices(const ChannelGroup &channelGroup, int dataType, int offset)
+double phaseFromGlobalTime(double t_global, double t_start_global,
+ double playbackRate, double duration,
+ int loopCount, int &currentLoop)
{
- static const QStringList standardSuffixes = (QStringList()
- << QLatin1String("x")
- << QLatin1String("y")
- << QLatin1String("z")
- << QLatin1String("w"));
- static const QStringList quaternionSuffixes = (QStringList()
- << QLatin1String("w")
- << QLatin1String("x")
- << QLatin1String("y")
- << QLatin1String("z"));
+ const double t_local = localTimeFromGlobalTime(t_global, t_start_global, playbackRate,
+ duration, loopCount, currentLoop);
+ return t_local / duration;
+}
+
+ComponentIndices channelComponentsToIndices(const Channel &channel, int dataType, int offset)
+{
+#if defined Q_COMPILER_UNIFORM_INIT
+ static const QVector<char> standardSuffixes = { 'X', 'Y', 'Z', 'W' };
+ static const QVector<char> quaternionSuffixes = { 'W', 'X', 'Y', 'Z' };
+#else
+ static const QVector<char> standardSuffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W');
+ static const QVector<char> quaternionSuffixes = (QVector<char>() << 'W' << 'X' << 'Y' << 'Z');
+#endif
if (dataType != QVariant::Quaternion)
- return channelsToIndicesHelper(channelGroup, dataType, offset, standardSuffixes);
+ return channelComponentsToIndicesHelper(channel, dataType, offset, standardSuffixes);
else
- return channelsToIndicesHelper(channelGroup, dataType, offset, quaternionSuffixes);
-
+ return channelComponentsToIndicesHelper(channel, dataType, offset, quaternionSuffixes);
}
-QVector<int> AnimationUtils::channelsToIndicesHelper(const ChannelGroup &channelGroup, int dataType, int offset, const QStringList &suffixes)
+ComponentIndices channelComponentsToIndicesHelper(const Channel &channel,
+ int dataType,
+ int offset,
+ const QVector<char> &suffixes)
{
- int expectedChannelCount = 1;
- switch (dataType) {
- case QVariant::Double:
- expectedChannelCount = 1;
- break;
-
- case QVariant::Vector2D:
- expectedChannelCount = 2;
- break;
-
- case QVariant::Vector3D:
- expectedChannelCount = 3;
- break;
-
- case QVariant::Vector4D:
- case QVariant::Quaternion:
- expectedChannelCount = 4;
- break;
-
- default:
- qWarning() << "Unhandled animation type";
- }
-
- const int foundChannelCount = channelGroup.channels.size();
- if (foundChannelCount != expectedChannelCount) {
- qWarning() << "Data type expects" << expectedChannelCount
- << "but found" << foundChannelCount << "channels in the animation clip";
+ const int expectedComponentCount = componentsForType(dataType);
+ const int actualComponentCount = channel.channelComponents.size();
+ if (actualComponentCount != expectedComponentCount) {
+ qWarning() << "Data type expects" << expectedComponentCount
+ << "but found" << actualComponentCount << "components in the animation clip";
}
- QVector<int> indices(expectedChannelCount);
- for (int i = 0; i < expectedChannelCount; ++i) {
- int index = suffixes.indexOf(channelGroup.channels[i].name);
+ ComponentIndices indices(expectedComponentCount);
+ for (int i = 0; i < expectedComponentCount; ++i) {
+ const QString &componentName = channel.channelComponents[i].name;
+ char suffix = componentName.at(componentName.length() - 1).toLatin1();
+ int index = suffixes.indexOf(suffix);
if (index != -1)
indices[i] = index + offset;
else
@@ -151,57 +185,35 @@ QVector<int> AnimationUtils::channelsToIndicesHelper(const ChannelGroup &channel
return indices;
}
-QVector<float> AnimationUtils::evaluateAtGlobalTime(AnimationClip *clip,
- qint64 globalTime,
- qint64 startTime,
- int loopCount,
- int &currentLoop,
- bool &finalFrame)
-{
- // Calculate local time from global time
- const double t_global = double(globalTime) / 1.0e9;
- const double t_start_global = double(startTime) / 1.0e9;
- const double playbackRate = 1.0; // Assume standard playback rate for now
- const double duration = clip->duration();
-
- const double localTime = localTimeFromGlobalTime(t_global, t_start_global,
- playbackRate, duration,
- loopCount, currentLoop);
- return AnimationUtils::evaluateAtLocalTime(clip, localTime,
- currentLoop, loopCount,
- finalFrame);
-}
-
-QVector<float> AnimationUtils::evaluateAtLocalTime(AnimationClip *clip, float localTime,
- int currentLoop, int loopCount,
- bool &finalFrame)
+ClipResults evaluateClipAtLocalTime(AnimationClip *clip, float localTime)
{
QVector<float> channelResults;
Q_ASSERT(clip);
- // TODO: Uncomment when we add loopCount property
- if (localTime >= clip->duration()
- && loopCount != 0
- && currentLoop == loopCount - 1)
- finalFrame = true;
-
// Ensure we have enough storage to hold the evaluations
channelResults.resize(clip->channelCount());
// Iterate over channels and evaluate the fcurves
- const QVector<ChannelGroup> &channelGroups = clip->channelGroups();
+ const QVector<Channel> &channels = clip->channels();
int i = 0;
- for (const ChannelGroup &channelGroup : channelGroups) {
- for (const auto channel : qAsConst(channelGroup.channels))
- channelResults[i++] = channel.fcurve.evaluateAtTime(localTime);
+ for (const Channel &channel : channels) {
+ for (const auto &channelComponent : qAsConst(channel.channelComponents))
+ channelResults[i++] = channelComponent.fcurve.evaluateAtTime(localTime);
}
return channelResults;
}
-QVector<Qt3DCore::QSceneChangePtr> AnimationUtils::preparePropertyChanges(Qt3DCore::QNodeId peerId,
- const QVector<MappingData> &mappingDataVec,
- const QVector<float> &channelResults,
- bool finalFrame)
+ClipResults evaluateClipAtPhase(AnimationClip *clip, float phase)
+{
+ // Calculate the clip local time from the phase and clip duration
+ const double localTime = phase * clip->duration();
+ return evaluateClipAtLocalTime(clip, localTime);
+}
+
+QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId animatorId,
+ const QVector<MappingData> &mappingDataVec,
+ const QVector<float> &channelResults,
+ bool finalFrame)
{
QVector<Qt3DCore::QSceneChangePtr> changes;
// Iterate over the mappings
@@ -212,7 +224,7 @@ QVector<Qt3DCore::QSceneChangePtr> AnimationUtils::preparePropertyChanges(Qt3DCo
e->setPropertyName(mappingData.propertyName);
// Handle intermediate updates vs final flag properly
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = finalFrame;
+ Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isIntermediate = !finalFrame;
// Build the new value from the channel/fcurve evaluation results
QVariant v;
@@ -269,21 +281,24 @@ QVector<Qt3DCore::QSceneChangePtr> AnimationUtils::preparePropertyChanges(Qt3DCo
// If it's the final frame, notify the frontend that we've stopped
if (finalFrame) {
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId);
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("running");
e->setValue(false);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
changes.push_back(e);
}
return changes;
}
-QVector<AnimationUtils::MappingData> AnimationUtils::buildPropertyMappings(Handler *handler, const AnimationClip *clip, const ChannelMapper *mapper)
+//TODO: Remove this and use new implementation below for both the unblended
+// and blended animation cases.
+QVector<MappingData> buildPropertyMappings(Handler *handler,
+ const AnimationClip *clip,
+ const ChannelMapper *mapper)
{
QVector<MappingData> mappingDataVec;
ChannelMappingManager *mappingManager = handler->channelMappingManager();
- const QVector<ChannelGroup> &channelGroups = clip->channelGroups();
+ const QVector<Channel> &channels = clip->channels();
// Iterate over the mappings in the mapper object
for (const Qt3DCore::QNodeId mappingId : mapper->mappingIds()) {
@@ -308,13 +323,13 @@ QVector<AnimationUtils::MappingData> AnimationUtils::buildPropertyMappings(Handl
const QString channelName = mapping->channelName();
int channelGroupIndex = 0;
bool foundMatch = false;
- for (const ChannelGroup &channelGroup : channelGroups) {
- if (channelGroup.name == channelName) {
+ for (const Channel &channel : channels) {
+ if (channel.name == channelName) {
foundMatch = true;
- const int channelBaseIndex = clip->channelBaseIndex(channelGroupIndex);
+ const int channelBaseIndex = clip->channelComponentBaseIndex(channelGroupIndex);
// Within this group, match channel names with index ordering
- mappingData.channelIndices = channelsToIndices(channelGroup, mappingData.type, channelBaseIndex);
+ mappingData.channelIndices = channelComponentsToIndices(channel, mappingData.type, channelBaseIndex);
// Store the mapping data
mappingDataVec.push_back(mappingData);
@@ -330,6 +345,226 @@ QVector<AnimationUtils::MappingData> AnimationUtils::buildPropertyMappings(Handl
return mappingDataVec;
}
+QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &channelMappings,
+ const QVector<ChannelNameAndType> &channelNamesAndTypes,
+ const QVector<ComponentIndices> &channelComponentIndices)
+{
+ QVector<MappingData> mappingDataVec;
+ mappingDataVec.reserve(channelMappings.size());
+
+ // Iterate over the mappings
+ for (const auto mapping : channelMappings) {
+ // Populate the data we need, easy stuff first
+ MappingData mappingData;
+ mappingData.targetId = mapping->targetId();
+ mappingData.propertyName = mapping->propertyName();
+ mappingData.type = mapping->type();
+
+ if (mappingData.type == static_cast<int>(QVariant::Invalid)) {
+ qWarning() << "Unknown type for node id =" << mappingData.targetId
+ << "and property =" << mapping->property();
+ continue;
+ }
+
+ // Try to find matching channel name and type
+ const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() };
+ const int index = channelNamesAndTypes.indexOf(nameAndType);
+ if (index != -1) {
+ // We got one!
+ mappingData.channelIndices = channelComponentIndices[index];
+ mappingDataVec.push_back(mappingData);
+ }
+ }
+
+ return mappingDataVec;
+}
+
+QVector<ChannelNameAndType> buildRequiredChannelsAndTypes(Handler *handler,
+ const ChannelMapper *mapper)
+{
+ ChannelMappingManager *mappingManager = handler->channelMappingManager();
+ const QVector<Qt3DCore::QNodeId> mappingIds = mapper->mappingIds();
+
+ // Reserve enough storage assuming each mapping is for a different channel.
+ // May be overkill but avoids potential for multiple allocations
+ QVector<ChannelNameAndType> namesAndTypes;
+ namesAndTypes.reserve(mappingIds.size());
+
+ // Iterate through the mappings and add ones not already used by an earlier mapping.
+ // We could add them all then sort and remove duplicates. However, our approach has the
+ // advantage of keeping the blend tree format more consistent with the mapping
+ // orderings which will have better cache locality when generating events.
+ for (const Qt3DCore::QNodeId mappingId : mappingIds) {
+ // Get the mapping object
+ ChannelMapping *mapping = mappingManager->lookupResource(mappingId);
+ Q_ASSERT(mapping);
+
+ // Get the name and type
+ const ChannelNameAndType nameAndType{ mapping->channelName(), mapping->type() };
+
+ // Add if not already contained
+ if (!namesAndTypes.contains(nameAndType))
+ namesAndTypes.push_back(nameAndType);
+ }
+
+ return namesAndTypes;
+}
+
+QVector<ComponentIndices> assignChannelComponentIndices(const QVector<ChannelNameAndType> &namesAndTypes)
+{
+ QVector<ComponentIndices> channelComponentIndices;
+ channelComponentIndices.reserve(namesAndTypes.size());
+
+ int baseIndex = 0;
+ for (const auto &entry : namesAndTypes) {
+ // Populate indices in order
+ const int componentCount = componentsForType(entry.type);
+ ComponentIndices indices(componentCount);
+ std::iota(indices.begin(), indices.end(), baseIndex);
+
+ // Append to the results
+ channelComponentIndices.push_back(indices);
+
+ // Increment baseIndex
+ baseIndex += componentCount;
+ }
+
+ return channelComponentIndices;
+}
+
+QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler,
+ Qt3DCore::QNodeId blendTreeRootId)
+{
+ Q_ASSERT(handler);
+ Q_ASSERT(blendTreeRootId.isNull() == false);
+
+ // We need the ClipBlendNodeManager to be able to lookup nodes from their Ids
+ ClipBlendNodeManager *nodeManager = handler->clipBlendNodeManager();
+
+ // Visit the tree in a pre-order manner and collect the dependencies
+ QVector<Qt3DCore::QNodeId> clipIds;
+ ClipBlendNodeVisitor visitor(nodeManager,
+ ClipBlendNodeVisitor::PreOrder,
+ ClipBlendNodeVisitor::VisitOnlyDependencies);
+
+ auto func = [&clipIds, nodeManager] (ClipBlendNode *blendNode) {
+ const auto dependencyIds = blendNode->currentDependencyIds();
+ for (const auto dependencyId : dependencyIds) {
+ // Look up the blend node and if it's a value type (clip),
+ // add it to the set of value node ids that need to be evaluated
+ ClipBlendNode *node = nodeManager->lookupNode(dependencyId);
+ if (node && node->blendType() == ClipBlendNode::ValueType)
+ clipIds.append(dependencyId);
+ }
+ };
+ visitor.traverse(blendTreeRootId, func);
+
+ // Sort and remove duplicates
+ std::sort(clipIds.begin(), clipIds.end());
+ auto last = std::unique(clipIds.begin(), clipIds.end());
+ clipIds.erase(last, clipIds.end());
+ return clipIds;
+}
+
+ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &targetChannels,
+ const QVector<ComponentIndices> &targetIndices,
+ const AnimationClip *clip)
+{
+ Q_ASSERT(targetChannels.size() == targetIndices.size());
+
+ // Reserve enough storage for all the format indices
+ int indexCount = 0;
+ for (const auto targetIndexVec : targetIndices)
+ indexCount += targetIndexVec.size();
+ ComponentIndices format;
+ format.resize(indexCount);
+
+
+ // Iterate through the target channels
+ const int channelCount = targetChannels.size();
+ auto formatIt = format.begin();
+ for (int i = 0; i < channelCount; ++i) {
+ // Find the index of the channel from the clip
+ const ChannelNameAndType &targetChannel = targetChannels[i];
+ const int clipChannelIndex = clip->channelIndex(targetChannel.name);
+
+ // TODO: Ensure channel in the clip has enough components to map to the type.
+ // Requires some improvements to the clip data structure first.
+ // TODO: I don't think we need the targetIndices, only the number of components
+ // for each target channel. Check once blend tree is complete.
+ const int componentCount = targetIndices[i].size();
+
+ if (clipChannelIndex != -1) {
+ // Found a matching channel in the clip. Get the base channel
+ // component index and populate the format indices for this channel.
+ const int baseIndex = clip->channelComponentBaseIndex(clipChannelIndex);
+ std::iota(formatIt, formatIt + componentCount, baseIndex);
+
+ } else {
+ // No such channel in this clip. We'll use default values when
+ // mapping from the clip to the formatted clip results.
+ std::fill(formatIt, formatIt + componentCount, -1);
+ }
+
+ formatIt += componentCount;
+ }
+
+ return format;
+}
+
+ClipResults formatClipResults(const ClipResults &rawClipResults,
+ const ComponentIndices &format)
+{
+ // Resize the output to match the number of indices
+ const int elementCount = format.size();
+ ClipResults formattedClipResults(elementCount);
+
+ // Perform a gather operation to format the data
+ // TODO: For large numbers of components do this in parallel with
+ // for e.g. a parallel_for() like construct
+ for (int i = 0; i < elementCount; ++i) {
+ const float value = format[i] != -1 ? rawClipResults[format[i]] : 0.0f;
+ formattedClipResults[i] = value;
+ }
+
+ return formattedClipResults;
+}
+
+ClipResults evaluateBlendTree(Handler *handler,
+ BlendedClipAnimator *animator,
+ Qt3DCore::QNodeId blendTreeRootId)
+{
+ Q_ASSERT(handler);
+ Q_ASSERT(blendTreeRootId.isNull() == false);
+ const Qt3DCore::QNodeId animatorId = animator->peerId();
+
+ // We need the ClipBlendNodeManager to be able to lookup nodes from their Ids
+ ClipBlendNodeManager *nodeManager = handler->clipBlendNodeManager();
+
+ // Visit the tree in a post-order manner and for each interior node call
+ // blending function. We only need to visit the nodes that affect the blend
+ // tree at this time.
+ ClipBlendNodeVisitor visitor(nodeManager,
+ ClipBlendNodeVisitor::PostOrder,
+ ClipBlendNodeVisitor::VisitOnlyDependencies);
+
+ // TODO: When jobs can spawn other jobs we could evaluate subtrees of
+ // the blend tree in parallel. Since it's just a dependency tree, it maps
+ // simply onto the dependencies between jobs.
+ auto func = [animatorId] (ClipBlendNode *blendNode) {
+ // Look up the blend node and if it's an interior node, perform
+ // the blend operation
+ if (blendNode->blendType() != ClipBlendNode::ValueType)
+ blendNode->blend(animatorId);
+ };
+ visitor.traverse(blendTreeRootId, func);
+
+ // The clip results stored in the root node for this animator
+ // now represent the result of the blend tree evaluation
+ ClipBlendNode *blendTreeRootNode = nodeManager->lookupNode(blendTreeRootId);
+ Q_ASSERT(blendTreeRootNode);
+ return blendTreeRootNode->clipResults(animatorId);
+}
} // Animation
} // Qt3DAnimation
diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h
index e7f019aee..f8fcbafa7 100644
--- a/src/animation/backend/animationutils_p.h
+++ b/src/animation/backend/animationutils_p.h
@@ -57,69 +57,150 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
-class ChannelGroup;
+struct Channel;
+class BlendedClipAnimator;
class Handler;
class AnimationClip;
class ChannelMapper;
+class ChannelMapping;
-class Q_AUTOTEST_EXPORT AnimationUtils
+typedef QVector<int> ComponentIndices;
+
+struct MappingData
+{
+ Qt3DCore::QNodeId targetId;
+ const char *propertyName;
+ int type;
+ ComponentIndices channelIndices;
+};
+
+struct AnimatorEvaluationData
{
-public:
- struct MappingData {
- Qt3DCore::QNodeId targetId;
- const char *propertyName;
- int type;
- int channelBaseIndex;
- QVector<int> channelIndices;
- };
-
- struct BlendingMappingData {
- Qt3DCore::QNodeId targetId;
- const char *propertyName;
- int type;
- QVector<int> channelIndicesClip1;
- QVector<int> channelIndicesClip2;
-
- enum BlendAction {
- NoBlending, // Use the channel from Clip1 only
- ClipBlending, // Blending 2 clips sharing the same channel
- };
- BlendAction blendAction;
- };
-
- static double localTimeFromGlobalTime(double t_global, double t_start_global,
- double playbackRate, double duration,
- int loopCount, int &currentLoop);
- static QVector<int> channelsToIndices(const ChannelGroup &channelGroup,
- int dataType,
- int offset = 0);
- static QVector<int> channelsToIndicesHelper(const ChannelGroup &channelGroup,
- int dataType,
- int offset,
- const QStringList &suffixes);
- static QVector<float> evaluateAtGlobalTime(AnimationClip *clip,
- qint64 globalTime,
- qint64 startTime,
- int loopCount,
- int &currentLoop,
- bool &finalFrame);
- static QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId peerId,
- const QVector<MappingData> &mappingData,
- const QVector<float> &channelResults,
- bool finalFrame);
- static QVector<MappingData> buildPropertyMappings(Handler *handler,
- const AnimationClip *clip,
- const ChannelMapper *mapper);
-
-
-private:
- static QVector<float> evaluateAtLocalTime(AnimationClip *clip,
- float localTime,
- int currentLoop,
- int loopCount,
- bool &finalFrame);
+ double globalTime;
+ double startTime;
+ int loopCount;
+ double playbackRate;
};
+struct ClipEvaluationData
+{
+ int currentLoop;
+ double localTime;
+ bool isFinalFrame;
+};
+
+typedef QVector<float> ClipResults;
+
+struct ChannelNameAndType
+{
+ QString name;
+ int type;
+
+ bool operator==(const ChannelNameAndType &rhs) const
+ {
+ return name == rhs.name && type == rhs.type;
+ }
+};
+
+template<typename Animator>
+AnimatorEvaluationData evaluationDataForAnimator(Animator animator, qint64 globalTime)
+{
+ AnimatorEvaluationData data;
+ data.loopCount = animator->loops();
+ data.playbackRate = 1.0; // should be a property on the animator
+ // Convert global time from nsec to sec
+ data.startTime = double(animator->startTime()) / 1.0e9;
+ data.globalTime = double(globalTime) / 1.0e9;
+ return data;
+}
+
+inline bool isFinalFrame(double localTime,
+ double duration,
+ int currentLoop,
+ int loopCount)
+{
+ return (localTime >= duration &&
+ loopCount != 0 &&
+ currentLoop >= loopCount - 1);
+}
+
+Q_AUTOTEST_EXPORT
+int componentsForType(int type);
+
+Q_AUTOTEST_EXPORT
+ClipEvaluationData evaluationDataForClip(AnimationClip *clip,
+ const AnimatorEvaluationData &animatorData);
+
+Q_AUTOTEST_EXPORT
+ComponentIndices channelComponentsToIndices(const Channel &channel,
+ int dataType,
+ int offset = 0);
+
+Q_AUTOTEST_EXPORT
+ComponentIndices channelComponentsToIndicesHelper(const Channel &channelGroup,
+ int dataType,
+ int offset,
+ const QVector<char> &suffixes);
+
+Q_AUTOTEST_EXPORT
+ClipResults evaluateClipAtLocalTime(AnimationClip *clip,
+ float localTime);
+
+Q_AUTOTEST_EXPORT
+ClipResults evaluateClipAtPhase(AnimationClip *clip,
+ float phase);
+
+Q_AUTOTEST_EXPORT
+QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId animatorId,
+ const QVector<MappingData> &mappingData,
+ const QVector<float> &channelResults,
+ bool finalFrame);
+
+Q_AUTOTEST_EXPORT
+QVector<MappingData> buildPropertyMappings(Handler *handler,
+ const AnimationClip *clip,
+ const ChannelMapper *mapper);
+
+Q_AUTOTEST_EXPORT
+QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping *> &channelMappings,
+ const QVector<ChannelNameAndType> &channelNamesAndTypes,
+ const QVector<ComponentIndices> &channelComponentIndices);
+
+Q_AUTOTEST_EXPORT
+QVector<ChannelNameAndType> buildRequiredChannelsAndTypes(Handler *handler,
+ const ChannelMapper *mapper);
+
+Q_AUTOTEST_EXPORT
+QVector<ComponentIndices> assignChannelComponentIndices(const QVector<ChannelNameAndType> &namesAndTypes);
+
+Q_AUTOTEST_EXPORT
+double localTimeFromGlobalTime(double t_global, double t_start_global,
+ double playbackRate, double duration,
+ int loopCount, int &currentLoop);
+
+Q_AUTOTEST_EXPORT
+double phaseFromGlobalTime(double t_global, double t_start_global,
+ double playbackRate, double duration,
+ int loopCount, int &currentLoop);
+
+Q_AUTOTEST_EXPORT
+QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler,
+ Qt3DCore::QNodeId blendTreeRootId);
+
+Q_AUTOTEST_EXPORT
+ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &targetChannels,
+ const QVector<ComponentIndices> &targetIndices,
+ const AnimationClip *clip);
+
+Q_AUTOTEST_EXPORT
+ClipResults formatClipResults(const ClipResults &rawClipResults,
+ const ComponentIndices &format);
+
+Q_AUTOTEST_EXPORT
+ClipResults evaluateBlendTree(Handler *handler,
+ BlendedClipAnimator *animator,
+ Qt3DCore::QNodeId blendNodeId);
+
} // Animation
} // Qt3DAnimation
diff --git a/src/animation/backend/backend.pri b/src/animation/backend/backend.pri
index b0b0feaf0..2bc72e1d3 100644
--- a/src/animation/backend/backend.pri
+++ b/src/animation/backend/backend.pri
@@ -2,7 +2,6 @@
INCLUDEPATH += $$PWD
HEADERS += \
- $$PWD/animationclip_p.h \
$$PWD/handle_types_p.h \
$$PWD/handler_p.h \
$$PWD/nodefunctor_p.h \
@@ -13,7 +12,6 @@ HEADERS += \
$$PWD/functionrangefinder_p.h \
$$PWD/clipanimator_p.h \
$$PWD/blendedclipanimator_p.h \
- $$PWD/conductedclipanimator_p.h \
$$PWD/backendnode_p.h \
$$PWD/loadanimationclipjob_p.h \
$$PWD/channelmapping_p.h \
@@ -21,21 +19,22 @@ HEADERS += \
$$PWD/findrunningclipanimatorsjob_p.h \
$$PWD/evaluateclipanimatorjob_p.h \
$$PWD/clipblendnode_p.h \
- $$PWD/lerpblend_p.h \
$$PWD/clipblendnodevisitor_p.h \
$$PWD/animationutils_p.h \
$$PWD/buildblendtreesjob_p.h \
- $$PWD/evaluateblendclipanimatorjob_p.h
+ $$PWD/evaluateblendclipanimatorjob_p.h \
+ $$PWD/lerpclipblend_p.h \
+ $$PWD/additiveclipblend_p.h \
+ $$PWD/clipblendvalue_p.h \
+ $$PWD/animationclip_p.h
SOURCES += \
- $$PWD/animationclip.cpp \
$$PWD/handler.cpp \
$$PWD/fcurve.cpp \
$$PWD/bezierevaluator.cpp \
$$PWD/functionrangefinder.cpp \
$$PWD/clipanimator.cpp \
$$PWD/blendedclipanimator.cpp \
- $$PWD/conductedclipanimator.cpp \
$$PWD/backendnode.cpp \
$$PWD/loadanimationclipjob.cpp \
$$PWD/channelmapping.cpp \
@@ -43,9 +42,12 @@ SOURCES += \
$$PWD/findrunningclipanimatorsjob.cpp \
$$PWD/evaluateclipanimatorjob.cpp \
$$PWD/clipblendnode.cpp \
- $$PWD/lerpblend.cpp \
$$PWD/managers.cpp \
$$PWD/clipblendnodevisitor.cpp \
$$PWD/animationutils.cpp \
$$PWD/buildblendtreesjob.cpp \
- $$PWD/evaluateblendclipanimatorjob.cpp
+ $$PWD/evaluateblendclipanimatorjob.cpp \
+ $$PWD/lerpclipblend.cpp \
+ $$PWD/additiveclipblend.cpp \
+ $$PWD/clipblendvalue.cpp \
+ $$PWD/animationclip.cpp
diff --git a/src/animation/backend/bezierevaluator.cpp b/src/animation/backend/bezierevaluator.cpp
index 6ed8b1aa2..9d81a2f2f 100644
--- a/src/animation/backend/bezierevaluator.cpp
+++ b/src/animation/backend/bezierevaluator.cpp
@@ -83,7 +83,7 @@ float BezierEvaluator::valueForTime(float time) const
{
const float u = parameterForTime(time);
- // Calulate powers of u and (1-u) that we need
+ // Calculate powers of u and (1-u) that we need
const float u2 = u * u;
const float u3 = u2 * u;
const float mu = 1.0f - u;
diff --git a/src/animation/backend/blendedclipanimator.cpp b/src/animation/backend/blendedclipanimator.cpp
index 1cb774f72..08789a5f9 100644
--- a/src/animation/backend/blendedclipanimator.cpp
+++ b/src/animation/backend/blendedclipanimator.cpp
@@ -74,7 +74,6 @@ void BlendedClipAnimator::cleanup()
m_startGlobalTime = 0;
m_currentLoop = 0;
m_loops = 1;
- m_mappingData.clear();
}
void BlendedClipAnimator::setBlendTreeRootId(Qt3DCore::QNodeId blendTreeId)
@@ -95,11 +94,6 @@ void BlendedClipAnimator::setRunning(bool running)
setDirty(Handler::BlendedClipAnimatorDirty);
}
-void BlendedClipAnimator::setMappingData(const QVector<AnimationUtils::BlendingMappingData> mappingData)
-{
- m_mappingData = mappingData;
-}
-
void BlendedClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes)
{
for (const Qt3DCore::QSceneChangePtr &change : changes)
diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h
index d0db13e53..4421cb43a 100644
--- a/src/animation/backend/blendedclipanimator_p.h
+++ b/src/animation/backend/blendedclipanimator_p.h
@@ -77,17 +77,18 @@ public:
void setMapperId(Qt3DCore::QNodeId mapperId);
void setRunning(bool running);
- void setMappingData(const QVector<AnimationUtils::BlendingMappingData> mappingData);
- QVector<AnimationUtils::BlendingMappingData> mappingData() const { return m_mappingData; }
-
void setStartTime(qint64 globalTime) { m_startGlobalTime = globalTime; }
qint64 startTime() const { return m_startGlobalTime; }
+ void setLoops(int loops) { m_loops = loops; }
int loops() const { return m_loops; }
int currentLoop() const { return m_currentLoop; }
void setCurrentLoop(int currentLoop) { m_currentLoop = currentLoop; }
+ void setMappingData(const QVector<MappingData> &mappingData) { m_mappingData = mappingData; }
+ QVector<MappingData> mappingData() const { return m_mappingData; }
+
void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes);
private:
@@ -97,9 +98,10 @@ private:
bool m_running;
qint64 m_startGlobalTime;
- QVector<AnimationUtils::BlendingMappingData> m_mappingData;
int m_currentLoop;
int m_loops;
+
+ QVector<MappingData> m_mappingData;
};
} // namespace Animation
diff --git a/src/animation/backend/buildblendtreesjob.cpp b/src/animation/backend/buildblendtreesjob.cpp
index a8e969a39..fe56099a2 100644
--- a/src/animation/backend/buildblendtreesjob.cpp
+++ b/src/animation/backend/buildblendtreesjob.cpp
@@ -39,7 +39,9 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/clipblendnodevisitor_p.h>
#include <Qt3DAnimation/private/clipblendnode_p.h>
-#include <Qt3DAnimation/private/lerpblend_p.h>
+#include <Qt3DAnimation/private/clipblendvalue_p.h>
+#include <Qt3DAnimation/private/lerpclipblend_p.h>
+#include <Qt3DAnimation/private/job_common_p.h>
QT_BEGIN_NAMESPACE
@@ -49,7 +51,7 @@ namespace Animation {
BuildBlendTreesJob::BuildBlendTreesJob()
: Qt3DCore::QAspectJob()
{
- // TO DO: Add Profiler ID
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::BuildBlendTree, 0);
}
void BuildBlendTreesJob::setBlendedClipAnimators(const QVector<HBlendedClipAnimator> &blendedClipAnimatorHandles)
@@ -57,84 +59,68 @@ void BuildBlendTreesJob::setBlendedClipAnimators(const QVector<HBlendedClipAnima
m_blendedClipAnimatorHandles = blendedClipAnimatorHandles;
}
+// Note this job is run once for all stopped blended animators that have been marked dirty
+// We assume that the structure of blend node tree does not change once a BlendClipAnimator has been set to running
void BuildBlendTreesJob::run()
{
- for (const HBlendedClipAnimator blendedClipAnimatorHandle : m_blendedClipAnimatorHandles) {
- // Retrive BlendTree node
+ for (const HBlendedClipAnimator blendedClipAnimatorHandle : qAsConst(m_blendedClipAnimatorHandles)) {
+ // Retrieve BlendTree node
BlendedClipAnimator *blendClipAnimator = m_handler->blendedClipAnimatorManager()->data(blendedClipAnimatorHandle);
Q_ASSERT(blendClipAnimator);
- // TO DO: Add support for tree of blend nodes
- // For now assumes only one
-
const bool canRun = blendClipAnimator->canRun();
m_handler->setBlendedClipAnimatorRunning(blendedClipAnimatorHandle, canRun);
- // Check if blend clip can run and if so build blend tree
- if (canRun) {
- const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(blendClipAnimator->mapperId());
- Q_ASSERT(mapper);
- ClipBlendNode *node = m_handler->clipBlendNodeManager()->lookupNode(blendClipAnimator->blendTreeRootId());
-
- const Qt3DCore::QNodeIdVector clipIds = node->clipIds();
- // There must be 2 clips
- if (clipIds.size() != 2) {
- qWarning() << "A Blend Tree requires exactly 2 clips";
- return;
- }
-
- // Retrieve Animation clips
- const AnimationClip *clip1 = m_handler->animationClipManager()->lookupResource(clipIds.first());
- const AnimationClip *clip2 = m_handler->animationClipManager()->lookupResource(clipIds.last());
-
- // Build mappings for the 2 clips
- const QVector<AnimationUtils::MappingData> mappingDataClip1 = AnimationUtils::buildPropertyMappings(m_handler, clip1, mapper);
- const QVector<AnimationUtils::MappingData> mappingDataClip2 = AnimationUtils::buildPropertyMappings(m_handler, clip2, mapper);
-
- // We can only blend channels that are in both clips
- // If a channel is present in one clip and not the other, we use 100% of its value (no blending)
- QVector<AnimationUtils::BlendingMappingData> blendingMappingData;
- const int mappingInClip1Size = mappingDataClip1.size();
- blendingMappingData.reserve(mappingInClip1Size);
-
- // Find mappings that are in both vectors and build mappingData out of that
- for (const AnimationUtils::MappingData &mappingDataInClip1 : mappingDataClip1) {
- AnimationUtils::BlendingMappingData mappingData;
- mappingData.channelIndicesClip1 = mappingDataInClip1.channelIndices;
- mappingData.propertyName = mappingDataInClip1.propertyName;
- mappingData.targetId = mappingDataInClip1.targetId;
- mappingData.type = mappingDataInClip1.type;
- mappingData.blendAction = AnimationUtils::BlendingMappingData::NoBlending;
- blendingMappingData.push_back(mappingData);
- }
-
- for (const AnimationUtils::MappingData &mappingDataInClip2 : mappingDataClip2) {
- bool sharedChannel = false;
- for (int i = 0; i < mappingInClip1Size; ++i) {
- AnimationUtils::BlendingMappingData &mappingDataInClip1 = blendingMappingData[i];
- if ((strcmp(mappingDataInClip1.propertyName, mappingDataInClip2.propertyName) == 0) &&
- mappingDataInClip1.targetId == mappingDataInClip2.targetId &&
- mappingDataInClip1.type == mappingDataInClip2.type) {
- // We have a channel shared in both clips
- mappingDataInClip1.channelIndicesClip2 = mappingDataInClip2.channelIndices;
- mappingDataInClip1.blendAction = AnimationUtils::BlendingMappingData::ClipBlending;
- sharedChannel = true;
- break;
- }
- }
- if (!sharedChannel) { // We have a channel defined in only one of the clips
- AnimationUtils::BlendingMappingData mappingData;
- mappingData.channelIndicesClip2 = mappingDataInClip2.channelIndices;
- mappingData.propertyName = mappingDataInClip2.propertyName;
- mappingData.targetId = mappingDataInClip2.targetId;
- mappingData.type = mappingDataInClip2.type;
- mappingData.blendAction = AnimationUtils::BlendingMappingData::NoBlending;
- blendingMappingData.push_back(mappingData);
- }
- }
+ if (!canRun)
+ continue;
+
+ // Build the format for clip results that should be used by nodes in the blend
+ // tree when used with this animator
+ const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(blendClipAnimator->mapperId());
+ Q_ASSERT(mapper);
+ QVector<ChannelNameAndType> channelNamesAndTypes
+ = buildRequiredChannelsAndTypes(m_handler, mapper);
+ QVector<ComponentIndices> channelComponentIndices
+ = assignChannelComponentIndices(channelNamesAndTypes);
+
+ // Find the leaf value nodes of the blend tree and for each of them
+ // create a set of format indices that can later be used to map the
+ // raw ClipResults resulting from evaluating an animation clip to the
+ // layout used by the blend tree for this animator
+ const QVector<Qt3DCore::QNodeId> valueNodeIds
+ = gatherValueNodesToEvaluate(m_handler, blendClipAnimator->blendTreeRootId());
+ for (const auto valueNodeId : valueNodeIds) {
+ ClipBlendValue *valueNode
+ = static_cast<ClipBlendValue *>(m_handler->clipBlendNodeManager()->lookupNode(valueNodeId));
+ Q_ASSERT(valueNode);
+
+ const Qt3DCore::QNodeId clipId = valueNode->clipId();
+ const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipId);
+ Q_ASSERT(clip);
+
+ const ComponentIndices formatIndices
+ = generateClipFormatIndices(channelNamesAndTypes,
+ channelComponentIndices,
+ clip);
+ valueNode->setFormatIndices(blendClipAnimator->peerId(), formatIndices);
+ }
- blendClipAnimator->setMappingData(blendingMappingData);
+ // Finally, build the mapping data vector for this blended clip animator. This
+ // gets used during the final stage of evaluation when sending the property changes
+ // out to the targets of the animation. We do the costly work once up front.
+ const QVector<Qt3DCore::QNodeId> channelMappingIds = mapper->mappingIds();
+ QVector<ChannelMapping *> channelMappings;
+ channelMappings.reserve(channelMappingIds.size());
+ for (const auto mappingId : channelMappingIds) {
+ ChannelMapping *mapping = m_handler->channelMappingManager()->lookupResource(mappingId);
+ Q_ASSERT(mapping);
+ channelMappings.push_back(mapping);
}
+ const QVector<MappingData> mappingDataVec
+ = buildPropertyMappings(channelMappings,
+ channelNamesAndTypes,
+ channelComponentIndices);
+ blendClipAnimator->setMappingData(mappingDataVec);
}
}
diff --git a/src/animation/backend/channelmapper_p.h b/src/animation/backend/channelmapper_p.h
index 66654d56d..710de01ab 100644
--- a/src/animation/backend/channelmapper_p.h
+++ b/src/animation/backend/channelmapper_p.h
@@ -71,6 +71,7 @@ public:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void setMappingIds(const QVector<Qt3DCore::QNodeId> &mappingIds) { m_mappingIds = mappingIds; }
QVector<Qt3DCore::QNodeId> mappingIds() const { return m_mappingIds; }
private:
diff --git a/src/animation/backend/channelmapping_p.h b/src/animation/backend/channelmapping_p.h
index 4d6d80bf2..93cf5efed 100644
--- a/src/animation/backend/channelmapping_p.h
+++ b/src/animation/backend/channelmapping_p.h
@@ -70,10 +70,19 @@ public:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void setChannelName(const QString &channelName) { m_channelName = channelName; }
QString channelName() const { return m_channelName; }
+
+ void setTargetId(Qt3DCore::QNodeId targetId) { m_targetId = targetId; }
Qt3DCore::QNodeId targetId() const { return m_targetId; }
+
+ void setProperty(const QString &property) { m_property = property; }
QString property() const { return m_property; }
+
+ void setType(int type) { m_type = type; }
int type() const { return m_type; }
+
+ void setPropertyName(const char *propertyName) { m_propertyName = propertyName; }
const char *propertyName() const { return m_propertyName; }
private:
diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp
index ff3cb1b12..65fd0f57f 100644
--- a/src/animation/backend/clipanimator.cpp
+++ b/src/animation/backend/clipanimator.cpp
@@ -123,11 +123,6 @@ void ClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
QBackendNode::sceneChangeEvent(e);
}
-void ClipAnimator::setMappingData(const QVector<AnimationUtils::MappingData> mappingData)
-{
- m_mappingData = mappingData;
-}
-
void ClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes)
{
for (const Qt3DCore::QSceneChangePtr &change : changes)
diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h
index 577d18d7b..da9109cfb 100644
--- a/src/animation/backend/clipanimator_p.h
+++ b/src/animation/backend/clipanimator_p.h
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
-class ChannelGroup;
+struct Channel;
class Handler;
class Q_AUTOTEST_EXPORT ClipAnimator : public BackendNode
@@ -73,6 +73,7 @@ public:
void setRunning(bool running);
bool isRunning() const { return m_running; }
+ void setLoops(int loops) { m_loops = loops; }
int loops() const { return m_loops; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
@@ -80,8 +81,8 @@ public:
// Called by jobs
bool canRun() const { return !m_clipId.isNull() && !m_mapperId.isNull() && m_running; }
- void setMappingData(const QVector<AnimationUtils::MappingData> mappingData);
- QVector<AnimationUtils::MappingData> mappingData() const { return m_mappingData; }
+ void setMappingData(const QVector<MappingData> &mappingData) { m_mappingData = mappingData; }
+ QVector<MappingData> mappingData() const { return m_mappingData; }
void setStartTime(qint64 globalTime) { m_startGlobalTime = globalTime; }
qint64 startTime() const { return m_startGlobalTime; }
@@ -101,7 +102,7 @@ private:
// Working state
qint64 m_startGlobalTime;
- QVector<AnimationUtils::MappingData> m_mappingData;
+ QVector<MappingData> m_mappingData;
int m_currentLoop;
};
diff --git a/src/animation/backend/clipblendnode.cpp b/src/animation/backend/clipblendnode.cpp
index a763f7f48..94a956837 100644
--- a/src/animation/backend/clipblendnode.cpp
+++ b/src/animation/backend/clipblendnode.cpp
@@ -36,7 +36,7 @@
#include "clipblendnode_p.h"
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
-#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/qabstractanimationclip.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
@@ -57,107 +57,101 @@ ClipBlendNode::~ClipBlendNode()
{
}
-Qt3DCore::QNodeId ClipBlendNode::parentId() const
-{
- return m_parentId;
-}
-
-Qt3DCore::QNodeIdVector ClipBlendNode::childrenIds() const
-{
- return m_childrenIds;
-}
-
-Qt3DCore::QNodeIdVector ClipBlendNode::clipIds() const
-{
- return m_clipIds;
-}
-
-void ClipBlendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
-
- case Qt3DCore::PropertyValueAdded: {
- Qt3DCore::QPropertyNodeAddedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->metaObject()->inherits(&QAbstractClipBlendNode::staticMetaObject))
- addChildId(change->addedNodeId());
- else if (change->metaObject()->inherits(&QAnimationClip::staticMetaObject))
- m_clipIds.push_back(change->addedNodeId());
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- Qt3DCore::QPropertyNodeRemovedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->metaObject()->inherits(&QAbstractClipBlendNode::staticMetaObject))
- removeChildId(change->removedNodeId());
- else if (change->metaObject()->inherits(&QAnimationClip::staticMetaObject))
- m_clipIds.removeOne(change->removedNodeId());
- break;
- }
-
- default:
- break;
- }
-
- Qt3DCore::QBackendNode::sceneChangeEvent(e);
-}
-
void ClipBlendNode::setClipBlendNodeManager(ClipBlendNodeManager *manager)
{
m_manager = manager;
}
-ClipBlendNodeManager *ClipBlendNode::clipBlendNodeManager() const
+void ClipBlendNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
- return m_manager;
+ Q_UNUSED(change);
}
-void ClipBlendNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+ClipBlendNode::BlendType Animation::ClipBlendNode::blendType() const
{
- const auto creationChange = qSharedPointerCast<QClipBlendNodeCreatedChangeBase>(change);
- setParentId(creationChange->parentClipBlendNodeId());
- m_clipIds = creationChange->clips();
+ return m_blendType;
}
-void ClipBlendNode::setParentId(Qt3DCore::QNodeId parentId)
+void ClipBlendNode::setClipResults(Qt3DCore::QNodeId animatorId, const ClipResults &clipResults)
{
- if (parentId != m_parentId) {
- // We already had a parent, tell it to abandon us
- if (!m_parentId.isNull()) {
- ClipBlendNode *parent = m_manager->lookupNode(m_parentId);
- if (parent != nullptr)
- parent->m_childrenIds.removeAll(peerId());
- }
- m_parentId = parentId;
- ClipBlendNode *parent = m_manager->lookupNode(m_parentId);
- if (parent != nullptr && !parent->m_childrenIds.contains(peerId()))
- parent->m_childrenIds.append(peerId());
+ // Do we already have an entry for this animator?
+ const int animatorIndex = m_animatorIds.indexOf(animatorId);
+ if (animatorIndex == -1) {
+ // Nope, add it
+ m_animatorIds.push_back(animatorId);
+ m_clipResults.push_back(clipResults);
+ } else {
+ m_clipResults[animatorIndex] = clipResults;
}
}
-void ClipBlendNode::addChildId(Qt3DCore::QNodeId childId)
+ClipResults ClipBlendNode::clipResults(Qt3DCore::QNodeId animatorId) const
{
- if (!m_childrenIds.contains(childId)) {
- ClipBlendNode *child = m_manager->lookupNode(childId);
- if (child != nullptr) {
- m_childrenIds.push_back(childId);
- child->m_parentId = peerId();
- }
- }
+ const int animatorIndex = m_animatorIds.indexOf(animatorId);
+ if (animatorIndex != -1)
+ return m_clipResults[animatorIndex];
+ return ClipResults();
}
-void ClipBlendNode::removeChildId(Qt3DCore::QNodeId childId)
+/*!
+ \fn QVector<Qt3DCore::QNodeId> ClipBlendNode::currentDependencyIds() const
+ \internal
+
+ Each subclass of ClipBlendNode must implement this function such that it
+ returns a vector of the ids of ClipBlendNodes upon which is it dependent
+ in order to be able to evaluate given its current internal state.
+
+ For example, a subclass implementing a simple lerp blend between two
+ other nodes, would always return the ids of the nodes between which it
+ is lerping.
+
+ A more generalised lerp node that is capable of lerping between a
+ series of nodes would return the ids of the two nodes that correspond
+ to the blend values which sandwich the currently set blend value.
+
+ The animation handler will submit a job that uses this function to
+ build a list of clips that must be evaluated in order to later
+ evaluate the entire blend tree. In this way, the clips can all be
+ evaluated in one pass, and the tree in a subsequent pass.
+*/
+
+/*!
+ \fn QVector<Qt3DCore::QNodeId> ClipBlendNode::allDependencyIds() const
+ \internal
+
+ Similar to currentDependencyIds() but returns the ids of all potential
+ dependency nodes, not just those that are dependencies given the current
+ internal state. For example a generalised lerp node would return the ids
+ of all nodes that can participate in the lerp for any value of the blend
+ parameter. Not just those bounding the current blend value.
+*/
+
+/*!
+ \internal
+
+ Fetches the ClipResults from the nodes listed in the dependencyIds
+ and passes them to the doBlend() virtual function which should be
+ implemented in subclasses to perform the actual blend operation.
+ The results are then inserted into the clip results for this blend
+ node indexed by the \a animatorId.
+*/
+void ClipBlendNode::blend(Qt3DCore::QNodeId animatorId)
{
- if (m_childrenIds.contains(childId)) {
- ClipBlendNode *child = m_manager->lookupNode(childId);
- if (child != nullptr)
- child->m_parentId = Qt3DCore::QNodeId();
- m_childrenIds.removeAll(childId);
+ // Obtain the clip results from each of the dependencies
+ const QVector<Qt3DCore::QNodeId> dependencyNodeIds = currentDependencyIds();
+ const int dependencyCount = dependencyNodeIds.size();
+ QVector<ClipResults> blendData;
+ blendData.reserve(dependencyCount);
+ for (const auto dependencyId : dependencyNodeIds) {
+ ClipBlendNode *dependencyNode = clipBlendNodeManager()->lookupNode(dependencyId);
+ ClipResults blendDataElement = dependencyNode->clipResults(animatorId);
+ blendData.push_back(blendDataElement);
}
-}
-ClipBlendNode::BlendType Animation::ClipBlendNode::blendType() const
-{
- return m_blendType;
+ // Ask the blend node to perform the actual blend operation on the data
+ // from the dependencies
+ ClipResults blendedResults = doBlend(blendData);
+ setClipResults(animatorId, blendedResults);
}
} // Animation
diff --git a/src/animation/backend/clipblendnode_p.h b/src/animation/backend/clipblendnode_p.h
index d3af9301b..17eeed9b3 100644
--- a/src/animation/backend/clipblendnode_p.h
+++ b/src/animation/backend/clipblendnode_p.h
@@ -67,35 +67,37 @@ public:
enum BlendType {
NoneBlendType,
- LerpBlendType
+ LerpBlendType,
+ AdditiveBlendType,
+ ValueType
};
void setClipBlendNodeManager(ClipBlendNodeManager *manager);
+ inline ClipBlendNodeManager *clipBlendNodeManager() const { return m_manager; }
- ClipBlendNodeManager *clipBlendNodeManager() const;
BlendType blendType() const;
- Qt3DCore::QNodeId parentId() const;
- Qt3DCore::QNodeIdVector childrenIds() const;
- Qt3DCore::QNodeIdVector clipIds() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void blend(Qt3DCore::QNodeId animatorId);
+
+ void setClipResults(Qt3DCore::QNodeId animatorId, const ClipResults &clipResults);
+ ClipResults clipResults(Qt3DCore::QNodeId animatorId) const;
+
+ virtual QVector<Qt3DCore::QNodeId> allDependencyIds() const = 0;
+ virtual QVector<Qt3DCore::QNodeId> currentDependencyIds() const = 0;
+ virtual double duration() const = 0;
protected:
explicit ClipBlendNode(BlendType blendType);
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_OVERRIDE;
+ virtual ClipResults doBlend(const QVector<ClipResults> &blendData) const = 0;
private:
- void setParentId(Qt3DCore::QNodeId parentId);
- void addChildId(Qt3DCore::QNodeId childId);
- void removeChildId(Qt3DCore::QNodeId childId);
-
- // Can either contain clips or nothing (tree of other blend nodes)
- Qt3DCore::QNodeIdVector m_clipIds;
-
- Qt3DCore::QNodeId m_parentId;
- Qt3DCore::QNodeIdVector m_childrenIds;
ClipBlendNodeManager *m_manager;
BlendType m_blendType;
+
+ // Store the results of evaluations indexed by animator id
+ QVector<Qt3DCore::QNodeId> m_animatorIds;
+ QVector<ClipResults> m_clipResults;
};
template<typename Backend, typename Frontend>
diff --git a/src/animation/backend/clipblendnodevisitor.cpp b/src/animation/backend/clipblendnodevisitor.cpp
index 9940bd1f8..5e63a4e79 100644
--- a/src/animation/backend/clipblendnodevisitor.cpp
+++ b/src/animation/backend/clipblendnodevisitor.cpp
@@ -41,34 +41,130 @@
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-
namespace Animation {
-ClipBlendNodeVisitor::ClipBlendNodeVisitor(ClipBlendNodeManager *manager)
+/*!
+ \class ClipBlendNodeVisitor
+ \internal
+ Visits a blend tree in either pre- or post-order manner, optionally taking care
+ to only visit the nodes that are dependencies of evaluating the blend
+ tree.
+*/
+ClipBlendNodeVisitor::ClipBlendNodeVisitor(ClipBlendNodeManager *manager,
+ TraversalOrder order,
+ NodeFilter filter)
: m_manager(manager)
+ , m_order(order)
+ , m_filter(filter)
{
}
-void ClipBlendNodeVisitor::traverse(Qt3DCore::QNodeId rootId, const VisitFunction &visitFunction) const
+void ClipBlendNodeVisitor::traverse(Qt3DCore::QNodeId rootId,
+ const VisitFunction &visitFunction) const
{
ClipBlendNode *node = m_manager->lookupNode(rootId);
- if (node != nullptr)
- visit(node, visitFunction);
+ if (node != nullptr) {
+ switch (m_order) {
+ case PreOrder: {
+ switch (m_filter) {
+ case VisitAllNodes:
+ visitPreOrderAllNodes(node, visitFunction);
+ break;
+
+ case VisitOnlyDependencies:
+ visitPreOrderDependencyNodes(node, visitFunction);
+ break;
+ }
+
+ break;
+ }
+
+ case PostOrder: {
+ switch (m_filter) {
+ case VisitAllNodes:
+ visitPostOrderAllNodes(node, visitFunction);
+ break;
+
+ case VisitOnlyDependencies:
+ visitPostOrderDependencyNodes(node, visitFunction);
+ break;
+ }
+
+ break;
+ }
+ }
+ }
}
-void ClipBlendNodeVisitor::visit(ClipBlendNode *node, const VisitFunction &visitFunction) const
+/*!
+ \internal
+ Leaf to root traversal (Pre-order traversal) visiting all nodes even if
+ they will not participate in current evaluation of the blend tree.
+*/
+void ClipBlendNodeVisitor::visitPreOrderAllNodes(ClipBlendNode *node,
+ const VisitFunction &visitFunction) const
{
visitFunction(node);
- const Qt3DCore::QNodeIdVector childIds = node->childrenIds();
+ const Qt3DCore::QNodeIdVector childIds = node->allDependencyIds();
for (const Qt3DCore::QNodeId childId: childIds) {
ClipBlendNode *childNode = m_manager->lookupNode(childId);
if (childNode != nullptr)
- visit(childNode, visitFunction);
+ visitPreOrderAllNodes(childNode, visitFunction);
}
}
-} // Animation
+/*!
+ \internal
+ Leaf to root traversal (Post-order traversal) visiting all nodes even if
+ they will not participate in current evaluation of the blend tree.
+*/
+void ClipBlendNodeVisitor::visitPostOrderAllNodes(ClipBlendNode *node,
+ const VisitFunction &visitFunction) const
+{
+ const Qt3DCore::QNodeIdVector childIds = node->allDependencyIds();
+ for (const Qt3DCore::QNodeId childId: childIds) {
+ ClipBlendNode *childNode = m_manager->lookupNode(childId);
+ if (childNode != nullptr)
+ visitPostOrderAllNodes(childNode, visitFunction);
+ }
+ visitFunction(node);
+}
+
+/*!
+ \internal
+ Leaf to root traversal (Pre-order traversal) visiting only nodes required
+ to evaluate the blend tree given its current state.
+*/
+void ClipBlendNodeVisitor::visitPreOrderDependencyNodes(ClipBlendNode *node,
+ const VisitFunction &visitFunction) const
+{
+ visitFunction(node);
+ const Qt3DCore::QNodeIdVector childIds = node->currentDependencyIds();
+ for (const Qt3DCore::QNodeId childId: childIds) {
+ ClipBlendNode *childNode = m_manager->lookupNode(childId);
+ if (childNode != nullptr)
+ visitPreOrderDependencyNodes(childNode, visitFunction);
+ }
+}
+
+/*!
+ \internal
+ Leaf to root traversal (Post-order traversal) visiting only nodes required
+ to evaluate the blend tree given its current state.
+*/
+void ClipBlendNodeVisitor::visitPostOrderDependencyNodes(ClipBlendNode *node,
+ const VisitFunction &visitFunction) const
+{
+ const Qt3DCore::QNodeIdVector childIds = node->currentDependencyIds();
+ for (const Qt3DCore::QNodeId childId: childIds) {
+ ClipBlendNode *childNode = m_manager->lookupNode(childId);
+ if (childNode != nullptr)
+ visitPostOrderDependencyNodes(childNode, visitFunction);
+ }
+ visitFunction(node);
+}
+} // Animation
} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/animation/backend/clipblendnodevisitor_p.h b/src/animation/backend/clipblendnodevisitor_p.h
index d619c7132..1bedb206a 100644
--- a/src/animation/backend/clipblendnodevisitor_p.h
+++ b/src/animation/backend/clipblendnodevisitor_p.h
@@ -55,7 +55,6 @@
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-
namespace Animation {
class ClipBlendNodeManager;
@@ -66,18 +65,35 @@ using VisitFunction = std::function<void (ClipBlendNode *)>;
class Q_AUTOTEST_EXPORT ClipBlendNodeVisitor
{
public:
- explicit ClipBlendNodeVisitor(ClipBlendNodeManager *manager);
+ enum TraversalOrder {
+ PreOrder,
+ PostOrder
+ };
+
+ enum NodeFilter {
+ VisitAllNodes,
+ VisitOnlyDependencies
+ };
+
+ explicit ClipBlendNodeVisitor(ClipBlendNodeManager *manager,
+ TraversalOrder order = PostOrder,
+ NodeFilter filter = VisitAllNodes);
void traverse(Qt3DCore::QNodeId rootId, const VisitFunction &visitFunction) const;
private:
- void visit(ClipBlendNode *node, const VisitFunction &visitFunction) const;
+ void visitPreOrderAllNodes(ClipBlendNode *node, const VisitFunction &visitFunction) const;
+ void visitPostOrderAllNodes(ClipBlendNode *node, const VisitFunction &visitFunction) const;
+
+ void visitPreOrderDependencyNodes(ClipBlendNode *node, const VisitFunction &visitFunction) const;
+ void visitPostOrderDependencyNodes(ClipBlendNode *node, const VisitFunction &visitFunction) const;
ClipBlendNodeManager *m_manager;
+ TraversalOrder m_order;
+ NodeFilter m_filter;
};
} // Animation
-
} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/animation/backend/clipblendvalue.cpp b/src/animation/backend/clipblendvalue.cpp
new file mode 100644
index 000000000..2d4ed99d2
--- /dev/null
+++ b/src/animation/backend/clipblendvalue.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "clipblendvalue_p.h"
+#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
+#include <Qt3DAnimation/qclipblendvalue.h>
+#include <Qt3DAnimation/private/qclipblendvalue_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+ClipBlendValue::ClipBlendValue()
+ : ClipBlendNode(ValueType)
+{
+}
+
+ClipBlendValue::~ClipBlendValue()
+{
+}
+
+void ClipBlendValue::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+{
+ ClipBlendNode::initializeFromPeer(change);
+ const auto creationChange
+ = qSharedPointerCast<QClipBlendNodeCreatedChange<QClipBlendValueData>>(change);
+ const Qt3DAnimation::QClipBlendValueData data = creationChange->data;
+ m_clipId = data.clipId;
+}
+
+void ClipBlendValue::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+{
+ if (e->type() == Qt3DCore::PropertyUpdated) {
+ Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("clip"))
+ m_clipId = change->value().value<Qt3DCore::QNodeId>();
+ }
+}
+
+ClipResults ClipBlendValue::doBlend(const QVector<ClipResults> &blendData) const
+{
+ // Should never be called for the value node
+ Q_UNUSED(blendData);
+ Q_UNREACHABLE();
+ return ClipResults();
+}
+
+double ClipBlendValue::duration() const
+{
+ if (m_clipId.isNull())
+ return 0.0;
+ AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(m_clipId);
+ Q_ASSERT(clip);
+ return clip->duration();
+}
+
+void ClipBlendValue::setFormatIndices(Qt3DCore::QNodeId animatorId, const ComponentIndices &formatIndices)
+{
+ // Do we already have an entry for this animator?
+ const int animatorIndex = m_animatorIds.indexOf(animatorId);
+ if (animatorIndex == -1) {
+ // Nope, add it
+ m_animatorIds.push_back(animatorId);
+ m_formatIndicies.push_back(formatIndices);
+ } else {
+ m_formatIndicies[animatorIndex] = formatIndices;
+ }
+}
+
+ComponentIndices ClipBlendValue::formatIndices(Qt3DCore::QNodeId animatorId)
+{
+ const int animatorIndex = m_animatorIds.indexOf(animatorId);
+ if (animatorIndex != -1)
+ return m_formatIndicies[animatorIndex];
+ return ComponentIndices();
+}
+
+} // namespace Animation
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/backend/clipblendvalue_p.h b/src/animation/backend/clipblendvalue_p.h
new file mode 100644
index 000000000..6da800f98
--- /dev/null
+++ b/src/animation/backend/clipblendvalue_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_ANIMATION_CLIPBLENDVALUE_H
+#define QT3DANIMATION_ANIMATION_CLIPBLENDVALUE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DAnimation/private/clipblendnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+class Q_AUTOTEST_EXPORT ClipBlendValue : public ClipBlendNode
+{
+public:
+ ClipBlendValue();
+ ~ClipBlendValue();
+
+ inline Qt3DCore::QNodeId clipId() const { return m_clipId; }
+ void setClipId(Qt3DCore::QNodeId clipId) { m_clipId = clipId; } // For unit tests
+
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+ inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE
+ {
+ return currentDependencyIds();
+ }
+
+ inline QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_OVERRIDE
+ {
+ return { m_clipId };
+ }
+
+ double duration() const Q_DECL_OVERRIDE;
+
+ void setFormatIndices(Qt3DCore::QNodeId animatorId, const ComponentIndices &formatIndices);
+ ComponentIndices formatIndices(Qt3DCore::QNodeId animatorId);
+
+protected:
+ ClipResults doBlend(const QVector<ClipResults> &blendData) const Q_DECL_OVERRIDE;
+
+private:
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+
+ Qt3DCore::QNodeId m_clipId;
+
+ QVector<Qt3DCore::QNodeId> m_animatorIds;
+ QVector<ComponentIndices> m_formatIndicies;
+};
+
+} // namespace Animation
+} // namespace Qt3DAnimation
+
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_CLIPBLENDVALUE_H
diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp
index e15a419b1..76d24a4d3 100644
--- a/src/animation/backend/evaluateblendclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp
@@ -39,7 +39,10 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/animationutils_p.h>
-#include <Qt3DAnimation/private/lerpblend_p.h>
+#include <Qt3DAnimation/private/clipblendvalue_p.h>
+#include <Qt3DAnimation/private/lerpclipblend_p.h>
+#include <Qt3DAnimation/private/clipblendnodevisitor_p.h>
+#include <Qt3DAnimation/private/job_common_p.h>
QT_BEGIN_NAMESPACE
@@ -49,110 +52,71 @@ namespace Animation {
EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob()
: Qt3DCore::QAspectJob()
{
- // TO DO: Add Profiler ID
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0);
}
void EvaluateBlendClipAnimatorJob::run()
{
- const qint64 globalTime = m_handler->simulationTime();
- //qDebug() << Q_FUNC_INFO << "t_global =" << globalTime;
-
+ // Find the set of clips that need to be evaluated by querying each node
+ // in the blend tree.
+ // TODO: We should be able to cache this for each blend animator and only
+ // update when a node indicates its dependencies have changed as a result
+ // of blend factors changing
BlendedClipAnimator *blendedClipAnimator = m_handler->blendedClipAnimatorManager()->data(m_blendClipAnimatorHandle);
- Q_ASSERT(blendedClipAnimator);
-
- // TO DO: Right now we are doing LERP but refactor to handle other types
- ClipBlendNode *blendNode = m_handler->clipBlendNodeManager()->lookupNode(blendedClipAnimator->blendTreeRootId());
- Q_ASSERT(blendNode->blendType() == ClipBlendNode::LerpBlendType);
- LerpBlend *lerpBlendNode = static_cast<LerpBlend *>(blendNode);
-
- const Qt3DCore::QNodeIdVector clipIds = lerpBlendNode->clipIds();
+ Qt3DCore::QNodeId blendTreeRootId = blendedClipAnimator->blendTreeRootId();
+ const QVector<Qt3DCore::QNodeId> valueNodeIdsToEvaluate = gatherValueNodesToEvaluate(m_handler, blendTreeRootId);
- bool globalFinalFrame = false;
+ // Calculate the resulting duration of the blend tree based upon its current state
+ ClipBlendNodeManager *blendNodeManager = m_handler->clipBlendNodeManager();
+ ClipBlendNode *blendTreeRootNode = blendNodeManager->lookupNode(blendTreeRootId);
+ Q_ASSERT(blendTreeRootNode);
+ const double duration = blendTreeRootNode->duration();
- // Evaluate the fcurves for both clip
- AnimationClip *clip1 = m_handler->animationClipManager()->lookupResource(clipIds.first());
- AnimationClip *clip2 = m_handler->animationClipManager()->lookupResource(clipIds.last());
- Q_ASSERT(clip1 && clip2);
- bool finalFrame1 = false;
- bool finalFrame2 = false;
+ // Calculate the phase given the blend tree duration and global time
+ const qint64 globalTime = m_handler->simulationTime();
+ const AnimatorEvaluationData animatorData = evaluationDataForAnimator(blendedClipAnimator, globalTime);
int currentLoop = 0;
- const QVector<float> channelResultsClip1 = AnimationUtils::evaluateAtGlobalTime(clip1,
- globalTime,
- blendedClipAnimator->startTime(),
- blendedClipAnimator->loops(),
- currentLoop,
- finalFrame1);
- const QVector<float> channelResultsClip2 = AnimationUtils::evaluateAtGlobalTime(clip2,
- globalTime,
- blendedClipAnimator->startTime(),
- blendedClipAnimator->loops(),
- currentLoop,
- finalFrame2);
- globalFinalFrame = (finalFrame1 && finalFrame2);
-
- blendedClipAnimator->setCurrentLoop(currentLoop);
-
- // Perform blending between the two clips
- const float blendFactor = lerpBlendNode->blendFactor();
-
- QVector<AnimationUtils::MappingData> blendedMappingData;
- QVector<float> blendedValues;
-
- // Build a combined vector of blended value
- const QVector<AnimationUtils::BlendingMappingData> blendingMappingData = blendedClipAnimator->mappingData();
- for (const AnimationUtils::BlendingMappingData &mapping : blendingMappingData) {
-
- AnimationUtils::MappingData finalMapping;
- finalMapping.type = mapping.type;
- finalMapping.targetId = mapping.targetId;
- finalMapping.propertyName = mapping.propertyName;
-
- switch (mapping.blendAction) {
- case AnimationUtils::BlendingMappingData::ClipBlending: {
- Q_ASSERT(mapping.channelIndicesClip1.size() == mapping.channelIndicesClip2.size());
- for (int i = 0, m = mapping.channelIndicesClip1.size(); i < m; ++i) {
- const float value1 = channelResultsClip1.at(mapping.channelIndicesClip1[i]);
- const float value2 = channelResultsClip2.at(mapping.channelIndicesClip2[i]);
- const float blendedValue = ((1.0f - blendFactor) * value1) + (blendFactor * value2);
- finalMapping.channelIndices.push_back(blendedValues.size());
- blendedValues.push_back(blendedValue);
- }
- break;
- }
- case AnimationUtils::BlendingMappingData::NoBlending: {
- const bool useClip1 = !mapping.channelIndicesClip1.empty();
- const QVector<int> channelIndices = useClip1 ? mapping.channelIndicesClip1 : mapping.channelIndicesClip2;
- const QVector<float> values = useClip1 ? channelResultsClip1 : channelResultsClip2;
- for (int i = 0, m = channelIndices.size(); i < m; ++i) {
- const float value = values.at(channelIndices[i]);
- finalMapping.channelIndices.push_back(blendedValues.size());
- blendedValues.push_back(value);
- }
- break;
- }
- default:
- Q_UNREACHABLE();
- break;
- }
-
- blendedMappingData.push_back(finalMapping);
+ const double phase = phaseFromGlobalTime(animatorData.globalTime,
+ animatorData.startTime,
+ animatorData.playbackRate,
+ duration,
+ animatorData.loopCount,
+ currentLoop);
+
+ // Iterate over the value nodes of the blend tree, evaluate the
+ // contained animation clips at the current phase and store the results
+ // in the animator indexed by node.
+ AnimationClipLoaderManager *clipLoaderManager = m_handler->animationClipLoaderManager();
+ for (const auto valueNodeId : valueNodeIdsToEvaluate) {
+ ClipBlendValue *valueNode = static_cast<ClipBlendValue *>(blendNodeManager->lookupNode(valueNodeId));
+ Q_ASSERT(valueNode);
+ AnimationClip *clip = clipLoaderManager->lookupResource(valueNode->clipId());
+ Q_ASSERT(clip);
+
+ ClipResults rawClipResults = evaluateClipAtPhase(clip, phase);
+
+ // Reformat the clip results into the layout used by this animator/blend tree
+ ComponentIndices format = valueNode->formatIndices(blendedClipAnimator->peerId());
+ ClipResults formattedClipResults = formatClipResults(rawClipResults, format);
+ valueNode->setClipResults(blendedClipAnimator->peerId(), formattedClipResults);
}
- if (globalFinalFrame)
- blendedClipAnimator->setRunning(false);
+ // Evaluate the blend tree
+ ClipResults blendedResults = evaluateBlendTree(m_handler, blendedClipAnimator, blendTreeRootId);
- // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend)
- const QVector<Qt3DCore::QSceneChangePtr> changes = AnimationUtils::preparePropertyChanges(blendedClipAnimator->peerId(),
- blendedMappingData,
- blendedValues,
- globalFinalFrame);
+ const double localTime = phase * duration;
+ const bool finalFrame = isFinalFrame(localTime, duration, currentLoop, animatorData.loopCount);
+ // Prepare the property change events
+ const QVector<MappingData> mappingData = blendedClipAnimator->mappingData();
+ const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(blendedClipAnimator->peerId(),
+ mappingData,
+ blendedResults,
+ finalFrame);
// Send the property changes
blendedClipAnimator->sendPropertyChanges(changes);
-
}
-
} // Animation
} // Qt3DAnimation
diff --git a/src/animation/backend/evaluateblendclipanimatorjob_p.h b/src/animation/backend/evaluateblendclipanimatorjob_p.h
index 07db68fdc..a7822c8f9 100644
--- a/src/animation/backend/evaluateblendclipanimatorjob_p.h
+++ b/src/animation/backend/evaluateblendclipanimatorjob_p.h
@@ -50,6 +50,8 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DAnimation/private/handle_types_p.h>
+#include <Qt3DAnimation/private/animationutils_p.h>
+#include <Qt3DAnimation/private/blendedclipanimator_p.h>
QT_BEGIN_NAMESPACE
@@ -57,6 +59,7 @@ namespace Qt3DAnimation {
namespace Animation {
class Handler;
+class ClipBlendNode;
class EvaluateBlendClipAnimatorJob : public Qt3DCore::QAspectJob
{
diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp
index e547ec441..e89405d63 100644
--- a/src/animation/backend/evaluateclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateclipanimatorjob.cpp
@@ -39,6 +39,7 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/animationutils_p.h>
+#include <Qt3DAnimation/private/job_common_p.h>
QT_BEGIN_NAMESPACE
@@ -48,6 +49,7 @@ namespace Animation {
EvaluateClipAnimatorJob::EvaluateClipAnimatorJob()
: Qt3DCore::QAspectJob()
{
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0);
}
void EvaluateClipAnimatorJob::run()
@@ -61,27 +63,23 @@ void EvaluateClipAnimatorJob::run()
Q_ASSERT(clipAnimator);
// Evaluate the fcurves
- AnimationClip *clip = m_handler->animationClipManager()->lookupResource(clipAnimator->clipId());
+ AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId());
Q_ASSERT(clip);
- bool finalFrame = false;
- int currentLoop = 0;
- const QVector<float> channelResults = AnimationUtils::evaluateAtGlobalTime(clip,
- globalTime,
- clipAnimator->startTime(),
- clipAnimator->loops(),
- currentLoop,
- finalFrame);
+ // Prepare for evaluation (convert global time to local time ....)
+ const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, globalTime);
+ const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorEvaluationData);
+ const ClipResults channelResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime);
- if (finalFrame)
+ if (preEvaluationDataForClip.isFinalFrame)
clipAnimator->setRunning(false);
- clipAnimator->setCurrentLoop(currentLoop);
+ clipAnimator->setCurrentLoop(preEvaluationDataForClip.currentLoop);
// Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend)
- const QVector<Qt3DCore::QSceneChangePtr> changes = AnimationUtils::preparePropertyChanges(clipAnimator->peerId(),
- clipAnimator->mappingData(),
- channelResults,
- finalFrame);
+ const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(),
+ clipAnimator->mappingData(),
+ channelResults,
+ preEvaluationDataForClip.isFinalFrame);
// Send the property changes
clipAnimator->sendPropertyChanges(changes);
diff --git a/src/animation/backend/fcurve.cpp b/src/animation/backend/fcurve.cpp
index ce16fb429..809949472 100644
--- a/src/animation/backend/fcurve.cpp
+++ b/src/animation/backend/fcurve.cpp
@@ -92,25 +92,25 @@ void FCurve::read(const QJsonObject &json)
{
clearKeyframes();
- const QJsonArray keyframeArray = json[QLatin1String("keyframes")].toArray();
+ const QJsonArray keyframeArray = json[QLatin1String("keyFrames")].toArray();
const int keyframeCount = keyframeArray.size();
for (int i = 0; i < keyframeCount; ++i) {
const QJsonObject keyframeData = keyframeArray.at(i).toObject();
// Extract the keyframe local time and value
- const QJsonArray keyframeCoords = keyframeData[QLatin1String("co")].toArray();
+ const QJsonArray keyframeCoords = keyframeData[QLatin1String("coords")].toArray();
float localTime = keyframeCoords.at(0).toDouble();
Keyframe keyframe;
- keyframe.interpolation = Keyframe::Bezier;
+ keyframe.interpolation = QKeyFrame::BezierInterpolation;
keyframe.value = keyframeCoords.at(1).toDouble();
- const QJsonArray leftHandle = keyframeData[QLatin1String("handle_left")].toArray();
+ const QJsonArray leftHandle = keyframeData[QLatin1String("leftHandle")].toArray();
keyframe.leftControlPoint[0] = leftHandle.at(0).toDouble();
keyframe.leftControlPoint[1] = leftHandle.at(1).toDouble();
- const QJsonArray rightHandle = keyframeData[QLatin1String("handle_right")].toArray();
+ const QJsonArray rightHandle = keyframeData[QLatin1String("rightHandle")].toArray();
keyframe.rightControlPoint[0] = rightHandle.at(0).toDouble();
keyframe.rightControlPoint[1] = rightHandle.at(1).toDouble();
@@ -121,25 +121,60 @@ void FCurve::read(const QJsonObject &json)
// back so they do not interset.
}
-void Channel::read(const QJsonObject &json)
+void FCurve::setFromQChannelComponent(const QChannelComponent &qcc)
+{
+ clearKeyframes();
+
+ for (const auto &frontendKeyFrame : qcc) {
+ // Extract the keyframe local time and value
+ const float localTime = frontendKeyFrame.coordinates()[0];
+
+ Keyframe keyFrame;
+ keyFrame.interpolation = frontendKeyFrame.interpolationType();
+ keyFrame.value = frontendKeyFrame.coordinates()[1];
+ keyFrame.leftControlPoint = frontendKeyFrame.leftControlPoint();
+ keyFrame.rightControlPoint = frontendKeyFrame.rightControlPoint();
+ appendKeyframe(localTime, keyFrame);
+ }
+
+ // TODO: Ensure beziers have no loops or cusps by scaling the control points
+ // back so they do not interset.
+}
+
+void ChannelComponent::read(const QJsonObject &json)
{
- name = json[QLatin1String("name")].toString();
+ name = json[QLatin1String("channelComponentName")].toString();
fcurve.read(json);
}
-void ChannelGroup::read(const QJsonObject &json)
+void ChannelComponent::setFromQChannelComponent(const QChannelComponent &qcc)
{
- name = json[QLatin1String("group")].toString();
- const QJsonArray channelsArray = json[QLatin1String("channels")].toArray();
- const int channelCount = channelsArray.size();
- channels.resize(channelCount);
+ name = qcc.name();
+ fcurve.setFromQChannelComponent(qcc);
+}
+
+void Channel::read(const QJsonObject &json)
+{
+ name = json[QLatin1String("channelName")].toString();
+ const QJsonArray channelComponentsArray = json[QLatin1String("channelComponents")].toArray();
+ const int channelCount = channelComponentsArray.size();
+ channelComponents.resize(channelCount);
for (int i = 0; i < channelCount; ++i) {
- const QJsonObject channel = channelsArray.at(i).toObject();
- channels[i].read(channel);
+ const QJsonObject channel = channelComponentsArray.at(i).toObject();
+ channelComponents[i].read(channel);
}
}
+void Channel::setFromQChannel(const QChannel &qch)
+{
+ name = qch.name();
+ channelComponents.resize(qch.channelComponentCount());
+ int i = 0;
+ for (const auto &frontendChannelComponent : qch)
+ channelComponents[i++].setFromQChannelComponent(frontendChannelComponent);
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/fcurve_p.h b/src/animation/backend/fcurve_p.h
index def33941e..7ab1593d1 100644
--- a/src/animation/backend/fcurve_p.h
+++ b/src/animation/backend/fcurve_p.h
@@ -50,6 +50,10 @@
#include "keyframe_p.h"
#include "functionrangefinder_p.h"
+
+#include <Qt3DAnimation/qchannel.h>
+#include <Qt3DAnimation/qchannelcomponent.h>
+#include <Qt3DAnimation/qkeyframe.h>
#include <QtCore/qvector.h>
#ifndef QT_NO_DEBUG_STREAM
@@ -81,6 +85,7 @@ public:
float evaluateAtTime(float localTime) const;
void read(const QJsonObject &json);
+ void setFromQChannelComponent(const QChannelComponent &qcc);
private:
QVector<float> m_localTimes;
@@ -106,41 +111,43 @@ inline QDebug operator<<(QDebug dbg, const FCurve &fcurve)
}
#endif
-struct Channel
+struct ChannelComponent
{
QString name;
FCurve fcurve;
void read(const QJsonObject &json);
+ void setFromQChannelComponent(const QChannelComponent &qcc);
};
#ifndef QT_NO_DEBUG_STREAM
-inline QDebug operator<<(QDebug dbg, const Channel &channel)
+inline QDebug operator<<(QDebug dbg, const ChannelComponent &channelComponent)
{
QDebugStateSaver saver(dbg);
- dbg << "Channel Name: " << channel.name << endl
- << "Fcurve:" << channel.fcurve << endl;
+ dbg << "Channel Component Name: " << channelComponent.name << endl
+ << "FCurve:" << channelComponent.fcurve << endl;
return dbg;
}
#endif
-struct ChannelGroup
+struct Channel
{
QString name;
- QVector<Channel> channels;
+ QVector<ChannelComponent> channelComponents;
void read(const QJsonObject &json);
+ void setFromQChannel(const QChannel &qch);
};
#ifndef QT_NO_DEBUG_STREAM
-inline QDebug operator<<(QDebug dbg, const ChannelGroup &channelGroup)
+inline QDebug operator<<(QDebug dbg, const Channel &channel)
{
QDebugStateSaver saver(dbg);
- dbg << "Name: " << channelGroup.name << endl
- << "Channels:" << channelGroup.channels.size() << endl;
+ dbg << "Channel Name: " << channel.name << endl
+ << "Channels:" << channel.channelComponents.size() << endl;
- for (const auto channel : qAsConst(channelGroup.channels)) {
- dbg << channel;
+ for (const auto &channelComponent : qAsConst(channel.channelComponents)) {
+ dbg << channelComponent;
}
return dbg;
}
diff --git a/src/animation/backend/findrunningclipanimatorsjob.cpp b/src/animation/backend/findrunningclipanimatorsjob.cpp
index 3b2d9d4f5..80739a02b 100644
--- a/src/animation/backend/findrunningclipanimatorsjob.cpp
+++ b/src/animation/backend/findrunningclipanimatorsjob.cpp
@@ -39,6 +39,7 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/animationutils_p.h>
+#include <Qt3DAnimation/private/job_common_p.h>
QT_BEGIN_NAMESPACE
@@ -48,6 +49,7 @@ namespace Animation {
FindRunningClipAnimatorsJob::FindRunningClipAnimatorsJob()
: Qt3DCore::QAspectJob()
{
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FindRunningClipAnimator, 0);
}
void FindRunningClipAnimatorsJob::setDirtyClipAnimators(const QVector<HClipAnimator> &clipAnimatorHandles)
@@ -71,10 +73,10 @@ void FindRunningClipAnimatorsJob::run()
// TODO: Should be possible to parallelise this with the fcurve evaluation as
// sending the property change events doesn't happen until after evaluation
if (canRun) {
- const AnimationClip *clip = m_handler->animationClipManager()->lookupResource(clipAnimator->clipId());
+ const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId());
const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId());
Q_ASSERT(clip && mapper);
- const QVector<AnimationUtils::MappingData> mappingData = AnimationUtils::buildPropertyMappings(m_handler, clip, mapper);
+ const QVector<MappingData> mappingData = buildPropertyMappings(m_handler, clip, mapper);
clipAnimator->setMappingData(mappingData);
}
}
diff --git a/src/animation/backend/handle_types_p.h b/src/animation/backend/handle_types_p.h
index f2c6774d2..f6f77eb20 100644
--- a/src/animation/backend/handle_types_p.h
+++ b/src/animation/backend/handle_types_p.h
@@ -61,14 +61,12 @@ namespace Animation {
class AnimationClip;
class ClipAnimator;
class BlendedClipAnimator;
-class ConductedClipAnimator;
class ChannelMapping;
class ChannelMapper;
typedef Qt3DCore::QHandle<AnimationClip, 16> HAnimationClip;
typedef Qt3DCore::QHandle<ClipAnimator, 16> HClipAnimator;
typedef Qt3DCore::QHandle<BlendedClipAnimator, 12> HBlendedClipAnimator;
-typedef Qt3DCore::QHandle<ConductedClipAnimator, 8> HConductedClipAnimator;
typedef Qt3DCore::QHandle<ChannelMapping, 16> HChannelMapping;
typedef Qt3DCore::QHandle<ChannelMapper, 16> HChannelMapper;
diff --git a/src/animation/backend/handler.cpp b/src/animation/backend/handler.cpp
index 6dea5d6f3..04c46b40a 100644
--- a/src/animation/backend/handler.cpp
+++ b/src/animation/backend/handler.cpp
@@ -42,6 +42,8 @@
#include <Qt3DAnimation/private/buildblendtreesjob_p.h>
#include <Qt3DAnimation/private/evaluateblendclipanimatorjob_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
+#include <Qt3DAnimation/private/buildblendtreesjob_p.h>
+#include <Qt3DAnimation/private/evaluateblendclipanimatorjob_p.h>
QT_BEGIN_NAMESPACE
@@ -49,10 +51,9 @@ namespace Qt3DAnimation {
namespace Animation {
Handler::Handler()
- : m_animationClipManager(new AnimationClipManager)
+ : m_animationClipLoaderManager(new AnimationClipLoaderManager)
, m_clipAnimatorManager(new ClipAnimatorManager)
, m_blendedClipAnimatorManager(new BlendedClipAnimatorManager)
- , m_conductedClipAnimatorManager(new ConductedClipAnimatorManager)
, m_channelMappingManager(new ChannelMappingManager)
, m_channelMapperManager(new ChannelMapperManager)
, m_clipBlendNodeManager(new ClipBlendNodeManager)
@@ -74,7 +75,7 @@ void Handler::setDirty(DirtyFlag flag, Qt3DCore::QNodeId nodeId)
{
switch (flag) {
case AnimationClipDirty: {
- const auto handle = m_animationClipManager->lookupHandle(nodeId);
+ const auto handle = m_animationClipLoaderManager->lookupHandle(nodeId);
m_dirtyAnimationClips.push_back(handle);
break;
}
diff --git a/src/animation/backend/handler_p.h b/src/animation/backend/handler_p.h
index 3abaae215..52892f9d0 100644
--- a/src/animation/backend/handler_p.h
+++ b/src/animation/backend/handler_p.h
@@ -50,8 +50,6 @@
#include <QtGlobal>
#include <Qt3DAnimation/private/handle_types_p.h>
-#include <Qt3DAnimation/private/buildblendtreesjob_p.h>
-#include <Qt3DAnimation/private/evaluateblendclipanimatorjob_p.h>
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
#include <QtCore/qscopedpointer.h>
@@ -66,13 +64,11 @@ namespace Qt3DAnimation {
namespace Animation {
class AnimationClip;
-class AnimationClipManager;
+class AnimationClipLoaderManager;
class ClipAnimator;
class ClipAnimatorManager;
class BlendedClipAnimator;
class BlendedClipAnimatorManager;
-class ConductedClipAnimator;
-class ConductedClipAnimatorManager;
class ChannelMapping;
class ChannelMappingManager;
class ChannelMapper;
@@ -82,6 +78,11 @@ class ClipBlendNodeManager;
class FindRunningClipAnimatorsJob;
class LoadAnimationClipJob;
class EvaluateClipAnimatorJob;
+class BuildBlendTreesJob;
+class EvaluateBlendClipAnimatorJob;
+
+using BuildBlendTreesJobPtr = QSharedPointer<BuildBlendTreesJob>;
+using EvaluateBlendClipAnimatorJobPtr = QSharedPointer<EvaluateBlendClipAnimatorJob>;
class Q_AUTOTEST_EXPORT Handler
{
@@ -106,10 +107,9 @@ public:
void setBlendedClipAnimatorRunning(const HBlendedClipAnimator &handle, bool running);
QVector<HBlendedClipAnimator> runningBlenndedClipAnimators() const { return m_runningBlendedClipAnimators; }
- AnimationClipManager *animationClipManager() const Q_DECL_NOTHROW { return m_animationClipManager.data(); }
+ AnimationClipLoaderManager *animationClipLoaderManager() const Q_DECL_NOTHROW { return m_animationClipLoaderManager.data(); }
ClipAnimatorManager *clipAnimatorManager() const Q_DECL_NOTHROW { return m_clipAnimatorManager.data(); }
BlendedClipAnimatorManager *blendedClipAnimatorManager() const Q_DECL_NOTHROW { return m_blendedClipAnimatorManager.data(); }
- ConductedClipAnimatorManager *conductedClipAnimatorManager() const Q_DECL_NOTHROW { return m_conductedClipAnimatorManager.data(); }
ChannelMappingManager *channelMappingManager() const Q_DECL_NOTHROW { return m_channelMappingManager.data(); }
ChannelMapperManager *channelMapperManager() const Q_DECL_NOTHROW { return m_channelMapperManager.data(); }
ClipBlendNodeManager *clipBlendNodeManager() const Q_DECL_NOTHROW { return m_clipBlendNodeManager.data(); }
@@ -117,10 +117,9 @@ public:
QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time);
private:
- QScopedPointer<AnimationClipManager> m_animationClipManager;
+ QScopedPointer<AnimationClipLoaderManager> m_animationClipLoaderManager;
QScopedPointer<ClipAnimatorManager> m_clipAnimatorManager;
QScopedPointer<BlendedClipAnimatorManager> m_blendedClipAnimatorManager;
- QScopedPointer<ConductedClipAnimatorManager> m_conductedClipAnimatorManager;
QScopedPointer<ChannelMappingManager> m_channelMappingManager;
QScopedPointer<ChannelMapperManager> m_channelMapperManager;
QScopedPointer<ClipBlendNodeManager> m_clipBlendNodeManager;
diff --git a/src/animation/backend/keyframe_p.h b/src/animation/backend/keyframe_p.h
index 550c9fde0..9d2c3bc47 100644
--- a/src/animation/backend/keyframe_p.h
+++ b/src/animation/backend/keyframe_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <Qt3DAnimation/qkeyframe.h>
#include <QtGui/qvector2d.h>
QT_BEGIN_NAMESPACE
@@ -57,13 +58,6 @@ namespace Animation {
struct Keyframe
{
- enum Interpolation {
- Constant,
- Linear,
- Bezier
- // TODO: Add other easing types
- };
-
inline bool operator==(const Keyframe &rhs) const
{
return value == rhs.value
@@ -75,7 +69,7 @@ struct Keyframe
float value; // Value (time is stored separately in FCurve)
QVector2D leftControlPoint; // Bezier control point (time, value)
QVector2D rightControlPoint; // Bezier control point (time, value)
- Interpolation interpolation; // Method to use for evaluation between this Keyframe and the next
+ QKeyFrame::InterpolationType interpolation; // Method to use for evaluation between this Keyframe and the next
};
} // namespace Animation
diff --git a/src/animation/backend/lerpblend.cpp b/src/animation/backend/lerpclipblend.cpp
index 29261aadf..eef0072f9 100644
--- a/src/animation/backend/lerpblend.cpp
+++ b/src/animation/backend/lerpclipblend.cpp
@@ -34,9 +34,9 @@
**
****************************************************************************/
-#include "lerpblend_p.h"
+#include "lerpclipblend_p.h"
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
-#include <Qt3DAnimation/private/qlerpblend_p.h>
+#include <Qt3DAnimation/private/qlerpclipblend_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -45,33 +45,65 @@ namespace Qt3DAnimation {
namespace Animation {
-LerpBlend::LerpBlend()
+LerpClipBlend::LerpClipBlend()
: ClipBlendNode(ClipBlendNode::LerpBlendType)
+ , m_startClipId()
+ , m_endClipId()
, m_blendFactor(0.0f)
{
}
-LerpBlend::~LerpBlend()
+LerpClipBlend::~LerpClipBlend()
{
}
-void LerpBlend::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void LerpClipBlend::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == Qt3DCore::PropertyUpdated) {
Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
if (change->propertyName() == QByteArrayLiteral("blendFactor"))
m_blendFactor = change->value().toFloat();
+ else if (change->propertyName() == QByteArrayLiteral("startClip"))
+ m_startClipId = change->value().value<Qt3DCore::QNodeId>();
+ else if (change->propertyName() == QByteArrayLiteral("endClip"))
+ m_endClipId = change->value().value<Qt3DCore::QNodeId>();
}
}
-void LerpBlend::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+ClipResults LerpClipBlend::doBlend(const QVector<ClipResults> &blendData) const
+{
+ Q_ASSERT(blendData.size() == 2);
+ Q_ASSERT(blendData[0].size() == blendData[1].size());
+ const int elementCount = blendData.first().size();
+ ClipResults blendResults(elementCount);
+
+ for (int i = 0; i < elementCount; ++i)
+ blendResults[i] = (1.0f - m_blendFactor) * blendData[0][i] + (m_blendFactor * blendData[1][i]);
+
+ return blendResults;
+}
+
+void LerpClipBlend::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
ClipBlendNode::initializeFromPeer(change);
- const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpBlendData>>(change);
- const Qt3DAnimation::QLerpBlendData cloneData = creationChangeData->data;
+ const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpClipBlendData>>(change);
+ const Qt3DAnimation::QLerpClipBlendData cloneData = creationChangeData->data;
+ m_startClipId = cloneData.startClipId;
+ m_endClipId = cloneData.endClipId;
m_blendFactor = cloneData.blendFactor;
}
+double LerpClipBlend::duration() const
+{
+ ClipBlendNode *startNode = clipBlendNodeManager()->lookupNode(m_startClipId);
+ const double startNodeDuration = startNode ? startNode->duration() : 0.0;
+
+ ClipBlendNode *endNode = clipBlendNodeManager()->lookupNode(m_endClipId);
+ const double endNodeDuration = endNode ? endNode->duration() : 0.0;
+
+ return (1.0f - m_blendFactor) * startNodeDuration + m_blendFactor * endNodeDuration;
+}
+
} // Animation
} // Qt3DAnimation
diff --git a/src/animation/backend/lerpclipblend_p.h b/src/animation/backend/lerpclipblend_p.h
new file mode 100644
index 000000000..e09987759
--- /dev/null
+++ b/src/animation/backend/lerpclipblend_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_ANIMATION_LERPCLIPBLEND_P_H
+#define QT3DANIMATION_ANIMATION_LERPCLIPBLEND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DAnimation/private/clipblendnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+namespace Animation {
+
+class Q_AUTOTEST_EXPORT LerpClipBlend : public ClipBlendNode
+{
+public:
+ LerpClipBlend();
+ ~LerpClipBlend();
+
+ inline float blendFactor() const { return m_blendFactor; }
+ void setBlendFactor(float blendFactor) { m_blendFactor = blendFactor; } // For unit tests
+
+ inline Qt3DCore::QNodeId startClipId() const { return m_startClipId; }
+ void setStartClipId(Qt3DCore::QNodeId startClipId) { m_startClipId = startClipId; } // For unit tests
+
+ inline Qt3DCore::QNodeId endClipId() const { return m_endClipId; }
+ void setEndClipId(Qt3DCore::QNodeId endClipId) { m_endClipId = endClipId; } // For unit tests
+
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_FINAL;
+
+ inline QVector<Qt3DCore::QNodeId> allDependencyIds() const Q_DECL_OVERRIDE
+ {
+ return currentDependencyIds();
+ }
+
+ inline QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_OVERRIDE
+ {
+ return { m_startClipId, m_endClipId };
+ }
+
+ double duration() const Q_DECL_OVERRIDE;
+
+protected:
+ ClipResults doBlend(const QVector<ClipResults> &blendData) const Q_DECL_FINAL;
+
+private:
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+
+ Qt3DCore::QNodeId m_startClipId;
+ Qt3DCore::QNodeId m_endClipId;
+ float m_blendFactor;
+};
+
+} // Animation
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_LERPCLIPBLEND_P_H
diff --git a/src/animation/backend/loadanimationclipjob.cpp b/src/animation/backend/loadanimationclipjob.cpp
index c94435398..c0201e0e9 100644
--- a/src/animation/backend/loadanimationclipjob.cpp
+++ b/src/animation/backend/loadanimationclipjob.cpp
@@ -39,6 +39,7 @@
#include <Qt3DAnimation/private/animationclip_p.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DAnimation/private/managers_p.h>
+#include <Qt3DAnimation/private/job_common_p.h>
QT_BEGIN_NAMESPACE
@@ -49,6 +50,7 @@ LoadAnimationClipJob::LoadAnimationClipJob()
: Qt3DCore::QAspectJob()
, m_animationClipHandles()
{
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadAnimationClip, 0);
}
void LoadAnimationClipJob::addDirtyAnimationClips(const QVector<HAnimationClip> &animationClipHandles)
@@ -67,7 +69,7 @@ void LoadAnimationClipJob::clearDirtyAnimationClips()
void LoadAnimationClipJob::run()
{
Q_ASSERT(m_handler);
- AnimationClipManager *animationClipManager = m_handler->animationClipManager();
+ AnimationClipLoaderManager *animationClipManager = m_handler->animationClipLoaderManager();
for (const auto animationClipHandle : qAsConst(m_animationClipHandles)) {
AnimationClip *animationClip = animationClipManager->data(animationClipHandle);
animationClip->loadAnimation();
diff --git a/src/animation/backend/managers_p.h b/src/animation/backend/managers_p.h
index 42484921f..f99ed0698 100644
--- a/src/animation/backend/managers_p.h
+++ b/src/animation/backend/managers_p.h
@@ -56,7 +56,6 @@
#include <Qt3DAnimation/private/animationclip_p.h>
#include <Qt3DAnimation/private/blendedclipanimator_p.h>
#include <Qt3DAnimation/private/clipanimator_p.h>
-#include <Qt3DAnimation/private/conductedclipanimator_p.h>
#include <Qt3DAnimation/private/channelmapping_p.h>
#include <Qt3DAnimation/private/channelmapper_p.h>
#include <Qt3DCore/private/qresourcemanager_p.h>
@@ -68,14 +67,14 @@ namespace Animation {
class ClipBlendNode;
-class AnimationClipManager : public Qt3DCore::QResourceManager<
+class AnimationClipLoaderManager : public Qt3DCore::QResourceManager<
AnimationClip,
Qt3DCore::QNodeId,
16,
Qt3DCore::ArrayAllocatingPolicy>
{
public:
- AnimationClipManager() {}
+ AnimationClipLoaderManager() {}
};
class ClipAnimatorManager : public Qt3DCore::QResourceManager<
@@ -98,16 +97,6 @@ public:
BlendedClipAnimatorManager() {}
};
-class ConductedClipAnimatorManager : public Qt3DCore::QResourceManager<
- ConductedClipAnimator,
- Qt3DCore::QNodeId,
- 8,
- Qt3DCore::ArrayAllocatingPolicy>
-{
-public:
- ConductedClipAnimatorManager() {}
-};
-
class ChannelMappingManager : public Qt3DCore::QResourceManager<
ChannelMapping,
Qt3DCore::QNodeId,
@@ -149,7 +138,6 @@ private:
Q_DECLARE_RESOURCE_INFO(Qt3DAnimation::Animation::AnimationClip, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DAnimation::Animation::ClipAnimator, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DAnimation::Animation::BlendedClipAnimator, Q_REQUIRES_CLEANUP)
-Q_DECLARE_RESOURCE_INFO(Qt3DAnimation::Animation::ConductedClipAnimator, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DAnimation::Animation::ChannelMapping, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DAnimation::Animation::ChannelMapper, Q_REQUIRES_CLEANUP)
diff --git a/src/animation/frontend/frontend.pri b/src/animation/frontend/frontend.pri
index 9eeeede97..9ea438395 100644
--- a/src/animation/frontend/frontend.pri
+++ b/src/animation/frontend/frontend.pri
@@ -1,35 +1,76 @@
HEADERS += \
$$PWD/qanimationaspect.h \
$$PWD/qanimationaspect_p.h \
- $$PWD/qanimationclip.h \
- $$PWD/qanimationclip_p.h \
+ $$PWD/qabstractclipanimator.h \
+ $$PWD/qabstractclipanimator_p.h \
+ $$PWD/qabstractanimationclip.h \
+ $$PWD/qabstractanimationclip_p.h \
$$PWD/qabstractclipblendnode.h \
$$PWD/qabstractclipblendnode_p.h \
$$PWD/qclipanimator.h \
$$PWD/qclipanimator_p.h \
$$PWD/qblendedclipanimator.h \
$$PWD/qblendedclipanimator_p.h \
- $$PWD/qconductedclipanimator.h \
- $$PWD/qconductedclipanimator_p.h \
$$PWD/qchannelmapper.h \
$$PWD/qchannelmapper_p.h \
$$PWD/qchannelmapping.h \
$$PWD/qchannelmapping_p.h \
- $$PWD/qlerpblend.h \
- $$PWD/qlerpblend_p.h \
$$PWD/qclipblendnodecreatedchange.h \
- $$PWD/qclipblendnodecreatedchange_p.h
+ $$PWD/qclipblendnodecreatedchange_p.h \
+ $$PWD/qanimationcontroller.h \
+ $$PWD/qanimationcontroller_p.h \
+ $$PWD/qanimationgroup.h \
+ $$PWD/qanimationgroup_p.h \
+ $$PWD/qkeyframeanimation.h \
+ $$PWD/qkeyframeanimation_p.h \
+ $$PWD/qmorphinganimation.h \
+ $$PWD/qmorphinganimation_p.h \
+ $$PWD/qabstractanimation.h \
+ $$PWD/qabstractanimation_p.h \
+ $$PWD/qmorphtarget.h \
+ $$PWD/qmorphtarget_p.h \
+ $$PWD/qvertexblendanimation.h \
+ $$PWD/qvertexblendanimation_p.h \
+ $$PWD/qanimationcliploader.h \
+ $$PWD/qanimationclip_p.h \
+ $$PWD/qlerpclipblend.h \
+ $$PWD/qlerpclipblend_p.h \
+ $$PWD/qadditiveclipblend.h \
+ $$PWD/qadditiveclipblend_p.h \
+ $$PWD/qclipblendvalue.h \
+ $$PWD/qclipblendvalue_p.h \
+ $$PWD/qanimationclipdata.h \
+ $$PWD/qchannel.h \
+ $$PWD/qchannelcomponent.h \
+ $$PWD/qkeyframe.h \
+ $$PWD/qanimationclip.h \
+ $$PWD/qanimationclip_p.h
SOURCES += \
$$PWD/qanimationaspect.cpp \
- $$PWD/qanimationclip.cpp \
+ $$PWD/qabstractclipanimator.cpp \
+ $$PWD/qabstractanimationclip.cpp \
$$PWD/qabstractclipblendnode.cpp \
$$PWD/qclipanimator.cpp \
$$PWD/qblendedclipanimator.cpp \
- $$PWD/qconductedclipanimator.cpp \
$$PWD/qchannelmapper.cpp \
$$PWD/qchannelmapping.cpp \
- $$PWD/qlerpblend.cpp \
- $$PWD/qclipblendnodecreatedchange.cpp
+ $$PWD/qclipblendnodecreatedchange.cpp \
+ $$PWD/qanimationcontroller.cpp \
+ $$PWD/qanimationgroup.cpp \
+ $$PWD/qkeyframeanimation.cpp \
+ $$PWD/qmorphinganimation.cpp \
+ $$PWD/qabstractanimation.cpp \
+ $$PWD/qmorphtarget.cpp \
+ $$PWD/qvertexblendanimation.cpp \
+ $$PWD/qanimationcliploader.cpp \
+ $$PWD/qlerpclipblend.cpp \
+ $$PWD/qadditiveclipblend.cpp \
+ $$PWD/qclipblendvalue.cpp \
+ $$PWD/qanimationclipdata.cpp \
+ $$PWD/qchannel.cpp \
+ $$PWD/qchannelcomponent.cpp \
+ $$PWD/qkeyframe.cpp \
+ $$PWD/qanimationclip.cpp
INCLUDEPATH += $$PWD
diff --git a/src/extras/animations/qabstractanimation.cpp b/src/animation/frontend/qabstractanimation.cpp
index f87455c18..efac3f5ec 100644
--- a/src/extras/animations/qabstractanimation.cpp
+++ b/src/animation/frontend/qabstractanimation.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -35,11 +35,85 @@
****************************************************************************/
#include "qabstractanimation.h"
-#include "Qt3DExtras/private/qabstractanimation_p.h"
+#include "Qt3DAnimation/private/qabstractanimation_p.h"
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QAbstractAnimation
+ \brief An abstract base class for Qt3D animations
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits QObject
+
+ Qt3DAnimation::QAbstractAnimation is an abstract base class for all animations.
+ Qt3DAnimation::QAbstractAnimation can not be directly instantiated, but rather
+ through its subclasses. QAbstractAnimation specifies common properties
+ for all Qt3D animations, such as animation name and type, current position and animation
+ duration, while leaving the actual animating for the subclasses.
+*/
+
+/*!
+ \qmltype AbstractAnimation
+ \brief An abstract base type for Qt3D animations
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \instantiates Qt3DAnimation::QAbstractAnimation
+
+ AbstractAnimation is an abstract base type for all animations.
+ AbstractAnimation can not be directly instantiated, but rather
+ through its subtypes. AbstractAnimation specifies common properties
+ for all Qt3D animations, such as animation type, current position and animation
+ duration, while leaving the actual animating for the subtypes.
+*/
+/*!
+ \enum QAbstractAnimation::AnimationType
+
+ This enumeration specifies the type of the animation
+ \value KeyframeAnimation Simple keyframe animation implementation for QTransform
+ \value MorphingAnimation Blend-shape morphing animation
+ \value VertexBlendAnimation Vertex-blend animation
+*/
+/*!
+ \property Qt3DAnimation::QAbstractAnimation::animationName
+ Holds the name of the animation.
+*/
+/*!
+ \property Qt3DAnimation::QAbstractAnimation::animationType
+ Holds the type of the animation.
+*/
+/*!
+ \property Qt3DAnimation::QAbstractAnimation::position
+ Holds the current position of the animation.
+*/
+/*!
+ \property Qt3DAnimation::QAbstractAnimation::duration
+ Holds the duration of the animation.
+*/
+
+/*!
+ \qmlproperty string AbstractAnimation::animationName
+ Holds the name of the animation.
+*/
+/*!
+ \qmlproperty enumeration AbstractAnimation::animationType
+ Holds the type of the animation.
+ \list
+ \li KeyframeAnimation
+ \li MorphingAnimation
+ \li VertexBlendAnimation
+ \endlist
+*/
+/*!
+ \qmlproperty real AbstractAnimation::position
+ Holds the current position of the animation.
+*/
+/*!
+ \qmlproperty real AbstractAnimation::duration
+ Holds the duration of the animation.
+*/
QAbstractAnimationPrivate::QAbstractAnimationPrivate(QAbstractAnimation::AnimationType type)
: QObjectPrivate()
@@ -98,6 +172,9 @@ void QAbstractAnimation::setPosition(float position)
}
}
+/*!
+ Sets the \a duration of the animation.
+*/
void QAbstractAnimation::setDuration(float duration)
{
Q_D(QAbstractAnimation);
@@ -107,6 +184,6 @@ void QAbstractAnimation::setDuration(float duration)
}
}
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/extras/animations/qabstractanimation.h b/src/animation/frontend/qabstractanimation.h
index 242fe293a..0c6fe865e 100644
--- a/src/extras/animations/qabstractanimation.h
+++ b/src/animation/frontend/qabstractanimation.h
@@ -34,21 +34,21 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QABSTRACTANIMATION_H
-#define QT3DEXTRAS_QABSTRACTANIMATION_H
+#ifndef QT3DANIMATION_QABSTRACTANIMATION_H
+#define QT3DANIMATION_QABSTRACTANIMATION_H
#include <QtCore/qobject.h>
#include <QtCore/qvector.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QAbstractAnimationPrivate;
-class QT3DEXTRASSHARED_EXPORT QAbstractAnimation : public QObject
+class QT3DANIMATIONSHARED_EXPORT QAbstractAnimation : public QObject
{
Q_OBJECT
Q_PROPERTY(QString animationName READ animationName WRITE setAnimationName NOTIFY animationNameChanged)
@@ -62,6 +62,7 @@ public:
MorphingAnimation = 2,
VertexBlendAnimation = 3,
};
+ Q_ENUM(AnimationType)
QString animationName() const;
QAbstractAnimation::AnimationType animationType() const;
@@ -86,8 +87,8 @@ private:
Q_DECLARE_PRIVATE(QAbstractAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QABSTRACTANIMATION_H
+#endif // QT3DANIMATION_QABSTRACTANIMATION_H
diff --git a/src/extras/animations/qabstractanimation_p.h b/src/animation/frontend/qabstractanimation_p.h
index 1370ef2c7..e1c412b01 100644
--- a/src/extras/animations/qabstractanimation_p.h
+++ b/src/animation/frontend/qabstractanimation_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QABSTRACTANIMATION_P_H
-#define QT3DEXTRAS_QABSTRACTANIMATION_P_H
+#ifndef QT3DANIMATION_QABSTRACTANIMATION_P_H
+#define QT3DANIMATION_QABSTRACTANIMATION_P_H
//
// W A R N I N G
@@ -49,13 +49,13 @@
//
#include <private/qobject_p.h>
-#include <Qt3DExtras/QAbstractAnimation>
+#include <Qt3DAnimation/QAbstractAnimation>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
-class QAbstractAnimationPrivate : public QObjectPrivate
+class Q_AUTOTEST_EXPORT QAbstractAnimationPrivate : public QObjectPrivate
{
public:
QAbstractAnimationPrivate(QAbstractAnimation::AnimationType type);
@@ -68,8 +68,8 @@ public:
Q_DECLARE_PUBLIC(QAbstractAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
+#endif // QT3DANIMATION_QANIMATIONCONTROLLER_P_H
diff --git a/src/animation/frontend/qabstractanimationclip.cpp b/src/animation/frontend/qabstractanimationclip.cpp
new file mode 100644
index 000000000..7e6df4d70
--- /dev/null
+++ b/src/animation/frontend/qabstractanimationclip.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractanimationclip.h"
+#include "qabstractanimationclip_p.h"
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+QAbstractAnimationClipPrivate::QAbstractAnimationClipPrivate()
+ : Qt3DCore::QNodePrivate()
+ , m_duration(0.0f)
+{
+}
+
+void QAbstractAnimationClipPrivate::setDuration(float duration)
+{
+ if (qFuzzyCompare(duration, m_duration))
+ return;
+
+ Q_Q(QAbstractAnimationClip);
+ bool wasBlocked = q->blockNotifications(true);
+ m_duration = duration;
+ emit q->durationChanged(duration);
+ q->blockNotifications(wasBlocked);
+}
+
+/*!
+ \class Qt3DAnimation::QAbstractAnimationClip
+ \inherits Qt3DCore::QNode
+
+ \inmodule Qt3DAnimation
+ \since 5.9
+
+ \brief QAbstractAnimationClip is the base class for types providing key frame animation data.
+
+ To utilise the key frame animation framework in the Qt 3D Animation module
+ the animator component in use needs to be provided with the key frame animation data. The
+ animation data is provided by one of the concrete subclasses of QAbstractAnimationClip:
+
+ \list
+ \li Qt3DAnimation::QAnimationClip
+ \li Qt3DAnimation::QAnimationClipLoader
+ \endlist
+
+ QAnimationClip should be used when you want to create the animation data
+ programmatically within your application. The actual data is set with a
+ QAnimationClipData value type.
+
+ If you are loading baked animation data from a file, e.g. as created by an
+ artist, then use the QAnimationClipLoader class and set its \c source property.
+
+ Once the animation clip has been populated with data using the above
+ methods, the read-only duration property will be updated by the Qt 3D Animation
+ backend.
+
+ The typical usage of animation clips is:
+
+ \code
+ auto animator = new QClipAnimator();
+ auto clip = new QAnimationClipLoader();
+ clip->setSource(QUrl::fromLocalFile("bounce.json"));
+ animator->setClip(clip);
+ animator->setChannelMapper(...);
+ animator->setRunning(true);
+ \endcode
+
+ Animation clips are also used as the leaf node values in animation blend trees:
+
+ \code
+ // Create leaf nodes of blend tree
+ auto slideClipValue = new QClipBlendValue(
+ new QAnimationClipLoader(QUrl::fromLocalFile("slide.json")));
+ auto bounceClipValue = new QClipBlendValue(
+ new QAnimationClipLoader(QUrl::fromLocalFile("bounce.json")));
+
+ // Create blend tree inner node
+ auto additiveNode = new QAdditiveClipBlend();
+ additiveNode->setBaseClip(slideClipValue);
+ additiveNode->setAdditiveClip(bounceClipValue);
+ additiveNode->setAdditiveFactor(0.5f);
+
+ // Run the animator
+ auto animator = new QBlendedClipAnimator();
+ animator->setBlendTree(additiveNode);
+ animator->setChannelMapper(...);
+ animator->setRunning(true);
+ \endcode
+
+ \sa QAnimationClip, QAnimationClipLoader
+*/
+
+/*!
+ \internal
+*/
+QAbstractAnimationClip::QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd,
+ Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(dd, parent)
+{
+}
+
+/*!
+ Destroys this animation clip.
+*/
+QAbstractAnimationClip::~QAbstractAnimationClip()
+{
+}
+
+/*!
+ \property QAbstractAnimationClip::duration
+
+ Holds the duration of the animation clip in seconds. Gets updated once the
+ animation data is provided to Qt 3D using one of the concrete subclasses.
+*/
+float QAbstractAnimationClip::duration() const
+{
+ Q_D(const QAbstractAnimationClip);
+ return d->m_duration;
+}
+
+/*!
+ \internal
+*/
+void QAbstractAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+{
+ Q_D(QAbstractAnimationClip);
+ if (change->type() == Qt3DCore::PropertyUpdated) {
+ Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (e->propertyName() == QByteArrayLiteral("duration"))
+ d->setDuration(e->value().toFloat());
+ }
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qlerpblend.h b/src/animation/frontend/qabstractanimationclip.h
index 58fad7ff1..377725fa1 100644
--- a/src/animation/frontend/qlerpblend.h
+++ b/src/animation/frontend/qabstractanimationclip.h
@@ -34,45 +34,42 @@
**
****************************************************************************/
-#ifndef QT3DANIMATION_QLERPBLEND_H
-#define QT3DANIMATION_QLERPBLEND_H
+#ifndef QT3DANIMATION_QABSTRACTANIMATIONCLIP_H
+#define QT3DANIMATION_QABSTRACTANIMATIONCLIP_H
-#include <Qt3DAnimation/qabstractclipblendnode.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DCore/qnode.h>
+#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QLerpBlendPrivate;
+class QAbstractAnimationClipPrivate;
-class QT3DANIMATIONSHARED_EXPORT QLerpBlend : public QAbstractClipBlendNode
+class QT3DANIMATIONSHARED_EXPORT QAbstractAnimationClip : public Qt3DCore::QNode
{
Q_OBJECT
- Q_PROPERTY(float blendFactor READ blendFactor WRITE setBlendFactor NOTIFY blendFactorChanged)
+ Q_PROPERTY(float duration READ duration NOTIFY durationChanged)
public:
- explicit QLerpBlend(Qt3DCore::QNode *parent = nullptr);
- ~QLerpBlend();
+ ~QAbstractAnimationClip();
- float blendFactor() const;
-
-public Q_SLOTS:
- void setBlendFactor(float blendFactor);
+ float duration() const;
Q_SIGNALS:
- void blendFactorChanged(float blendFactor);
+ void durationChanged(float duration);
protected:
- explicit QLerpBlend(QLerpBlendPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
private:
- Q_DECLARE_PRIVATE(QLerpBlend)
- Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+ Q_DECLARE_PRIVATE(QAbstractAnimationClip)
};
-} // Qt3DAnimation
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
-
-#endif // QT3DANIMATION_QLERPBLEND_H
+#endif // QT3DANIMATION_QABSTRACTANIMATIONCLIP_H
diff --git a/src/animation/backend/lerpblend_p.h b/src/animation/frontend/qabstractanimationclip_p.h
index a28815349..8b74bee94 100644
--- a/src/animation/backend/lerpblend_p.h
+++ b/src/animation/frontend/qabstractanimationclip_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DANIMATION_ANIMATION_LERPBLEND_P_H
-#define QT3DANIMATION_ANIMATION_LERPBLEND_P_H
+#ifndef QT3DANIMATION_QABSTRACTANIMATIONCLIP_P_H
+#define QT3DANIMATION_QABSTRACTANIMATIONCLIP_P_H
//
// W A R N I N G
@@ -48,34 +48,29 @@
// We mean it.
//
-#include <Qt3DAnimation/private/clipblendnode_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+#include "qabstractanimationclip.h"
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-namespace Animation {
-
-class Q_AUTOTEST_EXPORT LerpBlend : public ClipBlendNode
+class QAbstractAnimationClipPrivate : public Qt3DCore::QNodePrivate
{
public:
- LerpBlend();
- ~LerpBlend();
-
- inline float blendFactor() const { return m_blendFactor; }
+ QAbstractAnimationClipPrivate();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_FINAL;
+ Q_DECLARE_PUBLIC(QAbstractAnimationClip)
-private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void setDuration(float duration);
- float m_blendFactor;
+ // Set from the backend
+ float m_duration;
};
-} // Animation
+} // namespace Qt3DAnimation
-} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DANIMATION_ANIMATION_LERPBLEND_P_H
+#endif // QT3DANIMATION_QABSTRACTANIMATIONCLIP_P_H
diff --git a/src/animation/frontend/qabstractclipanimator.cpp b/src/animation/frontend/qabstractclipanimator.cpp
new file mode 100644
index 000000000..0d215b470
--- /dev/null
+++ b/src/animation/frontend/qabstractclipanimator.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractclipanimator.h"
+#include "qabstractclipanimator_p.h"
+#include <Qt3DAnimation/qchannelmapper.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+QAbstractClipAnimatorPrivate::QAbstractClipAnimatorPrivate()
+ : Qt3DCore::QComponentPrivate()
+ , m_mapper(nullptr)
+ , m_running(false)
+ , m_loops(1)
+{
+}
+
+/*!
+ \qmltype AbsractClipAnimator
+ \instantiates Qt3DAnimation::QAbstractClipAnimator
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+
+ \brief AbstractClipAnimator is the base class for types providing animation playback
+ capabilities.
+
+ Subclasses of AbstractClipAnimator can be aggregated by an Entity to
+ provide animation capabilities. The animator components provide an
+ interface for controlling the animation (e.g. start, stop). Each animator
+ type requires some form of animation data such as an AbstractAnimationClip
+ as well as a ChannelMapper which describes how the channels in the
+ animation clip should be mapped onto the properties of the objects you wish
+ to animate.
+
+ The following subclasses are available:
+
+ \list
+ \li Qt3D.Animation.ClipAnimator
+ \li Qt3D.Animation.BlendedClipAnimator
+ \endlist
+*/
+
+/*!
+ \class Qt3DAnimation::QAbstractClipAnimator
+ \inherits Qt3DCore::QComponent
+
+ \inmodule Qt3DAnimation
+ \since 5.9
+
+ \brief QAbstractClipAnimator is the base class for types providing animation playback
+ capabilities.
+
+ Subclasses of QAbstractClipAnimator can be aggregated by a QEntity to
+ provide animation capabilities. The animator components provide an
+ interface for controlling the animation (e.g. start, stop). Each animator
+ type requires some form of animation data such as a QAbstractAnimationClip
+ as well as a QChannelMapper which describes how the channels in the
+ animation clip should be mapped onto the properties of the objects you wish
+ to animate.
+
+ The following subclasses are available:
+
+ \list
+ \li Qt3DAnimation::QClipAnimator
+ \li Qt3DAnimation::QBlendedClipAnimator
+ \endlist
+*/
+
+QAbstractClipAnimator::QAbstractClipAnimator(Qt3DCore::QNode *parent)
+ : Qt3DCore::QComponent(*new QAbstractClipAnimatorPrivate, parent)
+{
+}
+
+QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Qt3DCore::QNode *parent)
+ : Qt3DCore::QComponent(dd, parent)
+{
+}
+
+QAbstractClipAnimator::~QAbstractClipAnimator()
+{
+}
+
+/*!
+ \qmlproperty bool running
+
+ This property holds whether the animation is currently running.
+*/
+
+/*!
+ \property running
+
+ This property holds whether the animation is currently running.
+*/
+bool QAbstractClipAnimator::isRunning() const
+{
+ Q_D(const QAbstractClipAnimator);
+ return d->m_running;
+}
+
+/*!
+ \property ChannelMapper channelMapper
+
+ This property holds the ChannelMapper that controls how the channels in
+ the animation clip map onto the properties of the target objects.
+*/
+
+/*!
+ \property channelMapper
+
+ This property holds the QChannelMapper that controls how the channels in
+ the animation clip map onto the properties of the target objects.
+*/
+QChannelMapper *QAbstractClipAnimator::channelMapper() const
+{
+ Q_D(const QAbstractClipAnimator);
+ return d->m_mapper;
+}
+
+/*!
+ \qmlproperty int loops
+
+ This property holds the number of times the animation should play.
+
+ By default, loops is 1: the animation will play through once and then stop.
+
+ If set to QAbstractClipAnimator::Infinite, the animation will continuously
+ repeat until it is explicitly stopped.
+*/
+
+/*!
+ \property loops
+
+ This property holds the number of times the animation should play.
+
+ By default, loops is 1: the animation will play through once and then stop.
+
+ If set to QAbstractClipAnimator::Infinite, the animation will continuously
+ repeat until it is explicitly stopped.
+*/
+int QAbstractClipAnimator::loopCount() const
+{
+ Q_D(const QAbstractClipAnimator);
+ return d->m_loops;
+}
+
+void QAbstractClipAnimator::setRunning(bool running)
+{
+ Q_D(QAbstractClipAnimator);
+ if (d->m_running == running)
+ return;
+
+ d->m_running = running;
+ emit runningChanged(running);
+}
+
+void QAbstractClipAnimator::setChannelMapper(QChannelMapper *mapping)
+{
+ Q_D(QAbstractClipAnimator);
+ if (d->m_mapper == mapping)
+ return;
+
+ if (d->m_mapper)
+ d->unregisterDestructionHelper(d->m_mapper);
+
+ if (mapping && !mapping->parent())
+ mapping->setParent(this);
+ d->m_mapper = mapping;
+
+ // Ensures proper bookkeeping
+ if (d->m_mapper)
+ d->registerDestructionHelper(d->m_mapper, &QAbstractClipAnimator::setChannelMapper, d->m_mapper);
+ emit channelMapperChanged(mapping);
+}
+
+void QAbstractClipAnimator::setLoopCount(int loops)
+{
+ Q_D(QAbstractClipAnimator);
+ if (d->m_loops == loops)
+ return;
+
+ d->m_loops = loops;
+ emit loopCountChanged(loops);
+}
+
+/*!
+ Starts the animation.
+*/
+void QAbstractClipAnimator::start()
+{
+ setRunning(true);
+}
+
+/*!
+ Stops the animation.
+*/
+void QAbstractClipAnimator::stop()
+{
+ setRunning(false);
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qabstractclipanimator.h b/src/animation/frontend/qabstractclipanimator.h
new file mode 100644
index 000000000..bd38fd68b
--- /dev/null
+++ b/src/animation/frontend/qabstractclipanimator.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QABSTRACTCLIPANIMATOR_H
+#define QT3DANIMATION_QABSTRACTCLIPANIMATOR_H
+
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DCore/qcomponent.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QAnimationClip;
+class QChannelMapper;
+class QAbstractClipAnimatorPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QAbstractClipAnimator : public Qt3DCore::QComponent
+{
+ Q_OBJECT
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
+ Q_PROPERTY(Qt3DAnimation::QChannelMapper *channelMapper READ channelMapper WRITE setChannelMapper NOTIFY channelMapperChanged)
+
+public:
+ enum Loops { Infinite = -1 };
+ Q_ENUM(Loops)
+
+ ~QAbstractClipAnimator();
+
+ bool isRunning() const;
+ Qt3DAnimation::QChannelMapper *channelMapper() const;
+ int loopCount() const;
+
+public Q_SLOTS:
+ void setRunning(bool running);
+ void setChannelMapper(Qt3DAnimation::QChannelMapper *channelMapper);
+ void setLoopCount(int loops);
+
+ void start();
+ void stop();
+
+Q_SIGNALS:
+ void runningChanged(bool running);
+ void channelMapperChanged(Qt3DAnimation::QChannelMapper *channelMapper);
+ void loopCountChanged(int loops);
+
+protected:
+ explicit QAbstractClipAnimator(Qt3DCore::QNode *parent = nullptr);
+ QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractClipAnimator)
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QABSTRACTCLIPANIMATOR_H
diff --git a/src/animation/frontend/qconductedclipanimator_p.h b/src/animation/frontend/qabstractclipanimator_p.h
index c50247fa2..58553c8c1 100644
--- a/src/animation/frontend/qconductedclipanimator_p.h
+++ b/src/animation/frontend/qabstractclipanimator_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DANIMATION_QCONDUCTEDCLIPANIMATOR_P_H
-#define QT3DANIMATION_QCONDUCTEDCLIPANIMATOR_P_H
+#ifndef QT3DANIMATION_QABSTRACTCLIPANIMATOR_P_H
+#define QT3DANIMATION_QABSTRACTCLIPANIMATOR_P_H
//
// W A R N I N G
@@ -57,19 +57,25 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QConductedClipAnimatorPrivate : public Qt3DCore::QComponentPrivate
+class QChannelMapper;
+
+class QAbstractClipAnimatorPrivate : public Qt3DCore::QComponentPrivate
{
public:
- QConductedClipAnimatorPrivate();
+ QAbstractClipAnimatorPrivate();
- Q_DECLARE_PUBLIC(QConductedClipAnimator)
+ Q_DECLARE_PUBLIC(QAbstractClipAnimator)
- // TODO Add member variables
+ Qt3DAnimation::QChannelMapper *m_mapper;
+ bool m_running;
+ int m_loops;
};
-struct QConductedClipAnimatorData
+struct QAbstractClipAnimatorData
{
- // TODO: Add members that should be sent to the backend
+ Qt3DCore::QNodeId mapperId;
+ bool running;
+ int loops;
};
} // namespace Qt3DAnimation
@@ -77,4 +83,4 @@ struct QConductedClipAnimatorData
QT_END_NAMESPACE
-#endif // QT3DANIMATION_QCONDUCTEDCLIPANIMATOR_P_H
+#endif // QT3DANIMATION_QABSTRACTCLIPANIMATOR_P_H
diff --git a/src/animation/frontend/qabstractclipblendnode.cpp b/src/animation/frontend/qabstractclipblendnode.cpp
index 4154b4223..9860e969f 100644
--- a/src/animation/frontend/qabstractclipblendnode.cpp
+++ b/src/animation/frontend/qabstractclipblendnode.cpp
@@ -36,9 +36,6 @@
#include "qabstractclipblendnode.h"
#include "qabstractclipblendnode_p.h"
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DAnimation/qanimationclip.h>
QT_BEGIN_NAMESPACE
@@ -49,11 +46,82 @@ QAbstractClipBlendNodePrivate::QAbstractClipBlendNodePrivate()
{
}
+/*!
+ \qmltype AbstractClipBlendNode
+ \instantiates Qt3DAnimation::QAbstractClipBlendNode
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+
+ \brief AbstractClipBlendNode is the base class for types used to construct animation blend
+ trees.
+
+ Animation blend trees are used with a BlendedClipAnimator to dynamically blend a set of
+ animation clips together. The way in which the blending of animation clips is performed is
+ controlled by the structure of the blend tree and the properties on the nodes it contains.
+
+ The leaf nodes in a blend tree are containers for the input animation clips. These clips can be
+ baked clips read from file via AnimationClipLoader, or they can be clips that you build within
+ your application with AnimatitonClip and AnimationClipData. To include a clip in your blend
+ tree, wrap it in a ClipBlendValue node.
+
+ The interior nodes of a blend tree represent blending operations that will be applied to their
+ arguments which hold the input clips or even entire sub-trees of other blend tree nodes.
+
+ At present, the Qt 3D Animation module provides the following blend tree node types:
+
+ \list
+ \li Qt3D.Animation.ClipBlendValue
+ \li Qt3D.Animation.LerpClipBlend
+ \li Qt3D.Animation.QAdditiveClipBlend
+ \endlist
+
+ Additional node types representing other blending operations will be added in the future.
+
+ \sa BlendedClipAnimator
+*/
+
+/*!
+ \class Qt3DAnimation::QAbstractClipBlendNode
+ \inherits Qt3DCore::QNode
+
+ \inmodule Qt3DAnimation
+ \since 5.9
+
+ \brief QAbstractClipBlendNode is the base class for types used to construct animation blend
+ trees.
+
+ Animation blend trees are used with a QBlendedClipAnimator to dynamically blend a set of
+ animation clips together. The way in which the blending of animation clips is performed is
+ controlled by the structure of the blend tree and the properties on the nodes it contains.
+
+ The leaf nodes in a blend tree are containers for the input animation clips. These clips can be
+ baked clips read from file via QAnimationClipLoader, or they can be clips that you build within
+ your application with QAnimatitonClip and QAnimationClipData. To include a clip in your blend
+ tree, wrap it in a QClipBlendValue node.
+
+ The interior nodes of a blend tree represent blending operations that will be applied to their
+ arguments which hold the input clips or even entire sub-trees of other blend tree nodes.
+
+ At present, the Qt 3D Animation module provides the following blend tree node types:
+
+ \list
+ \li Qt3DAnimation::QClipBlendValue
+ \li Qt3DAnimation::QLerpClipBlend
+ \li Qt3DAnimation::QAdditiveClipBlend
+ \endlist
+
+ Additional node types representing other blending operations will be added in the future.
+
+ \sa QBlendedClipAnimator
+*/
+
+/*! \internal */
QAbstractClipBlendNode::QAbstractClipBlendNode(Qt3DCore::QNode *parent)
: Qt3DCore::QNode(*new QAbstractClipBlendNodePrivate(), parent)
{
}
+/*! \internal */
QAbstractClipBlendNode::QAbstractClipBlendNode(QAbstractClipBlendNodePrivate &dd, Qt3DCore::QNode *parent)
: Qt3DCore::QNode(dd, parent)
{
@@ -63,62 +131,6 @@ QAbstractClipBlendNode::~QAbstractClipBlendNode()
{
}
-void QAbstractClipBlendNode::addClip(QAnimationClip *clip)
-{
- Q_D(QAbstractClipBlendNode);
- if (!d->m_clips.contains(clip)) {
- d->m_clips.push_back(clip);
-
- // Ensures proper bookkeeping
- d->registerDestructionHelper(clip, &QAbstractClipBlendNode::removeClip, d->m_clips);
-
- // We need to add it as a child of the current node if it has been declared inline
- // Or not previously added as a child of the current node so that
- // 1) The backend gets notified about it's creation
- // 2) When the current node is destroyed, it gets destroyed as well
- if (!clip->parent())
- clip->setParent(this);
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), clip);
- change->setPropertyName("clip");
- d->notifyObservers(change);
- }
- }
-}
-
-void QAbstractClipBlendNode::removeClip(QAnimationClip *clip)
-{
- Q_D(QAbstractClipBlendNode);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), clip);
- change->setPropertyName("clip");
- d->notifyObservers(change);
- }
- d->m_clips.removeOne(clip);
- // Remove bookkeeping connection
- d->unregisterDestructionHelper(clip);
-}
-
-QVector<QAnimationClip *> QAbstractClipBlendNode::clips() const
-{
- Q_D(const QAbstractClipBlendNode);
- return d->m_clips;
-}
-
-QAbstractClipBlendNode *QAbstractClipBlendNode::parentClipBlendNode() const
-{
- QAbstractClipBlendNode *parentBlendClipNode = nullptr;
- QNode *parentN = parentNode();
- while (parentN != nullptr) {
- parentBlendClipNode = qobject_cast<QAbstractClipBlendNode *>(parentN);
- if (parentBlendClipNode != nullptr)
- break;
- parentN = parentN->parentNode();
- }
- return parentBlendClipNode;
-}
-
} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/animation/frontend/qabstractclipblendnode.h b/src/animation/frontend/qabstractclipblendnode.h
index 35714026c..d981bd7a5 100644
--- a/src/animation/frontend/qabstractclipblendnode.h
+++ b/src/animation/frontend/qabstractclipblendnode.h
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QAnimationClip;
+class QAbstractAnimationClip;
class QAbstractClipBlendNodePrivate;
class QT3DANIMATIONSHARED_EXPORT QAbstractClipBlendNode : public Qt3DCore::QNode
@@ -53,16 +53,10 @@ class QT3DANIMATIONSHARED_EXPORT QAbstractClipBlendNode : public Qt3DCore::QNode
public:
~QAbstractClipBlendNode();
- QVector<QAnimationClip *> clips() const;
- QAbstractClipBlendNode *parentClipBlendNode() const;
- void addClip(QAnimationClip *clip);
- void removeClip(QAnimationClip *clip);
-
protected:
explicit QAbstractClipBlendNode(Qt3DCore::QNode *parent = nullptr);
explicit QAbstractClipBlendNode(QAbstractClipBlendNodePrivate &dd, Qt3DCore::QNode *parent = nullptr);
-
private:
Q_DECLARE_PRIVATE(QAbstractClipBlendNode)
};
diff --git a/src/animation/frontend/qabstractclipblendnode_p.h b/src/animation/frontend/qabstractclipblendnode_p.h
index 42e10f18c..3066682a5 100644
--- a/src/animation/frontend/qabstractclipblendnode_p.h
+++ b/src/animation/frontend/qabstractclipblendnode_p.h
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QAnimationClip;
+class QAbstractAnimationClip;
class QAbstractClipBlendNode;
class QAbstractClipBlendNodePrivate : public Qt3DCore::QNodePrivate
@@ -63,7 +63,7 @@ public:
QAbstractClipBlendNodePrivate();
Q_DECLARE_PUBLIC(QAbstractClipBlendNode)
- QVector<QAnimationClip *> m_clips;
+ QVector<QAbstractAnimationClip *> m_clips;
};
} // namespace Qt3DAnimation
diff --git a/src/animation/frontend/qadditiveclipblend.cpp b/src/animation/frontend/qadditiveclipblend.cpp
new file mode 100644
index 000000000..58ef5e577
--- /dev/null
+++ b/src/animation/frontend/qadditiveclipblend.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qadditiveclipblend.h"
+#include "qadditiveclipblend_p.h"
+#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+
+/*!
+ \qmltype AdditiveClipBlend
+ \instantiates Qt3DAnimation::QAdditiveClipBlend
+ \inqmlmodule Qt3D.Animation
+
+ \since 5.9
+
+ \brief Performs an additive blend of two animation clips based on an additive factor.
+
+ QAdditiveClipBlend can be useful to create advanced animation effects based on
+ individual animation clips. For example, if you:
+
+ \list
+ \li set the baseClip property to a normal walk cycle animation clip and
+ \li set the additiveClip property to a shaking head difference clip,
+ \endlist
+
+ then adjusting the additiveFactor property will control how much of the additiveClip gets added
+ on to the baseClip. This has he effect that with an additiveFactor of zero, this blend node will
+ yield the original walk cycle clip. With an additiveFactor of 1, it will yield the walk cycle
+ including a shaking head animation.
+
+ The blending operation implemented by this class is:
+
+ \badcode
+ resultClip = baseClip + additiveFactor * additiveClip
+ \endcode
+
+ There is nothing stopping you from using values for the additiveFacor property outside the 0 to
+ 1 range, but please be aware that the input animation clips may not be authored in such a way
+ for this to make sense.
+
+ \sa BlendedClipAnimator
+*/
+
+/*!
+ \class Qt3DAnimation::QAdditiveClipBlend
+ \inherits Qt3DAnimation::QAbstractClipBlendNode
+
+ \inmodule Qt3DAnimation
+ \since 5.9
+
+ \brief Performs an additive blend of two animation clips based on an additive factor.
+
+ QAdditiveClipBlend can be useful to create advanced animation effects based on
+ individual animation clips. For example, if you:
+
+ \list
+ \li set the baseClip property to a normal walk cycle animation clip and
+ \li set the additiveClip property to a shaking head difference clip,
+ \endlist
+
+ then adjusting the additiveFactor property will control how much of the additiveClip gets added
+ on to the baseClip. This has he effect that with an additiveFactor of zero, this blend node will
+ yield the original walk cycle clip. With an additiveFactor of 1, it will yield the walk cycle
+ including a shaking head animation.
+
+ The blending operation implemented by this class is:
+
+ \badcode
+ resultClip = baseClip + additiveFactor * additiveClip
+ \endcode
+
+ There is nothing stopping you from using values for the additiveFacor property outside the 0 to
+ 1 range, but please be aware that the input animation clips may not be authored in such a way
+ for this to make sense.
+
+ \sa QBlendedClipAnimator
+*/
+
+QAdditiveClipBlendPrivate::QAdditiveClipBlendPrivate()
+ : QAbstractClipBlendNodePrivate()
+ , m_baseClip(nullptr)
+ , m_additiveClip(nullptr)
+ , m_additiveFactor(0.0f)
+{
+}
+
+QAdditiveClipBlend::QAdditiveClipBlend(Qt3DCore::QNode *parent)
+ : QAbstractClipBlendNode(*new QAdditiveClipBlendPrivate(), parent)
+{
+}
+
+QAdditiveClipBlend::QAdditiveClipBlend(QAdditiveClipBlendPrivate &dd, Qt3DCore::QNode *parent)
+ : QAbstractClipBlendNode(dd, parent)
+{
+}
+
+QAdditiveClipBlend::~QAdditiveClipBlend()
+{
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QAdditiveClipBlend::createNodeCreationChange() const
+{
+ Q_D(const QAdditiveClipBlend);
+ auto creationChange = QClipBlendNodeCreatedChangePtr<QAdditiveClipBlendData>::create(this);
+ QAdditiveClipBlendData &data = creationChange->data;
+ data.baseClipId = Qt3DCore::qIdForNode(d->m_baseClip);
+ data.additiveClipId = Qt3DCore::qIdForNode(d->m_additiveClip);
+ data.additiveFactor = d->m_additiveFactor;
+ return creationChange;
+}
+
+/*!
+ \qmlproperty real AdditiveClipBlend::additiveFactor
+
+ Specifies the blending factor, typically between 0 and 1, to control the blending of
+ two animation clips.
+*/
+/*!
+ \property QAdditiveClipBlend::additiveFactor
+
+ Specifies the blending factor, typically between 0 and 1, to control the blending of
+ two animation clips.
+ */
+float QAdditiveClipBlend::additiveFactor() const
+{
+ Q_D(const QAdditiveClipBlend);
+ return d->m_additiveFactor;
+}
+
+/*!
+ \qmlproperty AbstractClipBlendNode baseClip
+
+ This property holds the base animation clip. When the additiveFacgtor is zero the baseClip will
+ also be the resulting clip of this blend node.
+*/
+/*!
+ \property baseClip
+
+ This property holds the base animation clip. When the additiveFacgtor is zero the baseClip will
+ also be the resulting clip of this blend node.
+*/
+QAbstractClipBlendNode *QAdditiveClipBlend::baseClip() const
+{
+ Q_D(const QAdditiveClipBlend);
+ return d->m_baseClip;
+}
+
+/*!
+ \qmlproperty AbstractClipBlendNode additiveClip
+
+ This property holds the additive clip to be blended with the baseClip. The amount of blending
+ is controlled by the additiveFactor property.
+*/
+/*!
+ \property additiveClip
+
+ This property holds the additive clip to be blended with the baseClip. The amount of blending
+ is controlled by the additiveFactor property.
+*/
+QAbstractClipBlendNode *QAdditiveClipBlend::additiveClip() const
+{
+ Q_D(const QAdditiveClipBlend);
+ return d->m_additiveClip;
+}
+
+void QAdditiveClipBlend::setAdditiveFactor(float additiveFactor)
+{
+ Q_D(QAdditiveClipBlend);
+ if (d->m_additiveFactor == additiveFactor)
+ return;
+
+ d->m_additiveFactor = additiveFactor;
+ emit additiveFactorChanged(additiveFactor);
+}
+
+void QAdditiveClipBlend::setBaseClip(QAbstractClipBlendNode *baseClip)
+{
+ Q_D(QAdditiveClipBlend);
+ if (d->m_baseClip == baseClip)
+ return;
+
+ if (d->m_baseClip)
+ d->unregisterDestructionHelper(d->m_baseClip);
+
+ if (baseClip && !baseClip->parent())
+ baseClip->setParent(this);
+ d->m_baseClip = baseClip;
+
+ // Ensures proper bookkeeping
+ if (d->m_baseClip)
+ d->registerDestructionHelper(d->m_baseClip, &QAdditiveClipBlend::setBaseClip, d->m_baseClip);
+
+ emit baseClipChanged(baseClip);
+}
+
+void QAdditiveClipBlend::setAdditiveClip(QAbstractClipBlendNode *additiveClip)
+{
+ Q_D(QAdditiveClipBlend);
+ if (d->m_additiveClip == additiveClip)
+ return;
+
+ if (d->m_additiveClip)
+ d->unregisterDestructionHelper(d->m_additiveClip);
+
+ if (additiveClip && !additiveClip->parent())
+ additiveClip->setParent(this);
+ d->m_additiveClip = additiveClip;
+
+ // Ensures proper bookkeeping
+ if (d->m_additiveClip)
+ d->registerDestructionHelper(d->m_additiveClip, &QAdditiveClipBlend::setAdditiveClip, d->m_additiveClip);
+ emit additiveClipChanged(additiveClip);
+}
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qadditiveclipblend.h b/src/animation/frontend/qadditiveclipblend.h
new file mode 100644
index 000000000..11731c702
--- /dev/null
+++ b/src/animation/frontend/qadditiveclipblend.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QADDITIVECLIPBLEND_H
+#define QT3DANIMATION_QADDITIVECLIPBLEND_H
+
+#include <Qt3DAnimation/qabstractclipblendnode.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QAdditiveClipBlendPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QAdditiveClipBlend : public QAbstractClipBlendNode
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *baseClip READ baseClip WRITE setBaseClip NOTIFY baseClipChanged)
+ Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *additiveClip READ additiveClip WRITE setAdditiveClip NOTIFY additiveClipChanged)
+ Q_PROPERTY(float additiveFactor READ additiveFactor WRITE setAdditiveFactor NOTIFY additiveFactorChanged)
+public:
+ explicit QAdditiveClipBlend(Qt3DCore::QNode *parent = nullptr);
+ ~QAdditiveClipBlend();
+
+ float additiveFactor() const;
+ Qt3DAnimation::QAbstractClipBlendNode *baseClip() const;
+ Qt3DAnimation::QAbstractClipBlendNode *additiveClip() const;
+
+public Q_SLOTS:
+ void setAdditiveFactor(float additiveFactor);
+ void setBaseClip(Qt3DAnimation::QAbstractClipBlendNode *baseClip);
+ void setAdditiveClip(Qt3DAnimation::QAbstractClipBlendNode *additiveClip);
+
+Q_SIGNALS:
+ void additiveFactorChanged(float additiveFactor);
+ void baseClipChanged(Qt3DAnimation::QAbstractClipBlendNode *baseClip);
+ void additiveClipChanged(Qt3DAnimation::QAbstractClipBlendNode *additiveClip);
+
+protected:
+ explicit QAdditiveClipBlend(QAdditiveClipBlendPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QAdditiveClipBlend)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QADDITIVECLIPBLEND_H
diff --git a/src/animation/frontend/qadditiveclipblend_p.h b/src/animation/frontend/qadditiveclipblend_p.h
new file mode 100644
index 000000000..0c408c9ff
--- /dev/null
+++ b/src/animation/frontend/qadditiveclipblend_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QADDITIVEBLEND_P_H
+#define QT3DANIMATION_QADDITIVEBLEND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DAnimation/private/qabstractclipblendnode_p.h>
+#include <Qt3DCore/qnodeid.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QAdditiveClipBlend;
+
+class QAdditiveClipBlendPrivate : public QAbstractClipBlendNodePrivate
+{
+public:
+ QAdditiveClipBlendPrivate();
+
+ Q_DECLARE_PUBLIC(QAdditiveClipBlend)
+ Qt3DAnimation::QAbstractClipBlendNode *m_baseClip;
+ Qt3DAnimation::QAbstractClipBlendNode *m_additiveClip;
+ float m_additiveFactor;
+};
+
+struct QAdditiveClipBlendData
+{
+ Qt3DCore::QNodeId baseClipId;
+ Qt3DCore::QNodeId additiveClipId;
+ float additiveFactor;
+};
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QADDITIVEBLEND_P_H
diff --git a/src/animation/frontend/qanimationaspect.cpp b/src/animation/frontend/qanimationaspect.cpp
index 3310a8b77..00f97d5b6 100644
--- a/src/animation/frontend/qanimationaspect.cpp
+++ b/src/animation/frontend/qanimationaspect.cpp
@@ -39,17 +39,20 @@
#include "qanimationaspect.h"
#include "qanimationaspect_p.h"
-#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/qabstractanimationclip.h>
#include <Qt3DAnimation/qblendedclipanimator.h>
#include <Qt3DAnimation/qclipanimator.h>
-#include <Qt3DAnimation/qconductedclipanimator.h>
#include <Qt3DAnimation/qchannelmapping.h>
#include <Qt3DAnimation/qchannelmapper.h>
-#include <Qt3DAnimation/qlerpblend.h>
+#include <Qt3DAnimation/qlerpclipblend.h>
+#include <Qt3DAnimation/qadditiveclipblend.h>
+#include <Qt3DAnimation/qclipblendvalue.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/nodefunctor_p.h>
-#include <Qt3DAnimation/private/lerpblend_p.h>
+#include <Qt3DAnimation/private/lerpclipblend_p.h>
+#include <Qt3DAnimation/private/clipblendvalue_p.h>
+#include <Qt3DAnimation/private/additiveclipblend_p.h>
QT_BEGIN_NAMESPACE
@@ -87,30 +90,33 @@ QAnimationAspect::QAnimationAspect(QAnimationAspectPrivate &dd, QObject *parent)
{
setObjectName(QStringLiteral("Animation Aspect"));
Q_D(QAnimationAspect);
- qRegisterMetaType<Qt3DAnimation::QAnimationClip*>();
+ qRegisterMetaType<Qt3DAnimation::QAnimationClipLoader*>();
qRegisterMetaType<Qt3DAnimation::QChannelMapper*>();
- registerBackendType<QAnimationClip>(
- QSharedPointer<Animation::NodeFunctor<Animation::AnimationClip, Animation::AnimationClipManager>>::create(d->m_handler.data(),
- d->m_handler->animationClipManager()));
+ registerBackendType<QAbstractAnimationClip>(
+ QSharedPointer<Animation::NodeFunctor<Animation::AnimationClip, Animation::AnimationClipLoaderManager>>::create(d->m_handler.data(),
+ d->m_handler->animationClipLoaderManager()));
registerBackendType<QClipAnimator>(
QSharedPointer<Animation::NodeFunctor<Animation::ClipAnimator, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->clipAnimatorManager()));
registerBackendType<QBlendedClipAnimator>(
QSharedPointer<Animation::NodeFunctor<Animation::BlendedClipAnimator, Animation::BlendedClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->blendedClipAnimatorManager()));
- registerBackendType<QConductedClipAnimator>(
- QSharedPointer<Animation::NodeFunctor<Animation::ConductedClipAnimator, Animation::ConductedClipAnimatorManager>>::create(d->m_handler.data(),
- d->m_handler->conductedClipAnimatorManager()));
registerBackendType<QChannelMapping>(
QSharedPointer<Animation::NodeFunctor<Animation::ChannelMapping, Animation::ChannelMappingManager>>::create(d->m_handler.data(),
d->m_handler->channelMappingManager()));
registerBackendType<QChannelMapper>(
QSharedPointer<Animation::NodeFunctor<Animation::ChannelMapper, Animation::ChannelMapperManager>>::create(d->m_handler.data(),
d->m_handler->channelMapperManager()));
- registerBackendType<QLerpBlend>(
- QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::LerpBlend, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
- d->m_handler->clipBlendNodeManager()));
+ registerBackendType<QLerpClipBlend>(
+ QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::LerpClipBlend, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
+ d->m_handler->clipBlendNodeManager()));
+ registerBackendType<QAdditiveClipBlend>(
+ QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::AdditiveClipBlend, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
+ d->m_handler->clipBlendNodeManager()));
+ registerBackendType<QClipBlendValue>(
+ QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::ClipBlendValue, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
+ d->m_handler->clipBlendNodeManager()));
}
/*! \internal */
diff --git a/src/animation/frontend/qanimationclip.cpp b/src/animation/frontend/qanimationclip.cpp
index 56fe3978c..c21d94b02 100644
--- a/src/animation/frontend/qanimationclip.cpp
+++ b/src/animation/frontend/qanimationclip.cpp
@@ -1,34 +1,37 @@
/****************************************************************************
**
** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt-project.org/legal
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL3$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -36,37 +39,24 @@
#include "qanimationclip.h"
#include "qanimationclip_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
QAnimationClipPrivate::QAnimationClipPrivate()
- : Qt3DCore::QNodePrivate()
- , m_duration(0.0f)
+ : QAbstractAnimationClipPrivate()
+ , m_clipData()
{
}
-void QAnimationClipPrivate::setDuration(float duration)
-{
- if (qFuzzyCompare(duration, m_duration))
- return;
-
- Q_Q(QAnimationClip);
- bool wasBlocked = q->blockNotifications(true);
- m_duration = duration;
- emit q->durationChanged(duration);
- q->blockNotifications(wasBlocked);
-}
-
QAnimationClip::QAnimationClip(Qt3DCore::QNode *parent)
- : Qt3DCore::QNode(*new QAnimationClipPrivate, parent)
+ : QAbstractAnimationClip(*new QAnimationClipPrivate, parent)
{
}
QAnimationClip::QAnimationClip(QAnimationClipPrivate &dd, Qt3DCore::QNode *parent)
- : Qt3DCore::QNode(dd, parent)
+ : QAbstractAnimationClip(dd, parent)
{
}
@@ -74,44 +64,28 @@ QAnimationClip::~QAnimationClip()
{
}
-QUrl QAnimationClip::source() const
+QAnimationClipData QAnimationClip::clipData() const
{
Q_D(const QAnimationClip);
- return d->m_source;
+ return d->m_clipData;
}
-float QAnimationClip::duration() const
-{
- Q_D(const QAnimationClip);
- return d->m_duration;
-}
-
-void QAnimationClip::setSource(QUrl source)
+void QAnimationClip::setClipData(const Qt3DAnimation::QAnimationClipData &clipData)
{
Q_D(QAnimationClip);
- if (d->m_source == source)
+ if (d->m_clipData == clipData)
return;
- d->m_source = source;
- emit sourceChanged(source);
-}
-
-void QAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QAnimationClip);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("duration"))
- d->setDuration(e->value().toFloat());
- }
+ d->m_clipData = clipData;
+ emit clipDataChanged(clipData);
}
Qt3DCore::QNodeCreatedChangeBasePtr QAnimationClip::createNodeCreationChange() const
{
- auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAnimationClipData>::create(this);
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAnimationClipChangeData>::create(this);
auto &data = creationChange->data;
Q_D(const QAnimationClip);
- data.source = d->m_source;
+ data.clipData = d->m_clipData;
return creationChange;
}
diff --git a/src/animation/frontend/qanimationclip.h b/src/animation/frontend/qanimationclip.h
index 55b1910fa..6e606c598 100644
--- a/src/animation/frontend/qanimationclip.h
+++ b/src/animation/frontend/qanimationclip.h
@@ -1,34 +1,37 @@
/****************************************************************************
**
** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt-project.org/legal
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL3$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -37,9 +40,9 @@
#ifndef QT3DANIMATION_QANIMATIONCLIP_H
#define QT3DANIMATION_QANIMATIONCLIP_H
+#include <Qt3DAnimation/qabstractanimationclip.h>
#include <Qt3DAnimation/qt3danimation_global.h>
-#include <Qt3DCore/qnode.h>
-#include <QtCore/qurl.h>
+#include <Qt3DAnimation/qanimationclipdata.h>
QT_BEGIN_NAMESPACE
@@ -47,29 +50,25 @@ namespace Qt3DAnimation {
class QAnimationClipPrivate;
-class QT3DANIMATIONSHARED_EXPORT QAnimationClip : public Qt3DCore::QNode
+class QT3DANIMATIONSHARED_EXPORT QAnimationClip : public QAbstractAnimationClip
{
Q_OBJECT
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
- Q_PROPERTY(float duration READ duration NOTIFY durationChanged)
+ Q_PROPERTY(Qt3DAnimation::QAnimationClipData clipData READ clipData WRITE setClipData NOTIFY clipDataChanged)
public:
explicit QAnimationClip(Qt3DCore::QNode *parent = nullptr);
~QAnimationClip();
- QUrl source() const;
- float duration() const;
+ Qt3DAnimation::QAnimationClipData clipData() const;
public Q_SLOTS:
- void setSource(QUrl source);
+ void setClipData(const Qt3DAnimation::QAnimationClipData &clipData);
Q_SIGNALS:
- void sourceChanged(QUrl source);
- void durationChanged(float duration);
+ void clipDataChanged(Qt3DAnimation::QAnimationClipData clipData);
protected:
QAnimationClip(QAnimationClipPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
private:
Q_DECLARE_PRIVATE(QAnimationClip)
diff --git a/src/animation/frontend/qanimationclip_p.h b/src/animation/frontend/qanimationclip_p.h
index 5e3df0e6e..514d568af 100644
--- a/src/animation/frontend/qanimationclip_p.h
+++ b/src/animation/frontend/qanimationclip_p.h
@@ -1,34 +1,37 @@
/****************************************************************************
**
** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: http://www.qt-project.org/legal
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL3$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -48,32 +51,26 @@
// We mean it.
//
-#include <Qt3DCore/private/qnode_p.h>
-#include "qanimationclip.h"
+#include <Qt3DAnimation/private/qabstractanimationclip_p.h>
+#include <Qt3DAnimation/qanimationclip.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QAnimationClipPrivate : public Qt3DCore::QNodePrivate
+class QAnimationClipPrivate : public QAbstractAnimationClipPrivate
{
public:
QAnimationClipPrivate();
Q_DECLARE_PUBLIC(QAnimationClip)
- void setDuration(float duration);
-
- QUrl m_source;
-
- // Set from the backend
- float m_duration;
+ QAnimationClipData m_clipData;
};
-struct QAnimationClipData
+struct QAnimationClipChangeData
{
- QUrl source;
- bool running;
+ QAnimationClipData clipData;
};
} // namespace Qt3DAnimation
diff --git a/src/animation/frontend/qanimationclipdata.cpp b/src/animation/frontend/qanimationclipdata.cpp
new file mode 100644
index 000000000..ef3b59012
--- /dev/null
+++ b/src/animation/frontend/qanimationclipdata.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qanimationclipdata.h"
+
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QAnimationClipDataPrivate
+{
+public:
+ QVector<QChannel> m_channels;
+ QString m_name;
+};
+
+QAnimationClipData::QAnimationClipData()
+ : d(new QAnimationClipDataPrivate)
+{
+}
+
+QAnimationClipData::QAnimationClipData(const QAnimationClipData &rhs)
+ : d(new QAnimationClipDataPrivate)
+{
+ *d = *(rhs.d);
+}
+
+QAnimationClipData &QAnimationClipData::operator=(const QAnimationClipData &rhs)
+{
+ if (this != &rhs)
+ *d = *(rhs.d);
+ return *this;
+}
+
+QAnimationClipData::~QAnimationClipData()
+{
+}
+
+void QAnimationClipData::setName(const QString &name)
+{
+ d->m_name = name;
+}
+
+QString QAnimationClipData::name() const
+{
+ return d->m_name;
+}
+
+int QAnimationClipData::channelCount() const
+{
+ return d->m_channels.size();
+}
+
+void QAnimationClipData::appendChannel(const QChannel &c)
+{
+ d->m_channels.append(c);
+}
+
+void QAnimationClipData::insertChannel(int index, const QChannel &c)
+{
+ d->m_channels.insert(index, c);
+}
+
+void QAnimationClipData::removeChannel(int index)
+{
+ d->m_channels.remove(index);
+}
+
+void QAnimationClipData::clearChannels()
+{
+ d->m_channels.clear();
+}
+
+bool QAnimationClipData::isValid() const Q_DECL_NOTHROW
+{
+ // TODO: Perform more thorough checks
+ return !d->m_channels.isEmpty();
+}
+
+QAnimationClipData::const_iterator QAnimationClipData::begin() const Q_DECL_NOTHROW
+{
+ return d->m_channels.begin();
+}
+
+QAnimationClipData::const_iterator QAnimationClipData::end() const Q_DECL_NOTHROW
+{
+ return d->m_channels.end();
+}
+
+
+bool operator==(const QAnimationClipData &lhs, const QAnimationClipData &rhs) Q_DECL_NOTHROW
+{
+ return lhs.d->m_name == rhs.d->m_name &&
+ lhs.d->m_channels == rhs.d->m_channels;
+}
+
+bool operator!=(const QAnimationClipData &lhs, const QAnimationClipData &rhs) Q_DECL_NOTHROW
+{
+ return lhs.d->m_name != rhs.d->m_name ||
+ lhs.d->m_channels != rhs.d->m_channels;
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qanimationclipdata.h b/src/animation/frontend/qanimationclipdata.h
new file mode 100644
index 000000000..605b17208
--- /dev/null
+++ b/src/animation/frontend/qanimationclipdata.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QANIMATIONCLIPDATA_H
+#define QT3DANIMATION_QANIMATIONCLIPDATA_H
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DAnimation/qchannel.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QAnimationClipDataPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QAnimationClipData
+{
+public:
+ QAnimationClipData();
+ QAnimationClipData(const QAnimationClipData &);
+ QAnimationClipData &operator=(const QAnimationClipData &);
+ ~QAnimationClipData();
+
+ void setName(const QString &name);
+ QString name() const;
+
+ int channelCount() const;
+ void appendChannel(const QChannel &c);
+ void insertChannel(int index, const QChannel &c);
+ void removeChannel(int index);
+ void clearChannels();
+
+ bool isValid() const Q_DECL_NOTHROW;
+
+ // Iterator API
+ typedef const QChannel *const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ const_iterator begin() const Q_DECL_NOTHROW;
+ const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
+ const_iterator end() const Q_DECL_NOTHROW;
+ const_iterator cend() const Q_DECL_NOTHROW { return end(); }
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+
+ friend bool operator==(const QAnimationClipData &,
+ const QAnimationClipData &) Q_DECL_NOTHROW;
+ friend bool operator!=(const QAnimationClipData &,
+ const QAnimationClipData &) Q_DECL_NOTHROW;
+
+private:
+ QScopedPointer<QAnimationClipDataPrivate> d;
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DAnimation::QAnimationClipData)
+
+#endif // QT3DANIMATION_QANIMATIONCLIPDATA_H
diff --git a/src/animation/frontend/qanimationcliploader.cpp b/src/animation/frontend/qanimationcliploader.cpp
new file mode 100644
index 000000000..ed48438de
--- /dev/null
+++ b/src/animation/frontend/qanimationcliploader.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qanimationcliploader.h"
+#include "qanimationcliploader_p.h"
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+QAnimationClipLoaderPrivate::QAnimationClipLoaderPrivate()
+ : QAbstractAnimationClipPrivate()
+ , m_source()
+ , m_status(QAnimationClipLoader::NotReady)
+{
+}
+
+void QAnimationClipLoaderPrivate::setStatus(QAnimationClipLoader::Status status)
+{
+ Q_Q(QAnimationClipLoader);
+ if (status != m_status) {
+ m_status = status;
+ const bool blocked = q->blockNotifications(true);
+ emit q->statusChanged(m_status);
+ q->blockNotifications(blocked);
+ }
+}
+
+/*!
+ \enum QAnimationClipLoader::Status
+
+ This enum identifies the status of animation clip.
+
+ \value NotReady The clip has not been loaded yet
+ \value Ready The clip was successfully loaded
+ \value Error An error occurred while loading the clip
+*/
+
+QAnimationClipLoader::QAnimationClipLoader(Qt3DCore::QNode *parent)
+ : QAbstractAnimationClip(*new QAnimationClipLoaderPrivate, parent)
+{
+}
+
+QAnimationClipLoader::QAnimationClipLoader(const QUrl &source,
+ Qt3DCore::QNode *parent)
+ : QAbstractAnimationClip(*new QAnimationClipLoaderPrivate, parent)
+{
+ setSource(source);
+}
+
+QAnimationClipLoader::QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3DCore::QNode *parent)
+ : QAbstractAnimationClip(dd, parent)
+{
+}
+
+QAnimationClipLoader::~QAnimationClipLoader()
+{
+}
+
+QUrl QAnimationClipLoader::source() const
+{
+ Q_D(const QAnimationClipLoader);
+ return d->m_source;
+}
+
+QAnimationClipLoader::Status QAnimationClipLoader::status() const
+{
+ Q_D(const QAnimationClipLoader);
+ return d->m_status;
+}
+
+void QAnimationClipLoader::setSource(const QUrl &source)
+{
+ Q_D(QAnimationClipLoader);
+ if (d->m_source == source)
+ return;
+
+ d->m_source = source;
+ emit sourceChanged(source);
+}
+
+void QAnimationClipLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+{
+ Q_D(QAnimationClipLoader);
+ if (change->type() == Qt3DCore::PropertyUpdated) {
+ const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (e->propertyName() == QByteArrayLiteral("status"))
+ d->setStatus(static_cast<QAnimationClipLoader::Status>(e->value().toInt()));
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QAnimationClipLoader::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAnimationClipLoaderData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QAnimationClipLoader);
+ data.source = d->m_source;
+ return creationChange;
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/backend/conductedclipanimator.cpp b/src/animation/frontend/qanimationcliploader.h
index 32db1b7ea..20f0f14da 100644
--- a/src/animation/backend/conductedclipanimator.cpp
+++ b/src/animation/frontend/qanimationcliploader.h
@@ -34,47 +34,59 @@
**
****************************************************************************/
-#include "conductedclipanimator_p.h"
-#include <Qt3DAnimation/qconductedclipanimator.h>
-#include <Qt3DAnimation/private/qconductedclipanimator_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#ifndef QT3DANIMATION_QANIMATIONCLIPLOADER_H
+#define QT3DANIMATION_QANIMATIONCLIPLOADER_H
+
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DAnimation/qabstractanimationclip.h>
+#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-namespace Animation {
-ConductedClipAnimator::ConductedClipAnimator()
- : BackendNode(ReadOnly)
-{
-}
+class QAnimationClipLoaderPrivate;
-void ConductedClipAnimator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+class QT3DANIMATIONSHARED_EXPORT QAnimationClipLoader : public QAbstractAnimationClip
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QConductedClipAnimatorData>>(change);
- const auto &data = typedChange->data;
-}
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
-void ConductedClipAnimator::cleanup()
-{
- setEnabled(false);
- m_handler = nullptr;
-}
+public:
+ explicit QAnimationClipLoader(Qt3DCore::QNode *parent = nullptr);
+ explicit QAnimationClipLoader(const QUrl &source,
+ Qt3DCore::QNode *parent = nullptr);
+ ~QAnimationClipLoader();
+
+ enum Status {
+ NotReady = 0,
+ Ready,
+ Error
+ };
+ Q_ENUM(Status) // LCOV_EXCL_LINE
+
+ QUrl source() const;
+ Status status() const;
+
+public Q_SLOTS:
+ void setSource(const QUrl &source);
+
+Q_SIGNALS:
+ void sourceChanged(const QUrl &source);
+ void statusChanged(Status status);
+
+protected:
+ explicit QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
+
+private:
+ Q_DECLARE_PRIVATE(QAnimationClipLoader)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
-void ConductedClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- break;
- }
-
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
-}
-
-} // namespace Animation
} // namespace Qt3DAnimation
QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QANIMATIONCLIPLOADER_H
diff --git a/src/animation/backend/conductedclipanimator_p.h b/src/animation/frontend/qanimationcliploader_p.h
index d4534447e..70b21dbb4 100644
--- a/src/animation/backend/conductedclipanimator_p.h
+++ b/src/animation/frontend/qanimationcliploader_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DANIMATION_ANIMATION_CONDUCTEDCLIPANIMATOR_P_H
-#define QT3DANIMATION_ANIMATION_CONDUCTEDCLIPANIMATOR_P_H
+#ifndef QT3DANIMATION_QANIMATIONCLIPLOADER_P_H
+#define QT3DANIMATION_QANIMATIONCLIPLOADER_P_H
//
// W A R N I N G
@@ -48,32 +48,34 @@
// We mean it.
//
-#include <Qt3DAnimation/private/backendnode_p.h>
+#include <Qt3DAnimation/private/qabstractanimationclip_p.h>
+#include "qanimationcliploader.h"
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-namespace Animation {
-class Handler;
-
-class Q_AUTOTEST_EXPORT ConductedClipAnimator : public BackendNode
+class QAnimationClipLoaderPrivate : public QAbstractAnimationClipPrivate
{
public:
- ConductedClipAnimator();
+ QAnimationClipLoaderPrivate();
+
+ void setStatus(QAnimationClipLoader::Status status);
- void cleanup();
+ Q_DECLARE_PUBLIC(QAnimationClipLoader)
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ QUrl m_source;
+ QAnimationClipLoader::Status m_status;
+};
-private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+struct QAnimationClipLoaderData
+{
+ QUrl source;
};
-} // namespace Animation
} // namespace Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DANIMATION_ANIMATION_CONDUCTEDCLIPANIMATOR_P_H
+#endif // QT3DANIMATION_QANIMATIONCLIPLOADER_P_H
diff --git a/src/extras/animations/qanimationcontroller.cpp b/src/animation/frontend/qanimationcontroller.cpp
index adef3d45c..d4c3c4005 100644
--- a/src/extras/animations/qanimationcontroller.cpp
+++ b/src/animation/frontend/qanimationcontroller.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -41,12 +41,124 @@
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QAnimationController
+ \brief A controller class for animations
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits QObject
+
+ Qt3DAnimation::QAnimationController class controls the selection and playback of animations.
+ The class can be used to find all animations from Qt3DCore::QEntity tree and create
+ \l {Qt3DAnimation::QAnimationGroup} {QAnimationGroups} from the animations with the same name.
+ The user can select which animation group is currently controlled with the animation
+ controller by setting the active animation. The animation position is then propagated to
+ that group after scaling and offsetting the provided position value with the
+ positionScale and positionOffset values.
+
+ \note that the animation controller doesn't have internal timer, but instead the user
+ is responsible for updating the position property in timely manner.
+*/
+
+/*!
+ \qmltype AnimationController
+ \brief A controller type for animations
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \instantiates Qt3DAnimation::QAnimationController
+
+ AnimationController type controls the selection and playback of animations.
+ The type can be used to find all animations from Entity tree and create
+ \l {AnimationGroup} {AnimationGroups} from the animations with the same name.
+ The user can select which animation group is currently controlled with the animation
+ controller by setting the active animation. The animation position is then propagated to
+ that group after scaling and offsetting the provided position value with the
+ positionScale and positionOffset values.
+
+ \note that the animation controller doesn't have internal timer, but instead the user
+ is responsible for updating the position property in timely manner.
+*/
+
+/*!
+ \property Qt3DAnimation::QAnimationController::activeAnimationGroup
+ Holds the currectly active animation group.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationController::position
+ Holds the current position of the animation. When the position is set,
+ it is scaled and offset with positionScale/positionOffset and propagated
+ to the active animation group.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationController::positionScale
+ Holds the position scale of the animation.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationController::positionOffset
+ Holds the position offset of the animation.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationController::entity
+ Holds the entity animations are gathered and grouped from. If the controller already
+ holds animations, they are cleared.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationController::recursive
+ Holds whether the recursively search the entity tree when gathering animations from the entity.
+ If set to true, the animations are searched also from the child entities of the entity.
+ If set to false, only the entity passed to the controller is searched.
+*/
+
+/*!
+ \qmlproperty int AnimationController::activeAnimationGroup
+ Holds the currectly active animation group.
+*/
+/*!
+ \qmlproperty real AnimationController::position
+ Holds the current position of the animation. When the position is set,
+ it is scaled and offset with positionScale/positionOffset and propagated
+ to the active animation group.
+*/
+/*!
+ \qmlproperty real AnimationController::positionScale
+ Holds the position scale of the animation.
+*/
+/*!
+ \qmlproperty real AnimationController::positionOffset
+ Holds the position offset of the animation.
+*/
+/*!
+ \qmlproperty Entity AnimationController::entity
+ Holds the entity animations are gathered and grouped from. If the controller already
+ holds animations, they are cleared.
+*/
+/*!
+ \qmlproperty bool AnimationController::recursive
+ Holds whether the recursively search the entity tree when gathering animations from the entity.
+ If set to true, the animations are searched also from the child entities of the entity.
+ If set to false, only the entity passed to the controller is searched.
+*/
+/*!
+ \qmlproperty list<AnimationGroup> AnimationController::animationGroups
+ Holds the list of animation groups in the controller.
+*/
+/*!
+ \qmlmethod int Qt3D.Animation::AnimationController::getAnimationIndex(name)
+ Returns the index of the animation with \a name. Returns -1 if no AnimationGroup
+ with the given name is found.
+*/
+/*!
+ \qmlmethod AnimationGroup Qt3D.Animation::AnimationController::getGroup(index)
+ Returns the AnimationGroup with the given \a index.
+*/
QAnimationControllerPrivate::QAnimationControllerPrivate()
: QObjectPrivate()
, m_activeAnimationGroup(0)
, m_position(0.0f)
+ , m_scaledPosition(0.0f)
, m_positionScale(1.0f)
, m_positionOffset(0.0f)
, m_entity(nullptr)
@@ -58,15 +170,19 @@ QAnimationControllerPrivate::QAnimationControllerPrivate()
void QAnimationControllerPrivate::updatePosition(float position)
{
m_position = position;
- if (m_activeAnimationGroup >= 0 && m_activeAnimationGroup < m_animationGroups.size()) {
- const float pos = m_positionScale * position + m_positionOffset;
- m_animationGroups[m_activeAnimationGroup]->setPosition(pos);
- }
+ m_scaledPosition = scaledPosition(position);
+ if (m_activeAnimationGroup >= 0 && m_activeAnimationGroup < m_animationGroups.size())
+ m_animationGroups[m_activeAnimationGroup]->setPosition(m_scaledPosition);
+}
+
+float QAnimationControllerPrivate::scaledPosition(float position) const
+{
+ return m_positionScale * position + m_positionOffset;
}
QAnimationGroup *QAnimationControllerPrivate::findGroup(const QString &name)
{
- for (QAnimationGroup *g : m_animationGroups) {
+ for (QAnimationGroup *g : qAsConst(m_animationGroups)) {
if (g->name() == name)
return g;
}
@@ -78,11 +194,11 @@ void QAnimationControllerPrivate::extractAnimations()
Q_Q(QAnimationController);
if (!m_entity)
return;
- QList<Qt3DExtras::QAbstractAnimation *> animations
- = m_entity->findChildren<Qt3DExtras::QAbstractAnimation *>(QString(),
+ QList<Qt3DAnimation::QAbstractAnimation *> animations
+ = m_entity->findChildren<Qt3DAnimation::QAbstractAnimation *>(QString(),
m_recursive ? Qt::FindChildrenRecursively : Qt::FindDirectChildrenOnly);
if (animations.size() > 0) {
- for (Qt3DExtras::QAbstractAnimation *a : animations) {
+ for (Qt3DAnimation::QAbstractAnimation *a : animations) {
QAnimationGroup *group = findGroup(a->animationName());
if (!group) {
group = new QAnimationGroup(q);
@@ -95,18 +211,24 @@ void QAnimationControllerPrivate::extractAnimations()
}
void QAnimationControllerPrivate::clearAnimations()
{
- for (Qt3DExtras::QAnimationGroup *a : m_animationGroups)
+ for (Qt3DAnimation::QAnimationGroup *a : qAsConst(m_animationGroups))
a->deleteLater();
m_animationGroups.clear();
m_activeAnimationGroup = 0;
}
+/*!
+ Constructs a new QAnimationController with \a parent.
+ */
QAnimationController::QAnimationController(QObject *parent)
: QObject(*new QAnimationControllerPrivate, parent)
{
}
+/*!
+ Returns the list of animation groups the conroller is currently holding.
+ */
QVector<QAnimationGroup *> QAnimationController::animationGroupList()
{
Q_D(QAnimationController);
@@ -149,7 +271,10 @@ bool QAnimationController::recursive() const
return d->m_recursive;
}
-void QAnimationController::setAnimationGroups(const QVector<QAnimationGroup *> &animationGroups)
+/*!
+ Sets the \a animationGroups for the controller. Old groups are cleared.
+ */
+void QAnimationController::setAnimationGroups(const QVector<Qt3DAnimation::QAnimationGroup *> &animationGroups)
{
Q_D(QAnimationController);
d->m_animationGroups = animationGroups;
@@ -158,14 +283,20 @@ void QAnimationController::setAnimationGroups(const QVector<QAnimationGroup *> &
d->updatePosition(d->m_position);
}
-void QAnimationController::addAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroup)
+/*!
+ Adds the given \a animationGroup to the controller.
+ */
+void QAnimationController::addAnimationGroup(Qt3DAnimation::QAnimationGroup *animationGroup)
{
Q_D(QAnimationController);
if (!d->m_animationGroups.contains(animationGroup))
d->m_animationGroups.push_back(animationGroup);
}
-void QAnimationController::removeAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroup)
+/*!
+ Removes the given \a animationGroup from the controller.
+ */
+void QAnimationController::removeAnimationGroup(Qt3DAnimation::QAnimationGroup *animationGroup)
{
Q_D(QAnimationController);
if (d->m_animationGroups.contains(animationGroup))
@@ -186,7 +317,7 @@ void QAnimationController::setActiveAnimationGroup(int index)
void QAnimationController::setPosition(float position)
{
Q_D(QAnimationController);
- if (!qFuzzyCompare(d->m_position, position)) {
+ if (!qFuzzyCompare(d->m_scaledPosition, d->scaledPosition(position))) {
d->updatePosition(position);
emit positionChanged(position);
}
@@ -231,6 +362,10 @@ void QAnimationController::setRecursive(bool recursive)
}
}
+/*!
+ Returns the index of the animation with \a name. Returns -1 if no AnimationGroup
+ with the given name is found.
+*/
int QAnimationController::getAnimationIndex(const QString &name) const
{
Q_D(const QAnimationController);
@@ -241,12 +376,15 @@ int QAnimationController::getAnimationIndex(const QString &name) const
return -1;
}
+/*!
+ Returns the AnimationGroup with the given \a index.
+*/
QAnimationGroup *QAnimationController::getGroup(int index) const
{
Q_D(const QAnimationController);
return d->m_animationGroups.at(index);
}
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/extras/animations/qanimationcontroller.h b/src/animation/frontend/qanimationcontroller.h
index 4ee32dd8b..ae3272517 100644
--- a/src/extras/animations/qanimationcontroller.h
+++ b/src/animation/frontend/qanimationcontroller.h
@@ -34,22 +34,22 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QANIMATIONCONTROLLER_H
-#define QT3DEXTRAS_QANIMATIONCONTROLLER_H
+#ifndef QT3DANIMATION_QANIMATIONCONTROLLER_H
+#define QT3DANIMATION_QANIMATIONCONTROLLER_H
-#include <Qt3DExtras/qkeyframeanimation.h>
-#include <Qt3DExtras/qanimationgroup.h>
+#include <Qt3DAnimation/qkeyframeanimation.h>
+#include <Qt3DAnimation/qanimationgroup.h>
#include <Qt3DCore/qentity.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QAnimationControllerPrivate;
-class QT3DEXTRASSHARED_EXPORT QAnimationController : public QObject
+class QT3DANIMATIONSHARED_EXPORT QAnimationController : public QObject
{
Q_OBJECT
Q_PROPERTY(int activeAnimationGroup READ activeAnimationGroup WRITE setActiveAnimationGroup NOTIFY activeAnimationGroupChanged)
@@ -62,7 +62,7 @@ class QT3DEXTRASSHARED_EXPORT QAnimationController : public QObject
public:
QAnimationController(QObject *parent = nullptr);
- QVector<Qt3DExtras::QAnimationGroup *> animationGroupList();
+ QVector<Qt3DAnimation::QAnimationGroup *> animationGroupList();
int activeAnimationGroup() const;
float position() const;
@@ -71,12 +71,12 @@ public:
Qt3DCore::QEntity *entity() const;
bool recursive() const;
- void setAnimationGroups(const QVector<Qt3DExtras::QAnimationGroup *> &animationGroups);
- void addAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroups);
- void removeAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroups);
+ void setAnimationGroups(const QVector<Qt3DAnimation::QAnimationGroup *> &animationGroups);
+ void addAnimationGroup(Qt3DAnimation::QAnimationGroup *animationGroups);
+ void removeAnimationGroup(Qt3DAnimation::QAnimationGroup *animationGroups);
Q_INVOKABLE int getAnimationIndex(const QString &name) const;
- Q_INVOKABLE Qt3DExtras::QAnimationGroup *getGroup(int index) const;
+ Q_INVOKABLE Qt3DAnimation::QAnimationGroup *getGroup(int index) const;
public Q_SLOTS:
void setActiveAnimationGroup(int index);
@@ -98,8 +98,8 @@ private:
Q_DECLARE_PRIVATE(QAnimationController)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QANIMATIONCONTROLLER_H
+#endif // QT3DANIMATION_QANIMATIONCONTROLLER_H
diff --git a/src/extras/animations/qanimationcontroller_p.h b/src/animation/frontend/qanimationcontroller_p.h
index dd5079ef5..c06484911 100644
--- a/src/extras/animations/qanimationcontroller_p.h
+++ b/src/animation/frontend/qanimationcontroller_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
-#define QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
+#ifndef QT3DANIMATION_QANIMATIONCONTROLLER_P_H
+#define QT3DANIMATION_QANIMATIONCONTROLLER_P_H
//
// W A R N I N G
@@ -49,11 +49,11 @@
//
#include <private/qobject_p.h>
-#include <Qt3DExtras/QAnimationGroup>
+#include <Qt3DAnimation/QAnimationGroup>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QAnimationControllerPrivate : public QObjectPrivate
{
@@ -64,6 +64,7 @@ public:
int m_activeAnimationGroup;
QVector<QAnimationGroup *> m_animationGroups;
float m_position;
+ float m_scaledPosition;
float m_positionScale;
float m_positionOffset;
Qt3DCore::QEntity *m_entity;
@@ -73,12 +74,13 @@ public:
void extractAnimations();
void clearAnimations();
QAnimationGroup *findGroup(const QString &name);
+ float scaledPosition(float position) const;
Q_DECLARE_PUBLIC(QAnimationController)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
+#endif // QT3DANIMATION_QANIMATIONCONTROLLER_P_H
diff --git a/src/animation/frontend/qanimationgroup.cpp b/src/animation/frontend/qanimationgroup.cpp
new file mode 100644
index 000000000..365745662
--- /dev/null
+++ b/src/animation/frontend/qanimationgroup.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qanimationgroup.h"
+#include "Qt3DAnimation/private/qanimationgroup_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QAnimationGroup
+ \brief A class grouping animations together
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits QObject
+
+ Qt3DAnimation::QAnimationGroup class is used to group multiple animations so that
+ they can act as one animation. The position set to the group is also set to
+ all animations in a group. The duration is the maximum of the individual animations.
+ The animations can be any supported animation type and do not have to have the same name.
+*/
+/*!
+ \qmltype AnimationGroup
+ \brief A type grouping animations together
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \inherits QObject
+
+ AnimationGroup type is used to group multiple animations so that
+ they can act as one animation. The position set to the group is also set to
+ all animations in a group. The duration is the maximum of the individual animations.
+ The animations can be any supported animation type and do not have to have the same name.
+*/
+
+/*!
+ \property Qt3DAnimation::QAnimationGroup::name
+ Holds the name of the animation group.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationGroup::position
+ Holds the animation position.
+*/
+/*!
+ \property Qt3DAnimation::QAnimationGroup::duration
+ Holds the maximum duration of the animations in the group.
+ \readonly
+*/
+
+/*!
+ \qmlproperty string AnimationGroup::name
+ Holds the name of the animation group.
+*/
+/*!
+ \qmlproperty real AnimationGroup::position
+ Holds the animation position.
+*/
+/*!
+ \qmlproperty real AnimationGroup::duration
+ Holds the maximum duration of the animations in the group.
+ \readonly
+*/
+/*!
+ \qmlproperty list<AbstractAnimation> AnimationGroup::animations
+ Holds the list of animations in the animation group.
+*/
+
+QAnimationGroupPrivate::QAnimationGroupPrivate()
+ : QObjectPrivate()
+ , m_position(0.0f)
+ , m_duration(0.0f)
+{
+
+}
+
+void QAnimationGroupPrivate::updatePosition(float position)
+{
+ m_position = position;
+ for (QAbstractAnimation *aa : qAsConst(m_animations))
+ aa->setPosition(position);
+}
+
+/*!
+ Constructs an QAnimationGroup with \a parent.
+*/
+QAnimationGroup::QAnimationGroup(QObject *parent)
+ : QObject(*new QAnimationGroupPrivate, parent)
+{
+
+}
+
+QString QAnimationGroup::name() const
+{
+ Q_D(const QAnimationGroup);
+ return d->m_name;
+}
+
+/*!
+ Returns the list of animations in the group.
+ */
+QVector<Qt3DAnimation::QAbstractAnimation *> QAnimationGroup::animationList()
+{
+ Q_D(QAnimationGroup);
+ return d->m_animations;
+}
+
+float QAnimationGroup::position() const
+{
+ Q_D(const QAnimationGroup);
+ return d->m_position;
+}
+
+float QAnimationGroup::duration() const
+{
+ Q_D(const QAnimationGroup);
+ return d->m_duration;
+}
+
+void QAnimationGroup::setName(const QString &name)
+{
+ Q_D(QAnimationGroup);
+ if (d->m_name != name) {
+ d->m_name = name;
+ emit nameChanged(name);
+ }
+}
+
+/*!
+ Sets the \a animations to the group. Old animations are removed.
+ */
+void QAnimationGroup::setAnimations(const QVector<Qt3DAnimation::QAbstractAnimation *> &animations)
+{
+ Q_D(QAnimationGroup);
+ d->m_animations = animations;
+ d->m_duration = 0.0f;
+ for (const Qt3DAnimation::QAbstractAnimation *a : animations)
+ d->m_duration = qMax(d->m_duration, a->duration());
+}
+
+/*!
+ Adds new \a animation to the group.
+ */
+void QAnimationGroup::addAnimation(Qt3DAnimation::QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ if (!d->m_animations.contains(animation)) {
+ d->m_animations.push_back(animation);
+ d->m_duration = qMax(d->m_duration, animation->duration());
+ }
+}
+
+/*!
+ Removes \a animation from the group.
+ */
+void QAnimationGroup::removeAnimation(Qt3DAnimation::QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ if (!d->m_animations.contains(animation)) {
+ d->m_animations.removeAll(animation);
+ if (qFuzzyCompare(d->m_duration, animation->duration())) {
+ d->m_duration = 0.0f;
+ for (const Qt3DAnimation::QAbstractAnimation *a : d->m_animations)
+ d->m_duration = qMax(d->m_duration, a->duration());
+ }
+ }
+}
+
+void QAnimationGroup::setPosition(float position)
+{
+ Q_D(QAnimationGroup);
+ if (!qFuzzyCompare(d->m_position, position)) {
+ d->updatePosition(position);
+ emit positionChanged(position);
+ }
+}
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qanimationgroup.h b/src/animation/frontend/qanimationgroup.h
index 4595a2082..1e23c61ee 100644
--- a/src/extras/animations/qanimationgroup.h
+++ b/src/animation/frontend/qanimationgroup.h
@@ -34,22 +34,22 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QANIMATIONGROUP_H
-#define QT3DEXTRAS_QANIMATIONGROUP_H
+#ifndef QT3DANIMATION_QANIMATIONGROUP_H
+#define QT3DANIMATION_QANIMATIONGROUP_H
#include <qobject.h>
-#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DAnimation/qabstractanimation.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QAnimationGroupPrivate;
-class QT3DEXTRASSHARED_EXPORT QAnimationGroup : public QObject
+class QT3DANIMATIONSHARED_EXPORT QAnimationGroup : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
@@ -60,13 +60,13 @@ public:
explicit QAnimationGroup(QObject *parent = nullptr);
QString name() const;
- QVector<Qt3DExtras::QAbstractAnimation *> animationList();
+ QVector<Qt3DAnimation::QAbstractAnimation *> animationList();
float position() const;
float duration() const;
- void setAnimations(const QVector<Qt3DExtras::QAbstractAnimation *> &animations);
- void addAnimation(Qt3DExtras::QAbstractAnimation *animation);
- void removeAnimation(Qt3DExtras::QAbstractAnimation *animation);
+ void setAnimations(const QVector<Qt3DAnimation::QAbstractAnimation *> &animations);
+ void addAnimation(Qt3DAnimation::QAbstractAnimation *animation);
+ void removeAnimation(Qt3DAnimation::QAbstractAnimation *animation);
public Q_SLOTS:
void setName(const QString &name);
@@ -82,8 +82,8 @@ private:
Q_DECLARE_PRIVATE(QAnimationGroup)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QANIMATIONGROUP_H
+#endif // QT3DANIMATION_QANIMATIONGROUP_H
diff --git a/src/extras/animations/qanimationgroup_p.h b/src/animation/frontend/qanimationgroup_p.h
index cffe44636..1e13952aa 100644
--- a/src/extras/animations/qanimationgroup_p.h
+++ b/src/animation/frontend/qanimationgroup_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QANIMATIONGROUP_P_H
-#define QT3DEXTRAS_QANIMATIONGROUP_P_H
+#ifndef QT3DANIMATION_QANIMATIONGROUP_P_H
+#define QT3DANIMATION_QANIMATIONGROUP_P_H
//
// W A R N I N G
@@ -49,11 +49,11 @@
//
#include <private/qobject_p.h>
-#include <Qt3DExtras/QAnimationGroup>
+#include <Qt3DAnimation/QAnimationGroup>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QAnimationGroupPrivate : public QObjectPrivate
{
@@ -61,7 +61,7 @@ public:
QAnimationGroupPrivate();
QString m_name;
- QVector<Qt3DExtras::QAbstractAnimation *> m_animations;
+ QVector<Qt3DAnimation::QAbstractAnimation *> m_animations;
float m_position;
float m_duration;
@@ -70,8 +70,8 @@ public:
Q_DECLARE_PUBLIC(QAnimationGroup)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QANIMATIONGROUP_P_H
+#endif // QT3DANIMATION_QANIMATIONGROUP_P_H
diff --git a/src/animation/frontend/qblendedclipanimator.cpp b/src/animation/frontend/qblendedclipanimator.cpp
index 8e0897b5c..e6b127bf1 100644
--- a/src/animation/frontend/qblendedclipanimator.cpp
+++ b/src/animation/frontend/qblendedclipanimator.cpp
@@ -46,21 +46,219 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
QBlendedClipAnimatorPrivate::QBlendedClipAnimatorPrivate()
- : Qt3DCore::QComponentPrivate()
+ : Qt3DAnimation::QAbstractClipAnimatorPrivate()
, m_blendTreeRoot(nullptr)
- , m_mapper(nullptr)
- , m_running(false)
- , m_loops(1)
{
}
+/*!
+ \qmltype BlendedClipAnimator
+ \instantiates Qt3DAnimation::QBlendedClipAnimator
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+
+ \brief BlendedClipAnimator is a component providing animation playback capabilities of a tree
+ of blend nodes.
+
+ An instance of BlendedClipAnimator can be aggregated by an Entity to add the ability to play
+ back animation clips and to apply the calculated animation values to properties of QObjects.
+
+ Whereas a ClipAnimator gets its animation data from a single animation clip,
+ BlendedClipAnimator can blend together multiple clips. The animation data is obtained by
+ evaluating a so called \e {blend tree}. A blend tree is a hierarchical tree structure where the
+ leaf nodes are value nodes that encapsulate an animation clip (AbstractAnimationClip); and the
+ internal nodes represent blending operations that operate on the nodes pointed to by their
+ operand properties.
+
+ To associate a blend tree with a BlendedClipAnimator, set the animator's blendTree property to
+ point at the root node of your blend tree:
+
+ \badcode
+ BlendedClipAnimator {
+ blendTree: AdditiveClipBlend {
+ ....
+ }
+ }
+ \endcode
+
+ A blend tree can be constructed from the following node types:
+
+ \note The blend node tree should only be edited when the animator is not running.
+
+ \list
+ \li Qt3D.Animation.ClipBlendValue
+ \li Qt3D.Animation.LerpClipBlend
+ \li Qt3D.Animation.AdditiveClipBlend
+ \endlist
+
+ Additional node types will be added over time.
+
+ As an example consider the following blend tree:
+
+ \badcode
+ Clip0----
+ |
+ Lerp Node----
+ | |
+ Clip1---- Additive Node
+ |
+ Clip2----
+ \endcode
+
+ This can be created and used as follows:
+
+ \badcode
+ BlendedClipAnimator {
+ blendTree: AdditiveClipBlend {
+ baseClip: LerpClipBlend {
+ startClip: ClipBlendValue {
+ clip: AnimationClipLoader { source: "walk.json" }
+ }
+
+ endClip: ClipBlendValue {
+ clip: AnimationClipLoader { source: "run.json" }
+ }
+ }
+
+ additiveClip: ClipBlendValue {
+ clip: AnimationClipLoader { source: "wave-arm.json" }
+ }
+ }
+
+ channelMapper: ChannelMapper {...}
+ running: true
+ }
+ \endcode
+
+ By authoring a set of animation clips and blending between them dynamically at runtime with a
+ blend tree, we open up a huge set of possible resulting animations. As some simple examples of
+ the above blend tree, where alpha is the additive factor and beta is the lerp blend factor we
+ can get a 2D continuum of possible animations:
+
+ \badcode
+ (alpha = 0, beta = 1) Running, No arm waving --- (alpha = 1, beta = 1) Running, Arm waving
+ | |
+ | |
+ | |
+ (alpha = 0, beta = 0) Walking, No arm waving --- (alpha = 0, beta = 1) Running, No arm waving
+ \endcode
+
+ More complex blend trees offer even more flexibility for combining your animation clips. Note
+ that the values used to control the blend tree (alpha and beta above) are simple properties on
+ the blend nodes. This means, that these properties themselves can also be controlled by
+ the animation framework.
+*/
+
+/*!
+ \class Qt3DAnimation::QBlendedClipAnimator
+ \inherits Qt3DAnimation::QAbstractClipAnimator
+
+ \inmodule Qt3DAnimation
+ \since 5.9
+
+ \brief QBlendedClipAnimator is a component providing animation playback capabilities of a tree
+ of blend nodes.
+
+ An instance of QBlendedClipAnimator can be aggregated by a QEntity to add the ability to play
+ back animation clips and to apply the calculated animation values to properties of QObjects.
+
+ Whereas a QClipAnimator gets its animation data from a single animation clip,
+ QBlendedClipAnimator can blend together multiple clips. The animation data is obtained by
+ evaluating a so called \e {blend tree}. A blend tree is a hierarchical tree structure where the
+ leaf nodes are value nodes that encapsulate an animation clip (QAbstractAnimationClip); and the
+ internal nodes represent blending operations that operate on the nodes pointed to by their
+ operand properties.
+
+ To associate a blend tree with a QBlendedClipAnimator, set the animator's blendTree property to
+ point at the root node of your blend tree:
+
+ \badcode
+ auto blendTreeRoot = new QAdditiveClipBlend();
+ ...
+ auto animator = new QBlendedClipAnimator();
+ animator->setBlendTree(blendTreeRoot);
+ \endcode
+
+ A blend tree can be constructed from the following node types:
+
+ \note The blend node tree should only be edited when the animator is not running.
+
+ \list
+ \li Qt3DAnimation::QClipBlendValue
+ \li Qt3DAnimation::QLerpClipBlend
+ \li Qt3DAnimation::QAdditiveClipBlend
+ \endlist
+
+ Additional node types will be added over time.
+
+ As an example consider the following blend tree:
+
+ \badcode
+ Clip0----
+ |
+ Lerp Node----
+ | |
+ Clip1---- Additive Node
+ |
+ Clip2----
+ \endcode
+
+ This can be created and used as follows:
+
+ \code
+ // Create leaf nodes of blend tree
+ auto clip0 = new QClipBlendValue(
+ new QAnimationClipLoader(QUrl::fromLocalFile("walk.json")));
+ auto clip1 = new QClipBlendValue(
+ new QAnimationClipLoader(QUrl::fromLocalFile("run.json")));
+ auto clip2 = new QClipBlendValue(
+ new QAnimationClipLoader(QUrl::fromLocalFile("wave-arm.json")));
+
+ // Create blend tree inner nodes
+ auto lerpNode = new QLerpClipBlend();
+ lerpNode->setStartClip(clip0);
+ lerpNode->setEndClip(clip1);
+ lerpNode->setBlendFactor(0.5f); // Half-walk, half-run
+
+ auto additiveNode = new QAdditiveClipBlend();
+ additiveNode->setBaseClip(lerpNode); // Comes from lerp sub-tree
+ additiveNode->setAdditiveClip(clip2);
+ additiveNode->setAdditiveFactor(1.0f); // Wave arm fully
+
+ // Run the animator
+ auto animator = new QBlendedClipAnimator();
+ animator->setBlendTree(additiveNode);
+ animator->setChannelMapper(...);
+ animator->setRunning(true);
+ \endcode
+
+ By authoring a set of animation clips and blending between them dynamically at runtime with a
+ blend tree, we open up a huge set of possible resulting animations. As some simple examples of
+ the above blend tree, where alpha is the additive factor and beta is the lerp blend factor we
+ can get a 2D continuum of possible animations:
+
+ \badcode
+ (alpha = 0, beta = 1) Running, No arm waving --- (alpha = 1, beta = 1) Running, Arm waving
+ | |
+ | |
+ | |
+ (alpha = 0, beta = 0) Walking, No arm waving --- (alpha = 0, beta = 1) Running, No arm waving
+ \endcode
+
+ More complex blend trees offer even more flexibility for combining your animation clips. Note
+ that the values used to control the blend tree (alpha and beta above) are simple properties on
+ the blend nodes. This means, that these properties themselves can also be controlled by
+ the animation framework.
+
+*/
QBlendedClipAnimator::QBlendedClipAnimator(Qt3DCore::QNode *parent)
- : Qt3DCore::QComponent(*new QBlendedClipAnimatorPrivate, parent)
+ : Qt3DAnimation::QAbstractClipAnimator(*new QBlendedClipAnimatorPrivate, parent)
{
}
+/*! \internal */
QBlendedClipAnimator::QBlendedClipAnimator(QBlendedClipAnimatorPrivate &dd, Qt3DCore::QNode *parent)
- : Qt3DCore::QComponent(dd, parent)
+ : Qt3DAnimation::QAbstractClipAnimator(dd, parent)
{
}
@@ -68,28 +266,23 @@ QBlendedClipAnimator::~QBlendedClipAnimator()
{
}
-QAbstractClipBlendNode *QBlendedClipAnimator::blendTree() const
-{
- Q_D(const QBlendedClipAnimator);
- return d->m_blendTreeRoot;
-}
+/*!
+ \qmlproperty AbstractClipBlendNode blendTree
-bool QBlendedClipAnimator::isRunning() const
-{
- Q_D(const QBlendedClipAnimator);
- return d->m_running;
-}
+ This property holds the root of the animation blend tree that will be evaluated before being
+ interpolated by the animator.
+*/
-QChannelMapper *QBlendedClipAnimator::channelMapper() const
-{
- Q_D(const QBlendedClipAnimator);
- return d->m_mapper;
-}
+/*!
+ \property blendTree
-int QBlendedClipAnimator::loops() const
+ This property holds the root of the animation blend tree that will be evaluated before being
+ interpolated by the animator.
+*/
+QAbstractClipBlendNode *QBlendedClipAnimator::blendTree() const
{
Q_D(const QBlendedClipAnimator);
- return d->m_loops;
+ return d->m_blendTreeRoot;
}
void QBlendedClipAnimator::setBlendTree(QAbstractClipBlendNode *blendTree)
@@ -112,45 +305,7 @@ void QBlendedClipAnimator::setBlendTree(QAbstractClipBlendNode *blendTree)
emit blendTreeChanged(blendTree);
}
-void QBlendedClipAnimator::setRunning(bool running)
-{
- Q_D(QBlendedClipAnimator);
- if (d->m_running == running)
- return;
-
- d->m_running = running;
- emit runningChanged(running);
-}
-
-void QBlendedClipAnimator::setLoops(int loops)
-{
- Q_D(QBlendedClipAnimator);
- if (d->m_loops == loops)
- return;
-
- d->m_loops = loops;
- emit loopsChanged(loops);
-}
-
-
-void QBlendedClipAnimator::setChannelMapper(QChannelMapper *mapping)
-{
- Q_D(QBlendedClipAnimator);
- if (d->m_mapper == mapping)
- return;
-
- if (d->m_mapper)
- d->unregisterDestructionHelper(d->m_mapper);
-
- if (mapping && !mapping->parent())
- mapping->setParent(this);
- d->m_mapper = mapping;
-
- if (d->m_mapper)
- d->registerDestructionHelper(d->m_mapper, &QBlendedClipAnimator::setChannelMapper, d->m_mapper);
- emit channelMapperChanged(mapping);
-}
-
+/*! \internal */
Qt3DCore::QNodeCreatedChangeBasePtr QBlendedClipAnimator::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QBlendedClipAnimatorData>::create(this);
diff --git a/src/animation/frontend/qblendedclipanimator.h b/src/animation/frontend/qblendedclipanimator.h
index be1189f4f..c227a05cc 100644
--- a/src/animation/frontend/qblendedclipanimator.h
+++ b/src/animation/frontend/qblendedclipanimator.h
@@ -41,47 +41,34 @@
#define QT3DANIMATION_QBLENDEDCLIPANIMATOR_H
#include <Qt3DAnimation/qt3danimation_global.h>
-#include <Qt3DCore/qcomponent.h>
+#include <Qt3DAnimation/qabstractclipanimator.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QChannelMapper;
class QAbstractClipBlendNode;
class QBlendedClipAnimatorPrivate;
-class QT3DANIMATIONSHARED_EXPORT QBlendedClipAnimator : public Qt3DCore::QComponent
+class QT3DANIMATIONSHARED_EXPORT QBlendedClipAnimator : public Qt3DAnimation::QAbstractClipAnimator
{
Q_OBJECT
Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *blendTree READ blendTree WRITE setBlendTree NOTIFY blendTreeChanged)
- Q_PROPERTY(Qt3DAnimation::QChannelMapper *channelMapper READ channelMapper WRITE setChannelMapper NOTIFY channelMapperChanged)
- Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged)
- Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
public:
explicit QBlendedClipAnimator(Qt3DCore::QNode *parent = nullptr);
~QBlendedClipAnimator();
- bool isRunning() const;
- Qt3DAnimation::QChannelMapper *channelMapper() const;
QAbstractClipBlendNode *blendTree() const;
- int loops() const;
public Q_SLOTS:
- void setRunning(bool running);
- void setChannelMapper(QChannelMapper *channelMapper);
void setBlendTree(QAbstractClipBlendNode * blendTree);
- void setLoops(int loops);
Q_SIGNALS:
void blendTreeChanged(QAbstractClipBlendNode * blendTree);
- void runningChanged(bool running);
- void channelMapperChanged(QChannelMapper *channelMapper);
- void loopsChanged(int loops);
protected:
- QBlendedClipAnimator(QBlendedClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ explicit QBlendedClipAnimator(QBlendedClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QBlendedClipAnimator)
diff --git a/src/animation/frontend/qblendedclipanimator_p.h b/src/animation/frontend/qblendedclipanimator_p.h
index 47a8bbfd5..e874a528d 100644
--- a/src/animation/frontend/qblendedclipanimator_p.h
+++ b/src/animation/frontend/qblendedclipanimator_p.h
@@ -51,33 +51,26 @@
// We mean it.
//
-#include <Qt3DCore/private/qcomponent_p.h>
+#include <Qt3DAnimation/private/qabstractclipanimator_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
class QAbstractClipBlendNode;
-class QChannelMapper;
-class QBlendedClipAnimatorPrivate : public Qt3DCore::QComponentPrivate
+class QBlendedClipAnimatorPrivate : public Qt3DAnimation::QAbstractClipAnimatorPrivate
{
public:
QBlendedClipAnimatorPrivate();
Q_DECLARE_PUBLIC(QBlendedClipAnimator)
QAbstractClipBlendNode *m_blendTreeRoot;
- QChannelMapper *m_mapper;
- bool m_running;
- int m_loops;
};
-struct QBlendedClipAnimatorData
+struct QBlendedClipAnimatorData : public QAbstractClipAnimatorData
{
Qt3DCore::QNodeId blendTreeRootId;
- Qt3DCore::QNodeId mapperId;
- bool running;
- int loops;
};
} // namespace Qt3DAnimation
diff --git a/src/animation/frontend/qchannel.cpp b/src/animation/frontend/qchannel.cpp
new file mode 100644
index 000000000..9c74fad09
--- /dev/null
+++ b/src/animation/frontend/qchannel.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qchannel.h"
+
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QChannelPrivate
+{
+public:
+ QVector<QChannelComponent> m_channelComponents;
+ QString m_name;
+};
+
+QChannel::QChannel()
+ : d(new QChannelPrivate)
+{
+}
+
+QChannel::QChannel(const QString &name)
+ : d(new QChannelPrivate)
+{
+ d->m_name = name;
+}
+
+QChannel::QChannel(const QChannel &rhs)
+ : d(new QChannelPrivate)
+{
+ *d = *(rhs.d);
+}
+
+QChannel &QChannel::operator=(const QChannel &rhs)
+{
+ if (this != &rhs)
+ *d = *(rhs.d);
+ return *this;
+}
+
+QChannel::~QChannel()
+{
+}
+
+void QChannel::setName(const QString &name)
+{
+ d->m_name = name;
+}
+
+QString QChannel::name() const
+{
+ return d->m_name;
+}
+
+int QChannel::channelComponentCount() const
+{
+ return d->m_channelComponents.size();
+}
+
+void QChannel::appendChannelComponent(const QChannelComponent &component)
+{
+ d->m_channelComponents.append(component);
+}
+
+void QChannel::insertChannelComponent(int index, const QChannelComponent &component)
+{
+ d->m_channelComponents.insert(index, component);
+}
+
+void QChannel::removeChannelComponent(int index)
+{
+ d->m_channelComponents.remove(index);
+}
+
+void QChannel::clearChannelComponents()
+{
+ d->m_channelComponents.clear();
+}
+
+QChannel::const_iterator QChannel::begin() const Q_DECL_NOTHROW
+{
+ return d->m_channelComponents.begin();
+}
+
+QChannel::const_iterator QChannel::end() const Q_DECL_NOTHROW
+{
+ return d->m_channelComponents.end();
+}
+
+bool operator==(const QChannel &lhs, const QChannel &rhs) Q_DECL_NOTHROW
+{
+ return lhs.d->m_name == rhs.d->m_name &&
+ lhs.d->m_channelComponents == rhs.d->m_channelComponents;
+}
+
+bool operator!=(const QChannel &lhs, const QChannel &rhs) Q_DECL_NOTHROW
+{
+ return lhs.d->m_name != rhs.d->m_name ||
+ lhs.d->m_channelComponents != rhs.d->m_channelComponents;
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qchannel.h b/src/animation/frontend/qchannel.h
new file mode 100644
index 000000000..b94780689
--- /dev/null
+++ b/src/animation/frontend/qchannel.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QCHANNEL_H
+#define QT3DANIMATION_QCHANNEL_H
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DAnimation/qchannelcomponent.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QChannelPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QChannel
+{
+public:
+ QChannel();
+ explicit QChannel(const QString &name);
+ QChannel(const QChannel &);
+ QChannel &operator=(const QChannel &);
+ ~QChannel();
+
+ void setName(const QString &name);
+ QString name() const;
+
+ int channelComponentCount() const;
+ void appendChannelComponent(const QChannelComponent &component);
+ void insertChannelComponent(int index, const QChannelComponent &component);
+ void removeChannelComponent(int index);
+ void clearChannelComponents();
+
+ // Iterator API
+ typedef const QChannelComponent *const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ const_iterator begin() const Q_DECL_NOTHROW;
+ const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
+ const_iterator end() const Q_DECL_NOTHROW;
+ const_iterator cend() const Q_DECL_NOTHROW { return end(); }
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+
+ friend bool operator==(const QChannel &,
+ const QChannel &) Q_DECL_NOTHROW;
+ friend bool operator!=(const QChannel &,
+ const QChannel &) Q_DECL_NOTHROW;
+
+private:
+ QScopedPointer<QChannelPrivate> d;
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QCHANNEL_H
diff --git a/src/quick3d/quick3danimation/items/quick3dabstractclipblendnode.cpp b/src/animation/frontend/qchannelcomponent.cpp
index 7a709c2d6..1ecc5520c 100644
--- a/src/quick3d/quick3danimation/items/quick3dabstractclipblendnode.cpp
+++ b/src/animation/frontend/qchannelcomponent.cpp
@@ -37,56 +37,106 @@
**
****************************************************************************/
-#include "quick3dabstractclipblendnode_p.h"
+#include "qchannelcomponent.h"
+
+#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-namespace Animation {
-namespace Quick {
-Quick3DAbstractClipBlendNode::Quick3DAbstractClipBlendNode(QObject *parent)
- : QObject(parent)
+class QChannelComponentPrivate
+{
+public:
+ QVector<QKeyFrame> m_keyFrames;
+ QString m_name;
+};
+
+QChannelComponent::QChannelComponent()
+ : d(new QChannelComponentPrivate)
+{
+}
+
+QChannelComponent::QChannelComponent(const QString &name)
+ : d(new QChannelComponentPrivate)
+{
+ d->m_name = name;
+}
+
+QChannelComponent::QChannelComponent(const QChannelComponent &rhs)
+ : d(new QChannelComponentPrivate)
+{
+ *d = *(rhs.d);
+}
+
+QChannelComponent &QChannelComponent::operator=(const QChannelComponent &rhs)
+{
+ if (this != &rhs)
+ *d = *(rhs.d);
+ return *this;
+}
+
+QChannelComponent::~QChannelComponent()
+{
+}
+
+void QChannelComponent::setName(const QString &name)
+{
+ d->m_name = name;
+}
+
+QString QChannelComponent::name() const
+{
+ return d->m_name;
+}
+
+int QChannelComponent::keyFrameCount() const
+{
+ return d->m_keyFrames.size();
+}
+
+void QChannelComponent::appendKeyFrame(const QKeyFrame &kf)
+{
+ d->m_keyFrames.append(kf);
+}
+
+void QChannelComponent::insertKeyFrame(int index, const QKeyFrame &kf)
+{
+ d->m_keyFrames.insert(index, kf);
+}
+
+void QChannelComponent::removeKeyFrame(int index)
{
+ d->m_keyFrames.remove(index);
}
-QQmlListProperty<QAnimationClip> Quick3DAbstractClipBlendNode::clipList()
+void QChannelComponent::clearKeyFrames()
{
- return QQmlListProperty<QAnimationClip>(this, 0,
- &Quick3DAbstractClipBlendNode::appendClip,
- &Quick3DAbstractClipBlendNode::clipCount,
- &Quick3DAbstractClipBlendNode::clipAt,
- &Quick3DAbstractClipBlendNode::clearClips);
+ d->m_keyFrames.clear();
}
-void Quick3DAbstractClipBlendNode::appendClip(QQmlListProperty<QAnimationClip> *list, QAnimationClip *clip)
+QChannelComponent::const_iterator QChannelComponent::begin() const Q_DECL_NOTHROW
{
- Quick3DAbstractClipBlendNode *extension = qobject_cast<Quick3DAbstractClipBlendNode *>(list->object);
- extension->parentAbstractClipBlendNode()->addClip(clip);
+ return d->m_keyFrames.begin();
}
-QAnimationClip *Quick3DAbstractClipBlendNode::clipAt(QQmlListProperty<QAnimationClip> *list, int index)
+QChannelComponent::const_iterator QChannelComponent::end() const Q_DECL_NOTHROW
{
- Quick3DAbstractClipBlendNode *extension = qobject_cast<Quick3DAbstractClipBlendNode *>(list->object);
- return extension->parentAbstractClipBlendNode()->clips().at(index);
+ return d->m_keyFrames.end();
}
-int Quick3DAbstractClipBlendNode::clipCount(QQmlListProperty<QAnimationClip> *list)
+bool operator==(const QChannelComponent &lhs, const QChannelComponent &rhs) Q_DECL_NOTHROW
{
- Quick3DAbstractClipBlendNode *extension = qobject_cast<Quick3DAbstractClipBlendNode *>(list->object);
- return extension->parentAbstractClipBlendNode()->clips().count();
+ return lhs.d->m_name == rhs.d->m_name &&
+ lhs.d->m_keyFrames == rhs.d->m_keyFrames;
}
-void Quick3DAbstractClipBlendNode::clearClips(QQmlListProperty<QAnimationClip> *list)
+bool operator!=(const QChannelComponent &lhs, const QChannelComponent &rhs) Q_DECL_NOTHROW
{
- Quick3DAbstractClipBlendNode *extension = qobject_cast<Quick3DAbstractClipBlendNode *>(list->object);
- const QVector<QAnimationClip *> clips = extension->parentAbstractClipBlendNode()->clips();
- for (QAnimationClip *clip : clips)
- extension->parentAbstractClipBlendNode()->removeClip(clip);
+ return lhs.d->m_name != rhs.d->m_name ||
+ lhs.d->m_keyFrames != rhs.d->m_keyFrames;
}
-} // Quick
-} // Animation
-} // Qt3DAnimation
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/animation/frontend/qchannelcomponent.h b/src/animation/frontend/qchannelcomponent.h
new file mode 100644
index 000000000..922073a85
--- /dev/null
+++ b/src/animation/frontend/qchannelcomponent.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QCHANNELCOMPONENT_H
+#define QT3DANIMATION_QCHANNELCOMPONENT_H
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DAnimation/qkeyframe.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QChannelComponentPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QChannelComponent
+{
+public:
+ QChannelComponent();
+ explicit QChannelComponent(const QString &name);
+ QChannelComponent(const QChannelComponent &);
+ QChannelComponent &operator=(const QChannelComponent &);
+ ~QChannelComponent();
+
+ void setName(const QString &name);
+ QString name() const;
+
+ int keyFrameCount() const;
+ void appendKeyFrame(const QKeyFrame &kf);
+ void insertKeyFrame(int index, const QKeyFrame &kf);
+ void removeKeyFrame(int index);
+ void clearKeyFrames();
+
+ // Iterator API
+ typedef const QKeyFrame *const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ const_iterator begin() const Q_DECL_NOTHROW;
+ const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
+ const_iterator end() const Q_DECL_NOTHROW;
+ const_iterator cend() const Q_DECL_NOTHROW { return end(); }
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+
+ friend bool operator==(const QChannelComponent &,
+ const QChannelComponent &) Q_DECL_NOTHROW;
+ friend bool operator!=(const QChannelComponent &,
+ const QChannelComponent &) Q_DECL_NOTHROW;
+
+private:
+ QScopedPointer<QChannelComponentPrivate> d;
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QCHANNELCOMPONENT_H
diff --git a/src/animation/frontend/qchannelmapper.h b/src/animation/frontend/qchannelmapper.h
index 399d92d5d..14319f29b 100644
--- a/src/animation/frontend/qchannelmapper.h
+++ b/src/animation/frontend/qchannelmapper.h
@@ -60,7 +60,7 @@ public:
QVector<QChannelMapping *> mappings() const;
protected:
- QChannelMapper(QChannelMapperPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ explicit QChannelMapper(QChannelMapperPrivate &dd, Qt3DCore::QNode *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QChannelMapper)
diff --git a/src/animation/frontend/qchannelmapping.h b/src/animation/frontend/qchannelmapping.h
index 0c4ca07f4..d768298fe 100644
--- a/src/animation/frontend/qchannelmapping.h
+++ b/src/animation/frontend/qchannelmapping.h
@@ -72,7 +72,7 @@ Q_SIGNALS:
void propertyChanged(QString property);
protected:
- QChannelMapping(QChannelMappingPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ explicit QChannelMapping(QChannelMappingPrivate &dd, Qt3DCore::QNode *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QChannelMapping)
diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp
index e6c06c989..eb6c80aee 100644
--- a/src/animation/frontend/qclipanimator.cpp
+++ b/src/animation/frontend/qclipanimator.cpp
@@ -39,7 +39,7 @@
#include "qclipanimator.h"
#include "qclipanimator_p.h"
-#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/qabstractanimationclip.h>
#include <Qt3DAnimation/qchannelmapper.h>
QT_BEGIN_NAMESPACE
@@ -47,21 +47,66 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
QClipAnimatorPrivate::QClipAnimatorPrivate()
- : Qt3DCore::QComponentPrivate()
+ : Qt3DAnimation::QAbstractClipAnimatorPrivate()
, m_clip(nullptr)
- , m_mapper(nullptr)
- , m_running(false)
- , m_loops(1)
{
}
+/*!
+ \qmltype ClipAnimator
+ \instantiates Qt3DAnimation::QClipAnimator
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+
+ \brief ClipAnimator is a component providing simple animation playback capabilities.
+
+ An instance of ClipAnimator can be aggregated by an Entity to add the ability to play back
+ animation clips and to apply the calculated animation values to properties of QObjects.
+
+ The animation key frame data is provided via the clip property. This can be created
+ programmatically with AnimationClip or loaded from file with AnimationClipLoader.
+
+ In order to apply the values played back from the channels of data in the animation clip, the
+ clip animator needs to have a ChannelMapper object assigned to the channelMapper property.
+
+ The properties for controlling the animator are provided by the AbstractClipAnimator base
+ class.
+
+ \sa AbstractClipAnimator, AbstractAnimationClip, ChannelMapper, BlendedClipAnimator
+*/
+
+/*!
+ \class Qt3DAnimation::QClipAnimator
+ \inherits Qt3DAnimation::QAbstractClipAnimator
+
+ \inmodule Qt3DAnimation
+ \since 5.9
+
+ \brief QClipAnimator is a component providing simple animation playback capabilities.
+
+ An instance of QClipAnimator can be aggregated by a QEntity to add the ability to play back
+ animation clips and to apply the calculated animation values to properties of QObjects.
+
+ The animation key frame data is provided via the clip property. This can be created
+ programmatically with QAnimationClip or loaded from file with QAnimationClipLoader.
+
+ In order to apply the values played back from the channels of data in the animation clip, the
+ clip animator needs to have a QChannelMapper object assigned to the channelMapper property.
+
+ The properties for controlling the animator are provided by the QAbstractClipAnimator base
+ class.
+
+ \sa QAbstractClipAnimator, QAbstractAnimationClip, QChannelMapper, QBlendedClipAnimator
+*/
+
QClipAnimator::QClipAnimator(Qt3DCore::QNode *parent)
- : Qt3DCore::QComponent(*new QClipAnimatorPrivate, parent)
+ : Qt3DAnimation::QAbstractClipAnimator(*new QClipAnimatorPrivate, parent)
{
}
+/*! \internal */
QClipAnimator::QClipAnimator(QClipAnimatorPrivate &dd, Qt3DCore::QNode *parent)
- : Qt3DCore::QComponent(dd, parent)
+ : Qt3DAnimation::QAbstractClipAnimator(dd, parent)
{
}
@@ -69,31 +114,26 @@ QClipAnimator::~QClipAnimator()
{
}
-QAnimationClip *QClipAnimator::clip() const
-{
- Q_D(const QClipAnimator);
- return d->m_clip;
-}
+/*!
+ \qmlproperty AbstractAnimationClip clip
-bool QClipAnimator::isRunning() const
-{
- Q_D(const QClipAnimator);
- return d->m_running;
-}
+ This property holds the animation clip which contains the key frame data to be played back.
+ The key frame data can be specified in either an AnimationClip or AnimationClipLoader.
+*/
-QChannelMapper *QClipAnimator::channelMapper() const
-{
- Q_D(const QClipAnimator);
- return d->m_mapper;
-}
+/*!
+ \property clip
-int QClipAnimator::loops() const
+ This property holds the animation clip which contains the key frame data to be played back.
+ The key frame data can be specified in either a QAnimationClip or QAnimationClipLoader.
+*/
+QAbstractAnimationClip *QClipAnimator::clip() const
{
Q_D(const QClipAnimator);
- return d->m_loops;
+ return d->m_clip;
}
-void QClipAnimator::setClip(QAnimationClip *clip)
+void QClipAnimator::setClip(QAbstractAnimationClip *clip)
{
Q_D(QClipAnimator);
if (d->m_clip == clip)
@@ -112,45 +152,7 @@ void QClipAnimator::setClip(QAnimationClip *clip)
emit clipChanged(clip);
}
-void QClipAnimator::setRunning(bool running)
-{
- Q_D(QClipAnimator);
- if (d->m_running == running)
- return;
-
- d->m_running = running;
- emit runningChanged(running);
-}
-
-void QClipAnimator::setChannelMapper(QChannelMapper *mapping)
-{
- Q_D(QClipAnimator);
- if (d->m_mapper == mapping)
- return;
-
- if (d->m_mapper)
- d->unregisterDestructionHelper(d->m_mapper);
-
- if (mapping && !mapping->parent())
- mapping->setParent(this);
- d->m_mapper = mapping;
-
- // Ensures proper bookkeeping
- if (d->m_mapper)
- d->registerDestructionHelper(d->m_mapper, &QClipAnimator::setChannelMapper, d->m_mapper);
- emit channelMapperChanged(mapping);
-}
-
-void QClipAnimator::setLoops(int loops)
-{
- Q_D(QClipAnimator);
- if (d->m_loops == loops)
- return;
-
- d->m_loops = loops;
- emit loopsChanged(loops);
-}
-
+/*! \internal */
Qt3DCore::QNodeCreatedChangeBasePtr QClipAnimator::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QClipAnimatorData>::create(this);
diff --git a/src/animation/frontend/qclipanimator.h b/src/animation/frontend/qclipanimator.h
index 176d6fc0c..311ac4ab0 100644
--- a/src/animation/frontend/qclipanimator.h
+++ b/src/animation/frontend/qclipanimator.h
@@ -41,44 +41,32 @@
#define QT3DANIMATION_QCLIPANIMATOR_H
#include <Qt3DAnimation/qt3danimation_global.h>
-#include <Qt3DCore/qcomponent.h>
+#include <Qt3DAnimation/qabstractclipanimator.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QAnimationClip;
+class QAbstractAnimationClip;
class QChannelMapper;
class QClipAnimatorPrivate;
-class QT3DANIMATIONSHARED_EXPORT QClipAnimator : public Qt3DCore::QComponent
+class QT3DANIMATIONSHARED_EXPORT QClipAnimator : public Qt3DAnimation::QAbstractClipAnimator
{
Q_OBJECT
- Q_PROPERTY(Qt3DAnimation::QAnimationClip *clip READ clip WRITE setClip NOTIFY clipChanged)
- Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
- Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged)
- Q_PROPERTY(Qt3DAnimation::QChannelMapper *channelMapper READ channelMapper WRITE setChannelMapper NOTIFY channelMapperChanged)
+ Q_PROPERTY(Qt3DAnimation::QAbstractAnimationClip *clip READ clip WRITE setClip NOTIFY clipChanged)
public:
explicit QClipAnimator(Qt3DCore::QNode *parent = nullptr);
~QClipAnimator();
- Qt3DAnimation::QAnimationClip *clip() const;
- bool isRunning() const;
- Qt3DAnimation::QChannelMapper *channelMapper() const;
- int loops() const;
+ Qt3DAnimation::QAbstractAnimationClip *clip() const;
public Q_SLOTS:
- void setClip(Qt3DAnimation::QAnimationClip *clip);
- void setRunning(bool running);
- void setChannelMapper(Qt3DAnimation::QChannelMapper *channelMapper);
- void setLoops(int loops);
+ void setClip(Qt3DAnimation::QAbstractAnimationClip *clip);
Q_SIGNALS:
- void clipChanged(Qt3DAnimation::QAnimationClip *clip);
- void runningChanged(bool running);
- void channelMapperChanged(Qt3DAnimation::QChannelMapper *channelMapper);
- void loopsChanged(int loops);
+ void clipChanged(Qt3DAnimation::QAbstractAnimationClip *clip);
protected:
QClipAnimator(QClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
diff --git a/src/animation/frontend/qclipanimator_p.h b/src/animation/frontend/qclipanimator_p.h
index 7bb9c526f..fe40ed442 100644
--- a/src/animation/frontend/qclipanimator_p.h
+++ b/src/animation/frontend/qclipanimator_p.h
@@ -51,34 +51,27 @@
// We mean it.
//
-#include <Qt3DCore/private/qcomponent_p.h>
-#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/private/qabstractclipanimator_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QChannelMapper;
+class QAbstractAnimationClip;
-class QClipAnimatorPrivate : public Qt3DCore::QComponentPrivate
+class QClipAnimatorPrivate : public Qt3DAnimation::QAbstractClipAnimatorPrivate
{
public:
QClipAnimatorPrivate();
Q_DECLARE_PUBLIC(QClipAnimator)
- QAnimationClip *m_clip;
- Qt3DAnimation::QChannelMapper *m_mapper;
- bool m_running;
- int m_loops;
+ QAbstractAnimationClip *m_clip;
};
-struct QClipAnimatorData
+struct QClipAnimatorData : public QAbstractClipAnimatorData
{
Qt3DCore::QNodeId clipId;
- Qt3DCore::QNodeId mapperId;
- bool running;
- int loops;
};
} // namespace Qt3DAnimation
diff --git a/src/animation/frontend/qclipblendnodecreatedchange.cpp b/src/animation/frontend/qclipblendnodecreatedchange.cpp
index 9e9104066..9251442bb 100644
--- a/src/animation/frontend/qclipblendnodecreatedchange.cpp
+++ b/src/animation/frontend/qclipblendnodecreatedchange.cpp
@@ -37,7 +37,7 @@
#include "qclipblendnodecreatedchange.h"
#include "qclipblendnodecreatedchange_p.h"
#include <Qt3DAnimation/qabstractclipblendnode.h>
-#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/qabstractanimationclip.h>
QT_BEGIN_NAMESPACE
@@ -45,8 +45,6 @@ namespace Qt3DAnimation {
QClipBlendNodeCreatedChangeBasePrivate::QClipBlendNodeCreatedChangeBasePrivate(const QAbstractClipBlendNode *node)
: Qt3DCore::QNodeCreatedChangeBasePrivate(node)
- , m_parentClipBlendNodeId(Qt3DCore::qIdForNode(node->parentClipBlendNode()))
- , m_clips(Qt3DCore::qIdsForNodes(node->clips()))
{
}
@@ -59,19 +57,6 @@ QClipBlendNodeCreatedChangeBase::~QClipBlendNodeCreatedChangeBase()
{
}
-Qt3DCore::QNodeId QClipBlendNodeCreatedChangeBase::parentClipBlendNodeId() const
-{
- Q_D(const QClipBlendNodeCreatedChangeBase);
- return d->m_parentClipBlendNodeId;
-}
-
-Qt3DCore::QNodeIdVector QClipBlendNodeCreatedChangeBase::clips() const
-{
- Q_D(const QClipBlendNodeCreatedChangeBase);
- return d->m_clips;
-}
-
-
} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/animation/frontend/qclipblendnodecreatedchange.h b/src/animation/frontend/qclipblendnodecreatedchange.h
index b07d080bd..01f17d7ca 100644
--- a/src/animation/frontend/qclipblendnodecreatedchange.h
+++ b/src/animation/frontend/qclipblendnodecreatedchange.h
@@ -53,9 +53,6 @@ public:
explicit QClipBlendNodeCreatedChangeBase(const QAbstractClipBlendNode *node);
~QClipBlendNodeCreatedChangeBase();
- Qt3DCore::QNodeId parentClipBlendNodeId() const;
- Qt3DCore::QNodeIdVector clips() const;
-
private:
Q_DECLARE_PRIVATE(QClipBlendNodeCreatedChangeBase)
};
diff --git a/src/animation/frontend/qclipblendnodecreatedchange_p.h b/src/animation/frontend/qclipblendnodecreatedchange_p.h
index 0b853cd96..31342d3a8 100644
--- a/src/animation/frontend/qclipblendnodecreatedchange_p.h
+++ b/src/animation/frontend/qclipblendnodecreatedchange_p.h
@@ -60,9 +60,6 @@ class QClipBlendNodeCreatedChangeBasePrivate : public Qt3DCore::QNodeCreatedChan
{
public:
QClipBlendNodeCreatedChangeBasePrivate(const QAbstractClipBlendNode *node);
-
- Qt3DCore::QNodeId m_parentClipBlendNodeId;
- Qt3DCore::QNodeIdVector m_clips;
};
} // Qt3DAnimation
diff --git a/src/animation/frontend/qclipblendvalue.cpp b/src/animation/frontend/qclipblendvalue.cpp
new file mode 100644
index 000000000..d329f6722
--- /dev/null
+++ b/src/animation/frontend/qclipblendvalue.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipblendvalue.h"
+#include "qclipblendvalue_p.h"
+#include <Qt3DAnimation/qabstractanimationclip.h>
+#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+QClipBlendValuePrivate::QClipBlendValuePrivate()
+ : QAbstractClipBlendNodePrivate()
+ , m_clip(nullptr)
+{
+}
+
+QClipBlendValue::QClipBlendValue(Qt3DCore::QNode *parent)
+ : QAbstractClipBlendNode(*new QClipBlendValuePrivate(), parent)
+{
+}
+
+QClipBlendValue::QClipBlendValue(Qt3DAnimation::QAbstractAnimationClip *clip,
+ Qt3DCore::QNode *parent)
+ : QAbstractClipBlendNode(*new QClipBlendValuePrivate(), parent)
+{
+ setClip(clip);
+}
+
+QClipBlendValue::QClipBlendValue(QClipBlendValuePrivate &dd, Qt3DCore::QNode *parent)
+ : QAbstractClipBlendNode(dd, parent)
+{
+}
+
+QClipBlendValue::~QClipBlendValue()
+{
+}
+
+Qt3DAnimation::QAbstractAnimationClip *QClipBlendValue::clip() const
+{
+ Q_D(const QClipBlendValue);
+ return d->m_clip;
+}
+
+void QClipBlendValue::setClip(Qt3DAnimation::QAbstractAnimationClip *clip)
+{
+ Q_D(QClipBlendValue);
+ if (d->m_clip == clip)
+ return;
+
+ if (d->m_clip)
+ d->unregisterDestructionHelper(d->m_clip);
+
+ if (clip && !clip->parent())
+ clip->setParent(this);
+ d->m_clip = clip;
+
+ // Ensures proper bookkeeping
+ if (d->m_clip)
+ d->registerDestructionHelper(d->m_clip, &QClipBlendValue::setClip, d->m_clip);
+ emit clipChanged(clip);
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QClipBlendValue::createNodeCreationChange() const
+{
+ Q_D(const QClipBlendValue);
+ auto creationChange = QClipBlendNodeCreatedChangePtr<QClipBlendValueData>::create(this);
+ QClipBlendValueData &data = creationChange->data;
+ data.clipId = Qt3DCore::qIdForNode(d->m_clip);
+ return creationChange;
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qclipblendvalue.h b/src/animation/frontend/qclipblendvalue.h
new file mode 100644
index 000000000..b18bfb57b
--- /dev/null
+++ b/src/animation/frontend/qclipblendvalue.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QCLIPBLENDVALUE_H
+#define QT3DANIMATION_QCLIPBLENDVALUE_H
+
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DAnimation/qabstractclipblendnode.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QClipBlendValuePrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QClipBlendValue : public Qt3DAnimation::QAbstractClipBlendNode
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DAnimation::QAbstractAnimationClip *clip READ clip WRITE setClip NOTIFY clipChanged)
+
+public:
+ explicit QClipBlendValue(Qt3DCore::QNode *parent = nullptr);
+ explicit QClipBlendValue(Qt3DAnimation::QAbstractAnimationClip *clip,
+ Qt3DCore::QNode *parent = nullptr);
+ ~QClipBlendValue();
+
+ Qt3DAnimation::QAbstractAnimationClip *clip() const;
+
+public Q_SLOTS:
+ void setClip(Qt3DAnimation::QAbstractAnimationClip *clip);
+
+Q_SIGNALS:
+ void clipChanged(Qt3DAnimation::QAbstractAnimationClip *clip);
+
+protected:
+ explicit QClipBlendValue(QClipBlendValuePrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QClipBlendValue)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QCLIPBLENDVALUE_H
diff --git a/src/animation/frontend/qclipblendvalue_p.h b/src/animation/frontend/qclipblendvalue_p.h
new file mode 100644
index 000000000..7a397a1b8
--- /dev/null
+++ b/src/animation/frontend/qclipblendvalue_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QCLIPBLENDNODE_P_H
+#define QT3DANIMATION_QCLIPBLENDNODE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DAnimation/private/qabstractclipblendnode_p.h>
+#include <Qt3DAnimation/qclipblendvalue.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QClipBlendValuePrivate : public QAbstractClipBlendNodePrivate
+{
+public:
+ QClipBlendValuePrivate();
+
+ Q_DECLARE_PUBLIC(QClipBlendValue)
+
+ Qt3DAnimation::QAbstractAnimationClip *m_clip;
+};
+
+struct QClipBlendValueData
+{
+ Qt3DCore::QNodeId clipId;
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QCLIPBLENDNODE_P_H
diff --git a/src/quick3d/imports/extras/defaults/qml/PerVertexColorMaterial.qml b/src/animation/frontend/qkeyframe.cpp
index 70c461edd..b3d339bf4 100644
--- a/src/quick3d/imports/extras/defaults/qml/PerVertexColorMaterial.qml
+++ b/src/animation/frontend/qkeyframe.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Lorenz Esch (TU Ilmenau).
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,17 +37,13 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
+#include "qkeyframe.h"
-Material {
- id: root
+QT_BEGIN_NAMESPACE
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/pervertexcolor.vert"
- fragmentES: "qrc:/shaders/es2/pervertexcolor.frag"
- vertex: "qrc:/shaders/gl3/pervertexcolor.vert"
- fragment: "qrc:/shaders/gl3/pervertexcolor.frag"
- }
-}
+namespace Qt3DAnimation {
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qkeyframe.h b/src/animation/frontend/qkeyframe.h
new file mode 100644
index 000000000..7eabbeb17
--- /dev/null
+++ b/src/animation/frontend/qkeyframe.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QKEYFRAME_H
+#define QT3DANIMATION_QKEYFRAME_H
+
+#include <QtGui/qvector2d.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QT3DANIMATIONSHARED_EXPORT QKeyFrame
+{
+public:
+ enum InterpolationType : quint8 {
+ ConstantInterpolation,
+ LinearInterpolation,
+ BezierInterpolation
+ };
+
+ Q_DECL_CONSTEXPR QKeyFrame() Q_DECL_NOTHROW
+ : m_coordinates()
+ , m_leftControlPoint()
+ , m_rightControlPoint()
+ , m_interpolationType(BezierInterpolation)
+ {
+ }
+
+ Q_DECL_CONSTEXPR explicit QKeyFrame(QVector2D coords) Q_DECL_NOTHROW
+ : m_coordinates(coords)
+ , m_leftControlPoint()
+ , m_rightControlPoint()
+ , m_interpolationType(LinearInterpolation)
+ {
+ }
+
+ Q_DECL_CONSTEXPR explicit QKeyFrame(QVector2D coords,
+ QVector2D lh,
+ QVector2D rh) Q_DECL_NOTHROW
+ : m_coordinates(coords)
+ , m_leftControlPoint(lh)
+ , m_rightControlPoint(rh)
+ , m_interpolationType(BezierInterpolation)
+ {
+ }
+
+ void setCoordinates(QVector2D coords) Q_DECL_NOTHROW
+ {
+ m_coordinates = coords;
+ }
+
+ Q_DECL_CONSTEXPR QVector2D coordinates() const Q_DECL_NOTHROW
+ {
+ return m_coordinates;
+ }
+
+ void setLeftControlPoint(QVector2D lh) Q_DECL_NOTHROW
+ {
+ m_leftControlPoint = lh;
+ }
+
+ Q_DECL_CONSTEXPR QVector2D leftControlPoint() const Q_DECL_NOTHROW
+ {
+ return m_leftControlPoint;
+ }
+
+ void setRightControlPoint(QVector2D rh) Q_DECL_NOTHROW
+ {
+ m_rightControlPoint = rh;
+ }
+
+ Q_DECL_CONSTEXPR QVector2D rightControlPoint() const Q_DECL_NOTHROW
+ {
+ return m_rightControlPoint;
+ }
+
+ void setInterpolationType(InterpolationType interp) Q_DECL_NOTHROW
+ {
+ m_interpolationType = interp;
+ }
+
+ Q_DECL_CONSTEXPR InterpolationType interpolationType() const Q_DECL_NOTHROW
+ {
+ return m_interpolationType;
+ }
+
+ friend inline bool operator==(const QKeyFrame &, const QKeyFrame &) Q_DECL_NOTHROW;
+ friend inline bool operator!=(const QKeyFrame &, const QKeyFrame &) Q_DECL_NOTHROW;
+
+private:
+ QVector2D m_coordinates;
+ QVector2D m_leftControlPoint;
+ QVector2D m_rightControlPoint;
+ InterpolationType m_interpolationType;
+};
+
+QT3D_DECLARE_TYPEINFO(Qt3DAnimation, QKeyFrame, Q_PRIMITIVE_TYPE)
+
+inline bool operator==(const QKeyFrame &lhs, const QKeyFrame &rhs) Q_DECL_NOTHROW
+{
+ if (lhs.m_interpolationType != rhs.m_interpolationType)
+ return false;
+
+ if (lhs.m_interpolationType == QKeyFrame::BezierInterpolation) {
+ return lhs.m_coordinates == rhs.m_coordinates &&
+ lhs.m_leftControlPoint == rhs.m_leftControlPoint &&
+ lhs.m_rightControlPoint == rhs.m_rightControlPoint;
+ }
+
+ return lhs.m_coordinates == rhs.m_coordinates;
+}
+
+inline bool operator!=(const QKeyFrame &lhs, const QKeyFrame &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QKEYFRAME_H
diff --git a/src/animation/frontend/qkeyframeanimation.cpp b/src/animation/frontend/qkeyframeanimation.cpp
new file mode 100644
index 000000000..597b34cee
--- /dev/null
+++ b/src/animation/frontend/qkeyframeanimation.cpp
@@ -0,0 +1,415 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeyframeanimation.h"
+#include "Qt3DAnimation/private/qkeyframeanimation_p.h"
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QKeyframeAnimation
+ \brief A class implementing simple keyframe animation to a QTransform
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits Qt3DAnimation::QAbstractAnimation
+
+ A Qt3DAnimation::QKeyframeAnimation class implements simple keyframe animation
+ that can be used to animate \l QTransform. The keyframes consists of multiple
+ timed QTransforms, which are interpolated and applied to the target \l QTransform.
+ \l QEasingCurve is used between keyframes to control the interpolator. RepeatMode
+ can be set for when the position set to the QKeyframeAnimation is below or above
+ the values defined in the keyframe positions.
+*/
+
+/*!
+ \qmltype KeyframeAnimation
+ \brief A type implementing simple keyframe animation to a Transform
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \inherits AbstractAnimation
+ \instantiates Qt3DAnimation::QKeyframeAnimation
+
+ A KeyframeAnimation type implements simple keyframe animation
+ that can be used to animate \l Transform. The keyframes consists of multiple
+ timed \l {Qt3D.Core::Transform}s, which are interpolated and applied
+ to the target Transform. EasingCurve is used between keyframes to control
+ the interpolator. RepeatMode can be set for when the position set to the
+ KeyframeAnimation is less or or greater than the values defined in the keyframe positions.
+*/
+
+/*!
+ \property Qt3DAnimation::QKeyframeAnimation::framePositions
+ Holds the positions of the keyframes. Each position in the list specifies the position
+ of the corresponding keyframe with the same index. The values must be in an ascending order.
+ Values can be positive or negative and do not have any predefined unit.
+*/
+/*!
+ \property Qt3DAnimation::QKeyframeAnimation::target
+ Holds the target QTransform the animation is applied to.
+*/
+/*!
+ \property Qt3DAnimation::QKeyframeAnimation::easing
+ Holds the easing curve of the interpolator between keyframes.
+*/
+/*!
+ \property Qt3DAnimation::QKeyframeAnimation::targetName
+ Holds the name of the target transform. This is a convenience property making it
+ easier to match the target transform to the keyframe animation. The name
+ is usually same as the name of the parent entity of the target transform, but
+ does not have to be.
+*/
+/*!
+ \property Qt3DAnimation::QKeyframeAnimation::startMode
+ Holds the repeat mode for the position values less than the first frame position.
+*/
+/*!
+ \property Qt3DAnimation::QKeyframeAnimation::endMode
+ Holds the repeat mode for the position values greater than the last frame position.
+*/
+/*!
+ \enum QKeyframeAnimation::RepeatMode
+
+ This enumeration specifies how position values outside keyframe values are handled.
+ \value None The animation is not applied to the target transform.
+ \value Constant The edge keyframe value is used.
+ \value Repeat The animation is repeated.
+*/
+/*!
+ \qmlproperty list<real> KeyframeAnimation::framePositions
+ Holds the positions of the keyframes. Each position in the list specifies the position
+ of the corresponding keyframe. The values must be in an ascending order. Values can
+ be positive or negative and do not have any predefined unit.
+*/
+/*!
+ \qmlproperty Transform KeyframeAnimation::target
+ Holds the target Transform the animation is applied to.
+*/
+/*!
+ \qmlproperty EasingCurve KeyframeAnimation::easing
+ Holds the easing curve of the interpolator between keyframes.
+*/
+/*!
+ \qmlproperty string KeyframeAnimation::targetName
+ Holds the name of the target transform. This is a convenience property making it
+ easier to match the target transform to the keyframe animation. The name
+ is usually same as the name of the parent entity of the target transform, but
+ does not have to be.
+*/
+/*!
+ \qmlproperty enumeration KeyframeAnimation::startMode
+ Holds the repeat mode for the position values less than the first frame position.
+ \list
+ \li None
+ \li Constant
+ \li Repeat
+ \endlist
+*/
+/*!
+ \qmlproperty enumeration KeyframeAnimation::endMode
+ Holds the repeat mode for the position values greater than the last frame position.
+ \list
+ \li None
+ \li Constant
+ \li Repeat
+ \endlist
+*/
+/*!
+ \qmlproperty list<Transform> KeyframeAnimation::keyframes
+ Holds the list of keyframes in the keyframe animation.
+*/
+
+QKeyframeAnimationPrivate::QKeyframeAnimationPrivate()
+ : QAbstractAnimationPrivate(QAbstractAnimation::KeyframeAnimation)
+ , m_target(nullptr)
+ , m_minposition(0.0f)
+ , m_maxposition(0.0f)
+ , m_startMode(QKeyframeAnimation::Constant)
+ , m_endMode(QKeyframeAnimation::Constant)
+{
+
+}
+
+/*!
+ Constructs an QKeyframeAnimation with \a parent.
+*/
+QKeyframeAnimation::QKeyframeAnimation(QObject *parent)
+ : QAbstractAnimation(*new QKeyframeAnimationPrivate(), parent)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
+ this, &QKeyframeAnimation::updateAnimation);
+}
+
+
+void QKeyframeAnimation::setFramePositions(const QVector<float> &positions)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_framePositions = positions;
+ d->m_position = -1.0f;
+ if (d->m_framePositions.size() == 0) {
+ d->m_minposition = d->m_maxposition = 0.0f;
+ return;
+ }
+ d->m_minposition = d->m_framePositions.first();
+ d->m_maxposition = d->m_framePositions.last();
+ float lastPos = d->m_minposition;
+ for (float p : qAsConst(d->m_framePositions)) {
+ if (p < lastPos || p > d->m_maxposition)
+ qWarning() << "positions not ordered correctly";
+ lastPos = p;
+ }
+ setDuration(d->m_maxposition);
+}
+
+/*!
+ Sets the \a keyframes of the animation. Old keyframes are cleared.
+ */
+void QKeyframeAnimation::setKeyframes(const QVector<Qt3DCore::QTransform *> &keyframes)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_keyframes = keyframes;
+}
+
+// slerp which allows long path
+QQuaternion lslerp(QQuaternion q1, QQuaternion q2, float t)
+{
+ QQuaternion ret;
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ float cos = qBound(-1.0f, QQuaternion::dotProduct(q1, q2), 1.0f);
+ float angle = std::acos(cos);
+ float sin = std::sin(angle);
+ if (!qFuzzyIsNull(sin)) {
+ float a = std::sin((1.0 - t) * angle) / sin;
+ float b = std::sin(t * angle) / sin;
+ ret = (q1 * a + q2 * b).normalized();
+ } else {
+ ret = q1 * (1.0f-t) + q2 * t;
+ }
+ return ret;
+}
+
+void QKeyframeAnimationPrivate::calculateFrame(float position)
+{
+ if (m_target && m_framePositions.size() > 0
+ && m_keyframes.size() == m_framePositions.size()) {
+ if (position < m_minposition) {
+ if (m_startMode == QKeyframeAnimation::None) {
+ return;
+ } else if (m_startMode == QKeyframeAnimation::Constant) {
+ m_target->setRotation(m_keyframes.first()->rotation());
+ m_target->setScale3D(m_keyframes.first()->scale3D());
+ m_target->setTranslation(m_keyframes.first()->translation());
+ return;
+ } else {
+ // must be repeat
+ position = std::fmod(-(position - m_minposition), m_maxposition - m_minposition)
+ + m_minposition;
+ }
+ } else if (position >= m_maxposition) {
+ if (m_endMode == QKeyframeAnimation::None) {
+ return;
+ } else if (m_endMode == QKeyframeAnimation::Constant) {
+ m_target->setRotation(m_keyframes.last()->rotation());
+ m_target->setScale3D(m_keyframes.last()->scale3D());
+ m_target->setTranslation(m_keyframes.last()->translation());
+ return;
+ } else {
+ // must be repeat
+ position = std::fmod(position - m_minposition, m_maxposition - m_minposition)
+ + m_minposition;
+ }
+ }
+ if (position >= m_minposition && position < m_maxposition) {
+ for (int i = 0; i < m_framePositions.size() - 1; i++) {
+ if (position >= m_framePositions.at(i)
+ && position < m_framePositions.at(i+1)) {
+ float ip = (position - m_framePositions.at(i))
+ / (m_framePositions.at(i+1) - m_framePositions.at(i));
+ float eIp = m_easing.valueForProgress(ip);
+ float eIip = 1.0f - eIp;
+
+ Qt3DCore::QTransform *a = m_keyframes.at(i);
+ Qt3DCore::QTransform *b = m_keyframes.at(i+1);
+
+ QVector3D s = a->scale3D() * eIip + b->scale3D() * eIp;
+ QVector3D t = a->translation() * eIip + b->translation() * eIp;
+ QQuaternion r = QQuaternion::slerp(a->rotation(), b->rotation(), eIp);
+
+ m_target->setRotation(r);
+ m_target->setScale3D(s);
+ m_target->setTranslation(t);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void QKeyframeAnimation::updateAnimation(float position)
+{
+ Q_D(QKeyframeAnimation);
+ d->calculateFrame(position);
+}
+
+QVector<float> QKeyframeAnimation::framePositions() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_framePositions;
+}
+
+/*!
+ Returns the list of keyframes.
+ */
+QVector<Qt3DCore::QTransform *> QKeyframeAnimation::keyframeList() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_keyframes;
+}
+
+void QKeyframeAnimation::setTarget(Qt3DCore::QTransform *target)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_target != target) {
+ d->m_target = target;
+ emit targetChanged(d->m_target);
+ d->m_position = -1.0f;
+
+ if (target) {
+ d->m_baseScale = target->scale3D();
+ d->m_baseTranslation = target->translation();
+ d->m_baseRotation = target->rotation();
+ }
+ }
+}
+
+QKeyframeAnimation::RepeatMode QKeyframeAnimation::startMode() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_startMode;
+}
+
+QKeyframeAnimation::RepeatMode QKeyframeAnimation::endMode() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_endMode;
+}
+
+void QKeyframeAnimation::setEasing(const QEasingCurve &easing)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_easing != easing) {
+ d->m_easing = easing;
+ emit easingChanged(easing);
+ }
+}
+
+void QKeyframeAnimation::setTargetName(const QString &name)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_targetName != name) {
+ d->m_targetName = name;
+ emit targetNameChanged(name);
+ }
+}
+
+void QKeyframeAnimation::setStartMode(QKeyframeAnimation::RepeatMode mode)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_startMode != mode) {
+ d->m_startMode = mode;
+ emit startModeChanged(mode);
+ }
+}
+
+void QKeyframeAnimation::setEndMode(QKeyframeAnimation::RepeatMode mode)
+{
+ Q_D(QKeyframeAnimation);
+ if (mode != d->m_endMode) {
+ d->m_endMode = mode;
+ emit endModeChanged(mode);
+ }
+}
+
+/*!
+ Adds new \a keyframe at the end of the animation. The QTransform can
+ be added to the animation multiple times.
+ */
+void QKeyframeAnimation::addKeyframe(Qt3DCore::QTransform *keyframe)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_keyframes.push_back(keyframe);
+}
+
+/*!
+ Removes a \a keyframe from the animation. If the same QTransform
+ is set as keyframe multiple times, all occurrences are removed.
+ */
+void QKeyframeAnimation::removeKeyframe(Qt3DCore::QTransform *keyframe)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_keyframes.removeAll(keyframe);
+}
+
+QString QKeyframeAnimation::targetName() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_targetName;
+}
+
+QEasingCurve QKeyframeAnimation::easing() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_easing;
+}
+
+Qt3DCore::QTransform *QKeyframeAnimation::target() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_target;
+}
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qkeyframeanimation.h b/src/animation/frontend/qkeyframeanimation.h
index 178c9dbf1..19cb192b4 100644
--- a/src/extras/animations/qkeyframeanimation.h
+++ b/src/animation/frontend/qkeyframeanimation.h
@@ -34,28 +34,28 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QKEYFRAMEANIMATION_H
-#define QT3DEXTRAS_QKEYFRAMEANIMATION_H
+#ifndef QT3DANIMATION_QKEYFRAMEANIMATION_H
+#define QT3DANIMATION_QKEYFRAMEANIMATION_H
#include <Qt3DCore/qtransform.h>
-#include <Qt3DExtras/qabstractanimation.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qabstractanimation.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
#include <QtCore/qeasingcurve.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QKeyframeAnimationPrivate;
-class QT3DEXTRASSHARED_EXPORT QKeyframeAnimation : public QAbstractAnimation
+class QT3DANIMATIONSHARED_EXPORT QKeyframeAnimation : public QAbstractAnimation
{
Q_OBJECT
Q_PROPERTY(QVector<float> framePositions READ framePositions WRITE setFramePositions NOTIFY framePositionsChanged)
Q_PROPERTY(Qt3DCore::QTransform *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(QEasingCurve::Type easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
Q_PROPERTY(QString targetName READ targetName WRITE setTargetName NOTIFY targetNameChanged)
Q_PROPERTY(QKeyframeAnimation::RepeatMode startMode READ startMode WRITE setStartMode NOTIFY startModeChanged)
Q_PROPERTY(QKeyframeAnimation::RepeatMode endMode READ endMode WRITE setEndMode NOTIFY endModeChanged)
@@ -74,7 +74,7 @@ public:
QVector<float> framePositions() const;
QVector<Qt3DCore::QTransform *> keyframeList() const;
Qt3DCore::QTransform *target() const;
- QEasingCurve::Type easing() const;
+ QEasingCurve easing() const;
QString targetName() const;
RepeatMode startMode() const;
RepeatMode endMode() const;
@@ -86,7 +86,7 @@ public:
public Q_SLOTS:
void setFramePositions(const QVector<float> &positions);
void setTarget(Qt3DCore::QTransform *target);
- void setEasing(QEasingCurve::Type easing);
+ void setEasing(const QEasingCurve &easing);
void setTargetName(const QString &name);
void setStartMode(RepeatMode mode);
void setEndMode(RepeatMode mode);
@@ -94,10 +94,10 @@ public Q_SLOTS:
Q_SIGNALS:
void framePositionsChanged(const QVector<float> &positions);
void targetChanged(Qt3DCore::QTransform *target);
- void easingChanged(QEasingCurve::Type easing);
+ void easingChanged(const QEasingCurve &easing);
void targetNameChanged(const QString &name);
- void startModeChanged(RepeatMode startMode);
- void endModeChanged(RepeatMode endMode);
+ void startModeChanged(QKeyframeAnimation::RepeatMode startMode);
+ void endModeChanged(QKeyframeAnimation::RepeatMode endMode);
private:
void updateAnimation(float position);
@@ -105,8 +105,8 @@ private:
Q_DECLARE_PRIVATE(QKeyframeAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QKEYFRAMEANIMATION_H
+#endif // QT3DANIMATION_QKEYFRAMEANIMATION_H
diff --git a/src/extras/animations/qkeyframeanimation_p.h b/src/animation/frontend/qkeyframeanimation_p.h
index 0095b9432..b9b1f8585 100644
--- a/src/extras/animations/qkeyframeanimation_p.h
+++ b/src/animation/frontend/qkeyframeanimation_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QKEYFRAMEANIMATION_P_H
-#define QT3DEXTRAS_QKEYFRAMEANIMATION_P_H
+#ifndef QT3DANIMATION_QKEYFRAMEANIMATION_P_H
+#define QT3DANIMATION_QKEYFRAMEANIMATION_P_H
//
// W A R N I N G
@@ -49,12 +49,12 @@
//
#include <private/qobject_p.h>
-#include <Qt3DExtras/qkeyframeanimation.h>
+#include <Qt3DAnimation/qkeyframeanimation.h>
#include <private/qabstractanimation_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QKeyframeAnimationPrivate : public QAbstractAnimationPrivate
{
@@ -63,7 +63,6 @@ public:
void calculateFrame(float position);
- float m_prevPosition;
QVector<float> m_framePositions;
QVector<Qt3DCore::QTransform *> m_keyframes;
Qt3DCore::QTransform *m_target;
@@ -82,8 +81,8 @@ public:
Q_DECLARE_PUBLIC(QKeyframeAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QKEYFRAMEANIMATION_P_H
+#endif // QT3DANIMATION_QKEYFRAMEANIMATION_P_H
diff --git a/src/animation/frontend/qlerpblend.cpp b/src/animation/frontend/qlerpclipblend.cpp
index 661c70ef0..3b26adbaa 100644
--- a/src/animation/frontend/qlerpblend.cpp
+++ b/src/animation/frontend/qlerpclipblend.cpp
@@ -34,9 +34,8 @@
**
****************************************************************************/
-#include "qlerpblend.h"
-#include "qlerpblend_p.h"
-#include <Qt3DAnimation/qanimationclip.h>
+#include "qlerpclipblend.h"
+#include "qlerpclipblend_p.h"
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -45,7 +44,7 @@ namespace Qt3DAnimation {
/*!
\qmltype LerpBlend
- \instantiates Qt3DAnimation::QLerpBlend
+ \instantiates Qt3DAnimation::QLerpClipBlend
\inqmlmodule Qt3D.Animation
\brief Performs a linear interpolation of two animation clips based on a
@@ -65,7 +64,7 @@ namespace Qt3DAnimation {
*/
/*!
- \class Qt3DAnimation::QLerpBlend
+ \class Qt3DAnimation::QLerpClipBlend
\inmodule Qt3DAnimation
\inherits Qt3DAnimation::QAbstractClipBlendNode
@@ -74,7 +73,7 @@ namespace Qt3DAnimation {
\since 5.9
- QLerpBlend can be useful to create advanced animation effects based on
+ QLerpClipBlend can be useful to create advanced animation effects based on
individual animation clips. For instance, given a player character,, lerp
blending could be used to combine a walking animation clip with an injured
animation clip based on a blend factor that increases the more the player
@@ -85,31 +84,35 @@ namespace Qt3DAnimation {
\sa QBlendedClipAnimator
*/
-QLerpBlendPrivate::QLerpBlendPrivate()
+QLerpClipBlendPrivate::QLerpClipBlendPrivate()
: QAbstractClipBlendNodePrivate()
+ , m_startClip(nullptr)
+ , m_endClip(nullptr)
, m_blendFactor(0.0f)
{
}
-QLerpBlend::QLerpBlend(Qt3DCore::QNode *parent)
- : QAbstractClipBlendNode(*new QLerpBlendPrivate(), parent)
+QLerpClipBlend::QLerpClipBlend(Qt3DCore::QNode *parent)
+ : QAbstractClipBlendNode(*new QLerpClipBlendPrivate(), parent)
{
}
-QLerpBlend::QLerpBlend(QLerpBlendPrivate &dd, Qt3DCore::QNode *parent)
+QLerpClipBlend::QLerpClipBlend(QLerpClipBlendPrivate &dd, Qt3DCore::QNode *parent)
: QAbstractClipBlendNode(dd, parent)
{
}
-QLerpBlend::~QLerpBlend()
+QLerpClipBlend::~QLerpClipBlend()
{
}
-Qt3DCore::QNodeCreatedChangeBasePtr QLerpBlend::createNodeCreationChange() const
+Qt3DCore::QNodeCreatedChangeBasePtr QLerpClipBlend::createNodeCreationChange() const
{
- Q_D(const QLerpBlend);
- auto creationChange = QClipBlendNodeCreatedChangePtr<QLerpBlendData>::create(this);
- QLerpBlendData &data = creationChange->data;
+ Q_D(const QLerpClipBlend);
+ auto creationChange = QClipBlendNodeCreatedChangePtr<QLerpClipBlendData>::create(this);
+ QLerpClipBlendData &data = creationChange->data;
+ data.startClipId = Qt3DCore::qIdForNode(d->m_startClip);
+ data.endClipId = Qt3DCore::qIdForNode(d->m_endClip);
data.blendFactor = d->m_blendFactor;
return creationChange;
}
@@ -121,20 +124,61 @@ Qt3DCore::QNodeCreatedChangeBasePtr QLerpBlend::createNodeCreationChange() const
two animation clips.
*/
/*!
- \property QLerpBlend::blendFactor
+ \property QLerpClipBlend::blendFactor
Specifies the blending factor between 0 and 1 to control the blending of
two animation clips.
*/
-float QLerpBlend::blendFactor() const
+float QLerpClipBlend::blendFactor() const
{
- Q_D(const QLerpBlend);
+ Q_D(const QLerpClipBlend);
return d->m_blendFactor;
}
-void QLerpBlend::setBlendFactor(float blendFactor)
+/*!
+ \qmlproperty AbstractClipBlendNode LerpClipBlend::startClip
+
+ Holds the sub-tree that should be used as the start clip for this
+ lerp blend node. That is, the clip returned by this blend node when
+ the blendFactor is set to a value of 0.
+*/
+/*!
+ \property QLerpClipBlend::startClip
+
+ Holds the sub-tree that should be used as the start clip for this
+ lerp blend node. That is, the clip returned by this blend node when
+ the blendFactor is set to a value of 0.
+*/
+Qt3DAnimation::QAbstractClipBlendNode *QLerpClipBlend::startClip() const
{
- Q_D(QLerpBlend);
+ Q_D(const QLerpClipBlend);
+ return d->m_startClip;
+}
+
+/*!
+ \qmlproperty AbstractClipBlendNode LerpClipBlend::endClip
+
+ Holds the sub-tree that should be used as the end clip for this
+ lerp blend node. That is, the clip returned by this blend node when
+ the blendFactor is set to a value of 1.
+*/
+/*!
+ \property QLerpClipBlend::endClip
+
+ Holds the sub-tree that should be used as the start clip for this
+ lerp blend node. That is, the clip returned by this blend node when
+ the blendFactor is set to a value of 1.
+*/
+Qt3DAnimation::QAbstractClipBlendNode *QLerpClipBlend::endClip() const
+{
+ Q_D(const QLerpClipBlend);
+ return d->m_endClip;
+}
+
+void QLerpClipBlend::setBlendFactor(float blendFactor)
+{
+ Q_D(QLerpClipBlend);
+
if (d->m_blendFactor == blendFactor)
return;
@@ -142,6 +186,44 @@ void QLerpBlend::setBlendFactor(float blendFactor)
emit blendFactorChanged(blendFactor);
}
+void QLerpClipBlend::setStartClip(Qt3DAnimation::QAbstractClipBlendNode *startClip)
+{
+ Q_D(QLerpClipBlend);
+ if (d->m_startClip == startClip)
+ return;
+
+ if (d->m_startClip)
+ d->unregisterDestructionHelper(d->m_startClip);
+
+ if (startClip && !startClip->parent())
+ startClip->setParent(this);
+ d->m_startClip = startClip;
+
+ // Ensures proper bookkeeping
+ if (d->m_startClip)
+ d->registerDestructionHelper(d->m_startClip, &QLerpClipBlend::setStartClip, d->m_startClip);
+ emit startClipChanged(startClip);
+}
+
+void QLerpClipBlend::setEndClip(Qt3DAnimation::QAbstractClipBlendNode *endClip)
+{
+ Q_D(QLerpClipBlend);
+ if (d->m_endClip == endClip)
+ return;
+
+ if (d->m_endClip)
+ d->unregisterDestructionHelper(d->m_endClip);
+
+ if (endClip && !endClip->parent())
+ endClip->setParent(this);
+ d->m_endClip = endClip;
+
+ // Ensures proper bookkeeping
+ if (d->m_endClip)
+ d->registerDestructionHelper(d->m_endClip, &QLerpClipBlend::setEndClip, d->m_endClip);
+ emit endClipChanged(endClip);
+}
+
/*!
\qmlproperty list<AnimationClip> LerpBlend::clips
@@ -152,19 +234,19 @@ void QLerpBlend::setBlendFactor(float blendFactor)
/*!
- \fn void QLerpBlend::addClip(QAnimationClip *clip);
+ \fn void QLerpClipBlend::addClip(QAbstractAnimationClip *clip);
Adds a \a clip to the blending node's clips list.
\note Only the two first AnimationClip are used, subsequent ones are ignored
*/
/*!
- \fn void QLerpBlend::removeClip(QAnimationClip *clip);
+ \fn void QLerpClipBlend::removeClip(QAbstractAnimationClip *clip);
Removes a \a clip from the blending node's clips list.
*/
/*!
- \fn QVector<QAnimationClip *> QLerpBlend::clips() const;
+ \fn QVector<QAbstractAnimationClip *> QLerpClipBlend::clips() const;
Returns the list of QAnimationClip against which the blending is performed.
*/
diff --git a/src/animation/frontend/qlerpclipblend.h b/src/animation/frontend/qlerpclipblend.h
new file mode 100644
index 000000000..f6707a5a5
--- /dev/null
+++ b/src/animation/frontend/qlerpclipblend.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QLERPCLIPBLEND_H
+#define QT3DANIMATION_QLERPCLIPBLEND_H
+
+#include <Qt3DAnimation/qabstractclipblendnode.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QLerpClipBlendPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QLerpClipBlend : public QAbstractClipBlendNode
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *startClip READ startClip WRITE setStartClip NOTIFY startClipChanged)
+ Q_PROPERTY(Qt3DAnimation::QAbstractClipBlendNode *endClip READ endClip WRITE setEndClip NOTIFY endClipChanged)
+ Q_PROPERTY(float blendFactor READ blendFactor WRITE setBlendFactor NOTIFY blendFactorChanged)
+
+public:
+ explicit QLerpClipBlend(Qt3DCore::QNode *parent = nullptr);
+ ~QLerpClipBlend();
+
+ float blendFactor() const;
+ Qt3DAnimation::QAbstractClipBlendNode *startClip() const;
+ Qt3DAnimation::QAbstractClipBlendNode *endClip() const;
+
+public Q_SLOTS:
+ void setBlendFactor(float blendFactor);
+ void setStartClip(Qt3DAnimation::QAbstractClipBlendNode * startClip);
+ void setEndClip(Qt3DAnimation::QAbstractClipBlendNode * endClip);
+
+Q_SIGNALS:
+ void blendFactorChanged(float blendFactor);
+ void startClipChanged(Qt3DAnimation::QAbstractClipBlendNode * startClip);
+ void endClipChanged(Qt3DAnimation::QAbstractClipBlendNode * endClip);
+
+protected:
+ explicit QLerpClipBlend(QLerpClipBlendPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QLerpClipBlend)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+
+#endif // QT3DANIMATION_QLERPCLIPBLEND_H
diff --git a/src/animation/frontend/qlerpblend_p.h b/src/animation/frontend/qlerpclipblend_p.h
index 035e6cf79..eee597059 100644
--- a/src/animation/frontend/qlerpblend_p.h
+++ b/src/animation/frontend/qlerpclipblend_p.h
@@ -50,25 +50,29 @@
#include <Qt3DAnimation/private/qabstractclipblendnode_p.h>
#include <Qt3DCore/qnodeid.h>
-#include "qlerpblend.h"
+#include "qlerpclipblend.h"
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
-class QLerpBlend;
+class QLerpClipBlend;
-class QLerpBlendPrivate : public QAbstractClipBlendNodePrivate
+class QLerpClipBlendPrivate : public QAbstractClipBlendNodePrivate
{
public:
- QLerpBlendPrivate();
+ QLerpClipBlendPrivate();
- Q_DECLARE_PUBLIC(QLerpBlend)
+ Q_DECLARE_PUBLIC(QLerpClipBlend)
+ QAbstractClipBlendNode *m_startClip;
+ QAbstractClipBlendNode *m_endClip;
float m_blendFactor;
};
-struct QLerpBlendData
+struct QLerpClipBlendData
{
+ Qt3DCore::QNodeId startClipId;
+ Qt3DCore::QNodeId endClipId;
float blendFactor;
};
diff --git a/src/animation/frontend/qmorphinganimation.cpp b/src/animation/frontend/qmorphinganimation.cpp
new file mode 100644
index 000000000..3824b8d64
--- /dev/null
+++ b/src/animation/frontend/qmorphinganimation.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmorphinganimation.h"
+#include <private/qmorphinganimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QMorphingAnimation
+ \brief A class implementing blend-shape morphing animation
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits Qt3DAnimation::QAbstractAnimation
+
+ A Qt3DAnimation::QMorphingAnimation class implements blend-shape morphing animation
+ to a target \l {Qt3DRender::QGeometryRenderer}{QGeometryRenderer}. The QMorphingAnimation
+ sets the correct \l {Qt3DRender::QAttribute}{QAttributes} from the
+ \l {Qt3DAnimation::QMorphTarget}{morph targets} to the target
+ \l {Qt3DRender::QGeometryRenderer::geometry} {QGeometryRenderer::geometry} and calculates
+ interpolator for the current position. The actual blending between the attributes must
+ be implemented in the material. Qt3DAnimation::QMorphPhongMaterial implements material
+ with morphing support for phong lighting model. The blending happens between
+ 2 attributes - 'base' and 'target'. The names for the base and target attributes are taken from
+ the morph target names, where the base attribute retains the name it already has and the
+ target attribute name gets 'Target' appended to the name. The interpolator can be
+ set as a \l {Qt3DRender::QParameter}{QParameter} to the used material.
+ All morph targets in the animation should contain the attributes with same names as those
+ in the base geometry.
+
+*/
+/*!
+ \qmltype MorphingAnimation
+ \brief A type implementing blend-shape morphing animation
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \inherits AbstractAnimation
+ \instantiates Qt3DAnimation::QMorphingAnimation
+
+ A MorphingAnimation type implements blend-shape morphing animation
+ to a target \l GeometryRenderer. The MorphingAnimation sets the correct
+ \l {Attribute}{Attributes} from the morph targets to the target
+ \l {Qt3D.Render::GeometryRenderer::geometry}{GeometryRenderer::geometry} and calculates
+ interpolator for the current position. The actual blending between the attributes must
+ be implemented in the material. MorphPhongMaterial implements material
+ with morphing support for phong lighting model. The blending happens between
+ 2 attributes - 'base' and 'target'. The names for the base and target attributes are taken from
+ the morph target names, where the base attribute retains the name it already has and the
+ target attribute name gets 'Target' appended to the name. All morph targets in the animation
+ should contain the attributes with same names as those in the base geometry.
+
+*/
+/*!
+ \property Qt3DAnimation::QMorphingAnimation::targetPositions
+ Holds the position values of the morph target. Each position in the list specifies the position
+ of the corresponding morph target with the same index. The values must be in an ascending order.
+ Values can be positive or negative and do not have any predefined unit.
+*/
+/*!
+ \property Qt3DAnimation::QMorphingAnimation::interpolator
+ Holds the interpolator between base and target attributes.
+ \readonly
+*/
+/*!
+ \property Qt3DAnimation::QMorphingAnimation::target
+ Holds the target QGeometryRenderer the morphing animation is applied to.
+*/
+/*!
+ \property Qt3DAnimation::QMorphingAnimation::targetName
+ Holds the name of the target geometry. This is a convenience property making it
+ easier to match the target geometry to the morphing animation. The name
+ is usually same as the name of the parent entity of the target QGeometryRenderer, but
+ does not have to be.
+*/
+/*!
+ \property Qt3DAnimation::QMorphingAnimation::method
+ Holds the morphing method. The default is Relative.
+*/
+/*!
+ \property Qt3DAnimation::QMorphingAnimation::easing
+ Holds the easing curve of the interpolator between morph targets.
+*/
+/*!
+ \enum Qt3DAnimation::QMorphingAnimation::Method
+
+ This enumeration specifies the morphing method.
+ \value Normalized The blending should use the normalized formula;
+ V' = Vbase * (1.0 - sum(Wi)) + sum[Vi * Wi]
+ \value Relative The blending should use the relative formula;
+ V' = Vbase + sum[Vi * Wi]
+*/
+
+/*!
+ \qmlproperty list<real> MorphingAnimation::targetPositions
+ Holds the position values of the morph target. Each position in the list specifies the position
+ of the corresponding morph target with the same index. The values must be in an ascending order.
+ Values can be positive or negative and do not have any predefined unit.
+*/
+/*!
+ \qmlproperty real MorphingAnimation::interpolator
+ Holds the interpolator between base and target attributes.
+ \readonly
+*/
+/*!
+ \qmlproperty GeometryRenderer MorphingAnimation::target
+ Holds the target GeometryRenderer the morphing animation is applied to.
+*/
+/*!
+ \qmlproperty string MorphingAnimation::targetName
+ Holds the name of the target geometry. This is a convenience property making it
+ easier to match the target geometry to the morphing animation. The name
+ is usually same as the name of the parent entity of the target GeometryRenderer, but
+ does not have to be.
+*/
+/*!
+ \qmlproperty enumeration MorphingAnimation::method
+ Holds the morphing method. The default is Relative.
+ \list
+ \li Normalized
+ \li Relative
+ \endlist
+*/
+/*!
+ \qmlproperty EasingCurve MorphingAnimation::easing
+ Holds the easing curve of the interpolator between morph targets.
+*/
+/*!
+ \qmlproperty list<MorphTarget> MorphingAnimation::morphTargets
+ Holds the list of morph targets in the morphing animation.
+*/
+
+QMorphingAnimationPrivate::QMorphingAnimationPrivate()
+ : QAbstractAnimationPrivate(QAbstractAnimation::MorphingAnimation)
+ , m_minposition(0.0f)
+ , m_maxposition(0.0f)
+ , m_flattened(nullptr)
+ , m_method(QMorphingAnimation::Relative)
+ , m_interpolator(0.0f)
+ , m_target(nullptr)
+ , m_currentTarget(nullptr)
+{
+
+}
+
+QMorphingAnimationPrivate::~QMorphingAnimationPrivate()
+{
+ for (QVector<float> *weights : qAsConst(m_weights))
+ delete weights;
+}
+
+void QMorphingAnimationPrivate::updateAnimation(float position)
+{
+ Q_Q(QMorphingAnimation);
+ if (!m_target || !m_target->geometry())
+ return;
+
+ QVector<int> relevantValues;
+ float sum = 0.0f;
+ float interpolator = 0.0f;
+ m_morphKey.resize(m_morphTargets.size());
+
+ // calculate morph key
+ if (position < m_minposition) {
+ m_morphKey = *m_weights.first();
+ } else if (position >= m_maxposition) {
+ m_morphKey = *m_weights.last();
+ } else {
+ for (int i = 0; i < m_targetPositions.size() - 1; ++i) {
+ if (position >= m_targetPositions.at(i) && position < m_targetPositions.at(i + 1)) {
+ interpolator = (position - m_targetPositions.at(i))
+ / (m_targetPositions.at(i + 1) - m_targetPositions.at(i));
+ interpolator = m_easing.valueForProgress(interpolator);
+ float iip = 1.0f - interpolator;
+
+ for (int j = 0; j < m_morphTargets.size(); ++j) {
+ m_morphKey[j] = interpolator * m_weights.at(i + 1)->at(j)
+ + iip * m_weights.at(i)->at(j);
+ }
+ }
+ }
+ }
+
+ // check relevant values
+ for (int j = 0; j < m_morphKey.size(); ++j) {
+ sum += m_morphKey[j];
+ if (!qFuzzyIsNull(m_morphKey[j]))
+ relevantValues.push_back(j);
+ }
+
+ if (relevantValues.size() == 0 || qFuzzyIsNull(sum)) {
+ // only base is used
+ interpolator = 0.0f;
+ } else if (relevantValues.size() == 1) {
+ // one morph target has non-zero weight
+ setTargetInterpolated(relevantValues[0]);
+ interpolator = sum;
+ } else {
+ // more than one morph target has non-zero weight
+ // flatten morph targets to one
+ qWarning() << Q_FUNC_INFO << "Flattening required";
+ }
+
+ // Relative method uses negative interpolator, normalized uses positive
+ if (m_method == QMorphingAnimation::Relative)
+ interpolator = -interpolator;
+
+ if (!qFuzzyCompare(interpolator, m_interpolator)) {
+ m_interpolator = interpolator;
+ emit q->interpolatorChanged(m_interpolator);
+ }
+}
+
+void QMorphingAnimationPrivate::setTargetInterpolated(int morphTarget)
+{
+ QMorphTarget *target = m_morphTargets[morphTarget];
+ Qt3DRender::QGeometry *geometry = m_target->geometry();
+
+ // remove attributes from previous frame
+ if (m_currentTarget && (target != m_currentTarget)) {
+ const QVector<Qt3DRender::QAttribute *> targetAttributes = m_currentTarget->attributeList();
+ for (int i = 0; i < targetAttributes.size(); ++i)
+ geometry->removeAttribute(targetAttributes.at(i));
+ }
+
+ const QVector<Qt3DRender::QAttribute *> targetAttributes = target->attributeList();
+
+ // add attributes from current frame to the geometry
+ if (target != m_currentTarget) {
+ for (int i = 0; i < m_attributeNames.size(); ++i) {
+ QString targetName = m_attributeNames.at(i);
+ targetName.append(QLatin1String("Target"));
+ targetAttributes[i]->setName(targetName);
+ geometry->addAttribute(targetAttributes.at(i));
+ }
+ }
+ m_currentTarget = target;
+}
+
+/*!
+ Construct a new QMorphingAnimation with \a parent.
+ */
+QMorphingAnimation::QMorphingAnimation(QObject *parent)
+ : QAbstractAnimation(*new QMorphingAnimationPrivate, parent)
+{
+ Q_D(QMorphingAnimation);
+ d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
+ this, &QMorphingAnimation::updateAnimation);
+}
+
+QVector<float> QMorphingAnimation::targetPositions() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_targetPositions;
+}
+
+float QMorphingAnimation::interpolator() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_interpolator;
+}
+
+Qt3DRender::QGeometryRenderer *QMorphingAnimation::target() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_target;
+}
+
+QString QMorphingAnimation::targetName() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_targetName;
+}
+
+QMorphingAnimation::Method QMorphingAnimation::method() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_method;
+}
+
+QEasingCurve QMorphingAnimation::easing() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_easing;
+}
+
+/*!
+ Set morph \a targets to animation. Old targets are cleared.
+*/
+void QMorphingAnimation::setMorphTargets(const QVector<Qt3DAnimation::QMorphTarget *> &targets)
+{
+ Q_D(QMorphingAnimation);
+ d->m_morphTargets = targets;
+ d->m_attributeNames = targets[0]->attributeNames();
+ d->m_position = -1.0f;
+}
+
+/*!
+ Add new morph \a target at the end of the animation.
+*/
+void QMorphingAnimation::addMorphTarget(Qt3DAnimation::QMorphTarget *target)
+{
+ Q_D(QMorphingAnimation);
+ if (!d->m_morphTargets.contains(target)) {
+ d->m_morphTargets.push_back(target);
+ d->m_position = -1.0f;
+ if (d->m_attributeNames.empty())
+ d->m_attributeNames = target->attributeNames();
+ }
+}
+
+/*!
+ Remove morph \a target from the animation.
+*/
+void QMorphingAnimation::removeMorphTarget(Qt3DAnimation::QMorphTarget *target)
+{
+ Q_D(QMorphingAnimation);
+ d->m_morphTargets.removeAll(target);
+ d->m_position = -1.0f;
+}
+
+void QMorphingAnimation::setTargetPositions(const QVector<float> &targetPositions)
+{
+ Q_D(QMorphingAnimation);
+ d->m_targetPositions = targetPositions;
+ emit targetPositionsChanged(targetPositions);
+ d->m_minposition = targetPositions.first();
+ d->m_maxposition = targetPositions.last();
+ setDuration(d->m_targetPositions.last());
+ if (d->m_weights.size() < targetPositions.size()) {
+ d->m_weights.resize(targetPositions.size());
+ for (int i = 0; i < d->m_weights.size(); ++i) {
+ if (d->m_weights[i] == nullptr)
+ d->m_weights[i] = new QVector<float>();
+ }
+ }
+ d->m_position = -1.0f;
+}
+
+void QMorphingAnimation::setTarget(Qt3DRender::QGeometryRenderer *target)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_target != target) {
+ d->m_position = -1.0f;
+ d->m_target = target;
+ emit targetChanged(target);
+ }
+}
+
+/*!
+ Sets morph \a weights at \a positionIndex.
+*/
+void QMorphingAnimation::setWeights(int positionIndex, const QVector<float> &weights)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_weights.size() < positionIndex)
+ d->m_weights.resize(positionIndex + 1);
+ if (d->m_weights[positionIndex] == nullptr)
+ d->m_weights[positionIndex] = new QVector<float>();
+ *d->m_weights[positionIndex] = weights;
+ d->m_position = -1.0f;
+}
+
+/*!
+ Return morph weights at \a positionIndex.
+*/
+QVector<float> QMorphingAnimation::getWeights(int positionIndex)
+{
+ Q_D(QMorphingAnimation);
+ return *d->m_weights[positionIndex];
+}
+
+/*!
+ Return morph target list.
+*/
+QVector<Qt3DAnimation::QMorphTarget *> QMorphingAnimation::morphTargetList()
+{
+ Q_D(QMorphingAnimation);
+ return d->m_morphTargets;
+}
+
+void QMorphingAnimation::setTargetName(const QString name)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_targetName != name) {
+ d->m_targetName = name;
+ emit targetNameChanged(name);
+ }
+}
+
+void QMorphingAnimation::setMethod(QMorphingAnimation::Method method)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_method != method) {
+ d->m_method = method;
+ d->m_position = -1.0f;
+ emit methodChanged(method);
+ }
+}
+
+void QMorphingAnimation::setEasing(const QEasingCurve &easing)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_easing != easing) {
+ d->m_easing = easing;
+ d->m_position = -1.0f;
+ emit easingChanged(easing);
+ }
+}
+
+void QMorphingAnimation::updateAnimation(float position)
+{
+ Q_D(QMorphingAnimation);
+ d->updateAnimation(position);
+}
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qmorphinganimation.h b/src/animation/frontend/qmorphinganimation.h
index f8ca71ec9..2944fad91 100644
--- a/src/extras/animations/qmorphinganimation.h
+++ b/src/animation/frontend/qmorphinganimation.h
@@ -34,24 +34,24 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QMORPHINGANIMATION_H
-#define QT3DEXTRAS_QMORPHINGANIMATION_H
+#ifndef QT3DANIMATION_QMORPHINGANIMATION_H
+#define QT3DANIMATION_QMORPHINGANIMATION_H
#include <Qt3DRender/qgeometryrenderer.h>
-#include <Qt3DExtras/qabstractanimation.h>
-#include <Qt3DExtras/qmorphtarget.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qabstractanimation.h>
+#include <Qt3DAnimation/qmorphtarget.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
#include <QtCore/qeasingcurve.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QMorphingAnimationPrivate;
-class QT3DEXTRASSHARED_EXPORT QMorphingAnimation : public QAbstractAnimation
+class QT3DANIMATIONSHARED_EXPORT QMorphingAnimation : public QAbstractAnimation
{
Q_OBJECT
Q_PROPERTY(QVector<float> targetPositions READ targetPositions WRITE setTargetPositions NOTIFY targetPositionsChanged)
@@ -59,7 +59,7 @@ class QT3DEXTRASSHARED_EXPORT QMorphingAnimation : public QAbstractAnimation
Q_PROPERTY(Qt3DRender::QGeometryRenderer *target READ target WRITE setTarget NOTIFY targetChanged)
Q_PROPERTY(QString targetName READ targetName WRITE setTargetName NOTIFY targetNameChanged)
Q_PROPERTY(QMorphingAnimation::Method method READ method WRITE setMethod NOTIFY methodChanged)
- Q_PROPERTY(QEasingCurve::Type easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
public:
enum Method
@@ -76,23 +76,23 @@ public:
Qt3DRender::QGeometryRenderer *target() const;
QString targetName() const;
QMorphingAnimation::Method method() const;
- QEasingCurve::Type easing() const;
+ QEasingCurve easing() const;
- void setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets);
- void addMorphTarget(Qt3DExtras::QMorphTarget *target);
- void removeMorphTarget(Qt3DExtras::QMorphTarget *target);
+ void setMorphTargets(const QVector<Qt3DAnimation::QMorphTarget *> &targets);
+ void addMorphTarget(Qt3DAnimation::QMorphTarget *target);
+ void removeMorphTarget(Qt3DAnimation::QMorphTarget *target);
void setWeights(int positionIndex, const QVector<float> &weights);
QVector<float> getWeights(int positionIndex);
- QVector<Qt3DExtras::QMorphTarget *> morphTargetList();
+ QVector<Qt3DAnimation::QMorphTarget *> morphTargetList();
public Q_SLOTS:
void setTargetPositions(const QVector<float> &targetPositions);
void setTarget(Qt3DRender::QGeometryRenderer *target);
void setTargetName(const QString name);
void setMethod(QMorphingAnimation::Method method);
- void setEasing(QEasingCurve::Type easing);
+ void setEasing(const QEasingCurve &easing);
Q_SIGNALS:
void targetPositionsChanged(const QVector<float> &targetPositions);
@@ -100,7 +100,7 @@ Q_SIGNALS:
void targetChanged(Qt3DRender::QGeometryRenderer *target);
void targetNameChanged(const QString &name);
void methodChanged(QMorphingAnimation::Method method);
- void easingChanged(QEasingCurve::Type easing);
+ void easingChanged(const QEasingCurve &easing);
private:
@@ -109,8 +109,8 @@ private:
Q_DECLARE_PRIVATE(QMorphingAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QMORPHINGANIMATION_H
+#endif // QT3DANIMATION_QMORPHINGANIMATION_H
diff --git a/src/extras/animations/qmorphinganimation_p.h b/src/animation/frontend/qmorphinganimation_p.h
index e4a18f199..c306f3309 100644
--- a/src/extras/animations/qmorphinganimation_p.h
+++ b/src/animation/frontend/qmorphinganimation_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QMORPHINGANIMATION_P_H
-#define QT3DEXTRAS_QMORPHINGANIMATION_P_H
+#ifndef QT3DANIMATION_QMORPHINGANIMATION_P_H
+#define QT3DANIMATION_QMORPHINGANIMATION_P_H
//
// W A R N I N G
@@ -49,14 +49,14 @@
//
#include <QtCore/qeasingcurve.h>
-#include <Qt3DExtras/qmorphinganimation.h>
+#include <Qt3DAnimation/qmorphinganimation.h>
#include <private/qobject_p.h>
#include <private/qabstractanimation_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QMorphingAnimationPrivate : public QAbstractAnimationPrivate
{
@@ -67,11 +67,13 @@ public:
void updateAnimation(float position);
void setTargetInterpolated(int morphTarget);
+ float m_minposition;
+ float m_maxposition;
QVector<float> m_targetPositions;
QVector<QVector<float>*> m_weights;
QVector<float> m_morphKey;
QStringList m_attributeNames;
- QVector<Qt3DExtras::QMorphTarget *> m_morphTargets;
+ QVector<Qt3DAnimation::QMorphTarget *> m_morphTargets;
QMorphTarget *m_flattened;
QMorphingAnimation::Method m_method;
QEasingCurve m_easing;
@@ -86,8 +88,8 @@ public:
Q_DECLARE_PUBLIC(QMorphingAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QMORPHINGANIMATION_P_H
+#endif // QT3DANIMATION_QMORPHINGANIMATION_P_H
diff --git a/src/extras/animations/qmorphtarget.cpp b/src/animation/frontend/qmorphtarget.cpp
index 0c327a490..9dc30b8ba 100644
--- a/src/extras/animations/qmorphtarget.cpp
+++ b/src/animation/frontend/qmorphtarget.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -35,11 +35,60 @@
****************************************************************************/
#include "qmorphtarget.h"
-#include "Qt3DExtras/private/qmorphtarget_p.h"
+#include "Qt3DAnimation/private/qmorphtarget_p.h"
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QMorphTarget
+ \brief A class providing morph targets to blend-shape animation
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits QObject
+
+ A Qt3DAnimation::QMorphTarget class is a convenience class, which provides a list
+ of \l {Qt3DRender::QAttribute} {QAttributes}, which the QMorphingAnimation uses
+ to animate geometry. A QMorphTarget can also be created based on existing
+ \l Qt3DRender::QGeometry.
+
+*/
+/*!
+ \qmltype MorphTarget
+ \brief A type providing morph targets to blend-shape animation
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \inherits QtObject
+ \instantiates Qt3DAnimation::QMorphTarget
+
+ A MorphTarget type is a convenience type, which provides a list
+ of \l {Qt3D.Render::Attribute} {Attributes}, which the MorphingAnimation uses
+ to animate geometry. A MorphTarget can also be created based on existing
+ \l {Qt3D.Render::Geometry}{Geometry}.
+
+*/
+
+/*!
+ \property Qt3DAnimation::QMorphTarget::attributeNames
+ Holds a list of attribute names contained in the morph target.
+ \readonly
+*/
+
+/*!
+ \qmlproperty list<string> MorphTarget::attributeNames
+ Holds a list of attribute names contained in the morph target.
+ \readonly
+*/
+/*!
+ \qmlproperty list<Attribute> MorphTarget::attributes
+ Holds the list of attributes in the morph target.
+*/
+/*!
+ \qmlmethod MorphTarget Qt3D.Animation::MorphTarget::fromGeometry(geometry, stringList)
+ Returns a morph target based on the attributes defined by the given stringList from
+ the given geometry.
+*/
QMorphTargetPrivate::QMorphTargetPrivate()
: QObjectPrivate()
@@ -50,16 +99,22 @@ QMorphTargetPrivate::QMorphTargetPrivate()
void QMorphTargetPrivate::updateAttributeNames()
{
m_attributeNames.clear();
- for (const Qt3DRender::QAttribute *attr : m_targetAttributes)
+ for (const Qt3DRender::QAttribute *attr : qAsConst(m_targetAttributes))
m_attributeNames.push_back(attr->name());
}
+/*!
+ Constructs a QMorphTarget with given \a parent.
+*/
QMorphTarget::QMorphTarget(QObject *parent)
: QObject(*new QMorphTargetPrivate, parent)
{
}
+/*!
+ Returns a list of attributes contained in the morph target.
+*/
QVector<Qt3DRender::QAttribute *> QMorphTarget::attributeList() const
{
Q_D(const QMorphTarget);
@@ -72,6 +127,9 @@ QStringList QMorphTarget::attributeNames() const
return d->m_attributeNames;
}
+/*!
+ Sets \a attributes to the morph target. Old attributes are cleared.
+*/
void QMorphTarget::setAttributes(const QVector<Qt3DRender::QAttribute *> &attributes)
{
Q_D(QMorphTarget);
@@ -83,10 +141,14 @@ void QMorphTarget::setAttributes(const QVector<Qt3DRender::QAttribute *> &attrib
emit attributeNamesChanged(d->m_attributeNames);
}
+/*!
+ Adds an \a attribute the morph target. An attribute with the same
+ name must not have been added previously to the morph target.
+*/
void QMorphTarget::addAttribute(Qt3DRender::QAttribute *attribute)
{
Q_D(QMorphTarget);
- for (const Qt3DRender::QAttribute *attr : d->m_targetAttributes) {
+ for (const Qt3DRender::QAttribute *attr : qAsConst(d->m_targetAttributes)) {
if (attr->name() == attribute->name())
return;
}
@@ -95,6 +157,9 @@ void QMorphTarget::addAttribute(Qt3DRender::QAttribute *attribute)
emit attributeNamesChanged(d->m_attributeNames);
}
+/*!
+ Removes an \a attribute from the morph target.
+*/
void QMorphTarget::removeAttribute(Qt3DRender::QAttribute *attribute)
{
Q_D(QMorphTarget);
@@ -105,6 +170,9 @@ void QMorphTarget::removeAttribute(Qt3DRender::QAttribute *attribute)
}
}
+/*!
+ Returns a morph target based on the \a attributes in the given \a geometry.
+*/
QMorphTarget *QMorphTarget::fromGeometry(Qt3DRender::QGeometry *geometry, const QStringList &attributes)
{
QMorphTarget *target = new QMorphTarget();
@@ -115,6 +183,6 @@ QMorphTarget *QMorphTarget::fromGeometry(Qt3DRender::QGeometry *geometry, const
return target;
}
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/extras/animations/qmorphtarget.h b/src/animation/frontend/qmorphtarget.h
index 64c3037cb..0435924e1 100644
--- a/src/extras/animations/qmorphtarget.h
+++ b/src/animation/frontend/qmorphtarget.h
@@ -34,23 +34,23 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QMORPHTARGET_H
-#define QT3DEXTRAS_QMORPHTARGET_H
+#ifndef QT3DANIMATION_QMORPHTARGET_H
+#define QT3DANIMATION_QMORPHTARGET_H
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qgeometry.h>
#include <QtCore/qstringlist.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QMorphTargetPrivate;
-class QT3DEXTRASSHARED_EXPORT QMorphTarget : public QObject
+class QT3DANIMATIONSHARED_EXPORT QMorphTarget : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList attributeNames READ attributeNames NOTIFY attributeNamesChanged)
@@ -76,8 +76,8 @@ private:
Q_DECLARE_PRIVATE(QMorphTarget)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QMORPHTARGET_H
+#endif // QT3DANIMATION_QMORPHTARGET_H
diff --git a/src/extras/animations/qmorphtarget_p.h b/src/animation/frontend/qmorphtarget_p.h
index 7d42f8eb4..1fc3734ae 100644
--- a/src/extras/animations/qmorphtarget_p.h
+++ b/src/animation/frontend/qmorphtarget_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QMORPHTARGET_P_H
-#define QT3DEXTRAS_QMORPHTARGET_P_H
+#ifndef QT3DANIMATION_QMORPHTARGET_P_H
+#define QT3DANIMATION_QMORPHTARGET_P_H
//
// W A R N I N G
@@ -48,13 +48,13 @@
// We mean it.
//
-#include <Qt3DExtras/qmorphtarget.h>
+#include <Qt3DAnimation/qmorphtarget.h>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QMorphTargetPrivate : public QObjectPrivate
{
@@ -69,8 +69,8 @@ public:
Q_DECLARE_PUBLIC(QMorphTarget)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QMORPHTARGET_P_H
+#endif // QT3DANIMATION_QMORPHTARGET_P_H
diff --git a/src/extras/animations/qvertexblendanimation.cpp b/src/animation/frontend/qvertexblendanimation.cpp
index 1b45992fe..3ddd83bf0 100644
--- a/src/extras/animations/qvertexblendanimation.cpp
+++ b/src/animation/frontend/qvertexblendanimation.cpp
@@ -40,10 +40,110 @@
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
+
+/*!
+ \class Qt3DAnimation::QVertexBlendAnimation
+ \brief A class implementing vertex-blend morphing animation
+ \inmodule Qt3DAnimation
+ \since 5.9
+ \inherits Qt3DAnimation::QAbstractAnimation
+
+ A Qt3DAnimation::QVertexBlendAnimation class implements vertex-blend morphing animation
+ to a target \l {Qt3DRender::QGeometryRenderer}{QGeometryRenderer}. The QVertexBlendAnimation
+ sets the correct \l {Qt3DRender::QAttribute}{QAttributes} from the
+ \l {Qt3DAnimation::QMorphTarget}{morph targets} to the target
+ \l {Qt3DRender::QGeometryRenderer::geometry} {QGeometryRenderer::geometry} and calculates
+ interpolator for the current position. Unlike with QMorphingAnimation, where the blending is
+ controller with blend weights, the blending occurs between sequential morph targets.
+ The actual blending between the attributes must be implemented in the material.
+ Qt3DAnimation::QMorphPhongMaterial implements material with morphing support for phong
+ lighting model. The blending happens between 2 attributes - 'base' and 'target'.
+ The names for the base and target attributes are taken from the morph target names,
+ where the base attribute retains the name it already has and the target attribute name
+ gets 'Target' appended to the name. The interpolator can be set as
+ a \l {Qt3DRender::QParameter}{QParameter} to the used material.
+ All morph targets in the animation should contain the attributes with same names as those
+ in the base geometry.
+
+*/
+/*!
+ \qmltype VertexBlendAnimation
+ \brief A type implementing vertex-blend morphing animation
+ \inqmlmodule Qt3D.Animation
+ \since 5.9
+ \inherits AbstractAnimation
+ \instantiates Qt3DAnimation::QVertexBlendAnimation
+
+ A VertexBlendAnimation type implements vertex-blend morphing animation
+ to a target \l GeometryRenderer. The VertexBlendAnimation sets the correct
+ \l {Attribute}{Attributes} from the morph targets to the target
+ \l {Qt3D.Render::GeometryRenderer::geometry}{GeometryRenderer::geometry} and calculates
+ interpolator for the current position. Unlike with MorphingAnimation, where the blending is
+ controller with blend weights, the blending occurs between sequential morph targets.
+ The actual blending between the attributes must be implemented in the material.
+ MorphPhongMaterial implements material with morphing support for phong lighting model.
+ The blending happens between 2 attributes - 'base' and 'target'. The names for the base
+ and target attributes are taken from the morph target names, where the base attribute
+ retains the name it already has and the target attribute name gets 'Target' appended to
+ the name. All morph targets in the animation should contain the attributes with same names
+ as those in the base geometry.
+
+*/
+/*!
+ \property Qt3DAnimation::QVertexBlendAnimation::targetPositions
+ Holds the position values of the morph target. Each position in the list specifies the position
+ of the corresponding morph target with the same index. The values must be in an ascending order.
+ Values can be positive or negative and do not have any predefined unit.
+*/
+/*!
+ \property Qt3DAnimation::QVertexBlendAnimation::interpolator
+ Holds the interpolator between base and target attributes.
+ \readonly
+*/
+/*!
+ \property Qt3DAnimation::QVertexBlendAnimation::target
+ Holds the target QGeometryRenderer the morphing animation is applied to.
+*/
+/*!
+ \property Qt3DAnimation::QVertexBlendAnimation::targetName
+ Holds the name of the target geometry. This is a convenience property making it
+ easier to match the target geometry to the morphing animation. The name
+ is usually same as the name of the parent entity of the target QGeometryRenderer, but
+ does not have to be.
+*/
+
+/*!
+ \qmlproperty list<real> VertexBlendAnimation::targetPositions
+ Holds the position values of the morph target. Each position in the list specifies the position
+ of the corresponding morph target with the same index. The values must be in an ascending order.
+ Values can be positive or negative and do not have any predefined unit.
+*/
+/*!
+ \qmlproperty real VertexBlendAnimation::interpolator
+ Holds the interpolator between base and target attributes.
+ \readonly
+*/
+/*!
+ \qmlproperty GeometryRenderer VertexBlendAnimation::target
+ Holds the target GeometryRenderer the morphing animation is applied to.
+*/
+/*!
+ \qmlproperty string VertexBlendAnimation::targetName
+ Holds the name of the target geometry. This is a convenience property making it
+ easier to match the target geometry to the morphing animation. The name
+ is usually same as the name of the parent entity of the target GeometryRenderer, but
+ does not have to be.
+*/
+/*!
+ \qmlproperty list<MorphTarget> VertexBlendAnimation::morphTargets
+ Holds the list of \l {MorphTarget}{morph targets} added to the animation.
+*/
QVertexBlendAnimationPrivate::QVertexBlendAnimationPrivate()
: QAbstractAnimationPrivate(QAbstractAnimation::VertexBlendAnimation)
+ , m_interpolator(0.0f)
+ , m_target(nullptr)
, m_currentBase(nullptr)
, m_currentTarget(nullptr)
{
@@ -74,24 +174,14 @@ void QVertexBlendAnimationPrivate::getAttributesInPosition(float position, int *
}
}
-static Qt3DRender::QAttribute *findAttribute(QVector<Qt3DRender::QAttribute *> &attributes,
- QString name)
-{
- for (Qt3DRender::QAttribute *gattr : attributes) {
- if (gattr->name() == name)
- return gattr;
- }
- return nullptr;
-}
-
void QVertexBlendAnimationPrivate::updateAnimation(float position)
{
Q_Q(QVertexBlendAnimation);
if (!m_target || !m_target->geometry())
return;
- Qt3DExtras::QMorphTarget *base;
- Qt3DExtras::QMorphTarget *target;
+ Qt3DAnimation::QMorphTarget *base;
+ Qt3DAnimation::QMorphTarget *target;
int target0, target1;
float interpolator;
getAttributesInPosition(position, &target0, &target1, &interpolator);
@@ -121,7 +211,7 @@ void QVertexBlendAnimationPrivate::updateAnimation(float position)
for (int i = 0; i < baseAttributes.size(); ++i) {
const QString baseName = attributeNames.at(i);
QString targetName = baseName;
- targetName.append("Target");
+ targetName.append(QLatin1String("Target"));
baseAttributes[i]->setName(baseName);
geometry->addAttribute(baseAttributes.at(i));
@@ -138,6 +228,9 @@ void QVertexBlendAnimationPrivate::updateAnimation(float position)
}
}
+/*!
+ Construct a new QVertexBlendAnimation with \a parent.
+ */
QVertexBlendAnimation::QVertexBlendAnimation(QObject *parent)
: QAbstractAnimation(*new QVertexBlendAnimationPrivate, parent)
{
@@ -170,20 +263,29 @@ QString QVertexBlendAnimation::targetName() const
return d->m_targetName;
}
-void QVertexBlendAnimation::setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets)
+/*!
+ Set morph \a targets to animation. Old targets are cleared.
+*/
+void QVertexBlendAnimation::setMorphTargets(const QVector<Qt3DAnimation::QMorphTarget *> &targets)
{
Q_D(QVertexBlendAnimation);
d->m_morphTargets = targets;
}
-void QVertexBlendAnimation::addMorphTarget(Qt3DExtras::QMorphTarget *target)
+/*!
+ Add new morph \a target at the end of the animation.
+*/
+void QVertexBlendAnimation::addMorphTarget(Qt3DAnimation::QMorphTarget *target)
{
Q_D(QVertexBlendAnimation);
if (!d->m_morphTargets.contains(target))
d->m_morphTargets.push_back(target);
}
-void QVertexBlendAnimation::removeMorphTarget(Qt3DExtras::QMorphTarget *target)
+/*!
+ Remove morph \a target from the animation.
+*/
+void QVertexBlendAnimation::removeMorphTarget(Qt3DAnimation::QMorphTarget *target)
{
Q_D(QVertexBlendAnimation);
d->m_morphTargets.removeAll(target);
@@ -208,7 +310,10 @@ void QVertexBlendAnimation::setTarget(Qt3DRender::QGeometryRenderer *target)
}
}
-QVector<Qt3DExtras::QMorphTarget *> QVertexBlendAnimation::morphTargetList()
+/*!
+ Return morph target list.
+*/
+QVector<Qt3DAnimation::QMorphTarget *> QVertexBlendAnimation::morphTargetList()
{
Q_D(QVertexBlendAnimation);
return d->m_morphTargets;
@@ -229,6 +334,6 @@ void QVertexBlendAnimation::updateAnimation(float position)
d->updateAnimation(position);
}
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/extras/animations/qvertexblendanimation.h b/src/animation/frontend/qvertexblendanimation.h
index ebd313e83..a7da2bcda 100644
--- a/src/extras/animations/qvertexblendanimation.h
+++ b/src/animation/frontend/qvertexblendanimation.h
@@ -34,22 +34,22 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QVERTEXBLENDANIMATION_H
-#define QT3DEXTRAS_QVERTEXBLENDANIMATION_H
+#ifndef QT3DANIMATION_QVERTEXBLENDANIMATION_H
+#define QT3DANIMATION_QVERTEXBLENDANIMATION_H
#include <Qt3DRender/qgeometryrenderer.h>
-#include <Qt3DExtras/qabstractanimation.h>
-#include <Qt3DExtras/qmorphtarget.h>
+#include <Qt3DAnimation/qabstractanimation.h>
+#include <Qt3DAnimation/qmorphtarget.h>
-#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DAnimation/qt3danimation_global.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QVertexBlendAnimationPrivate;
-class QT3DEXTRASSHARED_EXPORT QVertexBlendAnimation : public QAbstractAnimation
+class QT3DANIMATIONSHARED_EXPORT QVertexBlendAnimation : public QAbstractAnimation
{
Q_OBJECT
Q_PROPERTY(QVector<float> targetPositions READ targetPositions WRITE setTargetPositions NOTIFY targetPositionsChanged)
@@ -65,11 +65,11 @@ public:
Qt3DRender::QGeometryRenderer *target() const;
QString targetName() const;
- void setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets);
- void addMorphTarget(Qt3DExtras::QMorphTarget *target);
- void removeMorphTarget(Qt3DExtras::QMorphTarget *target);
+ void setMorphTargets(const QVector<Qt3DAnimation::QMorphTarget *> &targets);
+ void addMorphTarget(Qt3DAnimation::QMorphTarget *target);
+ void removeMorphTarget(Qt3DAnimation::QMorphTarget *target);
- QVector<Qt3DExtras::QMorphTarget *> morphTargetList();
+ QVector<Qt3DAnimation::QMorphTarget *> morphTargetList();
public Q_SLOTS:
void setTargetPositions(const QVector<float> &targetPositions);
@@ -89,8 +89,8 @@ private:
Q_DECLARE_PRIVATE(QVertexBlendAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QVERTEXBLENDANIMATION_H
+#endif // QT3DANIMATION_QVERTEXBLENDANIMATION_H
diff --git a/src/extras/animations/qvertexblendanimation_p.h b/src/animation/frontend/qvertexblendanimation_p.h
index 812953e04..8f2609fc8 100644
--- a/src/extras/animations/qvertexblendanimation_p.h
+++ b/src/animation/frontend/qvertexblendanimation_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QVERTEXBLENDANIMATION_P_H
-#define QT3DEXTRAS_QVERTEXBLENDANIMATION_P_H
+#ifndef QT3DANIMATION_QVERTEXBLENDANIMATION_P_H
+#define QT3DANIMATION_QVERTEXBLENDANIMATION_P_H
//
// W A R N I N G
@@ -49,14 +49,14 @@
//
-#include <Qt3DExtras/qvertexblendanimation.h>
+#include <Qt3DAnimation/qvertexblendanimation.h>
#include <private/qobject_p.h>
#include <private/qabstractanimation_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QVertexBlendAnimationPrivate : public QAbstractAnimationPrivate
{
@@ -67,7 +67,7 @@ public:
void updateAnimation(float position);
QVector<float> m_targetPositions;
- QVector<Qt3DExtras::QMorphTarget *> m_morphTargets;
+ QVector<Qt3DAnimation::QMorphTarget *> m_morphTargets;
float m_interpolator;
Qt3DRender::QGeometryRenderer *m_target;
QString m_targetName;
@@ -79,8 +79,8 @@ public:
Q_DECLARE_PUBLIC(QVertexBlendAnimation)
};
-} // Qt3DExtras
+} // Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QVertexBlendANIMATION_P_H
+#endif // QT3DANIMATION_QVertexBlendANIMATION_P_H
diff --git a/src/animation/job_common_p.h b/src/animation/job_common_p.h
new file mode 100644
index 000000000..882246a42
--- /dev/null
+++ b/src/animation/job_common_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DANIMATION_ANIMATION_JOB_COMMON_P_H
+#define QT3DANIMATION_ANIMATION_JOB_COMMON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qaspectjob_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+namespace Animation {
+
+namespace JobTypes {
+
+enum JobType {
+ BuildBlendTree = 8192,
+ EvaluateBlendClipAnimator,
+ EvaluateClipAnimator,
+ LoadAnimationClip,
+ FindRunningClipAnimator
+};
+
+} // JobTypes
+
+} // Animation
+
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_JOB_COMMON_P_H
diff --git a/src/core/aspects/aspectcommanddebugger.cpp b/src/core/aspects/aspectcommanddebugger.cpp
index 6bb93c827..eceec1bbd 100644
--- a/src/core/aspects/aspectcommanddebugger.cpp
+++ b/src/core/aspects/aspectcommanddebugger.cpp
@@ -37,14 +37,14 @@
**
****************************************************************************/
-#ifdef QT3D_JOBS_RUN_STATS
-
#include "aspectcommanddebugger_p.h"
+
#include <Qt3DCore/qaspectengine.h>
+#include <QtNetwork/QTcpSocket>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+
#include <Qt3DCore/private/qabstractaspect_p.h>
-#include <QTcpSocket>
-#include <QJsonDocument>
-#include <QJsonObject>
QT_BEGIN_NAMESPACE
@@ -216,5 +216,3 @@ void AspectCommandDebugger::executeCommand(const QString &command,
} // Qt3DCore
QT_END_NAMESPACE
-
-#endif
diff --git a/src/core/aspects/aspectcommanddebugger_p.h b/src/core/aspects/aspectcommanddebugger_p.h
index b173a5c09..bb6100df5 100644
--- a/src/core/aspects/aspectcommanddebugger_p.h
+++ b/src/core/aspects/aspectcommanddebugger_p.h
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#ifdef QT3D_JOBS_RUN_STATS
+#include <Qt3DCore/qt3dcore-config.h>
#ifndef QT3DCORE_DEBUG_ASPECTCOMMANDDEBUGGER_H
#define QT3DCORE_DEBUG_ASPECTCOMMANDDEBUGGER_H
@@ -108,5 +108,3 @@ private:
QT_END_NAMESPACE
#endif // QT3DCORE_DEBUG_ASPECTCOMMANDDEBUGGER_H
-
-#endif // QT3D_JOBS_RUN_STATS
diff --git a/src/core/aspects/aspects.pri b/src/core/aspects/aspects.pri
index 773c736a3..54d939138 100644
--- a/src/core/aspects/aspects.pri
+++ b/src/core/aspects/aspects.pri
@@ -5,8 +5,7 @@ SOURCES += \
$$PWD/qaspectengine.cpp \
$$PWD/qaspectfactory.cpp \
$$PWD/qaspectmanager.cpp \
- $$PWD/qaspectthread.cpp \
- $$PWD/aspectcommanddebugger.cpp
+ $$PWD/qaspectthread.cpp
HEADERS += \
$$PWD/qabstractaspect.h \
@@ -15,7 +14,13 @@ HEADERS += \
$$PWD/qaspectengine_p.h \
$$PWD/qaspectfactory_p.h \
$$PWD/qaspectmanager_p.h \
- $$PWD/qaspectthread_p.h \
- $$PWD/aspectcommanddebugger_p.h
+ $$PWD/qaspectthread_p.h
INCLUDEPATH += $$PWD
+
+include($$OUT_PWD/../core/qt3dcore-config.pri)
+QT_FOR_CONFIG += 3dcore-private
+qtConfig(qt3d-profile-jobs): {
+ HEADERS += $$PWD/aspectcommanddebugger_p.h
+ SOURCES += $$PWD/aspectcommanddebugger.cpp
+}
diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp
index c049d3503..d7e62db68 100644
--- a/src/core/aspects/qabstractaspect.cpp
+++ b/src/core/aspects/qabstractaspect.cpp
@@ -38,15 +38,17 @@
****************************************************************************/
#include "qabstractaspect.h"
-#include "qentity.h"
-#include <Qt3DCore/private/qaspectmanager_p.h>
-#include <private/qabstractaspect_p.h>
-#include <Qt3DCore/private/qaspectjobmanager_p.h>
-#include <private/qchangearbiter_p.h>
-#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/private/qnodevisitor_p.h>
+#include "qabstractaspect_p.h"
+
+#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DCore/private/corelogging_p.h>
+#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qchangearbiter_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qscene_p.h>
QT_BEGIN_NAMESPACE
@@ -157,6 +159,12 @@ void QAbstractAspect::registerBackendType(const QMetaObject &obj, const QBackend
d->m_backendCreatorFunctors.insert(&obj, functor);
}
+void QAbstractAspect::unregisterBackendType(const QMetaObject &obj)
+{
+ Q_D(QAbstractAspect);
+ d->m_backendCreatorFunctors.remove(&obj);
+}
+
void QAbstractAspectPrivate::sceneNodeAdded(QSceneChangePtr &change)
{
QNodeCreatedChangeBasePtr creationChange = qSharedPointerCast<QNodeCreatedChangeBase>(change);
@@ -282,7 +290,15 @@ QAbstractAspectJobManager *QAbstractAspectPrivate::jobManager() const
QVector<QAspectJobPtr> QAbstractAspectPrivate::jobsToExecute(qint64 time)
{
Q_Q(QAbstractAspect);
- return q->jobsToExecute(time);
+ auto res = q->jobsToExecute(time);
+
+ {
+ QMutexLocker lock(&m_singleShotMutex);
+ res << m_singleShotJobs;
+ m_singleShotJobs.clear();
+ }
+
+ return res;
}
/*!
@@ -324,6 +340,13 @@ void QAbstractAspect::onEngineShutdown()
{
}
+void QAbstractAspect::scheduleSingleShotJob(const Qt3DCore::QAspectJobPtr &job)
+{
+ Q_D(QAbstractAspect);
+ QMutexLocker lock(&d->m_singleShotMutex);
+ d->m_singleShotJobs.push_back(job);
+}
+
namespace Debug {
AsynchronousCommandReply::AsynchronousCommandReply(const QString &commandName, QObject *parent)
diff --git a/src/core/aspects/qabstractaspect.h b/src/core/aspects/qabstractaspect.h
index 86938d2d2..8ac1b251f 100644
--- a/src/core/aspects/qabstractaspect.h
+++ b/src/core/aspects/qabstractaspect.h
@@ -40,10 +40,10 @@
#ifndef QT3DCORE_QABSTRACTASPECT_H
#define QT3DCORE_QABSTRACTASPECT_H
-#include <QObject>
-#include <QSharedPointer>
#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/qnodeid.h>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -68,6 +68,8 @@ public:
explicit QAbstractAspect(QObject *parent = nullptr);
~QAbstractAspect();
+ void scheduleSingleShotJob(const Qt3DCore::QAspectJobPtr &job);
+
protected:
explicit QAbstractAspect(QAbstractAspectPrivate &dd, QObject *parent = nullptr);
@@ -76,6 +78,9 @@ protected:
template<class Frontend>
void registerBackendType(const QBackendNodeMapperPtr &functor);
void registerBackendType(const QMetaObject &, const QBackendNodeMapperPtr &functor);
+ template<class Frontend>
+ void unregisterBackendType();
+ void unregisterBackendType(const QMetaObject &);
private:
virtual QVariant executeCommand(const QStringList &args);
@@ -99,6 +104,12 @@ void QAbstractAspect::registerBackendType(const QBackendNodeMapperPtr &functor)
registerBackendType(Frontend::staticMetaObject, functor);
}
+template<class Frontend>
+void QAbstractAspect::unregisterBackendType()
+{
+ unregisterBackendType(Frontend::staticMetaObject);
+}
+
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/aspects/qabstractaspect_p.h b/src/core/aspects/qabstractaspect_p.h
index 53b01cc40..a6c47c494 100644
--- a/src/core/aspects/qabstractaspect_p.h
+++ b/src/core/aspects/qabstractaspect_p.h
@@ -51,14 +51,18 @@
// We mean it.
//
-#include <private/qobject_p.h>
-#include <private/qaspectjobproviderinterface_p.h>
-#include <private/qbackendnode_p.h>
-#include <private/qbackendnodefactory_p.h>
-#include <private/qsceneobserverinterface_p.h>
-#include <private/qt3dcore_global_p.h>
-#include <Qt3DCore/qnodedestroyedchange.h>
#include <Qt3DCore/qabstractaspect.h>
+#include <Qt3DCore/qnodedestroyedchange.h>
+
+#include <Qt3DCore/private/qaspectjobproviderinterface_p.h>
+#include <Qt3DCore/private/qbackendnode_p.h>
+#include <Qt3DCore/private/qbackendnodefactory_p.h>
+#include <Qt3DCore/private/qsceneobserverinterface_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <QtCore/private/qobject_p.h>
+
+#include <QMutex>
+#include <QVector>
QT_BEGIN_NAMESPACE
@@ -136,6 +140,8 @@ public:
QAbstractAspectJobManager *m_jobManager;
QChangeArbiter *m_arbiter;
QHash<const QMetaObject*, QBackendNodeMapperPtr> m_backendCreatorFunctors;
+ QMutex m_singleShotMutex;
+ QVector<QAspectJobPtr> m_singleShotJobs;
static QAbstractAspectPrivate *get(QAbstractAspect *aspect);
};
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index 15f975332..b9c9d2283 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -38,27 +38,30 @@
****************************************************************************/
#include "qaspectengine.h"
+#include "qaspectengine_p.h"
+
+#include <Qt3DCore/qabstractaspect.h>
+#include <Qt3DCore/qcomponent.h>
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qnode.h>
+#include <QtCore/QMetaObject>
-#include "qabstractaspect.h"
-#include "qaspectthread_p.h"
-#include "qaspectmanager_p.h"
-#include "qchangearbiter_p.h"
-#include "qabstractaspect.h"
-#include "qnode.h"
#include <Qt3DCore/private/corelogging_p.h>
-#include <QMetaObject>
-#include <private/qpostman_p.h>
-#include <private/qscene_p.h>
-#include <private/qaspectengine_p.h>
-#include <private/qnode_p.h>
-#include <private/qnodevisitor_p.h>
-#include <private/qscene_p.h>
-#include "qentity.h"
-#include "qcomponent.h"
+#include <Qt3DCore/private/qaspectthread_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qpostman_p.h>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/qt3dcore-config.h>
+
+#if defined(QT3D_JOBS_RUN_STATS)
#include <Qt3DCore/private/aspectcommanddebugger_p.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -100,8 +103,8 @@ QAspectEnginePrivate::~QAspectEnginePrivate()
*/
void QAspectEnginePrivate::initNode(QNode *node)
{
- QNodePrivate::get(node)->setScene(m_scene);
m_scene->addObservable(node);
+ QNodePrivate::get(node)->setScene(m_scene);
}
void QAspectEnginePrivate::initEntity(QEntity *entity)
@@ -177,10 +180,6 @@ void QAspectEnginePrivate::generateCreationChanges(QNode *root)
QAspectEngine::QAspectEngine(QObject *parent)
: QObject(*new QAspectEnginePrivate, parent)
{
- // Don't show any debug output from Qt3D. If you need to enable additional logging
- // for debugging use a rules file as explained in the QLoggingCategory documentation.
- QLoggingCategory::setFilterRules(QString::fromUtf8("Qt3D.*.debug=false\n"));
-
qCDebug(Aspects) << Q_FUNC_INFO;
Q_D(QAspectEngine);
d->m_scene = new QScene(this);
@@ -218,6 +217,8 @@ QAspectEngine::~QAspectEngine()
void QAspectEnginePrivate::initNodeTree(QNode *node)
{
+ // Set the root entity on the scene
+ m_scene->setRootNode(node);
QNodeVisitor visitor;
visitor.traverse(node, this, &QAspectEnginePrivate::initNode, &QAspectEnginePrivate::initEntity);
}
diff --git a/src/core/aspects/qaspectengine.h b/src/core/aspects/qaspectengine.h
index 6de5df42c..28b15046b 100644
--- a/src/core/aspects/qaspectengine.h
+++ b/src/core/aspects/qaspectengine.h
@@ -40,10 +40,9 @@
#ifndef QT3DCORE_QASPECTENGINE_H
#define QT3DCORE_QASPECTENGINE_H
-#include <QObject>
-#include <QVector>
-
#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QObject>
+#include <QtCore/QVector>
QT_BEGIN_NAMESPACE
diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h
index 10b3536df..a7311d054 100644
--- a/src/core/aspects/qaspectengine_p.h
+++ b/src/core/aspects/qaspectengine_p.h
@@ -51,11 +51,13 @@
// We mean it.
//
-#include <private/qobject_p.h>
+#include <Qt3DCore/qt3dcore-config.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/private/qaspectfactory_p.h>
#include <QtCore/qsharedpointer.h>
+#include <Qt3DCore/private/qaspectfactory_p.h>
+#include <QtCore/private/qobject_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/aspects/qaspectfactory.cpp b/src/core/aspects/qaspectfactory.cpp
index 3135e1653..94e04b34d 100644
--- a/src/core/aspects/qaspectfactory.cpp
+++ b/src/core/aspects/qaspectfactory.cpp
@@ -39,11 +39,9 @@
#include "qaspectfactory_p.h"
-#include <QtGlobal>
-
-#include <QDebug>
-
#include <Qt3DCore/QAbstractAspect>
+#include <QtCore/QDebug>
+#include <QtCore/QtGlobal>
QT_BEGIN_NAMESPACE
diff --git a/src/core/aspects/qaspectfactory_p.h b/src/core/aspects/qaspectfactory_p.h
index 9e2bedaaa..67b5e0b9d 100644
--- a/src/core/aspects/qaspectfactory_p.h
+++ b/src/core/aspects/qaspectfactory_p.h
@@ -51,8 +51,8 @@
// We mean it.
//
-#include <QHash>
-#include <QStringList>
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
#include <Qt3DCore/private/qt3dcore_global_p.h>
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index 98fb982df..5ccc89b9e 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -38,27 +38,27 @@
****************************************************************************/
#include "qaspectmanager_p.h"
-#include "qabstractaspect.h"
-#include "qabstractaspect_p.h"
-#include "qchangearbiter_p.h"
-// TODO Make the kind of job manager configurable (e.g. ThreadWeaver vs Intel TBB)
-#include "qaspectjobmanager_p.h"
-#include "qabstractaspectjobmanager_p.h"
-#include "qentity.h"
-#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/qabstractaspect.h>
+#include <Qt3DCore/qentity.h>
+#include <QtCore/QEventLoop>
+#include <QtCore/QThread>
+#include <QtCore/QWaitCondition>
+#include <QtGui/QSurface>
-#include <Qt3DCore/private/qaspectjob_p.h>
-#include <Qt3DCore/private/qthreadpooler_p.h>
-#include <Qt3DCore/private/qtickclockservice_p.h>
#include <Qt3DCore/private/corelogging_p.h>
+#include <Qt3DCore/private/qabstractaspect_p.h>
+#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
+#include <Qt3DCore/private/qabstractframeadvanceservice_p.h>
+// TODO Make the kind of job manager configurable (e.g. ThreadWeaver vs Intel TBB)
+#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qaspectjob_p.h>
+#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qscheduler_p.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qthreadpooler_p.h>
#include <Qt3DCore/private/qtickclock_p.h>
-#include <Qt3DCore/private/qabstractframeadvanceservice_p.h>
-#include <QEventLoop>
-#include <QThread>
-#include <QWaitCondition>
-#include <QSurface>
+#include <Qt3DCore/private/qtickclockservice_p.h>
#if defined(QT3D_CORE_JOB_TIMING)
#include <QElapsedTimer>
diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h
index e4795516c..1c87738ed 100644
--- a/src/core/aspects/qaspectmanager_p.h
+++ b/src/core/aspects/qaspectmanager_p.h
@@ -51,13 +51,14 @@
// We mean it.
//
-#include <QObject>
#include <Qt3DCore/qnodecreatedchange.h>
+#include <QtCore/QObject>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSemaphore>
+#include <QtCore/QVariant>
+#include <QtCore/QVector>
+
#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include <QVector>
-#include <QScopedPointer>
-#include <QVariant>
-#include <QSemaphore>
QT_BEGIN_NAMESPACE
diff --git a/src/core/aspects/qaspectthread.cpp b/src/core/aspects/qaspectthread.cpp
index 9e6961901..31715b04e 100644
--- a/src/core/aspects/qaspectthread.cpp
+++ b/src/core/aspects/qaspectthread.cpp
@@ -38,10 +38,11 @@
****************************************************************************/
#include "qaspectthread_p.h"
-#include "qaspectmanager_p.h"
+#include <QtCore/QMutexLocker>
+
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/corelogging_p.h>
-#include <QMutexLocker>
QT_BEGIN_NAMESPACE
diff --git a/src/core/aspects/qaspectthread_p.h b/src/core/aspects/qaspectthread_p.h
index dc508b271..91fb363c5 100644
--- a/src/core/aspects/qaspectthread_p.h
+++ b/src/core/aspects/qaspectthread_p.h
@@ -51,10 +51,10 @@
// We mean it.
//
-#include <QThread>
#include <Qt3DCore/qt3dcore_global.h>
-
#include <QtCore/QSemaphore>
+#include <QtCore/QThread>
+
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/changes.pri b/src/core/changes/changes.pri
index 49d560a56..11d66a83e 100644
--- a/src/core/changes/changes.pri
+++ b/src/core/changes/changes.pri
@@ -35,7 +35,9 @@ HEADERS += \
$$PWD/qpropertyvalueaddedchange.h \
$$PWD/qpropertyvalueaddedchange_p.h \
$$PWD/qpropertyvalueremovedchange.h \
- $$PWD/qpropertyvalueremovedchange_p.h
+ $$PWD/qpropertyvalueremovedchange_p.h \
+ $$PWD/qnodecommand.h \
+ $$PWD/qnodecommand_p.h
SOURCES += \
$$PWD/qscenechange.cpp \
@@ -54,4 +56,5 @@ SOURCES += \
$$PWD/qpropertynodeaddedchange.cpp \
$$PWD/qpropertynoderemovedchange.cpp \
$$PWD/qpropertyvalueaddedchange.cpp \
- $$PWD/qpropertyvalueremovedchange.cpp
+ $$PWD/qpropertyvalueremovedchange.cpp \
+ $$PWD/qnodecommand.cpp
diff --git a/src/core/changes/qcomponentaddedchange.cpp b/src/core/changes/qcomponentaddedchange.cpp
index 985567849..e00c4ffab 100644
--- a/src/core/changes/qcomponentaddedchange.cpp
+++ b/src/core/changes/qcomponentaddedchange.cpp
@@ -39,9 +39,11 @@
#include "qcomponentaddedchange.h"
#include "qcomponentaddedchange_p.h"
+
#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/qentity.h>
-#include <private/qnode_p.h>
+
+#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qcomponentaddedchange_p.h b/src/core/changes/qcomponentaddedchange_p.h
index 99550c92f..5eb453363 100644
--- a/src/core/changes/qcomponentaddedchange_p.h
+++ b/src/core/changes/qcomponentaddedchange_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include <private/qscenechange_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/private/qscenechange_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
struct QMetaObject;
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qcomponentremovedchange.cpp b/src/core/changes/qcomponentremovedchange.cpp
index 30863cd89..5e5dfa5aa 100644
--- a/src/core/changes/qcomponentremovedchange.cpp
+++ b/src/core/changes/qcomponentremovedchange.cpp
@@ -39,9 +39,11 @@
#include "qcomponentremovedchange.h"
#include "qcomponentremovedchange_p.h"
+
#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/qentity.h>
-#include <private/qnode_p.h>
+
+#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qcomponentremovedchange_p.h b/src/core/changes/qcomponentremovedchange_p.h
index ff5c71f84..5284c7bbd 100644
--- a/src/core/changes/qcomponentremovedchange_p.h
+++ b/src/core/changes/qcomponentremovedchange_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include <private/qscenechange_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/private/qscenechange_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
struct QMetaObject;
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qdynamicpropertyupdatedchange_p.h b/src/core/changes/qdynamicpropertyupdatedchange_p.h
index 729ae44d0..c71c2a71a 100644
--- a/src/core/changes/qdynamicpropertyupdatedchange_p.h
+++ b/src/core/changes/qdynamicpropertyupdatedchange_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <private/qpropertyupdatedchangebase_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qvariant.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/changes/qnodecommand.cpp b/src/core/changes/qnodecommand.cpp
new file mode 100644
index 000000000..fc7e01697
--- /dev/null
+++ b/src/core/changes/qnodecommand.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnodecommand.h"
+#include "qnodecommand_p.h"
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+QNodeCommandPrivate::QNodeCommandPrivate()
+ : QSceneChangePrivate()
+ , m_commandId(createId())
+ , m_replyToCommandId()
+{
+}
+
+QNodeCommand::CommandId QNodeCommandPrivate::createId()
+{
+ static QBasicAtomicInteger<QNodeCommand::CommandId> next = Q_BASIC_ATOMIC_INITIALIZER(0);
+ return next.fetchAndAddRelaxed(1) + 1;
+}
+
+/*!
+ * \class Qt3DCore::QNodeCommand
+ * \inheaderfile Qt3DCore/QNodeCommand
+ * \inherits Qt3DCore::QSceneChange
+ * \inmodule Qt3DCore
+ * \since 5.9
+ * \brief The QNodeCommand class is the base class for all CommandRequested QSceneChange events
+ *
+ * The QNodeCommand class is the base class for all QSceneChange events that
+ * have the changeType() CommandRequested.
+ *
+ * You can subclass this to create your own node update types for communication between
+ * your QNode and QBackendNode subclasses when writing your own aspects.
+ */
+
+/*!
+ * \typedef Qt3DCore::QNodeCommandPtr
+ * \relates Qt3DCore::QNodeCommand
+ *
+ * A shared pointer for QNodeCommand.
+ */
+
+/*!
+ * Constructs a new QNodeCommand with \a node.
+ */
+QNodeCommand::QNodeCommand(QNodeId id)
+ : QSceneChange(*new QNodeCommandPrivate(), CommandRequested, id)
+{
+}
+
+QNodeCommand::QNodeCommand(QNodeCommandPrivate &dd, QNodeId id)
+ : QSceneChange(dd, CommandRequested, id)
+{
+}
+
+QNodeCommand::~QNodeCommand()
+{
+}
+
+/*!
+ * \return commandId.
+ */
+QNodeCommand::CommandId QNodeCommand::commandId() const
+{
+ Q_D(const QNodeCommand);
+ return d->m_commandId;
+}
+
+/*!
+ * \return name.
+ */
+QString QNodeCommand::name() const
+{
+ Q_D(const QNodeCommand);
+ return d->m_name;
+}
+
+void QNodeCommand::setName(const QString &name)
+{
+ Q_D(QNodeCommand);
+ d->m_name = name;
+}
+
+/*!
+ * \return data.
+ */
+QVariant QNodeCommand::data() const
+{
+ Q_D(const QNodeCommand);
+ return d->m_data;
+}
+
+void QNodeCommand::setData(const QVariant &data)
+{
+ Q_D(QNodeCommand);
+ d->m_data = data;
+}
+
+QNodeCommand::CommandId QNodeCommand::inReplyTo() const
+{
+ Q_D(const QNodeCommand);
+ return d->m_replyToCommandId;
+}
+
+void QNodeCommand::setReplyToCommandId(QNodeCommand::CommandId id)
+{
+ Q_D(QNodeCommand);
+ d->m_replyToCommandId = id;
+}
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
diff --git a/src/core/changes/qnodecommand.h b/src/core/changes/qnodecommand.h
new file mode 100644
index 000000000..c02365a59
--- /dev/null
+++ b/src/core/changes/qnodecommand.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QNODECOMMAND_H
+#define QT3DCORE_QNODECOMMAND_H
+
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/qscenechange.h>
+
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QNodeCommandPrivate;
+
+class QT3DCORESHARED_EXPORT QNodeCommand : public QSceneChange
+{
+public:
+#if defined(Q_ATOMIC_INT64_IS_SUPPORTED)
+ typedef quint64 CommandId;
+#else
+ typedef quint32 CommandId;
+#endif
+
+ explicit QNodeCommand(QNodeId id);
+ ~QNodeCommand();
+
+ CommandId commandId() const;
+
+ QString name() const;
+ void setName(const QString &name);
+ QVariant data() const;
+ void setData(const QVariant &data);
+ CommandId inReplyTo() const;
+ void setReplyToCommandId(CommandId id);
+
+protected:
+ QNodeCommand(QNodeCommandPrivate &dd, QNodeId id);
+
+private:
+ Q_DECLARE_PRIVATE(QNodeCommand)
+};
+
+typedef QSharedPointer<QNodeCommand> QNodeCommandPtr;
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QNODECOMMAND_H
diff --git a/src/core/changes/qnodecommand_p.h b/src/core/changes/qnodecommand_p.h
new file mode 100644
index 000000000..09be873f5
--- /dev/null
+++ b/src/core/changes/qnodecommand_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QNODECOMMAND_P_H
+#define QT3DCORE_QNODECOMMAND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qt3dcore_global_p.h>
+#include <private/qscenechange_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QT3DCORE_PRIVATE_EXPORT QNodeCommandPrivate : public QSceneChangePrivate
+{
+public:
+ QNodeCommandPrivate();
+
+ static QNodeCommand::CommandId createId();
+
+ QNodeCommand::CommandId m_commandId;
+ QNodeCommand::CommandId m_replyToCommandId;
+ QString m_name;
+ QVariant m_data;
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QNODECOMMAND_P_H
diff --git a/src/core/changes/qnodecreatedchange.cpp b/src/core/changes/qnodecreatedchange.cpp
index a77721cdc..34ca939d7 100644
--- a/src/core/changes/qnodecreatedchange.cpp
+++ b/src/core/changes/qnodecreatedchange.cpp
@@ -36,7 +36,9 @@
#include "qnodecreatedchange.h"
#include "qnodecreatedchange_p.h"
+
#include <Qt3DCore/qnode.h>
+
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qnodecreatedchange.h b/src/core/changes/qnodecreatedchange.h
index 4b5e70b82..85444e00c 100644
--- a/src/core/changes/qnodecreatedchange.h
+++ b/src/core/changes/qnodecreatedchange.h
@@ -37,9 +37,8 @@
#ifndef QT3DCORE_QNODECREATEDCHANGE_H
#define QT3DCORE_QNODECREATEDCHANGE_H
-#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/qscenechange.h>
-
+#include <Qt3DCore/qt3dcore_global.h>
#include <QtCore/qsharedpointer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qnodecreatedchange_p.h b/src/core/changes/qnodecreatedchange_p.h
index 75969e461..cb1470970 100644
--- a/src/core/changes/qnodecreatedchange_p.h
+++ b/src/core/changes/qnodecreatedchange_p.h
@@ -48,10 +48,11 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include <private/qscenechange_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/private/qscenechange_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
struct QMetaObject;
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qnodedestroyedchange.h b/src/core/changes/qnodedestroyedchange.h
index 348fda23f..11a54f8e2 100644
--- a/src/core/changes/qnodedestroyedchange.h
+++ b/src/core/changes/qnodedestroyedchange.h
@@ -37,8 +37,8 @@
#ifndef QT3DCORE_QNODEDESTROYEDCHANGE_H
#define QT3DCORE_QNODEDESTROYEDCHANGE_H
-#include <Qt3DCore/qscenechange.h>
#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/qscenechange.h>
#include <QtCore/qsharedpointer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qnodedestroyedchange_p.h b/src/core/changes/qnodedestroyedchange_p.h
index 999976431..081ca858f 100644
--- a/src/core/changes/qnodedestroyedchange_p.h
+++ b/src/core/changes/qnodedestroyedchange_p.h
@@ -48,9 +48,10 @@
// We mean it.
//
-#include <private/qscenechange_p.h>
#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qscenechange_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/changes/qpropertynodeaddedchange.cpp b/src/core/changes/qpropertynodeaddedchange.cpp
index 66b5c70d3..390a170b6 100644
--- a/src/core/changes/qpropertynodeaddedchange.cpp
+++ b/src/core/changes/qpropertynodeaddedchange.cpp
@@ -39,6 +39,7 @@
#include "qpropertynodeaddedchange.h"
#include "qpropertynodeaddedchange_p.h"
+
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertynodeaddedchange_p.h b/src/core/changes/qpropertynodeaddedchange_p.h
index 01340ae8c..2930867ea 100644
--- a/src/core/changes/qpropertynodeaddedchange_p.h
+++ b/src/core/changes/qpropertynodeaddedchange_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <private/qstaticpropertyvalueaddedchangebase_p.h>
#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qstaticpropertyvalueaddedchangebase_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/changes/qpropertynoderemovedchange.cpp b/src/core/changes/qpropertynoderemovedchange.cpp
index a7b4e95f3..a0f342d0b 100644
--- a/src/core/changes/qpropertynoderemovedchange.cpp
+++ b/src/core/changes/qpropertynoderemovedchange.cpp
@@ -39,6 +39,7 @@
#include "qpropertynoderemovedchange.h"
#include "qpropertynoderemovedchange_p.h"
+
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertynoderemovedchange_p.h b/src/core/changes/qpropertynoderemovedchange_p.h
index 6cd23661b..0145cc507 100644
--- a/src/core/changes/qpropertynoderemovedchange_p.h
+++ b/src/core/changes/qpropertynoderemovedchange_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <private/qstaticpropertyvalueremovedchangebase_p.h>
#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qstaticpropertyvalueremovedchangebase_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/changes/qpropertyupdatedchange_p.h b/src/core/changes/qpropertyupdatedchange_p.h
index f985120c9..ad908a8c4 100644
--- a/src/core/changes/qpropertyupdatedchange_p.h
+++ b/src/core/changes/qpropertyupdatedchange_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
-#include <private/qstaticpropertyupdatedchangebase_p.h>
-#include <QVariant>
+#include <QtCore/QVariant>
+
+#include <Qt3DCore/private/qstaticpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertyupdatedchangebase.cpp b/src/core/changes/qpropertyupdatedchangebase.cpp
index d33c737e5..5d79b9049 100644
--- a/src/core/changes/qpropertyupdatedchangebase.cpp
+++ b/src/core/changes/qpropertyupdatedchangebase.cpp
@@ -46,7 +46,7 @@ namespace Qt3DCore {
QPropertyUpdatedChangeBasePrivate::QPropertyUpdatedChangeBasePrivate()
: QSceneChangePrivate()
- , m_isFinal(false)
+ , m_isIntermediate(false)
{
}
diff --git a/src/core/changes/qpropertyupdatedchangebase_p.h b/src/core/changes/qpropertyupdatedchangebase_p.h
index 3c32b2237..7c66812a1 100644
--- a/src/core/changes/qpropertyupdatedchangebase_p.h
+++ b/src/core/changes/qpropertyupdatedchangebase_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qscenechange_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
@@ -69,7 +69,12 @@ public:
static QPropertyUpdatedChangeBasePrivate *get(QPropertyUpdatedChangeBase *q);
Q_DECLARE_PUBLIC(QPropertyUpdatedChangeBase)
- bool m_isFinal;
+
+ // Frontend nodes should not receive intermediate animated property
+ // updated by default. Only if they subscribe. The animation aspect
+ // will set this to true for animating properties apart from the final
+ // frame's update.
+ bool m_isIntermediate;
};
} // namespace Qt3DCore
diff --git a/src/core/changes/qpropertyvalueaddedchange_p.h b/src/core/changes/qpropertyvalueaddedchange_p.h
index 538a591a1..edd59489f 100644
--- a/src/core/changes/qpropertyvalueaddedchange_p.h
+++ b/src/core/changes/qpropertyvalueaddedchange_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <private/qstaticpropertyvalueaddedchangebase_p.h>
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <QtCore/qvariant.h>
+#include <Qt3DCore/private/qstaticpropertyvalueaddedchangebase_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/changes/qpropertyvalueaddedchangebase.cpp b/src/core/changes/qpropertyvalueaddedchangebase.cpp
index 26dcd5555..3c9929496 100644
--- a/src/core/changes/qpropertyvalueaddedchangebase.cpp
+++ b/src/core/changes/qpropertyvalueaddedchangebase.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qpropertyvalueaddedchangebase.h"
+
#include "qpropertyvalueaddedchangebase_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertyvalueaddedchangebase_p.h b/src/core/changes/qpropertyvalueaddedchangebase_p.h
index 405b2ad3f..be92e2d5b 100644
--- a/src/core/changes/qpropertyvalueaddedchangebase_p.h
+++ b/src/core/changes/qpropertyvalueaddedchangebase_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qscenechange_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertyvalueremovedchange.cpp b/src/core/changes/qpropertyvalueremovedchange.cpp
index 6e8a1f817..9d420abc0 100644
--- a/src/core/changes/qpropertyvalueremovedchange.cpp
+++ b/src/core/changes/qpropertyvalueremovedchange.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qpropertyvalueremovedchange.h"
+
#include "qpropertyvalueremovedchange_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertyvalueremovedchange_p.h b/src/core/changes/qpropertyvalueremovedchange_p.h
index 82644b76c..b4e86bc9e 100644
--- a/src/core/changes/qpropertyvalueremovedchange_p.h
+++ b/src/core/changes/qpropertyvalueremovedchange_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <private/qstaticpropertyvalueremovedchangebase_p.h>
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <QtCore/qvariant.h>
+#include <Qt3DCore/private/qstaticpropertyvalueremovedchangebase_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/changes/qpropertyvalueremovedchangebase.cpp b/src/core/changes/qpropertyvalueremovedchangebase.cpp
index 8115d6e22..71213019c 100644
--- a/src/core/changes/qpropertyvalueremovedchangebase.cpp
+++ b/src/core/changes/qpropertyvalueremovedchangebase.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qpropertyvalueremovedchangebase.h"
+
#include "qpropertyvalueremovedchangebase_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qpropertyvalueremovedchangebase_p.h b/src/core/changes/qpropertyvalueremovedchangebase_p.h
index e4c4be640..f9c1b4009 100644
--- a/src/core/changes/qpropertyvalueremovedchangebase_p.h
+++ b/src/core/changes/qpropertyvalueremovedchangebase_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qscenechange_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qscenechange.cpp b/src/core/changes/qscenechange.cpp
index 959518904..df15e239d 100644
--- a/src/core/changes/qscenechange.cpp
+++ b/src/core/changes/qscenechange.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qscenechange.h"
+
#include "qscenechange_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qscenechange.h b/src/core/changes/qscenechange.h
index 4555983e2..854bab051 100644
--- a/src/core/changes/qscenechange.h
+++ b/src/core/changes/qscenechange.h
@@ -40,9 +40,9 @@
#ifndef QT3DCORE_QSCENECHANGE_H
#define QT3DCORE_QSCENECHANGE_H
-#include <Qt3DCore/qt3dcore_global.h>
-#include <QSharedPointer>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -56,6 +56,7 @@ enum ChangeFlag {
PropertyValueRemoved = 1 << 4,
ComponentAdded = 1 << 5,
ComponentRemoved = 1 << 6,
+ CommandRequested = 1 << 7,
AllChanges = 0xFFFFFFFF
};
Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
diff --git a/src/core/changes/qscenechange_p.h b/src/core/changes/qscenechange_p.h
index 80ce4eaa5..cd0194b01 100644
--- a/src/core/changes/qscenechange_p.h
+++ b/src/core/changes/qscenechange_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <QtGlobal>
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/qscenechange.h>
+#include <QtCore/QtGlobal>
+
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qstaticpropertyupdatedchangebase.cpp b/src/core/changes/qstaticpropertyupdatedchangebase.cpp
index 409d80add..d065dbf0b 100644
--- a/src/core/changes/qstaticpropertyupdatedchangebase.cpp
+++ b/src/core/changes/qstaticpropertyupdatedchangebase.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qstaticpropertyupdatedchangebase.h"
+
#include "qstaticpropertyupdatedchangebase_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qstaticpropertyupdatedchangebase_p.h b/src/core/changes/qstaticpropertyupdatedchangebase_p.h
index c81df4076..3f76e2f56 100644
--- a/src/core/changes/qstaticpropertyupdatedchangebase_p.h
+++ b/src/core/changes/qstaticpropertyupdatedchangebase_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qpropertyupdatedchangebase_p.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp b/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp
index 4fb658459..efd2c0165 100644
--- a/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp
+++ b/src/core/changes/qstaticpropertyvalueaddedchangebase.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qstaticpropertyvalueaddedchangebase.h"
+
#include "qstaticpropertyvalueaddedchangebase_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qstaticpropertyvalueaddedchangebase_p.h b/src/core/changes/qstaticpropertyvalueaddedchangebase_p.h
index 7a614c0d1..cd995d739 100644
--- a/src/core/changes/qstaticpropertyvalueaddedchangebase_p.h
+++ b/src/core/changes/qstaticpropertyvalueaddedchangebase_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qpropertyvalueaddedchangebase_p.h>
+#include <Qt3DCore/private/qpropertyvalueaddedchangebase_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/changes/qstaticpropertyvalueremovedchangebase_p.h b/src/core/changes/qstaticpropertyvalueremovedchangebase_p.h
index 47f43f745..ac4e1d875 100644
--- a/src/core/changes/qstaticpropertyvalueremovedchangebase_p.h
+++ b/src/core/changes/qstaticpropertyvalueremovedchangebase_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qpropertyvalueremovedchangebase_p.h>
+#include <Qt3DCore/private/qpropertyvalueremovedchangebase_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/configure.json b/src/core/configure.json
index ed44bfaeb..47a726d82 100644
--- a/src/core/configure.json
+++ b/src/core/configure.json
@@ -4,7 +4,9 @@
"commandline": {
"options": {
- "assimp": { "type": "enum", "values": [ "qt", "system" ] }
+ "assimp": { "type": "enum", "values": [ "qt", "system", "no" ] },
+ "qt3d-profile-jobs": "boolean",
+ "qt3d-profile-gl": "boolean"
}
},
@@ -13,7 +15,7 @@
"label": "Assimp",
"test": "assimp",
"sources": [
- { "type": "pkgConfig", "args": "assimp" },
+ { "type": "pkgConfig", "args": "assimp > 3.3.1" },
"-lassimp"
]
}
@@ -30,6 +32,22 @@
"disable": "input.assimp == 'qt'",
"condition": "features.assimp && libs.assimp",
"output": [ "privateFeature" ]
+ },
+ "qt3d-profile-jobs": {
+ "label": "Output Qt3D Job traces",
+ "autoDetect": false,
+ "output": [
+ "privateFeature",
+ { "type": "define", "name": "QT3D_JOBS_RUN_STATS", "value": 1 }
+ ]
+ },
+ "qt3d-profile-gl": {
+ "label": "Output Qt3D GL traces",
+ "autoDetect": false,
+ "output": [
+ "privateFeature",
+ { "type": "define", "name": "QT3D_OPENGL_RUN_STATS", "value": 1 }
+ ]
}
},
@@ -41,7 +59,9 @@
"section": "Qt 3D",
"entries": [
"assimp",
- "system-assimp"
+ "system-assimp",
+ "qt3d-profile-jobs",
+ "qt3d-profile-gl"
]
}
]
diff --git a/src/core/corelogging.cpp b/src/core/corelogging.cpp
index 4ad8c5f0e..6bd7bfcb7 100644
--- a/src/core/corelogging.cpp
+++ b/src/core/corelogging.cpp
@@ -43,10 +43,10 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-Q_LOGGING_CATEGORY(Nodes, "Qt3D.Core.Nodes")
-Q_LOGGING_CATEGORY(Aspects, "Qt3D.Core.Aspects")
-Q_LOGGING_CATEGORY(Resources, "Qt3D.Core.Resources")
-Q_LOGGING_CATEGORY(ChangeArbiter, "Qt3D.Core.ChangeArbiter")
+Q_LOGGING_CATEGORY(Nodes, "Qt3D.Core.Nodes", QtWarningMsg);
+Q_LOGGING_CATEGORY(Aspects, "Qt3D.Core.Aspects", QtWarningMsg);
+Q_LOGGING_CATEGORY(Resources, "Qt3D.Core.Resources", QtWarningMsg);
+Q_LOGGING_CATEGORY(ChangeArbiter, "Qt3D.Core.ChangeArbiter", QtWarningMsg);
} // Qt3D
diff --git a/src/core/corelogging_p.h b/src/core/corelogging_p.h
index 7fc3fff55..5ddd6ea73 100644
--- a/src/core/corelogging_p.h
+++ b/src/core/corelogging_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QLoggingCategory>
+#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/dependencyhandler.cpp b/src/core/jobs/dependencyhandler.cpp
index dcea66a62..6a925d037 100644
--- a/src/core/jobs/dependencyhandler.cpp
+++ b/src/core/jobs/dependencyhandler.cpp
@@ -37,10 +37,10 @@
**
****************************************************************************/
-#include <iterator>
-
#include "dependencyhandler_p.h"
+#include <iterator>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
@@ -104,6 +104,7 @@ namespace {
}
DependencyHandler::DependencyHandler()
+ : m_mutex()
{
}
diff --git a/src/core/jobs/dependencyhandler_p.h b/src/core/jobs/dependencyhandler_p.h
index abaa8e55f..a5a023139 100644
--- a/src/core/jobs/dependencyhandler_p.h
+++ b/src/core/jobs/dependencyhandler_p.h
@@ -51,18 +51,21 @@
// We mean it.
//
-#include "task_p.h"
-
#include <QtCore/QMutex>
#include <QtCore/QVector>
+#include <Qt3DCore/private/task_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
struct Dependency
{
- Dependency() {}
+ Dependency()
+ : depender(nullptr)
+ , dependee(nullptr)
+ {}
Dependency(RunnableInterface *depender, RunnableInterface *dependee)
: depender(qMove(depender)),
dependee(qMove(dependee)) {}
diff --git a/src/core/jobs/qabstractaspectjobmanager_p.h b/src/core/jobs/qabstractaspectjobmanager_p.h
index 32e6e499e..5c4e9f699 100644
--- a/src/core/jobs/qabstractaspectjobmanager_p.h
+++ b/src/core/jobs/qabstractaspectjobmanager_p.h
@@ -51,9 +51,8 @@
// We mean it.
//
-#include <QObject>
-
#include <Qt3DCore/qaspectjob.h>
+#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/qaspectjob.cpp b/src/core/jobs/qaspectjob.cpp
index 59f48e9bf..6016bd273 100644
--- a/src/core/jobs/qaspectjob.cpp
+++ b/src/core/jobs/qaspectjob.cpp
@@ -39,7 +39,8 @@
#include "qaspectjob.h"
#include "qaspectjob_p.h"
-#include <QByteArray>
+
+#include <QtCore/QByteArray>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/qaspectjob.h b/src/core/jobs/qaspectjob.h
index b2e5e587c..398cd88d1 100644
--- a/src/core/jobs/qaspectjob.h
+++ b/src/core/jobs/qaspectjob.h
@@ -41,8 +41,8 @@
#define QT3DCORE_QASPECTJOB_H
#include <Qt3DCore/qt3dcore_global.h>
-#include <QSharedPointer>
-#include <QVector>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QVector>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/qaspectjob_p.h b/src/core/jobs/qaspectjob_p.h
index c54240a4e..6786ccef7 100644
--- a/src/core/jobs/qaspectjob_p.h
+++ b/src/core/jobs/qaspectjob_p.h
@@ -51,8 +51,10 @@
// We mean it.
//
-#include <QWeakPointer>
+#include <QtCore/QWeakPointer>
+
#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DCore/qt3dcore-config.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/qaspectjobmanager.cpp b/src/core/jobs/qaspectjobmanager.cpp
index f2a71412d..468d904b4 100644
--- a/src/core/jobs/qaspectjobmanager.cpp
+++ b/src/core/jobs/qaspectjobmanager.cpp
@@ -38,16 +38,17 @@
****************************************************************************/
#include "qaspectjobmanager_p.h"
-#include "task_p.h"
-#include "qthreadpooler_p.h"
-#include "dependencyhandler_p.h"
-
-#include <QAtomicInt>
-#include <QDebug>
-#include <QThread>
-#include <QCoreApplication>
+
+#include <QtCore/QAtomicInt>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QThread>
#include <QtCore/QFuture>
+#include <Qt3DCore/private/dependencyhandler_p.h>
+#include <Qt3DCore/private/qthreadpooler_p.h>
+#include <Qt3DCore/private/task_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/jobs/qaspectjobmanager_p.h b/src/core/jobs/qaspectjobmanager_p.h
index 5b7f27ad6..6fbf03d22 100644
--- a/src/core/jobs/qaspectjobmanager_p.h
+++ b/src/core/jobs/qaspectjobmanager_p.h
@@ -51,12 +51,11 @@
// We mean it.
//
-#include <private/qabstractaspectjobmanager_p.h>
-#include <Qt3DCore/private/qt3dcore_global_p.h>
-
#include <Qt3DCore/qaspectjob.h>
+#include <QtCore/QVector>
-#include <QVector>
+#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/qaspectjobproviderinterface_p.h b/src/core/jobs/qaspectjobproviderinterface_p.h
index 1e2166ace..29b44b3c1 100644
--- a/src/core/jobs/qaspectjobproviderinterface_p.h
+++ b/src/core/jobs/qaspectjobproviderinterface_p.h
@@ -51,10 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/qaspectjob.h>
+#include <QtCore/QVector>
-#include <QVector>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp
index 35e2df2a1..8ad6f7f0a 100644
--- a/src/core/jobs/qthreadpooler.cpp
+++ b/src/core/jobs/qthreadpooler.cpp
@@ -38,16 +38,17 @@
****************************************************************************/
#include "qthreadpooler_p.h"
-#include "dependencyhandler_p.h"
-
-#include <QDebug>
+#include <Qt3DCore/qt3dcore-config.h>
+#include <QtCore/QDebug>
#ifdef QT3D_JOBS_RUN_STATS
-#include <QFile>
-#include <QThreadStorage>
-#include <QDateTime>
+#include <QtCore/QFile>
+#include <QtCore/QThreadStorage>
+#include <QtCore/QDateTime>
#endif
+#include <Qt3DCore/private/dependencyhandler_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
@@ -57,10 +58,11 @@ QElapsedTimer QThreadPooler::m_jobsStatTimer;
#endif
QThreadPooler::QThreadPooler(QObject *parent)
- : QObject(parent),
- m_futureInterface(nullptr),
- m_mutex(),
- m_taskCount(0)
+ : QObject(parent)
+ , m_futureInterface(nullptr)
+ , m_mutex()
+ , m_dependencyHandler(nullptr)
+ , m_taskCount(0)
{
// Ensures that threads will never be recycled
m_threadPool.setExpiryTimeout(-1);
@@ -196,7 +198,12 @@ void QThreadPooler::writeFrameJobLogStats()
static QScopedPointer<QFile> traceFile;
static quint32 frameId = 0;
if (!traceFile) {
- traceFile.reset(new QFile(QStringLiteral("trace_") + QDateTime::currentDateTime().toString() + QStringLiteral(".qt3d")));
+ const QString fileName = QStringLiteral("trace_") + QCoreApplication::applicationName() + QDateTime::currentDateTime().toString(QStringLiteral("_ddd_dd_MM_yy-hh_mm_ss_"))+ QSysInfo::productType() + QStringLiteral("_") + QSysInfo::buildAbi() + QStringLiteral(".qt3d");
+#ifdef Q_OS_ANDROID
+ traceFile.reset(new QFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QStringLiteral("/") + fileName));
+#else
+ traceFile.reset(new QFile(fileName));
+#endif
if (!traceFile->open(QFile::WriteOnly|QFile::Truncate))
qCritical("Failed to open trace file");
}
diff --git a/src/core/jobs/qthreadpooler_p.h b/src/core/jobs/qthreadpooler_p.h
index 47b28e639..9d632a696 100644
--- a/src/core/jobs/qthreadpooler_p.h
+++ b/src/core/jobs/qthreadpooler_p.h
@@ -51,17 +51,18 @@
// We mean it.
//
-#include "task_p.h"
-#include "dependencyhandler_p.h"
-#include "qaspectjob_p.h"
+#include <QtCore/QFuture>
+#include <QtCore/QFutureInterface>
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
-#include <QtCore/QFutureInterface>
-#include <QtCore/QFuture>
-#include <QThreadPool>
+#include <QtCore/QThreadPool>
+
+#include <Qt3DCore/private/dependencyhandler_p.h>
+#include <Qt3DCore/private/qaspectjob_p.h>
+#include <Qt3DCore/private/task_p.h>
#ifdef QT3D_JOBS_RUN_STATS
-#include <QElapsedTimer>
+#include <QtCore/QElapsedTimer>
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/core/jobs/task.cpp b/src/core/jobs/task.cpp
index 45da858f4..ca3c8b65a 100644
--- a/src/core/jobs/task.cpp
+++ b/src/core/jobs/task.cpp
@@ -38,12 +38,13 @@
****************************************************************************/
#include "task_p.h"
-#include "dependencyhandler_p.h"
-#include "qthreadpooler_p.h"
-#include <QMutexLocker>
-#include <QElapsedTimer>
-#include <QDebug>
+#include <QtCore/QDebug>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QMutexLocker>
+
+#include <Qt3DCore/private/dependencyhandler_p.h>
+#include <Qt3DCore/private/qthreadpooler_p.h>
QT_BEGIN_NAMESPACE
@@ -56,8 +57,9 @@ RunnableInterface::~RunnableInterface()
// Aspect task
AspectTaskRunnable::AspectTaskRunnable()
- : m_dependencyHandler(0),
- m_reserved(false)
+ : m_dependencyHandler(nullptr)
+ , m_pooler(nullptr)
+ , m_reserved(false)
{
}
@@ -106,11 +108,12 @@ DependencyHandler *AspectTaskRunnable::dependencyHandler()
SyncTaskRunnable::SyncTaskRunnable(QAbstractAspectJobManager::JobFunction func,
void *arg, QAtomicInt *atomicCount)
- : m_func(func),
- m_arg(arg),
- m_atomicCount(atomicCount),
- m_pooler(nullptr),
- m_reserved(false)
+ : m_func(func)
+ , m_arg(arg)
+ , m_atomicCount(atomicCount)
+ , m_pooler(nullptr)
+ , m_reserved(false)
+ , m_id(0)
{
}
diff --git a/src/core/jobs/task_p.h b/src/core/jobs/task_p.h
index 593d7d7ad..8193abaf6 100644
--- a/src/core/jobs/task_p.h
+++ b/src/core/jobs/task_p.h
@@ -51,13 +51,12 @@
// We mean it.
//
-#include "qaspectjobmanager_p.h"
-
-#include <QtCore/QtGlobal>
-#include <QtCore/QThread>
+#include <QtCore/QRunnable>
#include <QtCore/QSharedPointer>
+#include <QtCore/QThread>
+#include <QtCore/QtGlobal>
-#include <QtCore/QRunnable>
+#include <Qt3DCore/private/qaspectjobmanager_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/propertychangehandler_p.h b/src/core/nodes/propertychangehandler_p.h
index e91df5016..4bcfdef75 100644
--- a/src/core/nodes/propertychangehandler_p.h
+++ b/src/core/nodes/propertychangehandler_p.h
@@ -52,12 +52,11 @@
//
#include <Qt3DCore/qt3dcore_global.h>
-
-#include <QObject>
-#include <QHash>
-#include <QVector>
-#include <QMetaMethod>
-#include <QDebug>
+#include <QtCore/QDebug>
+#include <QtCore/QHash>
+#include <QtCore/QMetaMethod>
+#include <QtCore/QObject>
+#include <QtCore/QVector>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qabstractnodefactory_p.h b/src/core/nodes/qabstractnodefactory_p.h
index bb7533e94..dbe0adffe 100644
--- a/src/core/nodes/qabstractnodefactory_p.h
+++ b/src/core/nodes/qabstractnodefactory_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/nodes/qbackendnode.cpp b/src/core/nodes/qbackendnode.cpp
index 6970794b8..65d140067 100644
--- a/src/core/nodes/qbackendnode.cpp
+++ b/src/core/nodes/qbackendnode.cpp
@@ -39,9 +39,12 @@
#include "qbackendnode.h"
#include "qbackendnode_p.h"
-#include "qaspectengine.h"
-#include "qnode.h"
-#include "qpropertyupdatedchange.h"
+
+#include <Qt3DCore/qaspectengine.h>
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/qnodecommand.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DCore/private/corelogging_p.h>
QT_BEGIN_NAMESPACE
@@ -204,6 +207,25 @@ void QBackendNode::notifyObservers(const QSceneChangePtr &e)
d->notifyObservers(e);
}
+QNodeCommand::CommandId QBackendNode::sendCommand(const QString &name,
+ const QVariant &data,
+ QNodeCommand::CommandId replyTo)
+{
+ auto e = QNodeCommandPtr::create(peerId());
+ e->setName(name);
+ e->setData(data);
+ e->setReplyToCommandId(replyTo);
+ e->setDeliveryFlags(QSceneChange::Nodes);
+ notifyObservers(e);
+ return e->commandId();
+}
+
+void QBackendNode::sendReply(const QNodeCommandPtr &command)
+{
+ command->setDeliveryFlags(QSceneChange::Nodes);
+ notifyObservers(command);
+}
+
void QBackendNode::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
{
Q_UNUSED(change);
@@ -231,7 +253,7 @@ void QBackendNode::sceneChangeEvent(const QSceneChangePtr &e)
switch (e->type()) {
case PropertyUpdated: {
if (propertyChange->propertyName() == QByteArrayLiteral("enabled"))
- d->m_enabled = propertyChange->value().value<bool>();
+ d->m_enabled = propertyChange->value().toBool();
break;
}
default:
diff --git a/src/core/nodes/qbackendnode.h b/src/core/nodes/qbackendnode.h
index 39114034d..99e483cff 100644
--- a/src/core/nodes/qbackendnode.h
+++ b/src/core/nodes/qbackendnode.h
@@ -40,10 +40,11 @@
#ifndef QT3DCORE_QBACKENDNODE_H
#define QT3DCORE_QBACKENDNODE_H
-#include <Qt3DCore/qt3dcore_global.h>
-#include <Qt3DCore/qscenechange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qnodecommand.h>
+#include <Qt3DCore/qscenechange.h>
+#include <Qt3DCore/qt3dcore_global.h>
QT_BEGIN_NAMESPACE
@@ -90,6 +91,9 @@ protected:
Q_DECLARE_PRIVATE(QBackendNode)
explicit QBackendNode(QBackendNodePrivate &dd);
void notifyObservers(const QSceneChangePtr &e);
+ QNodeCommand::CommandId sendCommand(const QString &name, const QVariant &data,
+ QNodeCommand::CommandId replyTo = QNodeCommand::CommandId());
+ void sendReply(const QNodeCommandPtr &command);
virtual void sceneChangeEvent(const QSceneChangePtr &e);
QBackendNodePrivate *d_ptr;
diff --git a/src/core/nodes/qbackendnode_p.h b/src/core/nodes/qbackendnode_p.h
index 6cddfad11..6940f5623 100644
--- a/src/core/nodes/qbackendnode_p.h
+++ b/src/core/nodes/qbackendnode_p.h
@@ -51,13 +51,13 @@
// We mean it.
//
+#include <Qt3DCore/qbackendnode.h>
#include <Qt3DCore/qnodeid.h>
+
+#include <Qt3DCore/private/qlockableobserverinterface_p.h>
#include <Qt3DCore/private/qobservableinterface_p.h>
#include <Qt3DCore/private/qobserverinterface_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include <Qt3DCore/qbackendnode.h>
-#include <Qt3DCore/private/qlockableobserverinterface_p.h>
-#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qcomponent.cpp b/src/core/nodes/qcomponent.cpp
index abedb6244..8e337adf6 100644
--- a/src/core/nodes/qcomponent.cpp
+++ b/src/core/nodes/qcomponent.cpp
@@ -39,12 +39,14 @@
#include "qcomponent.h"
#include "qcomponent_p.h"
-#include "qentity.h"
-#include "qentity_p.h"
-#include "qscene_p.h"
+
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qcomponentaddedchange.h>
#include <Qt3DCore/qcomponentremovedchange.h>
+#include <Qt3DCore/qentity.h>
+
+#include <Qt3DCore/private/qentity_p.h>
+#include <Qt3DCore/private/qscene_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qcomponent_p.h b/src/core/nodes/qcomponent_p.h
index 74cef1629..6c7c3c89d 100644
--- a/src/core/nodes/qcomponent_p.h
+++ b/src/core/nodes/qcomponent_p.h
@@ -51,8 +51,8 @@
// We mean it.
//
-#include <private/qnode_p.h>
-#include <private/qt3dcore_global_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qdestructionidandtypecollector_p.h b/src/core/nodes/qdestructionidandtypecollector_p.h
index 3e5fd9138..8557c27f0 100644
--- a/src/core/nodes/qdestructionidandtypecollector_p.h
+++ b/src/core/nodes/qdestructionidandtypecollector_p.h
@@ -48,8 +48,8 @@
// We mean it.
//
-#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/private/qentity_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp
index b28898c60..9bc41f8cc 100644
--- a/src/core/nodes/qentity.cpp
+++ b/src/core/nodes/qentity.cpp
@@ -39,17 +39,18 @@
#include "qentity.h"
#include "qentity_p.h"
-#include "qcomponent.h"
-#include "qcomponent_p.h"
-#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/qcomponentaddedchange.h>
#include <Qt3DCore/qcomponentremovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaProperty>
+
#include <Qt3DCore/private/corelogging_p.h>
-#include <QMetaObject>
-#include <QMetaProperty>
+#include <Qt3DCore/private/qcomponent_p.h>
+#include <Qt3DCore/private/qscene_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qentity.h b/src/core/nodes/qentity.h
index a7f492a96..978f84ebe 100644
--- a/src/core/nodes/qentity.h
+++ b/src/core/nodes/qentity.h
@@ -42,8 +42,7 @@
#include <Qt3DCore/qnode.h>
#include <Qt3DCore/qt3dcore_global.h>
-
-#include <QMetaType>
+#include <QtCore/QMetaType>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qentity_p.h b/src/core/nodes/qentity_p.h
index a9dfb9b0d..9e9dbbd24 100644
--- a/src/core/nodes/qentity_p.h
+++ b/src/core/nodes/qentity_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
+#include <Qt3DCore/qentity.h>
+
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include "qentity.h"
QT_BEGIN_NAMESPACE
@@ -70,10 +71,6 @@ public :
QNodeId parentEntityId() const;
QComponentVector m_components;
- bool m_visible;
-
- // TODO: Is a bool enough here or do we need additional states for entities?
- // Perhaps aboutToBeDeleted would be useful?
mutable QNodeId m_parentEntityId;
};
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index ee327607f..58e016cda 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -40,25 +40,26 @@
#include "qnode.h"
#include "qnode_p.h"
-#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/QComponent>
+#include <Qt3DCore/qaspectengine.h>
#include <Qt3DCore/qdynamicpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qnodedestroyedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qnodedestroyedchange.h>
-#include <Qt3DCore/qaspectengine.h>
-#include <Qt3DCore/private/qdestructionidandtypecollector_p.h>
-#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/private/qpostman_p.h>
-#include <QEvent>
-#include <QChildEvent>
-#include <QMetaObject>
-#include <QMetaProperty>
-#include <QtCore/private/qmetaobject_p.h>
-#include <Qt3DCore/QComponent>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <QtCore/QChildEvent>
+#include <QtCore/QEvent>
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaProperty>
+
#include <Qt3DCore/private/corelogging_p.h>
+#include <Qt3DCore/private/qdestructionidandtypecollector_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qpostman_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <QtCore/private/qmetaobject_p.h>
QT_BEGIN_NAMESPACE
@@ -73,7 +74,7 @@ QNodePrivate::QNodePrivate()
, m_blockNotifications(false)
, m_hasBackendNode(false)
, m_enabled(true)
- , m_propertyTrackMode(QNode::DefaultTrackMode)
+ , m_defaultPropertyTrackMode(QNode::TrackFinalValues)
, m_propertyChangesSetup(false)
, m_signals(this)
{
@@ -113,7 +114,7 @@ void QNodePrivate::notifyCreationChange()
Q_Q(QNode);
// Do nothing if we already have already sent a node creation change
// and not a subsequent node destroyed change.
- if (m_hasBackendNode)
+ if (m_hasBackendNode || !m_scene)
return;
QNodeCreatedChangeGenerator generator(q);
const auto creationChanges = generator.creationChanges();
@@ -203,7 +204,7 @@ void QNodePrivate::_q_addChild(QNode *childNode)
// removed from the scene as part of the destruction of the parent, when the
// parent's children are deleted in the QObject dtor, we still have access to
// the parentId. If we didn't store this, we wouldn't have access at that time
- // because the parent woudl then only be a QObject, the QNode part would have
+ // because the parent would then only be a QObject, the QNode part would have
// been destroyed already.
QNodePrivate::get(childNode)->m_parentId = m_id;
@@ -304,7 +305,21 @@ void QNodePrivate::_q_setParentHelper(QNode *parent)
visitor.traverse(q, newParentNode->d_func(), &QNodePrivate::setSceneHelper);
}
- notifyCreationChange();
+ // We want to make sure that subTreeRoot is always created before
+ // child.
+ // Given a case such as below
+ // QEntity *subTreeRoot = new QEntity(someGlobalExisitingRoot)
+ // QEntity *child = new QEntity();
+ // child->setParent(subTreeRoot)
+ // We need to take into account that subTreeRoot needs to be
+ // created in the backend before the child.
+ // Therefore we only call notifyCreationChanges if the parent
+ // hasn't been created yet as we know that when the parent will be
+ // fully created, it will also send the changes for all of its
+ // children
+
+ if (QNodePrivate::get(newParentNode)->m_hasBackendNode)
+ notifyCreationChange();
}
// If we have a valid new parent, we let him know that we are its child
@@ -393,19 +408,22 @@ void QNodePrivate::setSceneHelper(QNode *root)
Recursively unsets and remove nodes in the subtree of base node \a root from
the scene. Also takes care of removing Components and Entities connections.
*/
-void QNodePrivate::unsetSceneHelper(QNode *root)
+void QNodePrivate::unsetSceneHelper(QNode *node)
{
+ QNodePrivate *nodePrivate = QNodePrivate::get(node);
+
// We also need to handle QEntity <-> QComponent relationships removal
- if (QComponent *c = qobject_cast<QComponent *>(root)) {
+ if (QComponent *c = qobject_cast<QComponent *>(node)) {
const QVector<QEntity *> entities = c->entities();
for (QEntity *entity : entities) {
- if (m_scene)
- m_scene->removeEntityForComponent(c->id(), entity->id());
+ if (nodePrivate->m_scene)
+ nodePrivate->m_scene->removeEntityForComponent(c->id(), entity->id());
}
}
- if (m_scene != nullptr)
- m_scene->removeObservable(root);
- root->d_func()->setScene(nullptr);
+
+ if (nodePrivate->m_scene != nullptr)
+ nodePrivate->m_scene->removeObservable(node);
+ nodePrivate->setScene(nullptr);
}
/*!
@@ -605,9 +623,9 @@ void QNodePrivate::updatePropertyTrackMode()
{
if (m_scene != nullptr) {
QScene::NodePropertyTrackData trackData;
- trackData.updateMode = m_propertyTrackMode;
- trackData.namedProperties = m_trackedProperties;
- m_scene->setPropertyTrackDataForNode(m_id,trackData);
+ trackData.defaultTrackMode = m_defaultPropertyTrackMode;
+ trackData.trackedPropertiesOverrides = m_trackedPropertiesOverrides;
+ m_scene->setPropertyTrackDataForNode(m_id, trackData);
}
}
@@ -800,30 +818,16 @@ void QNode::setEnabled(bool isEnabled)
emit enabledChanged(isEnabled);
}
-void QNode::setPropertyTrackMode(QNode::PropertyTrackMode mode)
+void QNode::setDefaultPropertyTrackingMode(QNode::PropertyTrackingMode mode)
{
Q_D(QNode);
- if (d->m_propertyTrackMode == mode)
+ if (d->m_defaultPropertyTrackMode == mode)
return;
- d->m_propertyTrackMode = mode;
+ d->m_defaultPropertyTrackMode = mode;
// The backend doesn't care about such notification
const bool blocked = blockNotifications(true);
- emit propertyUpdateModeChanged(mode);
- blockNotifications(blocked);
- d->updatePropertyTrackMode();
-}
-
-void QNode::setTrackedProperties(const QStringList &trackedProperties)
-{
- Q_D(QNode);
- if (d->m_trackedProperties == trackedProperties)
- return;
-
- d->m_trackedProperties = trackedProperties;
- // The backend doesn't care about such notification
- const bool blocked = blockNotifications(true);
- emit trackedPropertiesChanged(trackedProperties);
+ emit defaultPropertyTrackingModeChanged(mode);
blockNotifications(blocked);
d->updatePropertyTrackMode();
}
@@ -845,29 +849,45 @@ bool QNode::isEnabled() const
}
/*!
- \property Qt3DCore::QNode::propertyTrackMode
+ \property Qt3DCore::QNode::defaultPropertyTrackingMode
- Holds the property track mode which determines whether a QNode should
- be listening for property updates
+ Holds the default property tracking mode which determines whether a QNode should
+ be listening for property updates. This only applies to properties which
+ haven't been overridden by a call to setPropertyTracking.
- By default it is set to QNode::DontTrackProperties
+ By default it is set to QNode::TrackFinalValues
*/
-QNode::PropertyTrackMode QNode::propertyTrackMode() const
+QNode::PropertyTrackingMode QNode::defaultPropertyTrackingMode() const
{
Q_D(const QNode);
- return d->m_propertyTrackMode;
+ return d->m_defaultPropertyTrackMode;
}
-/*!
- \property Qt3DCore::QNode::trackedProperties
+void QNode::setPropertyTracking(const QString &propertyName, QNode::PropertyTrackingMode trackMode)
+{
+ Q_D(QNode);
+ d->m_trackedPropertiesOverrides.insert(propertyName, trackMode);
+ d->updatePropertyTrackMode();
+}
- Holds the names of the properties to be tracked when propertyTrackMode is
- set to TrackNamedProperties.
-*/
-QStringList QNode::trackedProperties() const
+QNode::PropertyTrackingMode QNode::propertyTracking(const QString &propertyName) const
{
Q_D(const QNode);
- return d->m_trackedProperties;
+ return d->m_trackedPropertiesOverrides.value(propertyName, d->m_defaultPropertyTrackMode);
+}
+
+void QNode::clearPropertyTracking(const QString &propertyName)
+{
+ Q_D(QNode);
+ d->m_trackedPropertiesOverrides.remove(propertyName);
+ d->updatePropertyTrackMode();
+}
+
+void QNode::clearPropertyTrackings()
+{
+ Q_D(QNode);
+ d->m_trackedPropertiesOverrides.clear();
+ d->updatePropertyTrackMode();
}
QNodeCreatedChangeBasePtr QNode::createNodeCreationChange() const
@@ -882,6 +902,51 @@ QNodeCreatedChangeBasePtr QNode::createNodeCreationChange() const
return QNodeCreatedChangeBasePtr::create(this);
}
+/*!
+ * \brief Sends a command messages to the backend node
+ *
+ * Creates a QNodeCommand message and dispatches it to the backend node. The
+ * command is given and a \a name and some \a data which can be used in the
+ * backend node to performe various operations.
+ * This returns a CommandId which can be used to identify the initial command
+ * when receiving a message in reply. If the command message is to be sent in
+ * reply to another command, \a replyTo contains the id of that command.
+ *
+ * \sa QNodeCommand, QNode::sendReply
+ */
+QNodeCommand::CommandId QNode::sendCommand(const QString &name,
+ const QVariant &data,
+ QNodeCommand::CommandId replyTo)
+{
+ Q_D(QNode);
+
+ // Bail out early if we can to avoid operator new
+ if (d->m_blockNotifications)
+ return QNodeCommand::CommandId(0);
+
+ auto e = QNodeCommandPtr::create(d->m_id);
+ e->setName(name);
+ e->setData(data);
+ e->setReplyToCommandId(replyTo);
+ d->notifyObservers(e);
+ return e->commandId();
+}
+
+/*!
+ * \brief Send a command back to the backend node
+ *
+ * Assumes the command is to be to sent back in reply to itself to the backend node
+ *
+ * \sa QNodeCommand, QNode::sendCommand
+ */
+void QNode::sendReply(const QNodeCommandPtr &command)
+{
+ Q_D(QNode);
+ command->setDeliveryFlags(QSceneChange::BackendNodes);
+ d->notifyObservers(command);
+}
+
+
namespace {
/*! \internal */
diff --git a/src/core/nodes/qnode.h b/src/core/nodes/qnode.h
index 75ea61cc7..1fe03f5e0 100644
--- a/src/core/nodes/qnode.h
+++ b/src/core/nodes/qnode.h
@@ -40,11 +40,12 @@
#ifndef QT3DCORE_QNODE_H
#define QT3DCORE_QNODE_H
-#include <QObject>
-#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qnodecommand.h>
#include <Qt3DCore/qscenechange.h>
-#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QObject>
#define Q_NODE_NULLPTR static_cast<Qt3DCore::QNode *>(nullptr)
@@ -69,16 +70,15 @@ class QT3DCORESHARED_EXPORT QNode : public QObject
Q_OBJECT
Q_PROPERTY(Qt3DCore::QNode *parent READ parentNode WRITE setParent NOTIFY parentChanged)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
- Q_PROPERTY(PropertyTrackMode propertyTrackMode READ propertyTrackMode WRITE setPropertyTrackMode NOTIFY propertyUpdateModeChanged)
- Q_PROPERTY(QStringList trackedProperties READ trackedProperties WRITE setTrackedProperties NOTIFY trackedPropertiesChanged)
+ Q_PROPERTY(PropertyTrackingMode defaultPropertyTrackingMode READ defaultPropertyTrackingMode WRITE setDefaultPropertyTrackingMode NOTIFY defaultPropertyTrackingModeChanged REVISION 9)
public:
- enum PropertyTrackMode {
- DefaultTrackMode,
- TrackNamedPropertiesMode,
- TrackAllPropertiesMode
+ enum PropertyTrackingMode : quint16 {
+ TrackFinalValues,
+ DontTrackValues,
+ TrackAllValues
};
- Q_ENUM(PropertyTrackMode)
+ Q_ENUM(PropertyTrackingMode)
explicit QNode(QNode *parent = nullptr);
virtual ~QNode();
@@ -92,20 +92,26 @@ public:
QNodeVector childNodes() const;
bool isEnabled() const;
- PropertyTrackMode propertyTrackMode() const;
- QStringList trackedProperties() const;
+ PropertyTrackingMode defaultPropertyTrackingMode() const;
+
+ void setPropertyTracking(const QString &propertyName, PropertyTrackingMode trackMode);
+ PropertyTrackingMode propertyTracking(const QString &propertyName) const;
+ void clearPropertyTracking(const QString &propertyName);
+ void clearPropertyTrackings();
+
+ QNodeCommand::CommandId sendCommand(const QString &name, const QVariant &data = QVariant(),
+ QNodeCommand::CommandId replyTo = QNodeCommand::CommandId());
+ void sendReply(const QNodeCommandPtr &command);
public Q_SLOTS:
void setParent(QNode *parent);
void setEnabled(bool isEnabled);
- void setPropertyTrackMode(PropertyTrackMode mode);
- void setTrackedProperties(const QStringList &trackedProperties);
+ void setDefaultPropertyTrackingMode(PropertyTrackingMode mode);
Q_SIGNALS:
void parentChanged(QObject *parent);
void enabledChanged(bool enabled);
- void propertyUpdateModeChanged(PropertyTrackMode mode);
- void trackedPropertiesChanged(const QStringList &trackedProperties);
+ void defaultPropertyTrackingModeChanged(PropertyTrackingMode mode);
void nodeDestroyed();
protected:
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index 5d6329e62..ad9d2376e 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -51,13 +51,15 @@
// We mean it.
//
-#include <private/qobject_p.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DCore/private/qobservableinterface_p.h>
+
+#include <functional>
+
+#include <Qt3DCore/private/propertychangehandler_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
+#include <Qt3DCore/private/qobservableinterface_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include "propertychangehandler_p.h"
-#include <functional>
+#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -74,7 +76,7 @@ public:
void init(QNode *parent);
- void setScene(QScene *scene);
+ virtual void setScene(QScene *scene);
QScene *scene() const;
void setArbiter(QLockableObserverInterface *arbiter) Q_DECL_OVERRIDE;
@@ -98,8 +100,8 @@ public:
bool m_blockNotifications;
bool m_hasBackendNode;
bool m_enabled;
- QNode::PropertyTrackMode m_propertyTrackMode;
- QStringList m_trackedProperties;
+ QNode::PropertyTrackingMode m_defaultPropertyTrackMode;
+ QHash<QString, QNode::PropertyTrackingMode> m_trackedPropertiesOverrides;
static QNodePrivate *get(QNode *q);
static void nodePtrDeleter(QNode *q);
diff --git a/src/core/nodes/qnodecreatedchangegenerator.cpp b/src/core/nodes/qnodecreatedchangegenerator.cpp
index c350c866a..d91949fb1 100644
--- a/src/core/nodes/qnodecreatedchangegenerator.cpp
+++ b/src/core/nodes/qnodecreatedchangegenerator.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include "qnodecreatedchangegenerator_p.h"
+
#include <Qt3DCore/private/qnodevisitor_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qnodecreatedchangegenerator_p.h b/src/core/nodes/qnodecreatedchangegenerator_p.h
index f00241b39..42c2847cc 100644
--- a/src/core/nodes/qnodecreatedchangegenerator_p.h
+++ b/src/core/nodes/qnodecreatedchangegenerator_p.h
@@ -48,12 +48,13 @@
// We mean it.
//
-#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/qnode.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/qt3dcore_global.h>
#include <QtCore/qvector.h>
+#include <Qt3DCore/private/qnode_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/nodes/qnodeid.cpp b/src/core/nodes/qnodeid.cpp
index f41627734..17bc4e8e1 100644
--- a/src/core/nodes/qnodeid.cpp
+++ b/src/core/nodes/qnodeid.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qnodeid.h"
+#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qnodeid.h b/src/core/nodes/qnodeid.h
index 7e8b1c97c..a00559df3 100644
--- a/src/core/nodes/qnodeid.h
+++ b/src/core/nodes/qnodeid.h
@@ -41,7 +41,7 @@
#define QT3DCORE_QNODEID_H
#include <Qt3DCore/qt3dcore_global.h>
-#include <QDebug>
+#include <QtCore/QDebug>
#include <QtCore/QHashFunctions>
QT_BEGIN_NAMESPACE
diff --git a/src/core/nodes/qnodevisitor_p.h b/src/core/nodes/qnodevisitor_p.h
index 3637293f5..15bfa90db 100644
--- a/src/core/nodes/qnodevisitor_p.h
+++ b/src/core/nodes/qnodevisitor_p.h
@@ -51,9 +51,9 @@
// We mean it.
//
-#include <Qt3DCore/qt3dcore_global.h>
-#include <Qt3DCore/qnode.h>
#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/qt3dcore_global.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/qbackendnodefactory_p.h b/src/core/qbackendnodefactory_p.h
index 9f2afb16d..46e68266f 100644
--- a/src/core/qbackendnodefactory_p.h
+++ b/src/core/qbackendnodefactory_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp
index a7ca3ed40..d6c7e05df 100644
--- a/src/core/qchangearbiter.cpp
+++ b/src/core/qchangearbiter.cpp
@@ -38,17 +38,18 @@
****************************************************************************/
#include "qchangearbiter_p.h"
-#include "qcomponent.h"
-#include "qabstractaspectjobmanager_p.h"
-#include "qsceneobserverinterface_p.h"
-#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/qcomponent.h>
+#include <QtCore/QMutexLocker>
+#include <QtCore/QReadLocker>
+#include <QtCore/QThread>
+#include <QtCore/QWriteLocker>
+
#include <Qt3DCore/private/corelogging_p.h>
-#include <QMutexLocker>
-#include <QReadLocker>
-#include <QThread>
-#include <QWriteLocker>
-#include <private/qpostman_p.h>
+#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
+#include <Qt3DCore/private/qpostman_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qsceneobserverinterface_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h
index e381abc65..54ef6a207 100644
--- a/src/core/qchangearbiter_p.h
+++ b/src/core/qchangearbiter_p.h
@@ -51,16 +51,17 @@
// We mean it.
//
-#include <QObject>
-#include <QFlags>
-#include <QReadWriteLock>
-#include <QVariant>
-#include <QVector>
-#include <QPair>
-#include <QThreadStorage>
-#include <QMutex>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DCore/qscenechange.h>
+#include <QtCore/QFlags>
+#include <QtCore/QMutex>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/QThreadStorage>
+#include <QtCore/QVariant>
+#include <QtCore/QVector>
+
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
diff --git a/src/core/qobservableinterface_p.h b/src/core/qobservableinterface_p.h
index e867f1b84..8b92168ff 100644
--- a/src/core/qobservableinterface_p.h
+++ b/src/core/qobservableinterface_p.h
@@ -52,7 +52,8 @@
//
#include <Qt3DCore/qscenechange.h>
-#include <private/qt3dcore_global_p.h>
+
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/qpostman.cpp b/src/core/qpostman.cpp
index 2b8e6c3a8..9fd8f9104 100644
--- a/src/core/qpostman.cpp
+++ b/src/core/qpostman.cpp
@@ -39,12 +39,15 @@
#include "qpostman_p.h"
#include "qpostman_p_p.h"
+
+#include <Qt3DCore/qnode.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qscene_p.h>
+
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
-#include <Qt3DCore/qnode.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -116,17 +119,25 @@ bool QPostman::shouldNotifyFrontend(const QSceneChangePtr &e)
Q_D(QPostman);
const QPropertyUpdatedChangePtr propertyChange = qSharedPointerDynamicCast<QPropertyUpdatedChange>(e);
if (Q_LIKELY(d->m_scene != nullptr) && !propertyChange.isNull()) {
- const bool isFinal = QPropertyUpdatedChangeBasePrivate::get(propertyChange.data())->m_isFinal;
- if (isFinal)
- return true;
- const QScene::NodePropertyTrackData propertyTrackData = d->m_scene->lookupNodePropertyTrackData(e->subjectId());
- switch (propertyTrackData.updateMode) {
- case QNode::TrackAllPropertiesMode:
+ const QScene::NodePropertyTrackData propertyTrackData
+ = d->m_scene->lookupNodePropertyTrackData(e->subjectId());
+
+ const QNode::PropertyTrackingMode trackMode = propertyTrackData.trackedPropertiesOverrides.value(QLatin1String(propertyChange->propertyName()),
+ propertyTrackData.defaultTrackMode);
+
+ switch (trackMode) {
+ case QNode::TrackAllValues:
return true;
- case QNode::TrackNamedPropertiesMode:
- return propertyTrackData.namedProperties.contains(QLatin1String(propertyChange->propertyName()));
- case QNode::DefaultTrackMode:
+
+ case QNode::DontTrackValues:
return false;
+
+ case QNode::TrackFinalValues: {
+ const bool isIntermediate
+ = QPropertyUpdatedChangeBasePrivate::get(propertyChange.data())->m_isIntermediate;
+ return !isIntermediate;
+ }
+
default:
Q_UNREACHABLE();
return false;
diff --git a/src/core/qscene.cpp b/src/core/qscene.cpp
index 972659131..b5895c7aa 100644
--- a/src/core/qscene.cpp
+++ b/src/core/qscene.cpp
@@ -38,12 +38,14 @@
****************************************************************************/
#include "qscene_p.h"
-#include <QHash>
-#include <QReadLocker>
+
#include <Qt3DCore/qnode.h>
+#include <QtCore/QHash>
+#include <QtCore/QReadLocker>
+
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
-#include <Qt3DCore/private/qobservableinterface_p.h>
#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qobservableinterface_p.h>
QT_BEGIN_NAMESPACE
@@ -55,6 +57,7 @@ public:
QScenePrivate(QAspectEngine *engine)
: m_engine(engine)
, m_arbiter(nullptr)
+ , m_rootNode(nullptr)
{
}
@@ -67,6 +70,7 @@ public:
QLockableObserverInterface *m_arbiter;
mutable QReadWriteLock m_lock;
mutable QReadWriteLock m_nodePropertyTrackModeLock;
+ QNode *m_rootNode;
};
@@ -171,6 +175,12 @@ QNodeId QScene::nodeIdFromObservable(QObservableInterface *observable) const
return d->m_observableToUuid.value(observable);
}
+QNode *QScene::rootNode() const
+{
+ Q_D(const QScene);
+ return d->m_rootNode;
+}
+
void QScene::setArbiter(QLockableObserverInterface *arbiter)
{
Q_D(QScene);
@@ -212,7 +222,8 @@ bool QScene::hasEntityForComponent(QNodeId componentUuid, QNodeId entityUuid)
{
Q_D(QScene);
QReadLocker lock(&d->m_lock);
- return d->m_componentToEntities.values(componentUuid).contains(entityUuid);
+ const auto range = d->m_componentToEntities.equal_range(componentUuid);
+ return std::find(range.first, range.second, entityUuid) != range.second;
}
QScene::NodePropertyTrackData QScene::lookupNodePropertyTrackData(QNodeId id) const
@@ -236,6 +247,12 @@ void QScene::removePropertyTrackDataForNode(QNodeId nodeId)
d->m_nodePropertyTrackModeLookupTable.remove(nodeId);
}
+void QScene::setRootNode(QNode *root)
+{
+ Q_D(QScene);
+ d->m_rootNode = root;
+}
+
} // Qt3D
QT_END_NAMESPACE
diff --git a/src/core/qscene_p.h b/src/core/qscene_p.h
index 1a313c249..aaa8d9e92 100644
--- a/src/core/qscene_p.h
+++ b/src/core/qscene_p.h
@@ -51,10 +51,12 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
-#include <Qt3DCore/private/qobservableinterface_p.h>
+#include <QtCore/QScopedPointer>
+
#include <Qt3DCore/qnode.h>
-#include <QScopedPointer>
+#include <QtCore/qscopedpointer.h>
+#include <Qt3DCore/private/qobservableinterface_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
@@ -83,6 +85,8 @@ public:
QVector<QNode *> lookupNodes(const QVector<QNodeId> &ids) const;
QNodeId nodeIdFromObservable(QObservableInterface *observable) const;
+ QNode *rootNode() const;
+
void setArbiter(Qt3DCore::QLockableObserverInterface *arbiter);
Qt3DCore::QLockableObserverInterface *arbiter() const;
@@ -95,8 +99,8 @@ public:
// Node -> Property Update Data
struct NodePropertyTrackData
{
- QNode::PropertyTrackMode updateMode = QNode::DefaultTrackMode;
- QStringList namedProperties;
+ QNode::PropertyTrackingMode defaultTrackMode = QNode::TrackFinalValues;
+ QHash<QString, QNode::PropertyTrackingMode> trackedPropertiesOverrides;
};
NodePropertyTrackData lookupNodePropertyTrackData(QNodeId id) const;
void setPropertyTrackDataForNode(QNodeId id, const NodePropertyTrackData &data);
@@ -105,6 +109,9 @@ public:
private:
Q_DECLARE_PRIVATE(QScene)
QScopedPointer<QScenePrivate> d_ptr;
+
+ void setRootNode(QNode *root);
+ friend class QAspectEnginePrivate;
};
} // Qt3D
diff --git a/src/core/qsceneobserverinterface_p.h b/src/core/qsceneobserverinterface_p.h
index 77b1c3626..f183ab571 100644
--- a/src/core/qsceneobserverinterface_p.h
+++ b/src/core/qsceneobserverinterface_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/qscenechange.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/qscheduler.cpp b/src/core/qscheduler.cpp
index 1df6d2607..cc2f9081e 100644
--- a/src/core/qscheduler.cpp
+++ b/src/core/qscheduler.cpp
@@ -39,10 +39,11 @@
#include "qscheduler_p.h"
-#include "qabstractaspect.h"
-#include "qabstractaspect_p.h"
-#include "qaspectmanager_p.h"
-#include "qabstractaspectjobmanager_p.h"
+#include <Qt3DCore/qabstractaspect.h>
+
+#include <Qt3DCore/private/qabstractaspect_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -50,6 +51,7 @@ namespace Qt3DCore {
QScheduler::QScheduler(QObject *parent)
: QObject(parent)
+ , m_aspectManager(nullptr)
{
}
diff --git a/src/core/qscheduler_p.h b/src/core/qscheduler_p.h
index 9d0f99ccb..9b1685e54 100644
--- a/src/core/qscheduler_p.h
+++ b/src/core/qscheduler_p.h
@@ -40,8 +40,8 @@
#ifndef QT3DCORE_QSCHEDULER_P_H
#define QT3DCORE_QSCHEDULER_P_H
-#include <QObject>
#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QObject>
//
// W A R N I N G
diff --git a/src/core/qtickclock.cpp b/src/core/qtickclock.cpp
index 4dfb29f1b..38ed07925 100644
--- a/src/core/qtickclock.cpp
+++ b/src/core/qtickclock.cpp
@@ -39,8 +39,9 @@
#include "qtickclock_p.h"
+#include <QtCore/QThread>
+
#include <Qt3DCore/private/corelogging_p.h>
-#include <QThread>
QT_BEGIN_NAMESPACE
diff --git a/src/core/qtickclock_p.h b/src/core/qtickclock_p.h
index b19417173..2b6686745 100644
--- a/src/core/qtickclock_p.h
+++ b/src/core/qtickclock_p.h
@@ -52,8 +52,7 @@
//
#include <Qt3DCore/qt3dcore_global.h>
-
-#include <QElapsedTimer>
+#include <QtCore/QElapsedTimer>
QT_BEGIN_NAMESPACE
diff --git a/src/core/resources/qboundedcircularbuffer_p.h b/src/core/resources/qboundedcircularbuffer_p.h
index f879a4a6f..22299d7da 100644
--- a/src/core/resources/qboundedcircularbuffer_p.h
+++ b/src/core/resources/qboundedcircularbuffer_p.h
@@ -51,12 +51,12 @@
// We mean it.
//
-#include <Qt3DCore/private/qcircularbuffer_p.h>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/QReadLocker>
+#include <QtCore/QSemaphore>
+#include <QtCore/QtGlobal>
-#include <QReadWriteLock>
-#include <QReadLocker>
-#include <QSemaphore>
-#include <QtGlobal>
+#include <Qt3DCore/private/qcircularbuffer_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/resources/qcircularbuffer_p.h b/src/core/resources/qcircularbuffer_p.h
index 08665f4b5..e10b7236d 100644
--- a/src/core/resources/qcircularbuffer_p.h
+++ b/src/core/resources/qcircularbuffer_p.h
@@ -51,21 +51,23 @@
// We mean it.
//
+#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QtGlobal>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qvector.h>
#include <algorithm>
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-# include <initializer_list>
-#endif
#include <iterator>
#include <limits>
#include <memory>
#include <new>
-#include <QtGlobal>
-#include <Qt3DCore/qt3dcore_global.h>
+
+
+#ifdef Q_COMPILER_INITIALIZER_LISTS
+# include <initializer_list>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/core/resources/qframeallocator_p.h b/src/core/resources/qframeallocator_p.h
index cd0fa504c..b3ded0760 100644
--- a/src/core/resources/qframeallocator_p.h
+++ b/src/core/resources/qframeallocator_p.h
@@ -56,9 +56,10 @@
#include <valgrind/memcheck.h>
#endif
-#include <QDebug>
-#include <QScopedPointer>
-#include <QVector>
+#include <QtCore/QDebug>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QVector>
+
#include <Qt3DCore/private/qt3dcore_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/resources/qhandlemanager_p.h b/src/core/resources/qhandlemanager_p.h
index b41fc75b1..0c3609bb9 100644
--- a/src/core/resources/qhandlemanager_p.h
+++ b/src/core/resources/qhandlemanager_p.h
@@ -51,12 +51,12 @@
// We mean it.
//
-#include <QtGlobal>
#include <Qt3DCore/qt3dcore_global.h>
-#include "qhandle_p.h"
-
+#include <QtCore/QtGlobal>
#include <QtCore/QVector>
+#include <Qt3DCore/private/qhandle_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/resources/qresourcemanager_p.h b/src/core/resources/qresourcemanager_p.h
index 1b79434fd..8ddc1c0a4 100644
--- a/src/core/resources/qresourcemanager_p.h
+++ b/src/core/resources/qresourcemanager_p.h
@@ -51,14 +51,15 @@
// We mean it.
//
-#include <QtGlobal>
-#include <QReadWriteLock>
-#include <QReadLocker>
-#include <QMutex>
-#include <QHash>
#include <Qt3DCore/qt3dcore_global.h>
-#include "qhandle_p.h"
-#include "qhandlemanager_p.h"
+#include <QtCore/QHash>
+#include <QtCore/QMutex>
+#include <QtCore/QReadLocker>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/QtGlobal>
+
+#include <Qt3DCore/private/qhandle_p.h>
+#include <Qt3DCore/private/qhandlemanager_p.h>
// Silence complaints about unreferenced local variables in
// ArrayAllocatingPolicy::deallocateBuckets() when the compiler
diff --git a/src/core/services/nullservices_p.h b/src/core/services/nullservices_p.h
index ed7bd3a39..f75c6abc1 100644
--- a/src/core/services/nullservices_p.h
+++ b/src/core/services/nullservices_p.h
@@ -52,8 +52,9 @@
//
#include <Qt3DCore/qt3dcore_global.h>
-#include "qopenglinformationservice_p.h"
-#include "qsysteminformationservice_p.h"
+
+#include <Qt3DCore/private/qopenglinformationservice_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/services/qabstractframeadvanceservice_p.h b/src/core/services/qabstractframeadvanceservice_p.h
index 2dde68f06..dac72a98d 100644
--- a/src/core/services/qabstractframeadvanceservice_p.h
+++ b/src/core/services/qabstractframeadvanceservice_p.h
@@ -52,8 +52,9 @@
//
#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QString>
+
#include <Qt3DCore/private/qservicelocator_p.h>
-#include <QString>
QT_BEGIN_NAMESPACE
@@ -63,6 +64,7 @@ class QAbstractFrameAdvanceServicePrivate;
class QT3DCORESHARED_EXPORT QAbstractFrameAdvanceService : public QAbstractServiceProvider
{
+ Q_OBJECT
public:
virtual qint64 waitForNextFrame() = 0;
virtual void start() = 0;
diff --git a/src/core/services/qabstractframeadvanceservice_p_p.h b/src/core/services/qabstractframeadvanceservice_p_p.h
index d73ca3116..c49586b8f 100644
--- a/src/core/services/qabstractframeadvanceservice_p_p.h
+++ b/src/core/services/qabstractframeadvanceservice_p_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qt3dcore_global.h>
+
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
diff --git a/src/core/services/qabstractserviceprovider_p.h b/src/core/services/qabstractserviceprovider_p.h
index 2913cee31..cef6ef034 100644
--- a/src/core/services/qabstractserviceprovider_p.h
+++ b/src/core/services/qabstractserviceprovider_p.h
@@ -51,23 +51,26 @@
// We mean it.
//
+#include <QtCore/private/qobject_p.h>
#include <Qt3DCore/qt3dcore_global.h>
#include <QtCore/qstring.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QAbstractServiceProviderPrivate
+class QAbstractServiceProviderPrivate : public QObjectPrivate
{
public:
- QAbstractServiceProviderPrivate(int type, const QString &description = QString())
- : m_type(type)
+ explicit QAbstractServiceProviderPrivate(int type, const QString &description = QString())
+ : QObjectPrivate()
+ , m_type(type)
, m_description(description)
{}
Q_DECLARE_PUBLIC(QAbstractServiceProvider)
- QAbstractServiceProvider *q_ptr;
int m_type;
QString m_description;
diff --git a/src/core/services/qdownloadhelperservice.cpp b/src/core/services/qdownloadhelperservice.cpp
new file mode 100644
index 000000000..231e9172b
--- /dev/null
+++ b/src/core/services/qdownloadhelperservice.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdownloadhelperservice_p.h"
+#include "qdownloadnetworkworker_p.h"
+#include <Qt3DCore/QAspectEngine>
+#include <Qt3DCore/private/qabstractserviceprovider_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectthread_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+QDownloadRequest::QDownloadRequest(const QUrl &url)
+ : m_url(url)
+ , m_succeeded(false)
+ , m_cancelled(false)
+{
+
+}
+
+QDownloadRequest::~QDownloadRequest()
+{
+
+}
+
+void QDownloadRequest::onDownloaded()
+{
+ // this is called in dl thread. It's an opportunity to do long running tasks
+ // like loading the data into a QImage
+}
+
+
+class Q_AUTOTEST_EXPORT QDownloadHelperServicePrivate : public QAbstractServiceProviderPrivate
+{
+public:
+ explicit QDownloadHelperServicePrivate(const QString &description);
+ ~QDownloadHelperServicePrivate();
+
+ void init();
+ void shutdown();
+ void _q_onRequestCompleted(const QDownloadRequestPtr &request);
+
+ Q_DECLARE_PUBLIC(QDownloadHelperService)
+
+ QThread *m_downloadThread;
+ QDownloadNetworkWorker *m_downloadWorker;
+};
+
+
+QDownloadHelperServicePrivate::QDownloadHelperServicePrivate(const QString &description)
+ : QAbstractServiceProviderPrivate(QServiceLocator::DownloadHelperService, description)
+ , m_downloadThread(nullptr)
+ , m_downloadWorker(nullptr)
+{
+}
+
+QDownloadHelperServicePrivate::~QDownloadHelperServicePrivate()
+{
+}
+
+void QDownloadHelperServicePrivate::init()
+{
+ Q_Q(QDownloadHelperService);
+ m_downloadThread = new QThread(q);
+ m_downloadWorker = new QDownloadNetworkWorker;
+ m_downloadWorker->moveToThread(m_downloadThread);
+ QObject::connect(m_downloadWorker, SIGNAL(requestDownloaded(const Qt3DCore::QDownloadRequestPtr &)),
+ q, SLOT(_q_onRequestCompleted(const Qt3DCore::QDownloadRequestPtr &)));
+ m_downloadThread->start();
+}
+
+void QDownloadHelperServicePrivate::shutdown()
+{
+ m_downloadWorker->cancelAllRequests();
+ m_downloadThread->exit();
+ m_downloadThread->wait();
+ m_downloadWorker->deleteLater();
+}
+
+void QDownloadHelperServicePrivate::_q_onRequestCompleted(const Qt3DCore::QDownloadRequestPtr &request)
+{
+ request->onCompleted();
+}
+
+
+QDownloadHelperService::QDownloadHelperService(const QString &description)
+ : QAbstractServiceProvider(*new QDownloadHelperServicePrivate(description))
+{
+ Q_D(QDownloadHelperService);
+ d->init();
+ qRegisterMetaType<Qt3DCore::QDownloadRequestPtr>();
+}
+
+QDownloadHelperService::~QDownloadHelperService()
+{
+ Q_D(QDownloadHelperService);
+ d->shutdown();
+}
+
+void QDownloadHelperService::submitRequest(const Qt3DCore::QDownloadRequestPtr &request)
+{
+ Q_D(QDownloadHelperService);
+
+ if (isLocal(request->url())) {
+ QFile file(urlToLocalFileOrQrc(request->url()));
+ if (file.open(QIODevice::ReadOnly)) {
+ request->m_data = file.readAll();
+ file.close();
+ request->m_succeeded = true;
+ } else {
+ request->m_succeeded = false;
+ }
+ request->onCompleted();
+ } else {
+ emit d->m_downloadWorker->submitRequest(request);
+ }
+}
+
+void QDownloadHelperService::cancelRequest(const Qt3DCore::QDownloadRequestPtr &request)
+{
+ Q_D(QDownloadHelperService);
+ request->m_cancelled = true;
+ emit d->m_downloadWorker->cancelRequest(request);
+}
+
+void QDownloadHelperService::cancelAllRequests()
+{
+ Q_D(QDownloadHelperService);
+ emit d->m_downloadWorker->cancelAllRequests();
+}
+
+QString QDownloadHelperService::urlToLocalFileOrQrc(const QUrl &url)
+{
+ const QString scheme(url.scheme().toLower());
+ if (scheme == QLatin1String("qrc")) {
+ if (url.authority().isEmpty())
+ return QLatin1Char(':') + url.path();
+ return QString();
+ }
+
+#if defined(Q_OS_ANDROID)
+ if (scheme == QLatin1String("assets")) {
+ if (url.authority().isEmpty())
+ return url.toString();
+ return QString();
+ }
+#endif
+
+ return url.toLocalFile();
+}
+
+QDownloadHelperService *QDownloadHelperService::getService(QAspectEngine *engine)
+{
+ auto enginePrivate = Qt3DCore::QAspectEnginePrivate::get(engine);
+ return enginePrivate->m_aspectThread->aspectManager()->serviceLocator()->downloadHelperService();
+}
+
+bool QDownloadHelperService::isLocal(const QUrl &url)
+{
+ const QString scheme(url.scheme().toLower());
+ if (scheme == QLatin1String("file") || scheme == QLatin1String("qrc"))
+ return true;
+#if defined(Q_OS_ANDROID)
+ if (scheme == QLatin1String("assets"))
+ return true;
+#endif
+ return false;
+}
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#include "moc_qdownloadhelperservice_p.cpp"
diff --git a/src/core/services/qdownloadhelperservice_p.h b/src/core/services/qdownloadhelperservice_p.h
new file mode 100644
index 000000000..780ed4806
--- /dev/null
+++ b/src/core/services/qdownloadhelperservice_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QDOWNLOADHELPERSERVICE_P_H
+#define QT3DCORE_QDOWNLOADHELPERSERVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QSharedPointer>
+#include <QObject>
+#include <QUrl>
+
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QThread;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+namespace Qt3DCore {
+
+class QAspectEngine;
+class QDownloadNetworkWorker;
+class QDownloadHelperService;
+class QDownloadHelperServicePrivate;
+
+class QT3DCORESHARED_EXPORT QDownloadRequest
+{
+public:
+ QDownloadRequest(const QUrl &url);
+ virtual ~QDownloadRequest();
+
+ QUrl url() const { return m_url; }
+ bool succeeded() const { return m_succeeded; }
+ bool cancelled() const { return m_cancelled; }
+
+ virtual void onDownloaded(); // this is called in dl thread
+ virtual void onCompleted() = 0; // this is called in job thread
+
+protected:
+ QUrl m_url;
+ QByteArray m_data;
+
+private:
+ friend class QDownloadNetworkWorker;
+ friend class QDownloadHelperService;
+ bool m_succeeded;
+ bool m_cancelled;
+};
+
+typedef QSharedPointer<QDownloadRequest> QDownloadRequestPtr;
+
+
+class QT3DCORESHARED_EXPORT QDownloadHelperService : public QAbstractServiceProvider
+{
+ Q_OBJECT
+public:
+ explicit QDownloadHelperService(const QString &description = QString());
+ ~QDownloadHelperService();
+
+ void submitRequest(const QDownloadRequestPtr &request);
+ void cancelRequest(const QDownloadRequestPtr &request);
+ void cancelAllRequests();
+
+ static QString urlToLocalFileOrQrc(const QUrl &url);
+ static bool isLocal(const QUrl &url);
+ static QDownloadHelperService *getService(QAspectEngine *engine);
+
+private:
+ Q_DECLARE_PRIVATE(QDownloadHelperService)
+ Q_PRIVATE_SLOT(d_func(), void _q_onRequestCompleted(const Qt3DCore::QDownloadRequestPtr &))
+};
+
+typedef QSharedPointer<QDownloadHelperService> QDownloadHelperServicePtr;
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DCore::QDownloadRequestPtr) // LCOV_EXCL_LINE
+
+#endif // QT3DCORE_QDOWNLOADHELPERSERVICE_P_H
diff --git a/src/core/services/qdownloadhelperservice_p_p.h b/src/core/services/qdownloadhelperservice_p_p.h
new file mode 100644
index 000000000..202ae5236
--- /dev/null
+++ b/src/core/services/qdownloadhelperservice_p_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Paul Lemire
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QDOWNLOADHELPERSERVICE_P_P_H
+#define QT3DCORE_QDOWNLOADHELPERSERVICE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QSharedPointer>
+#include <QObject>
+#include <QUrl>
+
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
+#include <Qt3DCore/private/qabstractserviceprovider_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QThread;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+namespace Qt3DCore {
+
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QDOWNLOADHELPERSERVICE_P_P_H
diff --git a/src/core/services/qdownloadnetworkworker.cpp b/src/core/services/qdownloadnetworkworker.cpp
new file mode 100644
index 000000000..c728a1779
--- /dev/null
+++ b/src/core/services/qdownloadnetworkworker.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdownloadhelperservice_p.h"
+#include "qdownloadnetworkworker_p.h"
+
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QDataStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+QDownloadNetworkWorker::QDownloadNetworkWorker(QObject *parent)
+ : QObject(parent)
+ , m_networkManager(nullptr)
+{
+ connect(this, &QDownloadNetworkWorker::submitRequest,
+ this, &QDownloadNetworkWorker::onRequestSubmited);
+ connect(this, &QDownloadNetworkWorker::cancelRequest,
+ this, &QDownloadNetworkWorker::onRequestCancelled);
+ connect(this, &QDownloadNetworkWorker::cancelAllRequests,
+ this, &QDownloadNetworkWorker::onAllRequestsCancelled);
+}
+
+void QDownloadNetworkWorker::onRequestSubmited(const QDownloadRequestPtr &request)
+{
+ QMutexLocker l(&m_mutex);
+ if (!m_networkManager) {
+ m_networkManager = new QNetworkAccessManager(this);
+ connect(m_networkManager, &QNetworkAccessManager::finished,
+ this, &QDownloadNetworkWorker::onRequestFinished);
+ }
+ auto reply = m_networkManager->get(QNetworkRequest(request->url()));
+ m_requests << QPair<QDownloadRequestPtr, QNetworkReply *>(request, reply);
+ connect(reply, &QNetworkReply::downloadProgress, this, &QDownloadNetworkWorker::onDownloadProgressed);
+}
+
+void QDownloadNetworkWorker::onRequestCancelled(const QDownloadRequestPtr &request)
+{
+ QMutexLocker l(&m_mutex);
+ auto it = std::find_if(m_requests.begin(), m_requests.end(),
+ [request](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
+ return e.first == request;
+ });
+ if (it == m_requests.end())
+ return;
+
+ (*it).first->m_cancelled = true;
+ (*it).second->abort();
+}
+
+void QDownloadNetworkWorker::onAllRequestsCancelled()
+{
+ QMutexLocker l(&m_mutex);
+ for (auto e: qAsConst(m_requests)) {
+ e.first->m_cancelled = true;
+ e.second->abort();
+ }
+ m_requests.clear();
+}
+
+void QDownloadNetworkWorker::onRequestFinished(QNetworkReply *reply)
+{
+ QMutexLocker l(&m_mutex);
+ auto it = std::find_if(m_requests.begin(), m_requests.end(),
+ [reply](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
+ return e.second == reply;
+ });
+ if (it == m_requests.end())
+ return;
+
+ auto request = (*it).first;
+ if (reply->error() == QNetworkReply::NoError) {
+ request->m_succeeded = true;
+ }
+ request->onDownloaded();
+ emit requestDownloaded(request);
+
+ m_requests.erase(it);
+}
+
+void QDownloadNetworkWorker::onDownloadProgressed(qint64 bytesReceived, qint64 bytesTotal)
+{
+ Q_UNUSED(bytesReceived);
+ Q_UNUSED(bytesTotal);
+ // TODO forward progress details somewhere
+
+ QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
+ if (!reply)
+ return;
+
+ QMutexLocker l(&m_mutex);
+ auto it = std::find_if(m_requests.begin(), m_requests.end(),
+ [reply](QPair<QDownloadRequestPtr, QNetworkReply *> e) {
+ return e.second == reply;
+ });
+ if (it == m_requests.end())
+ return;
+
+ auto request = (*it).first;
+ QDataStream stream(&request->m_data, QIODevice::Append);
+ QByteArray data = reply->readAll();
+ stream.writeRawData(data.data(), data.size());
+}
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
diff --git a/src/core/services/qdownloadnetworkworker_p.h b/src/core/services/qdownloadnetworkworker_p.h
new file mode 100644
index 000000000..faecbca2f
--- /dev/null
+++ b/src/core/services/qdownloadnetworkworker_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QDOWNLOADNETWORKWORKER_P_H
+#define QT3DCORE_QDOWNLOADNETWORKWORKER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QSharedPointer>
+#include <QObject>
+#include <QUrl>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
+#include <QMutex>
+
+QT_BEGIN_NAMESPACE
+
+class QThread;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+namespace Qt3DCore {
+
+class QDownloadRequest;
+typedef QSharedPointer<QDownloadRequest> QDownloadRequestPtr;
+
+class QDownloadNetworkWorker : public QObject
+{
+ Q_OBJECT
+public:
+ QDownloadNetworkWorker(QObject *parent = nullptr);
+
+signals:
+ void submitRequest(const Qt3DCore::QDownloadRequestPtr &request);
+ void cancelRequest(const Qt3DCore::QDownloadRequestPtr &request);
+ void cancelAllRequests();
+
+ void requestDownloaded(const Qt3DCore::QDownloadRequestPtr &request);
+
+private Q_SLOTS:
+ void onRequestSubmited(const Qt3DCore::QDownloadRequestPtr &request);
+ void onRequestCancelled(const Qt3DCore::QDownloadRequestPtr &request);
+ void onAllRequestsCancelled();
+ void onRequestFinished(QNetworkReply *reply);
+ void onDownloadProgressed(qint64 bytesReceived, qint64 bytesTotal);
+
+private:
+ QNetworkAccessManager *m_networkManager;
+ QVector< QPair<QDownloadRequestPtr, QNetworkReply *> > m_requests;
+ QMutex m_mutex;
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QDOWNLOADNETWORKWORKER_P_H
diff --git a/src/core/services/qeventfilterservice.cpp b/src/core/services/qeventfilterservice.cpp
index 489ab9b45..6584c5e24 100644
--- a/src/core/services/qeventfilterservice.cpp
+++ b/src/core/services/qeventfilterservice.cpp
@@ -38,10 +38,12 @@
****************************************************************************/
#include "qeventfilterservice_p.h"
-#include "qabstractserviceprovider_p.h"
-#include <QMap>
-#include <QObject>
-#include <QVector>
+
+#include <QtCore/QMap>
+#include <QtCore/QObject>
+#include <QtCore/QVector>
+
+#include <Qt3DCore/private/qabstractserviceprovider_p.h>
QT_BEGIN_NAMESPACE
@@ -83,6 +85,8 @@ public:
: QAbstractServiceProviderPrivate(QServiceLocator::EventFilterService, QStringLiteral("Default event filter service implementation"))
{}
+ Q_DECLARE_PUBLIC(QEventFilterService)
+
void registerEventFilter(QObject *eventFilter, int priority)
{
for (int i = 0, m = m_eventFilters.size(); i < m; ++i)
diff --git a/src/core/services/qeventfilterservice_p.h b/src/core/services/qeventfilterservice_p.h
index 4962e2af6..58b87d9cc 100644
--- a/src/core/services/qeventfilterservice_p.h
+++ b/src/core/services/qeventfilterservice_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qt3dcore_global.h>
+
#include <Qt3DCore/private/qservicelocator_p.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +63,7 @@ class QEventFilterServicePrivate;
class QT3DCORESHARED_EXPORT QEventFilterService : public QAbstractServiceProvider
{
+ Q_OBJECT
public:
QEventFilterService();
~QEventFilterService();
diff --git a/src/core/services/qopenglinformationservice.cpp b/src/core/services/qopenglinformationservice.cpp
index 0f62544c8..c1c05018e 100644
--- a/src/core/services/qopenglinformationservice.cpp
+++ b/src/core/services/qopenglinformationservice.cpp
@@ -62,7 +62,7 @@ namespace Qt3DCore {
instantiate a QOpenGLInformationService object.
*/
QOpenGLInformationService::QOpenGLInformationService(const QString &description)
- : QAbstractServiceProvider(QServiceLocator::OpenGLInformation, description)
+ : QAbstractServiceProvider(*new QOpenGLInformationServicePrivate(description))
{
}
diff --git a/src/core/services/qopenglinformationservice_p.h b/src/core/services/qopenglinformationservice_p.h
index a2c37c29a..2adf73307 100644
--- a/src/core/services/qopenglinformationservice_p.h
+++ b/src/core/services/qopenglinformationservice_p.h
@@ -52,9 +52,10 @@
//
#include <Qt3DCore/qt3dcore_global.h>
-#include <Qt3DCore/private/qservicelocator_p.h>
-#include <QtGui/qsurfaceformat.h>
#include <QtCore/qstring.h>
+#include <QtGui/qsurfaceformat.h>
+
+#include <Qt3DCore/private/qservicelocator_p.h>
QT_BEGIN_NAMESPACE
@@ -64,6 +65,7 @@ class QOpenGLInformationServicePrivate;
class QT3DCORESHARED_EXPORT QOpenGLInformationService : public QAbstractServiceProvider
{
+ Q_OBJECT
public:
virtual QSurfaceFormat format() const = 0;
diff --git a/src/core/services/qopenglinformationservice_p_p.h b/src/core/services/qopenglinformationservice_p_p.h
index 4abef6f18..d10d81d71 100644
--- a/src/core/services/qopenglinformationservice_p_p.h
+++ b/src/core/services/qopenglinformationservice_p_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qt3dcore_global.h>
+
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
diff --git a/src/core/services/qservicelocator.cpp b/src/core/services/qservicelocator.cpp
index 3d3d56386..bdcb4a521 100644
--- a/src/core/services/qservicelocator.cpp
+++ b/src/core/services/qservicelocator.cpp
@@ -38,11 +38,15 @@
****************************************************************************/
#include "qservicelocator_p.h"
-#include "qabstractserviceprovider_p.h"
-#include "nullservices_p.h"
-#include "qtickclockservice_p.h"
-#include "qeventfilterservice_p.h"
-#include <QHash>
+
+#include <QtCore/QHash>
+
+#include <Qt3DCore/private/nullservices_p.h>
+#include <Qt3DCore/private/qabstractserviceprovider_p.h>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
+#include <Qt3DCore/private/qeventfilterservice_p.h>
+#include <Qt3DCore/private/qtickclockservice_p.h>
+
QT_BEGIN_NAMESPACE
@@ -53,17 +57,15 @@ namespace Qt3DCore {
\inmodule Qt3DCore
*/
-QAbstractServiceProvider::QAbstractServiceProvider(int type, const QString &description)
- : d_ptr(new QAbstractServiceProviderPrivate(type, description))
+QAbstractServiceProvider::QAbstractServiceProvider(int type, const QString &description, QObject *parent)
+ : QObject(*new QAbstractServiceProviderPrivate(type, description), parent)
{
- d_ptr->q_ptr = this;
}
/* \internal */
-QAbstractServiceProvider::QAbstractServiceProvider(QAbstractServiceProviderPrivate &dd)
- : d_ptr(&dd)
+QAbstractServiceProvider::QAbstractServiceProvider(QAbstractServiceProviderPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
{
- d_ptr->q_ptr = this;
}
QAbstractServiceProvider::~QAbstractServiceProvider()
@@ -96,6 +98,7 @@ public:
NullOpenGLInformationService m_nullOpenGLInfo;
QTickClockService m_defaultFrameAdvanceService;
QEventFilterService m_eventFilterService;
+ QDownloadHelperService m_downloadHelperService;
int m_nonNullDefaultServices;
};
@@ -229,6 +232,12 @@ QEventFilterService *QServiceLocator::eventFilterService()
return static_cast<QEventFilterService *>(d->m_services.value(EventFilterService, &d->m_eventFilterService));
}
+QDownloadHelperService *QServiceLocator::downloadHelperService()
+{
+ Q_D(QServiceLocator);
+ return static_cast<QDownloadHelperService *>(d->m_services.value(DownloadHelperService, &d->m_downloadHelperService));
+}
+
/*
\internal
*/
@@ -244,6 +253,8 @@ QAbstractServiceProvider *QServiceLocator::_q_getServiceHelper(int type)
return frameAdvanceService();
case EventFilterService:
return eventFilterService();
+ case DownloadHelperService:
+ return downloadHelperService();
default:
return d->m_services.value(type, nullptr);
}
diff --git a/src/core/services/qservicelocator_p.h b/src/core/services/qservicelocator_p.h
index c68b56ffd..9534b33ce 100644
--- a/src/core/services/qservicelocator_p.h
+++ b/src/core/services/qservicelocator_p.h
@@ -52,7 +52,8 @@
//
#include <Qt3DCore/qt3dcore_global.h>
-#include <QScopedPointer>
+#include <QtCore/qobject.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
@@ -60,8 +61,9 @@ namespace Qt3DCore {
class QAbstractServiceProviderPrivate;
-class QT3DCORESHARED_EXPORT QAbstractServiceProvider
+class QT3DCORESHARED_EXPORT QAbstractServiceProvider : public QObject
{
+ Q_OBJECT
public:
virtual ~QAbstractServiceProvider();
@@ -69,9 +71,8 @@ public:
QString description() const;
protected:
- QAbstractServiceProvider(int type, const QString &description);
- QAbstractServiceProvider(QAbstractServiceProviderPrivate &dd);
- QScopedPointer<QAbstractServiceProviderPrivate> d_ptr;
+ explicit QAbstractServiceProvider(int type, const QString &description, QObject* parent = nullptr);
+ explicit QAbstractServiceProvider(QAbstractServiceProviderPrivate &dd, QObject* parent = nullptr);
private:
Q_DISABLE_COPY(QAbstractServiceProvider)
@@ -83,6 +84,7 @@ class QOpenGLInformationService;
class QSystemInformationService;
class QServiceLocatorPrivate;
class QEventFilterService;
+class QDownloadHelperService;
class QT3DCORESHARED_EXPORT QServiceLocator
{
@@ -96,6 +98,7 @@ public:
CollisionService,
FrameAdvanceService,
EventFilterService,
+ DownloadHelperService,
#if !defined(Q_QDOC)
DefaultServiceCount, // Add additional default services before here
#endif
@@ -119,6 +122,7 @@ public:
QOpenGLInformationService *openGLInformation();
QAbstractFrameAdvanceService *frameAdvanceService();
QEventFilterService *eventFilterService();
+ QDownloadHelperService *downloadHelperService();
private:
Q_DISABLE_COPY(QServiceLocator)
diff --git a/src/core/services/qsysteminformationservice_p.h b/src/core/services/qsysteminformationservice_p.h
index dc384fb93..01e976b77 100644
--- a/src/core/services/qsysteminformationservice_p.h
+++ b/src/core/services/qsysteminformationservice_p.h
@@ -52,9 +52,10 @@
//
#include <Qt3DCore/qt3dcore_global.h>
-#include <Qt3DCore/private/qservicelocator_p.h>
#include <QtCore/qstringlist.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
@@ -63,6 +64,7 @@ class QSystemInformationServicePrivate;
class QT3DCORESHARED_EXPORT QSystemInformationService : public QAbstractServiceProvider
{
+ Q_OBJECT
public:
virtual QStringList aspectNames() const = 0;
virtual int threadPoolThreadCount() const = 0;
diff --git a/src/core/services/qsysteminformationservice_p_p.h b/src/core/services/qsysteminformationservice_p_p.h
index 897caf62b..e3ce9fe49 100644
--- a/src/core/services/qsysteminformationservice_p_p.h
+++ b/src/core/services/qsysteminformationservice_p_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qt3dcore_global.h>
+
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
diff --git a/src/core/services/qtickclockservice.cpp b/src/core/services/qtickclockservice.cpp
index 3691959ed..225e70ec2 100644
--- a/src/core/services/qtickclockservice.cpp
+++ b/src/core/services/qtickclockservice.cpp
@@ -38,9 +38,10 @@
****************************************************************************/
#include "qtickclockservice_p.h"
-#include "qtickclock_p.h"
-#include "qabstractframeadvanceservice_p.h"
-#include "qabstractframeadvanceservice_p_p.h"
+
+#include <Qt3DCore/private/qabstractframeadvanceservice_p.h>
+#include <Qt3DCore/private/qabstractframeadvanceservice_p_p.h>
+#include <Qt3DCore/private/qtickclock_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/services/qtickclockservice_p.h b/src/core/services/qtickclockservice_p.h
index b84018d0b..6f02643f4 100644
--- a/src/core/services/qtickclockservice_p.h
+++ b/src/core/services/qtickclockservice_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qabstractframeadvanceservice_p.h"
+#include <Qt3DCore/private/qabstractframeadvanceservice_p.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +61,7 @@ class QTickClockServicePrivate;
class QTickClockService : public QAbstractFrameAdvanceService
{
+ Q_OBJECT
public:
QTickClockService();
~QTickClockService();
diff --git a/src/core/services/services.pri b/src/core/services/services.pri
index ae0cfd9f8..f311b8329 100644
--- a/src/core/services/services.pri
+++ b/src/core/services/services.pri
@@ -5,7 +5,9 @@ SOURCES += \
$$PWD/qopenglinformationservice.cpp \
$$PWD/qtickclockservice.cpp \
$$PWD/qabstractframeadvanceservice.cpp \
- $$PWD/qeventfilterservice.cpp
+ $$PWD/qeventfilterservice.cpp \
+ $$PWD/qdownloadhelperservice.cpp \
+ $$PWD/qdownloadnetworkworker.cpp
HEADERS += \
$$PWD/qservicelocator_p.h \
@@ -18,6 +20,8 @@ HEADERS += \
$$PWD/qtickclockservice_p.h \
$$PWD/qabstractframeadvanceservice_p.h \
$$PWD/qabstractframeadvanceservice_p_p.h \
- $$PWD/qeventfilterservice_p.h
+ $$PWD/qeventfilterservice_p.h \
+ $$PWD/qdownloadhelperservice_p.h \
+ $$PWD/qdownloadnetworkworker_p.h
INCLUDEPATH += $$PWD
diff --git a/src/core/transforms/qmath3d_p.h b/src/core/transforms/qmath3d_p.h
index 38ebbd99a..8c2afac31 100644
--- a/src/core/transforms/qmath3d_p.h
+++ b/src/core/transforms/qmath3d_p.h
@@ -50,7 +50,6 @@
//
// We mean it.
//
-
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qquaternion.h>
#include <QtGui/qvector3d.h>
diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp
index d28138cad..a551d83d8 100644
--- a/src/core/transforms/qtransform.cpp
+++ b/src/core/transforms/qtransform.cpp
@@ -39,10 +39,11 @@
#include "qtransform.h"
#include "qtransform_p.h"
-#include "qmath3d_p.h"
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qmath3d_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/core/transforms/qtransform.h b/src/core/transforms/qtransform.h
index 25b1da8cd..cb2b1bdce 100644
--- a/src/core/transforms/qtransform.h
+++ b/src/core/transforms/qtransform.h
@@ -41,7 +41,6 @@
#define QT3DCORE_QTRANSFORM_H
#include <Qt3DCore/qcomponent.h>
-
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qquaternion.h>
#include <QtGui/qvector3d.h>
diff --git a/src/core/transforms/qtransform_p.h b/src/core/transforms/qtransform_p.h
index 8d1a60566..89bc55491 100644
--- a/src/core/transforms/qtransform_p.h
+++ b/src/core/transforms/qtransform_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qcomponent_p.h>
+#include <Qt3DCore/private/qcomponent_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/doc/qt3d.qdocconf b/src/doc/qt3d.qdocconf
index 623a2c5d5..7da047ced 100644
--- a/src/doc/qt3d.qdocconf
+++ b/src/doc/qt3d.qdocconf
@@ -47,7 +47,9 @@ headerdirs += . \
../plugins \
../quick3d/quick3d \
../input \
- ../extras
+ ../extras \
+ ../animation \
+ ../quick3d/quick3dscene2d
# Exclude private header files from the documentation build
excludefiles += "*_p.h"
@@ -59,7 +61,9 @@ sourcedirs += . \
../plugins \
../quick3d/quick3d \
../input \
- ../extras
+ ../extras \
+ ../animation \
+ ../quick3d/quick3dscene2d
exampledirs += ../../examples/qt3d \
snippets
@@ -67,14 +71,19 @@ exampledirs += ../../examples/qt3d \
examples.fileextensions += "*.fraq *.geom *.vert"
examples.imageextensions += "*.png"
-#excludedirs +=
+excludedirs += \
+ ../plugins/renderplugins
+
macro.TODO = " "
imagedirs += images \
../../examples/qt3d/shadow-map-qml/doc/images \
../../examples/qt3d/basicshapes-cpp/doc/images \
../../examples/qt3d/planets-qml/doc/images \
../../examples/qt3d/wireframe/doc/images \
- ../../examples/qt3d/audio-visualizer-qml/doc/images
+ ../../examples/qt3d/audio-visualizer-qml/doc/images \
+ ../../examples/qt3d/simplecustommaterial/doc/images \
+ ../../examples/qt3d/scene2d/doc/images \
+ ../../examples/qt3d/advancedcustommaterial/doc/images
Cpp.ignoretokens += QT3DINPUTSHARED_EXPORT \
QT3DCORESHARED_EXPORT \
@@ -83,12 +92,16 @@ Cpp.ignoretokens += QT3DINPUTSHARED_EXPORT \
QT3DRENDERSHARED_EXPORT \
QT3DRENDERSHARED_PRIVATE_EXPORT \
QT3DQUICKSHARED_PRIVATE_EXPORT \
- QT3DEXTRASSHARED_EXPORT
+ QT3DEXTRASSHARED_EXPORT \
+ QT3DANIMATIONSHARED_EXPORT \
+ QT3DQUICKSCENE2DSHARED_EXPORT
Cpp.ignoredirectives += Q_DECLARE_LOGGING_CATEGORY
-manifestmeta.highlighted.names = "Qt3D/Qt 3D: Audio Visualizer Example" \
- "Qt3D/Qt 3D: Planets QML Example"
+manifestmeta.highlighted.names = \
+ "Qt3D/Qt 3D: Advanced custom material QML Example" \
+ "Qt3D/Qt 3D: Audio Visualizer Example" \
+ "Qt3D/Qt 3D: Planets QML Example"
manifestmeta.thumbnail.names += "Qt3D/Qt 3D: Deferred Renderer C++ Example"
diff --git a/src/doc/src/levelofdetailloader.qdoc b/src/doc/src/levelofdetailloader.qdoc
index 65fda072a..6294e4735 100644
--- a/src/doc/src/levelofdetailloader.qdoc
+++ b/src/doc/src/levelofdetailloader.qdoc
@@ -40,12 +40,12 @@
/*!
\qmltype LevelOfDetailLoader
\inqmlmodule Qt3D.Render
+ \inherits Entity
\since 5.9
\brief An entity loader that changes depending on distance to camera or screen size
A LevelOfDetailLoader will load the entity matching the \l LevelOfDetail::currentIndex.
The source is selected from the \l sources property.
- The range is specified using the \l {minimum} and the \l{maximum} values.
\sa LevelOfDetail
*/
diff --git a/src/doc/src/qt3d-index.qdoc b/src/doc/src/qt3d-index.qdoc
index f14909cec..2031fcfdc 100644
--- a/src/doc/src/qt3d-index.qdoc
+++ b/src/doc/src/qt3d-index.qdoc
@@ -61,7 +61,7 @@
\l qmake \c .pro file:
\badcode
- QT += 3dcore 3drender 3dinput 3dlogic 3dextras
+ QT += 3dcore 3drender 3dinput 3dlogic 3dextras 3danimation
\endcode
To include the definitions of the modules' classes, use the following
@@ -73,12 +73,13 @@
#include <Qt3DInput>
#include <Qt3DLogic>
#include <Qt3DExtras>
+ #include <Qt3DAnimation>
\endcode
A Qt Quick application requires also additional dependencies:
\badcode
- QT += 3dcore 3drender 3dinput 3dlogic 3dextras qml quick 3dquick
+ QT += 3dcore 3drender 3dinput 3dlogic 3dextras qml quick 3dquick 3danimation
\endcode
\section1 Overview
diff --git a/src/doc/src/qt3d-module.qdoc b/src/doc/src/qt3d-module.qdoc
index c82c528f1..0e26375a9 100644
--- a/src/doc/src/qt3d-module.qdoc
+++ b/src/doc/src/qt3d-module.qdoc
@@ -77,6 +77,12 @@
\section2 Qt 3D Extras Module
\generatelist {classesbymodule Qt3DExtras}
+
+ \section2 Qt 3D Animation Module
+ \generatelist {classesbymodule Qt3DAnimation}
+
+ \section2 Qt 3D Scene2D Module
+ \generatelist {classesbymodule Qt3DScene2D}
*/
/*!
@@ -111,6 +117,7 @@
import Qt3D.Input 2.0
import Qt3D.Logic 2.0
import Qt3D.Extras 2.0
+ import Qt3D.Animation 2.0
\endcode
\section1 QML Types
@@ -131,4 +138,12 @@
\section2 Qt 3D Extras Module
\generatelist {qmltypesbymodule Qt3D.Extras}
\noautolist
+
+ \section2 Qt 3D Animation Module
+ \generatelist {qmltypesbymodule Qt3D.Animation}
+ \noautolist
+
+ \section2 Qt 3D Scene2D Module
+ \generatelist {qmltypesbymodule Qt3D.Scene2D}
+ \noautolist
*/
diff --git a/src/doc/src/qt3danimation-module.qdoc b/src/doc/src/qt3danimation-module.qdoc
new file mode 100644
index 000000000..0601a8973
--- /dev/null
+++ b/src/doc/src/qt3danimation-module.qdoc
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module Qt3DAnimation
+ \title Qt 3D Animation C++ Classes
+
+ \brief The Qt 3D Animation modules provides a set of prebuilt elements to help
+ you get started with Qt 3D.
+
+ This module is still in tech preview. This means it is unstable, likely to
+ change and provided as a convenience only.
+
+ \ingroup modules
+ \ingroup qt3d-modules
+ \qtvariable 3danimation
+
+ \code
+ #include <Qt3DAnimation>
+ \endcode
+
+ To link against the corresponding C++ library, add the following to your qmake project file:
+
+ \badcode
+ QT += 3danimation
+ \endcode
+
+ Classes, types, and functions are declared under the \l [Qt3DAnimation]{Qt3DAnimation} namespace.
+
+ \section1 Overview
+
+ The Qt 3D Animation module adds support for specifying and using animations
+ that can be applied to the properties of objects in your simulation.
+ Initially this module supports key frame based animations. That is,
+ properties have values 'keyed' at certain times and when played back the
+ property values are calculated by interpolating between the known values
+ within the key frames. All of the animation evaluation within the Qt 3D
+ Animation module takes place on the Qt 3D threadpool. This allows the
+ animations to run smoothly and to scale up to high throughput.
+
+ \section2 Animation Data
+
+ Key frame animation data can either be created programmatically via the Qt
+ 3D Animation APIs such as Qt3DAnimation::QKeyFrameData or it can come from
+ digital content creation (DCC) tools such as Blender, Maya or 3D Studio
+ Max. Qt 3D provides an example export script for animation data for
+ Blender. The format consumed by Qt 3D Animation at present is a simple JSON
+ based format. This allows both developers and artists to easily work with
+ animation data. More formats optimised for runtime consumption will be
+ added later.
+
+ The key frame animation data can be loaded from file using the
+ Qt3DAnimation::QAnimationClipLoader class. To specify animation data
+ programmatically use the Qt3DAnimation::QAnimationClip class.
+
+ By default, the key frame data is specified using cubic bezier curves. This
+ allows smooth animations to be created from a small number of key frame
+ data points. Other interpolation types will be added later.
+
+ \section2 Playing Animations
+
+ In addition to the animation data containing the key frames, Qt 3D
+ Animation also provides APIs for playing the animations and mapping the
+ resulting property values onto properties of objects in your simulation.
+ There are currently two ways of playing the animations:
+
+ \list
+ \li Qt3DAnimation::QClipAnimator
+ \li Qt3DAnimation::QBlendedClipAnimator
+ \endlist
+
+ Both of these are implemented as subclasses of Qt3DCore::QComponent meaning
+ that objects of these types can be aggregated by Qt3DCore::QEntity objects
+ to add animation capabilities to your simulated entities.
+
+ \section2 Simple Animation Playback
+
+ The Qt3DAnimation::QClipAnimator class allows the playback of a single
+ Qt3DAnimation::QAbstractAnimationClip at a time. To add an animation to an
+ entity, simply add an instance of the Qt3DAnimation::QClipAnimator class to
+ your entity's \c components property.
+
+ The Qt 3D Animation module takes a slightly different approach to
+ QPropertyAnimation and AbstractAnimation. With those animation frameworks,
+ the animation specifies both the animation values \e {and} the target
+ objects and properties. The animation components in Qt 3D separate these
+ two orthogonal concepts. For example, the Qt3DAnimation::QClipAnimator
+ component has a \c clip property for specifying the animation data
+ (Qt3DAnimation::QAnimationClip or Qt3DAnimation::QAnimationClipLoader).
+
+ This allows calculation of the animated values, but more information is
+ needed in order to map these values onto properties of objects. This is
+ accomplished with the a Qt3DAnimation::QChannelMapper which contains a list
+ of Qt3DAnimation::QChannelMapping objects. A Qt3DAnimation::QChannelMapping
+ is used to map a specific channel from an animation clip onto a named
+ property of a target object. By separating the animation data and property
+ mappings like this, the same animation can be applied to many objects
+ without needing to have multiple copies of the animation data or objects.
+ It also allows animation data to easily be retargeted to other objects.
+
+ \section2 Blended Animation Playback
+
+ The Qt3DAnimation::QBlendedClipAnimator component allows to go beyond what
+ is possible with Qt3DAnimation::QClipAnimator by blending several animation
+ clips together before applying the property changes to the target
+ properties. The animator component still takes a channel mapper just like
+ the standard Qt3DAnimation::QClipAnimator component. However, instead of
+ specifying a single animation clip, it is necessary to set the \c blendTree
+ property to point to the root node of a \e {blend tree}.
+
+ A blend tree is a data structure representing how animation clips get
+ aggregated or blended together as the function of properties on the blend
+ tree nodes. The currently supported set of blend tree nodes are:
+
+ \list
+ \li Qt3DAnimation::QClipBlendValue
+ \li Qt3DAnimation::QLerpClipBlend
+ \li Qt3DAnimation::QAdditiveClipBlend
+ \endlist
+
+ The source animation clip inputs are specified as leaf nodes in the blend
+ tree using instances of the Qt3DAnimation::QClipBlendValue class. These
+ animation clips can be combined in a large number of ways. For now the Qt3D
+ Animation module provides linear interpolation (LERP) and additive blend
+ operations. More blend node types will be added over time. These are
+ expected to include at least a generalised LERP node and a barycentric LERP
+ node.
+
+ As an example consider the following blend tree:
+
+ \badcode
+ Clip0----
+ |
+ Lerp Node----
+ | |
+ Clip1---- Additive Node
+ |
+ Clip2----
+ \endcode
+
+ Let's assume that \c Clip0 represents a walk animation cycle with a
+ duration of 3 seconds and that \c Clip1 is a run animation cycle with a
+ duration of 2 seconds. These are both inputs (and dependencies) of the \c
+ Lerp blend node. The result of evaluating the \c Lerp node depends upon the
+ \c blendFactor property of the \c Lerp node. This could be bound to the
+ speed of a humanoid character entity for example. As the speed of the
+ character increases the animation gradually cross-fades from the walk
+ animation in \c Clip0 to the run animation in \c Clip1.
+
+ Furthermore, let's assume that \c Clip2 represents some variation animation
+ that can be added on (waving arms or shaking head for e.g.). The amount of
+ this additive clip that is added can be controlled by the \c additiveFactor
+ property on the \c Additive blend node.
+
+ When evaluating a blend tree, normalized time (or phase) is used so that
+ clips of different durations can be blended together without problems. For
+ example, even though the walk and run animation clips are of different
+ lengths, as long as they are created by the animator such that the
+ foot-falls line up at the same phase these can be nicely interpolated.
+
+ The implication of this is that the duration of the blended clip is
+ actually a function of the blend factors of the nodes in the tree.
+ Considering only the \c Lerp node in the above example, when the blend
+ factor of the \c Lerp node is 0, only the walk animation in Clip0 is used
+ resulting in a duration of 3 seconds. With a blend factor of 1 the
+ resulting duration will be 2 seconds. For intermediate blend factors, the
+ duration will be linearly interpolated between 3 and 2 seconds.
+
+ By definining your own blend trees, you have complete control over how to
+ combine your collection of input animation clips. The blend tree can be
+ configured by the properties on the blend nodes. Note also that the
+ properties on the blend nodes themselves are just standard properties, so
+ these could in turn be driven by other animations if desired.
+
+ \section1 Reference
+ \list
+ \li \l {Qt 3D Animation C++ Classes}
+ \li \l {Qt 3D Examples}
+ \endlist
+ */
+
+/*!
+ \namespace Qt3DAnimation
+ \inmodule Qt3DAnimation
+ \ingroup qt3d-namespaces
+
+ \brief Contains classes from the Qt3DAnimation module.
+*/
+
+/*!
+ \qmlmodule Qt3D.Animation 2.0
+ \title Qt 3D Qt3DAnimation QML Types
+ \ingroup qmlmodules
+ \ingroup qt3d-qmlmodules
+
+ \brief Provides Qt 3D QML types for the animation module.
+
+ To import and use the module's QML types, use the following statement:
+
+ \badcode
+ import Qt3D.Animation 2.0
+ \endcode
+*/
diff --git a/src/doc/src/qt3dscene2d-module.qdoc b/src/doc/src/qt3dscene2d-module.qdoc
new file mode 100644
index 000000000..a389a8ed0
--- /dev/null
+++ b/src/doc/src/qt3dscene2d-module.qdoc
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module Qt3DScene2D
+ \title Qt 3D Scene2D C++ Classes
+
+ \brief The Qt 3D Scene2D module provides a way to render Quick2 qml content
+ to a Qt 3D texture.
+
+ This module is still in tech preview. This means it is unstable, likely to
+ change and provided as a convenience only.
+
+ \ingroup modules
+ \ingroup qt3d-modules
+ \qtvariable 3dquickscene2d
+
+ \code
+ #include <Qt3DQuickScene2D>
+ \endcode
+
+ To link against the corresponding C++ library, add the following to your qmake project file:
+
+ \badcode
+ QT += 3dquickscene2d
+ \endcode
+
+ Classes, types, and functions are declared under the \l [Qt3DScene2D]{Qt3DScene2D} namespace.
+
+ \section1 Overview
+
+ \section2 Scene2D
+
+ \list
+ \li Qt3DRender::Quick::QScene2D
+ \endlist
+
+ \section1 Reference
+ \list
+ \li \l {Qt 3D Extras C++ Classes}
+ \li \l {Qt 3D Examples}
+ \endlist
+ */
+
+/*!
+ \qmlmodule Qt3D.Scene2D 2.9
+ \title Qt 3D Scene2D QML Types
+ \ingroup qmlmodules
+ \ingroup qt3d-qmlmodules
+
+ \brief Provides Qt 3D QML types for the scene2d module.
+
+ To import and use the module's QML types, use the following statement:
+
+ \badcode
+ import Qt3D.Scene2D 2.9
+ \endcode
+*/
diff --git a/src/extras/3dtext/3dtext.pri b/src/extras/3dtext/3dtext.pri
index bcf2ce948..d7855f1b0 100644
--- a/src/extras/3dtext/3dtext.pri
+++ b/src/extras/3dtext/3dtext.pri
@@ -1,11 +1,11 @@
SOURCES += \
- $$PWD/qtext3dgeometry.cpp \
- $$PWD/qtext3dmesh.cpp
+ $$PWD/qextrudedtextgeometry.cpp \
+ $$PWD/qextrudedtextmesh.cpp
HEADERS += \
- $$PWD/qtext3dgeometry.h \
- $$PWD/qtext3dgeometry_p.h \
- $$PWD/qtext3dmesh.h
+ $$PWD/qextrudedtextgeometry.h \
+ $$PWD/qextrudedtextgeometry_p.h \
+ $$PWD/qextrudedtextmesh.h
INCLUDEPATH += $$PWD
diff --git a/src/extras/3dtext/qtext3dgeometry.cpp b/src/extras/3dtext/qextrudedtextgeometry.cpp
index 529c93b79..4a460bfc7 100644
--- a/src/extras/3dtext/qtext3dgeometry.cpp
+++ b/src/extras/3dtext/qextrudedtextgeometry.cpp
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#include "qtext3dgeometry.h"
-#include "qtext3dgeometry_p.h"
+#include "qextrudedtextgeometry.h"
+#include "qextrudedtextgeometry_p.h"
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qattribute.h>
@@ -65,7 +65,9 @@ namespace Qt3DExtras {
namespace {
-using IndexType = unsigned short;
+static float edgeSplitAngle = 90.f * 0.1f;
+
+using IndexType = unsigned int;
struct TriangulationData {
struct Outline {
@@ -103,7 +105,7 @@ TriangulationData triangulate(const QString &text, const QFont &font)
for (QPolygonF &p : polygons)
path.addPolygon(p);
- // Extract polylines out of the path, this allows us to retrive indicies for each glyph outline
+ // Extract polylines out of the path, this allows us to retrieve indices for each glyph outline
QPolylineSet polylines = qPolyline(path);
QVector<IndexType> tmpIndices;
tmpIndices.resize(polylines.indices.size());
@@ -145,11 +147,10 @@ inline QVector3D mix(const QVector3D &a, const QVector3D &b, float ratio)
} // anonymous namespace
-QText3DGeometryPrivate::QText3DGeometryPrivate()
+QExtrudedTextGeometryPrivate::QExtrudedTextGeometryPrivate()
: QGeometryPrivate()
, m_font(QFont(QStringLiteral("Arial")))
, m_depth(1.f)
- , m_edgeSplitAngle(90.f * 0.1f)
, m_positionAttribute(nullptr)
, m_normalAttribute(nullptr)
, m_indexAttribute(nullptr)
@@ -159,9 +160,9 @@ QText3DGeometryPrivate::QText3DGeometryPrivate()
m_font.setPointSize(4);
}
-void QText3DGeometryPrivate::init()
+void QExtrudedTextGeometryPrivate::init()
{
- Q_Q(QText3DGeometry);
+ Q_Q(QExtrudedTextGeometry);
m_positionAttribute = new Qt3DRender::QAttribute(q);
m_normalAttribute = new Qt3DRender::QAttribute(q);
m_indexAttribute = new Qt3DRender::QAttribute(q);
@@ -190,7 +191,7 @@ void QText3DGeometryPrivate::init()
m_normalAttribute->setCount(0);
m_indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
- m_indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
+ m_indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
m_indexAttribute->setBuffer(m_indexBuffer);
m_indexAttribute->setCount(0);
@@ -202,101 +203,96 @@ void QText3DGeometryPrivate::init()
}
/*!
- * \qmltype Text3DGeometry
- * \instantiates Qt3DExtras::QText3DGeometry
+ * \qmltype ExtrudedTextGeometry
+ * \instantiates Qt3DExtras::QExtrudedTextGeometry
* \inqmlmodule Qt3D.Extras
- * \brief Text3DGeometry allows creation of a 3D text in 3D space.
+ * \brief ExtrudedTextGeometry allows creation of a 3D text in 3D space.
*
- * The Text3DGeometry type is most commonly used internally by the Text3DMesh type
- * but can also be used in custom GeometryRenderer types.
+ * The ExtrudedTextGeometry type is most commonly used internally by the
+ * ExtrudedTextMesh type but can also be used in custom GeometryRenderer types.
*/
/*!
- * \qmlproperty QString Text3DGeometry::text
+ * \qmlproperty QString ExtrudedTextGeometry::text
*
* Holds the text used for the mesh.
*/
/*!
- * \qmlproperty QFont Text3DGeometry::font
+ * \qmlproperty QFont ExtrudedTextGeometry::font
*
* Holds the font of the text.
*/
/*!
- * \qmlproperty float Text3DGeometry::depth
+ * \qmlproperty float ExtrudedTextGeometry::depth
*
* Holds the extrusion depth of the text.
*/
/*!
- * \qmlproperty float Text3DGeometry::edgeSplitAngle
- *
- * Holds the threshold angle for smooth normals.
- */
-
-/*!
- * \qmlproperty Attribute Text3DGeometry::positionAttribute
+ * \qmlproperty Attribute ExtrudedTextGeometry::positionAttribute
*
* Holds the geometry position attribute.
*/
/*!
- * \qmlproperty Attribute Text3DGeometry::normalAttribute
+ * \qmlproperty Attribute ExtrudedTextGeometry::normalAttribute
*
* Holds the geometry normal attribute.
*/
/*!
- * \qmlproperty Attribute Text3DGeometry::indexAttribute
+ * \qmlproperty Attribute ExtrudedTextGeometry::indexAttribute
*
* Holds the geometry index attribute.
*/
/*!
- * \class Qt3DExtras::QText3DGeometry
- * \inheaderfile Qt3DExtras/QText3DGeometry
+ * \class Qt3DExtras::QExtrudedTextGeometry
+ * \inheaderfile Qt3DExtras/QExtrudedTextGeometry
* \inmodule Qt3DExtras
- * \brief The QText3DGeometry class allows creation of a 3D text in 3D space.
- * \since 5.8
+ * \brief The QExtrudedTextGeometry class allows creation of a 3D extruded text
+ * in 3D space.
+ * \since 5.9
* \ingroup geometries
* \inherits Qt3DRender::QGeometry
*
- * The QText3DGeometry class is most commonly used internally by the QText3DMesh
+ * The QExtrudedTextGeometry class is most commonly used internally by the QText3DMesh
* but can also be used in custom Qt3DRender::QGeometryRenderer subclasses.
*/
/*!
- * Constructs a new QText3DGeometry with \a parent.
+ * Constructs a new QExtrudedTextGeometry with \a parent.
*/
-QText3DGeometry::QText3DGeometry(Qt3DCore::QNode *parent)
- : QGeometry(*new QText3DGeometryPrivate(), parent)
+QExtrudedTextGeometry::QExtrudedTextGeometry(Qt3DCore::QNode *parent)
+ : QGeometry(*new QExtrudedTextGeometryPrivate(), parent)
{
- Q_D(QText3DGeometry);
+ Q_D(QExtrudedTextGeometry);
d->init();
}
/*!
* \internal
*/
-QText3DGeometry::QText3DGeometry(QText3DGeometryPrivate &dd, Qt3DCore::QNode *parent)
+QExtrudedTextGeometry::QExtrudedTextGeometry(QExtrudedTextGeometryPrivate &dd, Qt3DCore::QNode *parent)
: QGeometry(dd, parent)
{
- Q_D(QText3DGeometry);
+ Q_D(QExtrudedTextGeometry);
d->init();
}
/*!
* \internal
*/
-QText3DGeometry::~QText3DGeometry()
+QExtrudedTextGeometry::~QExtrudedTextGeometry()
{}
/*!
* \internal
- * Updates vertices based on text, font, depth and smoothAngle properties.
+ * Updates vertices based on text, font, extrusionLength and smoothAngle properties.
*/
-void QText3DGeometryPrivate::update()
+void QExtrudedTextGeometryPrivate::update()
{
if (m_text.trimmed().isEmpty()) // save enough?
return;
@@ -328,6 +324,9 @@ void QText3DGeometryPrivate::update()
const int end = data.outlines[i].end;
const int verticesIndexBegin = verticesIndex;
+ if (begin == end)
+ continue;
+
QVector3D prevNormal = QVector3D::crossProduct(
vertices[data.outlineIndices[end - 1] + numVertices].position - vertices[data.outlineIndices[end - 1]].position,
vertices[data.outlineIndices[begin]].position - vertices[data.outlineIndices[end - 1]].position).normalized();
@@ -339,7 +338,7 @@ void QText3DGeometryPrivate::update()
const QVector3D normal = QVector3D::crossProduct(vertices[cur + numVertices].position - vertices[cur].position, vertices[next].position - vertices[cur].position).normalized();
// use smooth normals in case of a short angle
- const bool smooth = QVector3D::dotProduct(prevNormal, normal) > (90.0f - m_edgeSplitAngle) / 90.0f;
+ const bool smooth = QVector3D::dotProduct(prevNormal, normal) > (90.0f - edgeSplitAngle) / 90.0f;
const QVector3D resultNormal = smooth ? mix(prevNormal, normal, 0.5f) : normal;
if (!smooth) {
vertices.push_back({vertices[cur].position, prevNormal});
@@ -403,9 +402,9 @@ void QText3DGeometryPrivate::update()
}
}
-void QText3DGeometry::setText(QString text)
+void QExtrudedTextGeometry::setText(const QString &text)
{
- Q_D(QText3DGeometry);
+ Q_D(QExtrudedTextGeometry);
if (d->m_text != text) {
d->m_text = text;
d->update();
@@ -413,9 +412,9 @@ void QText3DGeometry::setText(QString text)
}
}
-void QText3DGeometry::setFont(QFont font)
+void QExtrudedTextGeometry::setFont(const QFont &font)
{
- Q_D(QText3DGeometry);
+ Q_D(QExtrudedTextGeometry);
if (d->m_font != font) {
d->m_font = font;
d->update();
@@ -423,9 +422,9 @@ void QText3DGeometry::setFont(QFont font)
}
}
-void QText3DGeometry::setDepth(float depth)
+void QExtrudedTextGeometry::setDepth(float depth)
{
- Q_D(QText3DGeometry);
+ Q_D(QExtrudedTextGeometry);
if (d->m_depth != depth) {
d->m_depth = depth;
d->update();
@@ -433,90 +432,69 @@ void QText3DGeometry::setDepth(float depth)
}
}
-void QText3DGeometry::setEdgeSplitAngle(float smoothAngle)
-{
- Q_D(QText3DGeometry);
- if (d->m_edgeSplitAngle != smoothAngle) {
- d->m_edgeSplitAngle = smoothAngle;
- d->update();
- emit edgeSplitAngleChanged(smoothAngle);
- }
-}
-
/*!
- * \property QString Text3DGeometry::text
+ * \property QString QExtrudedTextGeometry::text
*
* Holds the text used for the mesh.
*/
-QString QText3DGeometry::text() const
+QString QExtrudedTextGeometry::text() const
{
- Q_D(const QText3DGeometry);
+ Q_D(const QExtrudedTextGeometry);
return d->m_text;
}
/*!
- * \property QFont Text3DGeometry::font
+ * \property QFont QExtrudedTextGeometry::font
*
* Holds the font of the text.
*/
-QFont QText3DGeometry::font() const
+QFont QExtrudedTextGeometry::font() const
{
- Q_D(const QText3DGeometry);
+ Q_D(const QExtrudedTextGeometry);
return d->m_font;
}
/*!
- * \property float Text3DGeometry::depth
+ * \property float QExtrudedTextGeometry::extrusionLength
*
- * Holds the extrusion depth of the text.
+ * Holds the extrusion length of the text.
*/
-float QText3DGeometry::depth() const
+float QExtrudedTextGeometry::extrusionLength() const
{
- Q_D(const QText3DGeometry);
+ Q_D(const QExtrudedTextGeometry);
return d->m_depth;
}
/*!
- * \property float Text3DGeometry::edgeSplitAngle
- *
- * Holds the threshold angle for smooth normals.
- */
-float QText3DGeometry::edgeSplitAngle() const
-{
- Q_D(const QText3DGeometry);
- return d->m_edgeSplitAngle;
-}
-
-/*!
- * \property Text3DGeometry::positionAttribute
+ * \property QExtrudedTextGeometry::positionAttribute
*
* Holds the geometry position attribute.
*/
-Qt3DRender::QAttribute *QText3DGeometry::positionAttribute() const
+Qt3DRender::QAttribute *QExtrudedTextGeometry::positionAttribute() const
{
- Q_D(const QText3DGeometry);
+ Q_D(const QExtrudedTextGeometry);
return d->m_positionAttribute;
}
/*!
- * \property Text3DGeometry::normalAttribute
+ * \property QExtrudedTextMesh::normalAttribute
*
* Holds the geometry normal attribute.
*/
-Qt3DRender::QAttribute *QText3DGeometry::normalAttribute() const
+Qt3DRender::QAttribute *QExtrudedTextGeometry::normalAttribute() const
{
- Q_D(const QText3DGeometry);
+ Q_D(const QExtrudedTextGeometry);
return d->m_normalAttribute;
}
/*!
- * \property Text3DGeometry::indexAttribute
+ * \property QExtrudedTextMesh::indexAttribute
*
* Holds the geometry index attribute.
*/
-Qt3DRender::QAttribute *QText3DGeometry::indexAttribute() const
+Qt3DRender::QAttribute *QExtrudedTextGeometry::indexAttribute() const
{
- Q_D(const QText3DGeometry);
+ Q_D(const QExtrudedTextGeometry);
return d->m_indexAttribute;
}
diff --git a/src/extras/3dtext/qtext3dgeometry.h b/src/extras/3dtext/qextrudedtextgeometry.h
index 4cd89b112..9ee8b23f0 100644
--- a/src/extras/3dtext/qtext3dgeometry.h
+++ b/src/extras/3dtext/qextrudedtextgeometry.h
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QTEXT3DGEOMETRY_H
-#define QT3DEXTRAS_QTEXT3DGEOMETRY_H
+#ifndef QT3DEXTRAS_QEXTRUDEDTEXTGEOMETRY_H
+#define QT3DEXTRAS_QEXTRUDEDTEXTGEOMETRY_H
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qgeometry.h>
@@ -66,52 +66,48 @@ class QAttribute;
namespace Qt3DExtras {
-class QText3DGeometryPrivate;
+class QExtrudedTextGeometryPrivate;
-class QT3DEXTRASSHARED_EXPORT QText3DGeometry : public Qt3DRender::QGeometry
+class QT3DEXTRASSHARED_EXPORT QExtrudedTextGeometry : public Qt3DRender::QGeometry
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
- Q_PROPERTY(float depth READ depth WRITE setDepth NOTIFY depthChanged)
- Q_PROPERTY(float edgeSplitAngle READ edgeSplitAngle WRITE setEdgeSplitAngle NOTIFY edgeSplitAngleChanged)
+ Q_PROPERTY(float extrusionLength READ extrusionLength WRITE setDepth NOTIFY depthChanged)
Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT)
Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT)
Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT)
public:
- explicit QText3DGeometry(Qt3DCore::QNode *parent = nullptr);
- ~QText3DGeometry();
+ explicit QExtrudedTextGeometry(Qt3DCore::QNode *parent = nullptr);
+ ~QExtrudedTextGeometry();
Qt3DRender::QAttribute *positionAttribute() const;
Qt3DRender::QAttribute *normalAttribute() const;
Qt3DRender::QAttribute *indexAttribute() const;
QString text() const;
QFont font() const;
- float depth() const;
- float edgeSplitAngle() const;
+ float extrusionLength() const;
public Q_SLOTS:
- void setText(QString text);
- void setFont(QFont font);
- void setDepth(float depth);
- void setEdgeSplitAngle(float edgeSplitAngle);
+ void setText(const QString &text);
+ void setFont(const QFont &font);
+ void setDepth(float extrusionLength);
Q_SIGNALS:
- void textChanged(QString text);
- void fontChanged(QFont font);
- void depthChanged(float depth);
- void edgeSplitAngleChanged(float edgeSplitAngle);
+ void textChanged(const QString &text);
+ void fontChanged(const QFont &font);
+ void depthChanged(float extrusionLength);
protected:
- QText3DGeometry(QText3DGeometryPrivate &dd, QNode *parent = nullptr);
+ explicit QExtrudedTextGeometry(QExtrudedTextGeometryPrivate &dd, QNode *parent = nullptr);
private:
- Q_DECLARE_PRIVATE(QText3DGeometry)
+ Q_DECLARE_PRIVATE(QExtrudedTextGeometry)
};
} // namespace Qt3DExtras
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QTEXT3DGEOMETRY_H
+#endif // QT3DEXTRAS_QEXTRUDEDTEXTGEOMETRY_H
diff --git a/src/extras/3dtext/qtext3dgeometry_p.h b/src/extras/3dtext/qextrudedtextgeometry_p.h
index dc5e2f6a7..0bfa45e17 100644
--- a/src/extras/3dtext/qtext3dgeometry_p.h
+++ b/src/extras/3dtext/qextrudedtextgeometry_p.h
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QTEXT3DGEOMETRY_P_H
-#define QT3DEXTRAS_QTEXT3DGEOMETRY_P_H
+#ifndef QT3DEXTRAS_QEXTRUDEDTEXTGEOMETRY_P_H
+#define QT3DEXTRAS_QEXTRUDEDTEXTGEOMETRY_P_H
//
// W A R N I N G
@@ -76,12 +76,12 @@ class QBuffer;
namespace Qt3DExtras {
-class QText3DGeometry;
+class QExtrudedTextGeometry;
-class QText3DGeometryPrivate : public Qt3DRender::QGeometryPrivate
+class QExtrudedTextGeometryPrivate : public Qt3DRender::QGeometryPrivate
{
public:
- QText3DGeometryPrivate();
+ QExtrudedTextGeometryPrivate();
void init();
void update();
@@ -96,11 +96,11 @@ public:
Qt3DRender::QBuffer *m_vertexBuffer;
Qt3DRender::QBuffer *m_indexBuffer;
- Q_DECLARE_PUBLIC(QText3DGeometry)
+ Q_DECLARE_PUBLIC(QExtrudedTextGeometry)
};
} // namespace Qt3DExtras
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QTEXT3DGEOMETRY_P_H
+#endif // QT3DEXTRAS_QEXTRUDEDTEXTGEOMETRY_P_H
diff --git a/src/extras/3dtext/qtext3dmesh.cpp b/src/extras/3dtext/qextrudedtextmesh.cpp
index a89c01a4d..9d1dc7359 100644
--- a/src/extras/3dtext/qtext3dmesh.cpp
+++ b/src/extras/3dtext/qextrudedtextmesh.cpp
@@ -48,130 +48,108 @@
**
****************************************************************************/
-#include "qtext3dmesh.h"
-#include "qtext3dgeometry.h"
+#include "qextrudedtextmesh.h"
+#include "qextrudedtextgeometry.h"
QT_BEGIN_NAMESPACE
namespace Qt3DExtras {
/*!
- * \qmltype Text3DMesh
- * \instantiates Qt3DExtras::QText3DMesh
+ * \qmltype ExtrudedTextMesh
+ * \instantiates Qt3DExtras::QExtrudedTextMesh
* \inqmlmodule Qt3D.Extras
- * \brief A 3D Text mesh.
+ * \brief A 3D extruded Text mesh.
*/
/*!
- * \qmlproperty QString Text3DMesh::text
+ * \qmlproperty QString ExtrudedTextMesh::text
*
* Holds the text used for the mesh.
*/
/*!
- * \qmlproperty QFont Text3DMesh::font
+ * \qmlproperty QFont ExtrudedTextMesh::font
*
* Holds the font of the text.
*/
/*!
- * \qmlproperty float Text3DMesh::depth
+ * \qmlproperty float ExtrudedTextMesh::depth
*
* Holds the extrusion depth of the text.
*/
/*!
- * \qmlproperty float Text3DMesh::edgeSplitAngle
- *
- * Holds the threshold angle for smooth normals.
- */
-
-/*!
- * \class Qt3DExtras::QText3DMesh
- * \inheaderfile Qt3DExtras/QText3DMesh
+ * \class Qt3DExtras::QExtrudedTextMesh
+ * \inheaderfile Qt3DExtras/QExtrudedTextMesh
* \inmodule Qt3DExtras
*
* \inherits Qt3DRender::QGeometryRenderer
*
- * \brief A 3D Text mesh.
+ * \brief A 3D extruded Text mesh.
*/
/*!
* Constructs a new QText3DMesh with \a parent.
*/
-QText3DMesh::QText3DMesh(Qt3DCore::QNode *parent)
+QExtrudedTextMesh::QExtrudedTextMesh(Qt3DCore::QNode *parent)
: QGeometryRenderer(parent)
{
- QText3DGeometry *geometry = new QText3DGeometry();
- QObject::connect(geometry, &QText3DGeometry::depthChanged, this, &QText3DMesh::depthChanged);
- QObject::connect(geometry, &QText3DGeometry::textChanged, this, &QText3DMesh::textChanged);
- QObject::connect(geometry, &QText3DGeometry::fontChanged, this, &QText3DMesh::fontChanged);
- QObject::connect(geometry, &QText3DGeometry::edgeSplitAngleChanged, this, &QText3DMesh::edgeSplitAngleChanged);
+ QExtrudedTextGeometry *geometry = new QExtrudedTextGeometry();
+ QObject::connect(geometry, &QExtrudedTextGeometry::depthChanged, this, &QExtrudedTextMesh::depthChanged);
+ QObject::connect(geometry, &QExtrudedTextGeometry::textChanged, this, &QExtrudedTextMesh::textChanged);
+ QObject::connect(geometry, &QExtrudedTextGeometry::fontChanged, this, &QExtrudedTextMesh::fontChanged);
QGeometryRenderer::setGeometry(geometry);
}
/*! \internal */
-QText3DMesh::~QText3DMesh()
+QExtrudedTextMesh::~QExtrudedTextMesh()
{}
-void QText3DMesh::setText(QString text)
-{
- static_cast<QText3DGeometry*>(geometry())->setText(text);
-}
-
-void QText3DMesh::setFont(QFont font)
+void QExtrudedTextMesh::setText(const QString &text)
{
- static_cast<QText3DGeometry*>(geometry())->setFont(font);
+ static_cast<QExtrudedTextGeometry*>(geometry())->setText(text);
}
-void QText3DMesh::setDepth(float depth)
+void QExtrudedTextMesh::setFont(const QFont &font)
{
- static_cast<QText3DGeometry*>(geometry())->setDepth(depth);
+ static_cast<QExtrudedTextGeometry*>(geometry())->setFont(font);
}
-void QText3DMesh::setEdgeSplitAngle(float smoothAngle)
+void QExtrudedTextMesh::setDepth(float depth)
{
- static_cast<QText3DGeometry*>(geometry())->setEdgeSplitAngle(smoothAngle);
+ static_cast<QExtrudedTextGeometry*>(geometry())->setDepth(depth);
}
/*!
- * \property QString QText3DMesh::text
+ * \property QString QExtrudedTextMesh::text
*
* Holds the text used for the mesh.
*/
-QString QText3DMesh::text()
+QString QExtrudedTextMesh::text() const
{
- return static_cast<QText3DGeometry*>(geometry())->text();
+ return static_cast<QExtrudedTextGeometry*>(geometry())->text();
}
/*!
- * \property QFont QText3DMesh::font
+ * \property QFont QExtrudedTextMesh::font
*
* Holds the font of the text.
*/
-QFont QText3DMesh::font()
+QFont QExtrudedTextMesh::font() const
{
- return static_cast<QText3DGeometry*>(geometry())->font();
+ return static_cast<QExtrudedTextGeometry*>(geometry())->font();
}
/*!
- * \property float QText3DMesh::depth
+ * \property float QExtrudedTextMesh::depth
*
* Holds the extrusion depth of the text.
*/
-float QText3DMesh::depth()
-{
- return static_cast<QText3DGeometry*>(geometry())->depth();
-}
-
-/*!
- * \property float QText3DMesh::edgeSplitAngle
- *
- * Holds the threshold angle for smooth normals.
- */
-float QText3DMesh::edgeSplitAngle()
+float QExtrudedTextMesh::depth() const
{
- return static_cast<QText3DGeometry*>(geometry())->edgeSplitAngle();
+ return static_cast<QExtrudedTextGeometry*>(geometry())->extrusionLength();
}
} // namespace Qt3DExtras
diff --git a/src/extras/3dtext/qtext3dmesh.h b/src/extras/3dtext/qextrudedtextmesh.h
index 6bb546675..3f2f41a37 100644
--- a/src/extras/3dtext/qtext3dmesh.h
+++ b/src/extras/3dtext/qextrudedtextmesh.h
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QTEXT3DMESH_H
-#define QT3DEXTRAS_QTEXT3DMESH_H
+#ifndef QT3DEXTRAS_QEXTRUDEDTEXTMESH_H
+#define QT3DEXTRAS_QEXTRUDEDTEXTMESH_H
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qgeometryrenderer.h>
@@ -60,38 +60,34 @@ QT_BEGIN_NAMESPACE
namespace Qt3DExtras {
-class QT3DEXTRASSHARED_EXPORT QText3DMesh : public Qt3DRender::QGeometryRenderer
+class QT3DEXTRASSHARED_EXPORT QExtrudedTextMesh : public Qt3DRender::QGeometryRenderer
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
Q_PROPERTY(float depth READ depth WRITE setDepth NOTIFY depthChanged)
- Q_PROPERTY(float edgeSplitAngle READ edgeSplitAngle WRITE setEdgeSplitAngle NOTIFY edgeSplitAngleChanged)
public:
- QText3DMesh(Qt3DCore::QNode *parent = nullptr);
- ~QText3DMesh();
+ explicit QExtrudedTextMesh(Qt3DCore::QNode *parent = nullptr);
+ ~QExtrudedTextMesh();
- QString text();
- QFont font();
- float depth();
- float edgeSplitAngle();
+ QString text() const;
+ QFont font() const;
+ float depth() const;
public Q_SLOTS:
- void setText(QString text);
- void setFont(QFont font);
+ void setText(const QString &text);
+ void setFont(const QFont &font);
void setDepth(float depth);
- void setEdgeSplitAngle(float edgeSplitAngle);
Q_SIGNALS:
- void textChanged(QString text);
- void fontChanged(QFont font);
+ void textChanged(const QString &text);
+ void fontChanged(const QFont &font);
void depthChanged(float depth);
- void edgeSplitAngleChanged(float edgeSplitAngle);
};
} // namespace Qt3DExtras
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QTEXT3DMESH_H
+#endif // QT3DEXTRAS_QEXTRUDEDTEXTMESH_H
diff --git a/src/extras/animations/animations.pri b/src/extras/animations/animations.pri
deleted file mode 100644
index 71d6099fc..000000000
--- a/src/extras/animations/animations.pri
+++ /dev/null
@@ -1,26 +0,0 @@
-HEADERS += \
- $$PWD/qanimationcontroller.h \
- $$PWD/qanimationcontroller_p.h \
- $$PWD/qanimationgroup.h \
- $$PWD/qanimationgroup_p.h \
- $$PWD/qkeyframeanimation.h \
- $$PWD/qkeyframeanimation_p.h \
- $$PWD/qmorphinganimation.h \
- $$PWD/qmorphinganimation_p.h \
- $$PWD/qabstractanimation.h \
- $$PWD/qabstractanimation_p.h \
- $$PWD/qmorphtarget.h \
- $$PWD/qmorphtarget_p.h \
- $$PWD/qvertexblendanimation.h \
- $$PWD/qvertexblendanimation_p.h
-
-SOURCES += \
- $$PWD/qanimationcontroller.cpp \
- $$PWD/qanimationgroup.cpp \
- $$PWD/qkeyframeanimation.cpp \
- $$PWD/qmorphinganimation.cpp \
- $$PWD/qabstractanimation.cpp \
- $$PWD/qmorphtarget.cpp \
- $$PWD/qvertexblendanimation.cpp
-
-INCLUDEPATH += $$PWD
diff --git a/src/extras/animations/qanimationgroup.cpp b/src/extras/animations/qanimationgroup.cpp
deleted file mode 100644
index e9febe811..000000000
--- a/src/extras/animations/qanimationgroup.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qanimationgroup.h"
-#include "Qt3DExtras/private/qanimationgroup_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DExtras {
-
-QAnimationGroupPrivate::QAnimationGroupPrivate()
- : QObjectPrivate()
- , m_position(0.0f)
- , m_duration(0.0f)
-{
-
-}
-
-void QAnimationGroupPrivate::updatePosition(float position)
-{
- m_position = position;
- for (QAbstractAnimation *aa : m_animations)
- aa->setPosition(position);
-}
-
-QAnimationGroup::QAnimationGroup(QObject *parent)
- : QObject(*new QAnimationGroupPrivate, parent)
-{
-
-}
-
-QString QAnimationGroup::name() const
-{
- Q_D(const QAnimationGroup);
- return d->m_name;
-}
-
-QVector<Qt3DExtras::QAbstractAnimation *> QAnimationGroup::animationList()
-{
- Q_D(QAnimationGroup);
- return d->m_animations;
-}
-
-float QAnimationGroup::position() const
-{
- Q_D(const QAnimationGroup);
- return d->m_position;
-}
-
-float QAnimationGroup::duration() const
-{
- Q_D(const QAnimationGroup);
- return d->m_duration;
-}
-
-void QAnimationGroup::setName(const QString &name)
-{
- Q_D(QAnimationGroup);
- if (d->m_name != name) {
- d->m_name = name;
- emit nameChanged(name);
- }
-}
-
-void QAnimationGroup::setAnimations(const QVector<Qt3DExtras::QAbstractAnimation *> &animations)
-{
- Q_D(QAnimationGroup);
- d->m_animations = animations;
- d->m_duration = 0.0f;
- for (const Qt3DExtras::QAbstractAnimation *a : animations)
- d->m_duration = qMax(d->m_duration, a->duration());
-}
-
-void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
-{
- Q_D(QAnimationGroup);
- d->m_animations.push_back(animation);
- d->m_duration = qMax(d->m_duration, animation->duration());
-}
-
-void QAnimationGroup::setPosition(float position)
-{
- Q_D(QAnimationGroup);
- if (!qFuzzyCompare(d->m_position, position)) {
- d->updatePosition(position);
- emit positionChanged(position);
- }
-}
-
-} // Qt3DExtras
-
-QT_END_NAMESPACE
diff --git a/src/extras/animations/qkeyframeanimation.cpp b/src/extras/animations/qkeyframeanimation.cpp
deleted file mode 100644
index 425cbe0df..000000000
--- a/src/extras/animations/qkeyframeanimation.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkeyframeanimation.h"
-#include "Qt3DExtras/private/qkeyframeanimation_p.h"
-
-#include <cmath>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DExtras {
-
-QKeyframeAnimationPrivate::QKeyframeAnimationPrivate()
- : QAbstractAnimationPrivate(QAbstractAnimation::KeyframeAnimation)
- , m_minposition(0.0f)
- , m_maxposition(0.0f)
- , m_prevPosition(-1.0f)
- , m_target(nullptr)
- , m_startMode(QKeyframeAnimation::Constant)
- , m_endMode(QKeyframeAnimation::Constant)
-{
-
-}
-
-QKeyframeAnimation::QKeyframeAnimation(QObject *parent)
- : QAbstractAnimation(*new QKeyframeAnimationPrivate(), parent)
-{
- Q_D(QKeyframeAnimation);
- d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
- this, &QKeyframeAnimation::updateAnimation);
-}
-
-
-void QKeyframeAnimation::setFramePositions(const QVector<float> &positions)
-{
- Q_D(QKeyframeAnimation);
- d->m_framePositions = positions;
- d->m_prevPosition = -1.0f;
- if (d->m_framePositions.size() == 0) {
- d->m_minposition = d->m_maxposition = 0.0f;
- return;
- }
- d->m_minposition = d->m_framePositions.first();
- d->m_maxposition = d->m_framePositions.last();
- float lastPos = d->m_minposition;
- for (float p : d->m_framePositions) {
- if (p < lastPos || p > d->m_maxposition)
- qWarning() << "positions not ordered correctly";
- lastPos = p;
- }
- setDuration(d->m_maxposition);
-}
-
-void QKeyframeAnimation::setKeyframes(const QVector<Qt3DCore::QTransform *> &keyframes)
-{
- Q_D(QKeyframeAnimation);
- d->m_keyframes = keyframes;
-}
-
-// slerp which allows long path
-QQuaternion lslerp(QQuaternion q1, QQuaternion q2, float t)
-{
- QQuaternion ret;
- // Handle the easy cases first.
- if (t <= 0.0f)
- return q1;
- else if (t >= 1.0f)
- return q2;
-
- float cos = qBound(-1.0f, QQuaternion::dotProduct(q1, q2), 1.0f);
- float angle = std::acos(cos);
- float sin = std::sin(angle);
- if (!qFuzzyIsNull(sin)) {
- float a = std::sin((1.0 - t) * angle) / sin;
- float b = std::sin(t * angle) / sin;
- ret = (q1 * a + q2 * b).normalized();
- } else {
- ret = q1 * (1.0f-t) + q2 * t;
- }
- return ret;
-}
-
-void QKeyframeAnimationPrivate::calculateFrame(float position)
-{
- if (m_target && m_framePositions.size() > 0
- && m_keyframes.size() == m_framePositions.size()
- && m_prevPosition != m_position) {
- if (m_position >= m_minposition && m_position < m_maxposition) {
- for (int i = 0; i < m_framePositions.size() - 1; i++) {
- if (position >= m_framePositions.at(i)
- && position < m_framePositions.at(i+1)) {
- float ip = (position - m_framePositions.at(i))
- / (m_framePositions.at(i+1) - m_framePositions.at(i));
- float eIp = m_easing.valueForProgress(ip);
- float eIip = 1.0f - eIp;
-
- Qt3DCore::QTransform *a = m_keyframes.at(i);
- Qt3DCore::QTransform *b = m_keyframes.at(i+1);
-
- QVector3D s = a->scale3D() * eIip + b->scale3D() * eIp;
- QVector3D t = a->translation() * eIip + b->translation() * eIp;
- QQuaternion r = QQuaternion::slerp(a->rotation(), b->rotation(), eIp);
-
- m_target->setRotation(r);
- m_target->setScale3D(s);
- m_target->setTranslation(t);
- return;
- }
- }
- } else if (position < m_minposition) {
- m_target->setRotation(m_keyframes.first()->rotation());
- m_target->setScale3D(m_keyframes.first()->scale3D());
- m_target->setTranslation(m_keyframes.first()->translation());
- } else {
- m_target->setRotation(m_keyframes.last()->rotation());
- m_target->setScale3D(m_keyframes.last()->scale3D());
- m_target->setTranslation(m_keyframes.last()->translation());
- }
- m_prevPosition = m_position;
- }
-}
-
-void QKeyframeAnimation::updateAnimation(float position)
-{
- Q_D(QKeyframeAnimation);
- d->calculateFrame(position);
-}
-
-QVector<float> QKeyframeAnimation::framePositions() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_framePositions;
-}
-
-QVector<Qt3DCore::QTransform *> QKeyframeAnimation::keyframeList() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_keyframes;
-}
-
-void QKeyframeAnimation::setTarget(Qt3DCore::QTransform *target)
-{
- Q_D(QKeyframeAnimation);
- if (d->m_target != target) {
- d->m_target = target;
- emit targetChanged(d->m_target);
- d->m_prevPosition = -1.0f;
-
- if (target) {
- d->m_baseScale = target->scale3D();
- d->m_baseTranslation = target->translation();
- d->m_baseRotation = target->rotation();
- }
- }
-}
-
-QKeyframeAnimation::RepeatMode QKeyframeAnimation::startMode() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_startMode;
-}
-
-QKeyframeAnimation::RepeatMode QKeyframeAnimation::endMode() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_endMode;
-}
-
-void QKeyframeAnimation::setEasing(QEasingCurve::Type easing)
-{
- Q_D(QKeyframeAnimation);
- if (d->m_easing.type() != easing) {
- d->m_easing.setType(easing);
- emit easingChanged(easing);
- }
-}
-
-void QKeyframeAnimation::setTargetName(const QString &name)
-{
- Q_D(QKeyframeAnimation);
- d->m_targetName = name;
- emit targetNameChanged(name);
-}
-
-void QKeyframeAnimation::setStartMode(QKeyframeAnimation::RepeatMode mode)
-{
- Q_D(QKeyframeAnimation);
- if (d->m_startMode != mode) {
- d->m_startMode = mode;
- emit startModeChanged(mode);
- }
-}
-
-void QKeyframeAnimation::setEndMode(QKeyframeAnimation::RepeatMode mode)
-{
- Q_D(QKeyframeAnimation);
- if (mode != d->m_endMode) {
- d->m_endMode = mode;
- emit endModeChanged(mode);
- }
-}
-
-void QKeyframeAnimation::addKeyframe(Qt3DCore::QTransform *keyframe)
-{
- Q_D(QKeyframeAnimation);
- d->m_keyframes.push_back(keyframe);
-}
-
-QString QKeyframeAnimation::targetName() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_targetName;
-}
-
-QEasingCurve::Type QKeyframeAnimation::easing() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_easing.type();
-}
-
-Qt3DCore::QTransform *QKeyframeAnimation::target() const
-{
- Q_D(const QKeyframeAnimation);
- return d->m_target;
-}
-
-} // Qt3DExtras
-
-QT_END_NAMESPACE
diff --git a/src/extras/animations/qmorphinganimation.cpp b/src/extras/animations/qmorphinganimation.cpp
deleted file mode 100644
index e7fe05147..000000000
--- a/src/extras/animations/qmorphinganimation.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmorphinganimation.h"
-#include <private/qmorphinganimation_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DExtras {
-
-QMorphingAnimationPrivate::QMorphingAnimationPrivate()
- : QAbstractAnimationPrivate(QAbstractAnimation::MorphingAnimation)
- , m_flattened(nullptr)
- , m_method(QMorphingAnimation::Relative)
- , m_interpolator(0.0f)
- , m_target(nullptr)
- , m_currentTarget(nullptr)
-{
- m_easing.setType(QEasingCurve::InOutCubic);
-}
-
-QMorphingAnimationPrivate::~QMorphingAnimationPrivate()
-{
- for (QVector<float> *weights : m_weights)
- delete weights;
-}
-
-void QMorphingAnimationPrivate::updateAnimation(float position)
-{
- Q_Q(QMorphingAnimation);
- if (!m_target || !m_target->geometry())
- return;
-
- m_morphKey.resize(m_morphTargets.size());
-
- for (int i = 0; i < m_targetPositions.size() - 1; ++i) {
- if (position > m_targetPositions.at(i) && position <= m_targetPositions.at(i + 1)) {
- float interpolator = (position - m_targetPositions.at(i))
- / (m_targetPositions.at(i + 1) - m_targetPositions.at(i));
- interpolator = m_easing.valueForProgress(interpolator);
- float iip = 1.0f - interpolator;
- float sum = 0.0f;
- QVector<int> relevantValues;
- for (int j = 0; j < m_morphTargets.size(); ++j) {
- m_morphKey[j] = interpolator * m_weights.at(i + 1)->at(j)
- + iip * m_weights.at(i)->at(j);
- sum += m_morphKey[j];
- if (!qFuzzyIsNull(m_morphKey[j]))
- relevantValues.push_back(j);
- }
-
- if (relevantValues.size() == 0 || qFuzzyIsNull(sum)) {
- // only base is used
- interpolator = 0.0f;
- } else if (relevantValues.size() == 1) {
- // one morph target has non-zero weight
- setTargetInterpolated(relevantValues[0]);
- interpolator = sum;
- } else {
- // more than one morph target has non-zero weight
- // flatten morph targets to one
- qWarning() << Q_FUNC_INFO << "Flattening required";
- }
- if (!qFuzzyCompare(interpolator, m_interpolator)) {
- if (m_method == QMorphingAnimation::Normalized)
- m_interpolator = interpolator;
- else
- m_interpolator = -interpolator;
- emit q->interpolatorChanged(m_interpolator);
- }
- return;
- }
- }
-}
-
-void QMorphingAnimationPrivate::setTargetInterpolated(int morphTarget)
-{
- QMorphTarget *target = m_morphTargets[morphTarget];
- Qt3DRender::QGeometry *geometry = m_target->geometry();
-
- // remove attributes from previous frame
- if (m_currentTarget && (target != m_currentTarget)) {
- const QVector<Qt3DRender::QAttribute *> targetAttributes = m_currentTarget->attributeList();
- for (int i = 0; i < targetAttributes.size(); ++i)
- geometry->removeAttribute(targetAttributes.at(i));
- }
-
- const QVector<Qt3DRender::QAttribute *> targetAttributes = target->attributeList();
-
- // add attributes from current frame to the geometry
- if (target != m_currentTarget) {
- for (int i = 0; i < m_attributeNames.size(); ++i) {
- QString targetName = m_attributeNames.at(i);
- targetName.append("Target");
- targetAttributes[i]->setName(targetName);
- geometry->addAttribute(targetAttributes.at(i));
- }
- }
- m_currentTarget = target;
-}
-
-QMorphingAnimation::QMorphingAnimation(QObject *parent)
- : QAbstractAnimation(*new QMorphingAnimationPrivate, parent)
-{
- Q_D(QMorphingAnimation);
- d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
- this, &QMorphingAnimation::updateAnimation);
-}
-
-QVector<float> QMorphingAnimation::targetPositions() const
-{
- Q_D(const QMorphingAnimation);
- return d->m_targetPositions;
-}
-
-float QMorphingAnimation::interpolator() const
-{
- Q_D(const QMorphingAnimation);
- return d->m_interpolator;
-}
-
-Qt3DRender::QGeometryRenderer *QMorphingAnimation::target() const
-{
- Q_D(const QMorphingAnimation);
- return d->m_target;
-}
-
-QString QMorphingAnimation::targetName() const
-{
- Q_D(const QMorphingAnimation);
- return d->m_targetName;
-}
-
-QMorphingAnimation::Method QMorphingAnimation::method() const
-{
- Q_D(const QMorphingAnimation);
- return d->m_method;
-}
-
-QEasingCurve::Type QMorphingAnimation::easing() const
-{
- Q_D(const QMorphingAnimation);
- return d->m_easing.type();
-}
-
-void QMorphingAnimation::setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets)
-{
- Q_D(QMorphingAnimation);
- d->m_morphTargets = targets;
- d->m_attributeNames = targets[0]->attributeNames();
-}
-
-void QMorphingAnimation::addMorphTarget(Qt3DExtras::QMorphTarget *target)
-{
- Q_D(QMorphingAnimation);
- if (!d->m_morphTargets.contains(target))
- d->m_morphTargets.push_back(target);
-}
-
-void QMorphingAnimation::removeMorphTarget(Qt3DExtras::QMorphTarget *target)
-{
- Q_D(QMorphingAnimation);
- d->m_morphTargets.removeAll(target);
-}
-
-void QMorphingAnimation::setTargetPositions(const QVector<float> &targetPositions)
-{
- Q_D(QMorphingAnimation);
- d->m_targetPositions = targetPositions;
- emit targetPositionsChanged(targetPositions);
- setDuration(d->m_targetPositions.last());
- if (d->m_weights.size() < targetPositions.size()) {
- d->m_weights.resize(targetPositions.size());
- for (int i = 0; i < d->m_weights.size(); ++i) {
- if (d->m_weights[i] == nullptr)
- d->m_weights[i] = new QVector<float>();
- }
- }
-}
-
-void QMorphingAnimation::setTarget(Qt3DRender::QGeometryRenderer *target)
-{
- Q_D(QMorphingAnimation);
- if (d->m_target != target) {
- d->m_target = target;
- emit targetChanged(target);
- }
-}
-
-void QMorphingAnimation::setWeights(int positionIndex, const QVector<float> &weights)
-{
- Q_D(QMorphingAnimation);
- if (d->m_weights.size() < positionIndex)
- d->m_weights.resize(positionIndex + 1);
- if (d->m_weights[positionIndex] == nullptr)
- d->m_weights[positionIndex] = new QVector<float>();
- *d->m_weights[positionIndex] = weights;
-}
-
-QVector<float> QMorphingAnimation::getWeights(int positionIndex)
-{
- Q_D(QMorphingAnimation);
- return *d->m_weights[positionIndex];
-}
-
-QVector<Qt3DExtras::QMorphTarget *> QMorphingAnimation::morphTargetList()
-{
- Q_D(QMorphingAnimation);
- return d->m_morphTargets;
-}
-
-void QMorphingAnimation::setTargetName(const QString name)
-{
- Q_D(QMorphingAnimation);
- if (d->m_targetName != name) {
- d->m_targetName = name;
- emit targetNameChanged(name);
- }
-}
-
-void QMorphingAnimation::setMethod(QMorphingAnimation::Method method)
-{
- Q_D(QMorphingAnimation);
- if (d->m_method != method) {
- d->m_method = method;
- emit methodChanged(method);
- }
-}
-
-void QMorphingAnimation::setEasing(QEasingCurve::Type easing)
-{
- Q_D(QMorphingAnimation);
- if (d->m_easing.type() != easing) {
- d->m_easing.setType(easing);
- emit easingChanged(easing);
- }
-}
-
-void QMorphingAnimation::updateAnimation(float position)
-{
- Q_D(QMorphingAnimation);
- d->updateAnimation(position);
-}
-
-} // Qt3DExtras
-
-QT_END_NAMESPACE
diff --git a/src/extras/defaults/defaults.pri b/src/extras/defaults/defaults.pri
index 21ef6fef6..8a18fb6e9 100644
--- a/src/extras/defaults/defaults.pri
+++ b/src/extras/defaults/defaults.pri
@@ -4,6 +4,7 @@ HEADERS += \
$$PWD/qphongmaterial.h \
$$PWD/qphongmaterial_p.h \
$$PWD/qdiffusemapmaterial_p.h \
+ $$PWD/qdiffusemapmaterial.h \
$$PWD/qnormaldiffusespecularmapmaterial.h \
$$PWD/qnormaldiffusespecularmapmaterial_p.h \
$$PWD/qnormaldiffusemapmaterial.h \
@@ -23,13 +24,19 @@ HEADERS += \
$$PWD/qphongalphamaterial.h \
$$PWD/qphongalphamaterial_p.h \
$$PWD/qt3dwindow.h \
+ $$PWD/qt3dwindow_p.h \
$$PWD/qfirstpersoncameracontroller.h \
$$PWD/qfirstpersoncameracontroller_p.h \
$$PWD/qorbitcameracontroller.h \
$$PWD/qorbitcameracontroller_p.h \
+ $$PWD/qtexturematerial.h \
+ $$PWD/qtexturematerial_p.h \
+ $$PWD/qmetalroughmaterial.h \
+ $$PWD/qmetalroughmaterial_p.h \
+ $$PWD/qtexturedmetalroughmaterial.h \
+ $$PWD/qtexturedmetalroughmaterial_p.h \
$$PWD/qmorphphongmaterial.h \
- $$PWD/qmorphphongmaterial_p.h \
- $$PWD/qdiffusemapmaterial.h
+ $$PWD/qmorphphongmaterial_p.h
SOURCES += \
$$PWD/qphongmaterial.cpp \
@@ -46,5 +53,8 @@ SOURCES += \
$$PWD/qt3dwindow.cpp \
$$PWD/qfirstpersoncameracontroller.cpp \
$$PWD/qorbitcameracontroller.cpp \
+ $$PWD/qtexturematerial.cpp \
+ $$PWD/qmetalroughmaterial.cpp \
+ $$PWD/qtexturedmetalroughmaterial.cpp \
$$PWD/qmorphphongmaterial.cpp
diff --git a/src/extras/defaults/qdiffusemapmaterial.cpp b/src/extras/defaults/qdiffusemapmaterial.cpp
index b3aa3bf00..a6da98a2e 100644
--- a/src/extras/defaults/qdiffusemapmaterial.cpp
+++ b/src/extras/defaults/qdiffusemapmaterial.cpp
@@ -39,6 +39,7 @@
#include "qdiffusemapmaterial.h"
#include "qdiffusemapmaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qeffect.h>
@@ -48,9 +49,9 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qdiffusemapmaterial.h b/src/extras/defaults/qdiffusemapmaterial.h
index b6bba9b36..e6c632ed2 100644
--- a/src/extras/defaults/qdiffusemapmaterial.h
+++ b/src/extras/defaults/qdiffusemapmaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qdiffusespecularmapmaterial.cpp b/src/extras/defaults/qdiffusespecularmapmaterial.cpp
index 4b79eea2b..615ee6305 100644
--- a/src/extras/defaults/qdiffusespecularmapmaterial.cpp
+++ b/src/extras/defaults/qdiffusespecularmapmaterial.cpp
@@ -39,6 +39,7 @@
#include "qdiffusespecularmapmaterial.h"
#include "qdiffusespecularmapmaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qeffect.h>
@@ -48,9 +49,9 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qdiffusespecularmapmaterial.h b/src/extras/defaults/qdiffusespecularmapmaterial.h
index d5dd053bd..d86948673 100644
--- a/src/extras/defaults/qdiffusespecularmapmaterial.h
+++ b/src/extras/defaults/qdiffusespecularmapmaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qfirstpersoncameracontroller.cpp b/src/extras/defaults/qfirstpersoncameracontroller.cpp
index e31448eb8..5321bfcf2 100644
--- a/src/extras/defaults/qfirstpersoncameracontroller.cpp
+++ b/src/extras/defaults/qfirstpersoncameracontroller.cpp
@@ -1,66 +1,53 @@
/****************************************************************************
**
** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
+** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:BSD$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "qfirstpersoncameracontroller_p.h"
#include "qfirstpersoncameracontroller.h"
-#include <Qt3DRender/QCamera>
-#include <Qt3DInput/QAxis>
-#include <Qt3DInput/QAnalogAxisInput>
-#include <Qt3DInput/QButtonAxisInput>
+#include "qfirstpersoncameracontroller_p.h"
+
#include <Qt3DInput/QAction>
#include <Qt3DInput/QActionInput>
-#include <Qt3DInput/QLogicalDevice>
+#include <Qt3DInput/QAnalogAxisInput>
+#include <Qt3DInput/QAxis>
+#include <Qt3DInput/QButtonAxisInput>
+#include <Qt3DLogic/QFrameAction>
#include <Qt3DInput/QKeyboardDevice>
+#include <Qt3DInput/QLogicalDevice>
#include <Qt3DInput/QMouseDevice>
#include <Qt3DInput/QMouseEvent>
-#include <Qt3DLogic/QFrameAction>
+#include <Qt3DRender/QCamera>
QT_BEGIN_NAMESPACE
@@ -80,6 +67,8 @@ QFirstPersonCameraControllerPrivate::QFirstPersonCameraControllerPrivate()
, m_fineMotionKeyInput(new Qt3DInput::QActionInput())
, m_mouseRxInput(new Qt3DInput::QAnalogAxisInput())
, m_mouseRyInput(new Qt3DInput::QAnalogAxisInput())
+ , m_mouseTzXInput(new Qt3DInput::QAnalogAxisInput())
+ , m_mouseTzYInput(new Qt3DInput::QAnalogAxisInput())
, m_keyboardTxPosInput(new Qt3DInput::QButtonAxisInput())
, m_keyboardTyPosInput(new Qt3DInput::QButtonAxisInput())
, m_keyboardTzPosInput(new Qt3DInput::QButtonAxisInput())
@@ -92,6 +81,8 @@ QFirstPersonCameraControllerPrivate::QFirstPersonCameraControllerPrivate()
, m_frameAction(new Qt3DLogic::QFrameAction())
, m_linearSpeed(10.0f)
, m_lookSpeed(180.0f)
+ , m_acceleration(-1.0f)
+ , m_deceleration(-1.0f)
, m_firstPersonUp(QVector3D(0.0f, 1.0f, 0.0f))
{}
@@ -121,6 +112,16 @@ void QFirstPersonCameraControllerPrivate::init()
m_mouseRyInput->setSourceDevice(m_mouseDevice);
m_ryAxis->addInput(m_mouseRyInput);
+ // Mouse Wheel X
+ m_mouseTzXInput->setAxis(Qt3DInput::QMouseDevice::WheelX);
+ m_mouseTzXInput->setSourceDevice(m_mouseDevice);
+ m_tzAxis->addInput(m_mouseTzXInput);
+
+ // Mouse Wheel Y
+ m_mouseTzYInput->setAxis(Qt3DInput::QMouseDevice::WheelY);
+ m_mouseTzYInput->setSourceDevice(m_mouseDevice);
+ m_tzAxis->addInput(m_mouseTzYInput);
+
// Keyboard Pos Tx
m_keyboardTxPosInput->setButtons(QVector<int>() << Qt::Key_Right);
m_keyboardTxPosInput->setScale(1.0f);
@@ -167,6 +168,8 @@ void QFirstPersonCameraControllerPrivate::init()
m_logicalDevice->addAxis(m_tyAxis);
m_logicalDevice->addAxis(m_tzAxis);
+ applyAccelerations();
+
Q_Q(QFirstPersonCameraController);
//// FrameAction
@@ -181,6 +184,23 @@ void QFirstPersonCameraControllerPrivate::init()
q->addComponent(m_logicalDevice);
}
+void QFirstPersonCameraControllerPrivate::applyAccelerations()
+{
+ const auto inputs = {
+ m_keyboardTxPosInput,
+ m_keyboardTyPosInput,
+ m_keyboardTzPosInput,
+ m_keyboardTxNegInput,
+ m_keyboardTyNegInput,
+ m_keyboardTzNegInput
+ };
+
+ for (auto input : inputs) {
+ input->setAcceleration(m_acceleration);
+ input->setDeceleration(m_deceleration);
+ }
+}
+
void QFirstPersonCameraControllerPrivate::_q_onTriggered(float dt)
{
if (m_camera != nullptr) {
@@ -215,6 +235,9 @@ void QFirstPersonCameraControllerPrivate::_q_onTriggered(float dt)
\li While the left mouse button is pressed, mouse movement along x-axis pans the camera and
movement along y-axis tilts it.
\row
+ \li Mouse scroll wheel
+ \li Zooms the camera in and out without changing the view center.
+ \row
\li Shift key
\li Turns the fine motion control active while pressed. Makes mouse pan and tilt less
sensitive.
@@ -273,6 +296,28 @@ float QFirstPersonCameraController::lookSpeed() const
return d->m_lookSpeed;
}
+/*!
+ \property QFirstPersonCameraController::acceleration
+
+ Holds the current acceleration of the camera controller.
+*/
+float QFirstPersonCameraController::acceleration() const
+{
+ Q_D(const QFirstPersonCameraController);
+ return d->m_acceleration;
+}
+
+/*!
+ \property QFirstPersonCameraController::deceleration
+
+ Holds the current deceleration of the camera controller.
+*/
+float QFirstPersonCameraController::deceleration() const
+{
+ Q_D(const QFirstPersonCameraController);
+ return d->m_deceleration;
+}
+
void QFirstPersonCameraController::setCamera(Qt3DRender::QCamera *camera)
{
Q_D(QFirstPersonCameraController);
@@ -312,6 +357,26 @@ void QFirstPersonCameraController::setLookSpeed(float lookSpeed)
}
}
+void QFirstPersonCameraController::setAcceleration(float acceleration)
+{
+ Q_D(QFirstPersonCameraController);
+ if (d->m_acceleration != acceleration) {
+ d->m_acceleration = acceleration;
+ d->applyAccelerations();
+ emit accelerationChanged(acceleration);
+ }
+}
+
+void QFirstPersonCameraController::setDeceleration(float deceleration)
+{
+ Q_D(QFirstPersonCameraController);
+ if (d->m_deceleration != deceleration) {
+ d->m_deceleration = deceleration;
+ d->applyAccelerations();
+ emit decelerationChanged(deceleration);
+ }
+}
+
} // Qt3DExtras
QT_END_NAMESPACE
diff --git a/src/extras/defaults/qfirstpersoncameracontroller.h b/src/extras/defaults/qfirstpersoncameracontroller.h
index e50d4db5a..3f7a6acc4 100644
--- a/src/extras/defaults/qfirstpersoncameracontroller.h
+++ b/src/extras/defaults/qfirstpersoncameracontroller.h
@@ -1,48 +1,34 @@
/****************************************************************************
**
** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
+** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:BSD$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
@@ -70,7 +56,8 @@ class QT3DEXTRASSHARED_EXPORT QFirstPersonCameraController : public Qt3DCore::QE
Q_PROPERTY(Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged)
Q_PROPERTY(float linearSpeed READ linearSpeed WRITE setLinearSpeed NOTIFY linearSpeedChanged)
Q_PROPERTY(float lookSpeed READ lookSpeed WRITE setLookSpeed NOTIFY lookSpeedChanged)
-
+ Q_PROPERTY(float acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
+ Q_PROPERTY(float deceleration READ deceleration WRITE setDeceleration NOTIFY decelerationChanged)
public:
explicit QFirstPersonCameraController(Qt3DCore::QNode *parent = nullptr);
~QFirstPersonCameraController();
@@ -78,15 +65,21 @@ public:
Qt3DRender::QCamera *camera() const;
float linearSpeed() const;
float lookSpeed() const;
+ float acceleration() const;
+ float deceleration() const;
void setCamera(Qt3DRender::QCamera *camera);
void setLinearSpeed(float linearSpeed);
void setLookSpeed(float lookSpeed);
+ void setAcceleration(float acceleration);
+ void setDeceleration(float deceleration);
Q_SIGNALS:
void cameraChanged();
void linearSpeedChanged();
void lookSpeedChanged();
+ void accelerationChanged(float acceleration);
+ void decelerationChanged(float deceleration);
private:
Q_DECLARE_PRIVATE(QFirstPersonCameraController)
diff --git a/src/extras/defaults/qfirstpersoncameracontroller_p.h b/src/extras/defaults/qfirstpersoncameracontroller_p.h
index 9ea830f85..48a7c7998 100644
--- a/src/extras/defaults/qfirstpersoncameracontroller_p.h
+++ b/src/extras/defaults/qfirstpersoncameracontroller_p.h
@@ -51,9 +51,11 @@
#ifndef QT3DEXTRAS_QFIRSTPERSONCAMERACONTROLLER_P_H
#define QT3DEXTRAS_QFIRSTPERSONCAMERACONTROLLER_P_H
+#include <Qt3DExtras/qfirstpersoncameracontroller.h>
+#include <QtGui/QVector3D>
+
#include <Qt3DCore/private/qentity_p.h>
-#include <QVector3D>
-#include "qfirstpersoncameracontroller.h"
+
//
// W A R N I N G
@@ -98,6 +100,7 @@ public:
QFirstPersonCameraControllerPrivate();
void init();
+ void applyAccelerations();
Qt3DRender::QCamera *m_camera;
@@ -115,6 +118,8 @@ public:
Qt3DInput::QAnalogAxisInput *m_mouseRxInput;
Qt3DInput::QAnalogAxisInput *m_mouseRyInput;
+ Qt3DInput::QAnalogAxisInput *m_mouseTzXInput;
+ Qt3DInput::QAnalogAxisInput *m_mouseTzYInput;
Qt3DInput::QButtonAxisInput *m_keyboardTxPosInput;
Qt3DInput::QButtonAxisInput *m_keyboardTyPosInput;
Qt3DInput::QButtonAxisInput *m_keyboardTzPosInput;
@@ -131,6 +136,8 @@ public:
float m_linearSpeed;
float m_lookSpeed;
+ float m_acceleration;
+ float m_deceleration;
QVector3D m_firstPersonUp;
void _q_onTriggered(float);
diff --git a/src/extras/defaults/qforwardrenderer.cpp b/src/extras/defaults/qforwardrenderer.cpp
index d556b58d3..3a5c6803b 100644
--- a/src/extras/defaults/qforwardrenderer.cpp
+++ b/src/extras/defaults/qforwardrenderer.cpp
@@ -134,6 +134,8 @@ QForwardRenderer::QForwardRenderer(QNode *parent)
QObject::connect(d->m_cameraSelector, &QCameraSelector::cameraChanged, this, &QForwardRenderer::cameraChanged);
QObject::connect(d->m_surfaceSelector, &QRenderSurfaceSelector::surfaceChanged, this, &QForwardRenderer::surfaceChanged);
QObject::connect(d->m_surfaceSelector, &QRenderSurfaceSelector::externalRenderTargetSizeChanged, this, &QForwardRenderer::externalRenderTargetSizeChanged);
+ QObject::connect(d->m_frustumCulling, &QFrustumCulling::enabledChanged, this, &QForwardRenderer::frustumCullingEnabledChanged);
+ QObject::connect(d->m_viewport, &QViewport::gammaChanged, this, &QForwardRenderer::gammaChanged);
d->init();
}
@@ -171,6 +173,18 @@ void QForwardRenderer::setExternalRenderTargetSize(const QSize &size)
d->m_surfaceSelector->setExternalRenderTargetSize(size);
}
+void QForwardRenderer::setFrustumCullingEnabled(bool enabled)
+{
+ Q_D(QForwardRenderer);
+ d->m_frustumCulling->setEnabled(enabled);
+}
+
+void QForwardRenderer::setGamma(float gamma)
+{
+ Q_D(QForwardRenderer);
+ d->m_viewport->setGamma(gamma);
+}
+
/*!
\qmlproperty rect ForwardRenderer::viewportRect
@@ -226,6 +240,21 @@ Qt3DCore::QEntity *QForwardRenderer::camera() const
}
/*!
+ \qmlproperty Object ForwardRenderer::window
+
+ Holds the current render surface.
+
+ \deprecated
+*/
+/*!
+ \property QForwardRenderer::window
+
+ Holds the current render surface.
+
+ \deprecated
+*/
+
+/*!
\qmlproperty Object ForwardRenderer::surface
Holds the current render surface.
@@ -247,6 +276,38 @@ QSize QForwardRenderer::externalRenderTargetSize() const
return d->m_surfaceSelector->externalRenderTargetSize();
}
+/*!
+ \qmlproperty color ForwardRenderer::frustumCulling
+
+ Indicates if the renderer applies frustum culling to the scene.
+*/
+/*!
+ \property QForwardRenderer::frustumCulling
+
+ Indicates if the renderer applies frustum culling to the scene.
+*/
+bool QForwardRenderer::isFrustumCullingEnabled() const
+{
+ Q_D(const QForwardRenderer);
+ return d->m_frustumCulling->isEnabled();
+}
+
+/*!
+ \qmlproperty color ForwardRenderer::gamma
+
+ Holds the gamma value the renderer applies to the scene.
+*/
+/*!
+ \property QForwardRenderer::gamma
+
+ Holds the gamma value the renderer applies to the scene.
+*/
+float QForwardRenderer::gamma() const
+{
+ Q_D(const QForwardRenderer);
+ return d->m_viewport->gamma();
+}
+
} // namespace Qt3DExtras
QT_END_NAMESPACE
diff --git a/src/extras/defaults/qforwardrenderer.h b/src/extras/defaults/qforwardrenderer.h
index 01f50f452..7b6078169 100644
--- a/src/extras/defaults/qforwardrenderer.h
+++ b/src/extras/defaults/qforwardrenderer.h
@@ -42,8 +42,9 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qtechniquefilter.h>
-#include <QRectF>
-#include <QColor>
+#include <QtCore/QRectF>
+#include <QtGui/QColor>
+
QT_BEGIN_NAMESPACE
@@ -57,10 +58,13 @@ class QT3DEXTRASSHARED_EXPORT QForwardRenderer : public Qt3DRender::QTechniqueFi
{
Q_OBJECT
Q_PROPERTY(QObject *surface READ surface WRITE setSurface NOTIFY surfaceChanged)
+ Q_PROPERTY(QObject *window READ surface WRITE setSurface NOTIFY surfaceChanged)
Q_PROPERTY(QRectF viewportRect READ viewportRect WRITE setViewportRect NOTIFY viewportRectChanged)
Q_PROPERTY(QColor clearColor READ clearColor WRITE setClearColor NOTIFY clearColorChanged)
Q_PROPERTY(Qt3DCore::QEntity *camera READ camera WRITE setCamera NOTIFY cameraChanged)
Q_PROPERTY(QSize externalRenderTargetSize READ externalRenderTargetSize WRITE setExternalRenderTargetSize NOTIFY externalRenderTargetSizeChanged)
+ Q_PROPERTY(bool frustumCulling READ isFrustumCullingEnabled WRITE setFrustumCullingEnabled NOTIFY frustumCullingEnabledChanged)
+ Q_PROPERTY(float gamma READ gamma WRITE setGamma NOTIFY gammaChanged REVISION 9)
public:
explicit QForwardRenderer(Qt3DCore::QNode *parent = nullptr);
~QForwardRenderer();
@@ -70,6 +74,8 @@ public:
Qt3DCore::QEntity *camera() const;
QObject *surface() const;
QSize externalRenderTargetSize() const;
+ bool isFrustumCullingEnabled() const;
+ float gamma() const;
public Q_SLOTS:
void setViewportRect(const QRectF &viewportRect);
@@ -77,6 +83,8 @@ public Q_SLOTS:
void setCamera(Qt3DCore::QEntity *camera);
void setSurface(QObject * surface);
void setExternalRenderTargetSize(const QSize &size);
+ void setFrustumCullingEnabled(bool enabled);
+ void setGamma(float gamma);
Q_SIGNALS:
void viewportRectChanged(const QRectF &viewportRect);
@@ -84,6 +92,8 @@ Q_SIGNALS:
void cameraChanged(Qt3DCore::QEntity *camera);
void surfaceChanged(QObject *surface);
void externalRenderTargetSizeChanged(const QSize &size);
+ void frustumCullingEnabledChanged(bool enabled);
+ void gammaChanged(float gamma);
private:
Q_DECLARE_PRIVATE(QForwardRenderer)
diff --git a/src/extras/defaults/qgoochmaterial.cpp b/src/extras/defaults/qgoochmaterial.cpp
index f2f34fc84..ba7ef8dab 100644
--- a/src/extras/defaults/qgoochmaterial.cpp
+++ b/src/extras/defaults/qgoochmaterial.cpp
@@ -39,13 +39,13 @@
#include "qgoochmaterial.h"
#include "qgoochmaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qeffect.h>
#include <Qt3DRender/qgraphicsapifilter.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qtechnique.h>
-
#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qgoochmaterial.h b/src/extras/defaults/qgoochmaterial.h
index 232257513..6afddfe8b 100644
--- a/src/extras/defaults/qgoochmaterial.h
+++ b/src/extras/defaults/qgoochmaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qmetalroughmaterial.cpp b/src/extras/defaults/qmetalroughmaterial.cpp
new file mode 100644
index 000000000..ea213ab82
--- /dev/null
+++ b/src/extras/defaults/qmetalroughmaterial.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetalroughmaterial.h"
+#include "qmetalroughmaterial_p.h"
+#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
+#include <QUrl>
+#include <QVector3D>
+#include <QVector4D>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DRender;
+
+namespace Qt3DExtras {
+
+QMetalRoughMaterialPrivate::QMetalRoughMaterialPrivate()
+ : QMaterialPrivate()
+ , m_environmentIrradianceTexture(new QTexture2D())
+ , m_environmentSpecularTexture(new QTexture2D())
+ , m_baseColorParameter(new QParameter(QStringLiteral("baseColor"), QColor("grey")))
+ , m_metalnessParameter(new QParameter(QStringLiteral("metalness"), 0.0f))
+ , m_roughnessParameter(new QParameter(QStringLiteral("roughness"), 0.0f))
+ , m_environmentIrradianceParameter(new QParameter(QStringLiteral("envLight.irradiance"), m_environmentIrradianceTexture))
+ , m_environmentSpecularParameter(new QParameter(QStringLiteral("envLight.specular"), m_environmentSpecularTexture))
+ , m_metalRoughEffect(new QEffect())
+ , m_metalRoughGL3Technique(new QTechnique())
+ , m_metalRoughGL3RenderPass(new QRenderPass())
+ , m_metalRoughGL3Shader(new QShaderProgram())
+ , m_filterKey(new QFilterKey)
+{
+ m_environmentIrradianceTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_environmentIrradianceTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_environmentIrradianceTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_environmentIrradianceTexture->setGenerateMipMaps(true);
+ m_environmentIrradianceTexture->setMaximumAnisotropy(16.0f);
+
+ m_environmentSpecularTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_environmentSpecularTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_environmentSpecularTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_environmentSpecularTexture->setGenerateMipMaps(true);
+ m_environmentSpecularTexture->setMaximumAnisotropy(16.0f);
+}
+
+void QMetalRoughMaterialPrivate::init()
+{
+ connect(m_baseColorParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMetalRoughMaterialPrivate::handleBaseColorChanged);
+ connect(m_metalnessParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMetalRoughMaterialPrivate::handleMetallicChanged);
+ connect(m_roughnessParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMetalRoughMaterialPrivate::handleRoughnessChanged);
+
+ m_metalRoughGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalrough.vert"))));
+ m_metalRoughGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalroughuniform.frag"))));
+
+ m_metalRoughGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_metalRoughGL3Technique->graphicsApiFilter()->setMajorVersion(3);
+ m_metalRoughGL3Technique->graphicsApiFilter()->setMinorVersion(1);
+ m_metalRoughGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ Q_Q(QMetalRoughMaterial);
+ m_filterKey->setParent(q);
+ m_filterKey->setName(QStringLiteral("renderingStyle"));
+ m_filterKey->setValue(QStringLiteral("forward"));
+
+ m_metalRoughGL3Technique->addFilterKey(m_filterKey);
+ m_metalRoughGL3RenderPass->setShaderProgram(m_metalRoughGL3Shader);
+ m_metalRoughGL3Technique->addRenderPass(m_metalRoughGL3RenderPass);
+ m_metalRoughEffect->addTechnique(m_metalRoughGL3Technique);
+
+ m_metalRoughEffect->addParameter(m_baseColorParameter);
+ m_metalRoughEffect->addParameter(m_metalnessParameter);
+ m_metalRoughEffect->addParameter(m_roughnessParameter);
+
+ // Note that even though those parameters are not exposed in the API,
+ // they need to be kept around for now due to a bug in some drivers/GPUs
+ // (at least Intel) which cause issues with unbound textures even if you
+ // don't try to sample from them.
+ // Can probably go away once we generate the shaders and deal in this
+ // case in a better way.
+ m_metalRoughEffect->addParameter(m_environmentIrradianceParameter);
+ m_metalRoughEffect->addParameter(m_environmentSpecularParameter);
+
+ q->setEffect(m_metalRoughEffect);
+}
+
+void QMetalRoughMaterialPrivate::handleBaseColorChanged(const QVariant &var)
+{
+ Q_Q(QMetalRoughMaterial);
+ emit q->baseColorChanged(var.value<QColor>());
+}
+
+void QMetalRoughMaterialPrivate::handleMetallicChanged(const QVariant &var)
+{
+ Q_Q(QMetalRoughMaterial);
+ emit q->metalnessChanged(var.toFloat());
+}
+void QMetalRoughMaterialPrivate::handleRoughnessChanged(const QVariant &var)
+{
+ Q_Q(QMetalRoughMaterial);
+ emit q->roughnessChanged(var.toFloat());
+}
+
+/*!
+ \class Qt3DExtras::QMetalRoughMaterial
+ \brief The QMetalRoughMaterial provides a default implementation of PBR
+ lighting.
+ \inmodule Qt3DExtras
+ \since 5.9
+ \inherits Qt3DRender::QMaterial
+
+ This material uses an effect with a single render pass approach and performs per fragment
+ lighting. Techniques are provided for OpenGL 3 only.
+*/
+
+/*!
+ Constructs a new QMetalRoughMaterial instance with parent object \a parent.
+*/
+QMetalRoughMaterial::QMetalRoughMaterial(QNode *parent)
+ : QMaterial(*new QMetalRoughMaterialPrivate, parent)
+{
+ Q_D(QMetalRoughMaterial);
+ d->init();
+}
+
+/*! \internal */
+QMetalRoughMaterial::QMetalRoughMaterial(QMetalRoughMaterialPrivate &dd, QNode *parent)
+ : QMaterial(dd, parent)
+{
+ Q_D(QMetalRoughMaterial);
+ d->init();
+}
+
+/*!
+ Destroys the QMetalRoughMaterial instance.
+*/
+QMetalRoughMaterial::~QMetalRoughMaterial()
+{
+}
+
+/*!
+ \property QMetalRoughMaterial::baseColor
+
+ Holds the current base color of the material.
+*/
+QColor QMetalRoughMaterial::baseColor() const
+{
+ Q_D(const QMetalRoughMaterial);
+ return d->m_baseColorParameter->value().value<QColor>();
+}
+
+/*!
+ \property QMetalRoughMaterial::metalness
+
+ Holds the current metalness level of the material, since is a value between 0 (purely dielectric, the default)
+ and 1 (purely metallic).
+*/
+float QMetalRoughMaterial::metalness() const
+{
+ Q_D(const QMetalRoughMaterial);
+ return d->m_metalnessParameter->value().toFloat();
+}
+
+/*!
+ \property QMetalRoughMaterial::roughness
+
+ Holds the current roughness level of the material.
+*/
+float QMetalRoughMaterial::roughness() const
+{
+ Q_D(const QMetalRoughMaterial);
+ return d->m_roughnessParameter->value().toFloat();
+}
+
+void QMetalRoughMaterial::setBaseColor(const QColor &baseColor)
+{
+ Q_D(QMetalRoughMaterial);
+ d->m_baseColorParameter->setValue(QVariant::fromValue(baseColor));
+}
+
+void QMetalRoughMaterial::setMetalness(float metalness)
+{
+ Q_D(QMetalRoughMaterial);
+ d->m_metalnessParameter->setValue(QVariant::fromValue(metalness));
+}
+
+void QMetalRoughMaterial::setRoughness(float roughness)
+{
+ Q_D(QMetalRoughMaterial);
+ d->m_roughnessParameter->setValue(QVariant::fromValue(roughness));
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/defaults/qmetalroughmaterial.h b/src/extras/defaults/qmetalroughmaterial.h
new file mode 100644
index 000000000..28c9438a7
--- /dev/null
+++ b/src/extras/defaults/qmetalroughmaterial.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMETALROUGHMATERIAL_H
+#define QT3DEXTRAS_QMETALROUGHMATERIAL_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qmaterial.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QAbstractTexture;
+}
+
+namespace Qt3DExtras {
+
+class QMetalRoughMaterialPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QMetalRoughMaterial : public Qt3DRender::QMaterial
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged)
+ Q_PROPERTY(float metalness READ metalness WRITE setMetalness NOTIFY metalnessChanged)
+ Q_PROPERTY(float roughness READ roughness WRITE setRoughness NOTIFY roughnessChanged)
+
+public:
+ explicit QMetalRoughMaterial(Qt3DCore::QNode *parent = nullptr);
+ ~QMetalRoughMaterial();
+
+ QColor baseColor() const;
+ float metalness() const;
+ float roughness() const;
+
+public Q_SLOTS:
+ void setBaseColor(const QColor &baseColor);
+ void setMetalness(float metalness);
+ void setRoughness(float roughness);
+
+Q_SIGNALS:
+ void baseColorChanged(const QColor &baseColor);
+ void metalnessChanged(float metalness);
+ void roughnessChanged(float roughness);
+
+protected:
+ explicit QMetalRoughMaterial(QMetalRoughMaterialPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QMetalRoughMaterial)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMETALROUGHMATERIAL_H
diff --git a/src/extras/defaults/qmetalroughmaterial_p.h b/src/extras/defaults/qmetalroughmaterial_p.h
new file mode 100644
index 000000000..3090b9757
--- /dev/null
+++ b/src/extras/defaults/qmetalroughmaterial_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMETALROUGHMATERIAL_P_H
+#define QT3DEXTRAS_QMETALROUGHMATERIAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qmaterial_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QFilterKey;
+class QEffect;
+class QAbstractTexture;
+class QTechnique;
+class QParameter;
+class QShaderProgram;
+class QRenderPass;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QMetalRoughMaterial;
+
+class QMetalRoughMaterialPrivate : public Qt3DRender::QMaterialPrivate
+{
+public:
+ QMetalRoughMaterialPrivate();
+
+ void init();
+
+ void handleBaseColorChanged(const QVariant &var);
+ void handleMetallicChanged(const QVariant &var);
+ void handleRoughnessChanged(const QVariant &var);
+
+ Qt3DRender::QAbstractTexture *m_environmentIrradianceTexture;
+ Qt3DRender::QAbstractTexture *m_environmentSpecularTexture;
+ Qt3DRender::QParameter *m_baseColorParameter;
+ Qt3DRender::QParameter *m_metalnessParameter;
+ Qt3DRender::QParameter *m_roughnessParameter;
+ Qt3DRender::QParameter *m_environmentIrradianceParameter;
+ Qt3DRender::QParameter *m_environmentSpecularParameter;
+ Qt3DRender::QEffect *m_metalRoughEffect;
+ Qt3DRender::QTechnique *m_metalRoughGL3Technique;
+ Qt3DRender::QRenderPass *m_metalRoughGL3RenderPass;
+ Qt3DRender::QShaderProgram *m_metalRoughGL3Shader;
+ Qt3DRender::QFilterKey *m_filterKey;
+
+ Q_DECLARE_PUBLIC(QMetalRoughMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMETALROUGHMATERIAL_P_H
+
diff --git a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp
index 92564ee3f..eb6398341 100644
--- a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp
@@ -49,10 +49,9 @@
#include <Qt3DRender/qgraphicsapifilter.h>
#include <Qt3DRender/qalphacoverage.h>
#include <Qt3DRender/qdepthtest.h>
-
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qnormaldiffusemapalphamaterial_p.h b/src/extras/defaults/qnormaldiffusemapalphamaterial_p.h
index 91b0961f1..5994d87eb 100644
--- a/src/extras/defaults/qnormaldiffusemapalphamaterial_p.h
+++ b/src/extras/defaults/qnormaldiffusemapalphamaterial_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <qnormaldiffusemapmaterial_p.h>
+#include <Qt3DExtras/private/qnormaldiffusemapmaterial_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qnormaldiffusemapmaterial.cpp b/src/extras/defaults/qnormaldiffusemapmaterial.cpp
index 8373c4d5d..35cea095a 100644
--- a/src/extras/defaults/qnormaldiffusemapmaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusemapmaterial.cpp
@@ -39,6 +39,7 @@
#include "qnormaldiffusemapmaterial.h"
#include "qnormaldiffusemapmaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qeffect.h>
#include <Qt3DRender/qtexture.h>
@@ -47,10 +48,9 @@
#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
-
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qnormaldiffusemapmaterial.h b/src/extras/defaults/qnormaldiffusemapmaterial.h
index f60a27b86..c38d53352 100644
--- a/src/extras/defaults/qnormaldiffusemapmaterial.h
+++ b/src/extras/defaults/qnormaldiffusemapmaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qnormaldiffusemapmaterial_p.h b/src/extras/defaults/qnormaldiffusemapmaterial_p.h
index 8dff59218..d88b01f1f 100644
--- a/src/extras/defaults/qnormaldiffusemapmaterial_p.h
+++ b/src/extras/defaults/qnormaldiffusemapmaterial_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DRender/private/qmaterial_p.h>
+#include <private/qmaterial_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
index e4a83c50c..c6f8ced9c 100644
--- a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
@@ -39,6 +39,7 @@
#include "qnormaldiffusespecularmapmaterial.h"
#include "qnormaldiffusespecularmapmaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qeffect.h>
@@ -48,9 +49,9 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial.h b/src/extras/defaults/qnormaldiffusespecularmapmaterial.h
index 586715971..164b07710 100644
--- a/src/extras/defaults/qnormaldiffusespecularmapmaterial.h
+++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qorbitcameracontroller.cpp b/src/extras/defaults/qorbitcameracontroller.cpp
index 95b0e19dc..565a75ea1 100644
--- a/src/extras/defaults/qorbitcameracontroller.cpp
+++ b/src/extras/defaults/qorbitcameracontroller.cpp
@@ -34,9 +34,9 @@
**
****************************************************************************/
-#include "qorbitcameracontroller_p.h"
#include "qorbitcameracontroller.h"
-#include <QtGlobal>
+#include "qorbitcameracontroller_p.h"
+
#include <Qt3DRender/QCamera>
#include <Qt3DInput/QAxis>
#include <Qt3DInput/QAnalogAxisInput>
@@ -48,6 +48,7 @@
#include <Qt3DInput/QMouseDevice>
#include <Qt3DInput/QMouseEvent>
#include <Qt3DLogic/QFrameAction>
+#include <QtCore/QtGlobal>
QT_BEGIN_NAMESPACE
@@ -79,6 +80,9 @@ namespace Qt3DExtras {
\li While both the left and the right mouse button are pressed, mouse movement along y-axis
zooms the camera in and out without changing the view center.
\row
+ \li Mouse scroll wheel
+ \li Zooms the camera in and out without changing the view center.
+ \row
\li Arrow keys
\li Move the camera vertically and horizontally relative to camera viewport.
\row
@@ -113,6 +117,8 @@ QOrbitCameraControllerPrivate::QOrbitCameraControllerPrivate()
, m_shiftButtonInput(new Qt3DInput::QActionInput())
, m_mouseRxInput(new Qt3DInput::QAnalogAxisInput())
, m_mouseRyInput(new Qt3DInput::QAnalogAxisInput())
+ , m_mouseTzXInput(new Qt3DInput::QAnalogAxisInput())
+ , m_mouseTzYInput(new Qt3DInput::QAnalogAxisInput())
, m_keyboardTxPosInput(new Qt3DInput::QButtonAxisInput())
, m_keyboardTyPosInput(new Qt3DInput::QButtonAxisInput())
, m_keyboardTzPosInput(new Qt3DInput::QButtonAxisInput())
@@ -165,6 +171,16 @@ void QOrbitCameraControllerPrivate::init()
m_mouseRyInput->setSourceDevice(m_mouseDevice);
m_ryAxis->addInput(m_mouseRyInput);
+ // Mouse Wheel X
+ m_mouseTzXInput->setAxis(Qt3DInput::QMouseDevice::WheelX);
+ m_mouseTzXInput->setSourceDevice(m_mouseDevice);
+ m_tzAxis->addInput(m_mouseTzXInput);
+
+ // Mouse Wheel Y
+ m_mouseTzYInput->setAxis(Qt3DInput::QMouseDevice::WheelY);
+ m_mouseTzYInput->setSourceDevice(m_mouseDevice);
+ m_tzAxis->addInput(m_mouseTzYInput);
+
// Keyboard Pos Tx
m_keyboardTxPosInput->setButtons(QVector<int>() << Qt::Key_Right);
m_keyboardTxPosInput->setScale(1.0f);
diff --git a/src/extras/defaults/qorbitcameracontroller.h b/src/extras/defaults/qorbitcameracontroller.h
index e48e39142..7cb8b3eb7 100644
--- a/src/extras/defaults/qorbitcameracontroller.h
+++ b/src/extras/defaults/qorbitcameracontroller.h
@@ -37,8 +37,8 @@
#ifndef QT3DEXTRAS_QORBITCAMERACONTROLLER_H
#define QT3DEXTRAS_QORBITCAMERACONTROLLER_H
-#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DCore/QEntity>
+#include <Qt3DExtras/qt3dextras_global.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qorbitcameracontroller_p.h b/src/extras/defaults/qorbitcameracontroller_p.h
index d207df712..8105d4375 100644
--- a/src/extras/defaults/qorbitcameracontroller_p.h
+++ b/src/extras/defaults/qorbitcameracontroller_p.h
@@ -48,9 +48,10 @@
// We mean it.
//
+#include <Qt3DExtras/qorbitcameracontroller.h>
+#include <QtGui/QVector3D>
+
#include <Qt3DCore/private/qentity_p.h>
-#include <QVector3D>
-#include "qorbitcameracontroller.h"
QT_BEGIN_NAMESPACE
@@ -105,6 +106,8 @@ public:
Qt3DInput::QAnalogAxisInput *m_mouseRxInput;
Qt3DInput::QAnalogAxisInput *m_mouseRyInput;
+ Qt3DInput::QAnalogAxisInput *m_mouseTzXInput;
+ Qt3DInput::QAnalogAxisInput *m_mouseTzYInput;
Qt3DInput::QButtonAxisInput *m_keyboardTxPosInput;
Qt3DInput::QButtonAxisInput *m_keyboardTyPosInput;
Qt3DInput::QButtonAxisInput *m_keyboardTzPosInput;
diff --git a/src/extras/defaults/qpervertexcolormaterial.cpp b/src/extras/defaults/qpervertexcolormaterial.cpp
index 514f994c1..5619a71e7 100644
--- a/src/extras/defaults/qpervertexcolormaterial.cpp
+++ b/src/extras/defaults/qpervertexcolormaterial.cpp
@@ -39,6 +39,7 @@
#include "qpervertexcolormaterial.h"
#include "qpervertexcolormaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qeffect.h>
@@ -47,9 +48,9 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qpervertexcolormaterial.h b/src/extras/defaults/qpervertexcolormaterial.h
index 485e2fe0e..8b64eb2d3 100644
--- a/src/extras/defaults/qpervertexcolormaterial.h
+++ b/src/extras/defaults/qpervertexcolormaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qphongalphamaterial.cpp b/src/extras/defaults/qphongalphamaterial.cpp
index 7a05610c2..d7f054d71 100644
--- a/src/extras/defaults/qphongalphamaterial.cpp
+++ b/src/extras/defaults/qphongalphamaterial.cpp
@@ -39,6 +39,7 @@
#include "qphongalphamaterial.h"
#include "qphongalphamaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qeffect.h>
@@ -50,9 +51,9 @@
#include <Qt3DRender/qblendequation.h>
#include <Qt3DRender/qblendequationarguments.h>
#include <Qt3DRender/qnodepthmask.h>
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qphongalphamaterial.h b/src/extras/defaults/qphongalphamaterial.h
index b67524ef7..667c5b283 100644
--- a/src/extras/defaults/qphongalphamaterial.h
+++ b/src/extras/defaults/qphongalphamaterial.h
@@ -41,10 +41,10 @@
#define QT3DEXTRAS_QPHONGALPHAMATERIAL_H
#include <Qt3DExtras/qt3dextras_global.h>
-#include <Qt3DRender/qmaterial.h>
-#include <Qt3DRender/qblendequationarguments.h>
#include <Qt3DRender/qblendequation.h>
-#include <QColor>
+#include <Qt3DRender/qblendequationarguments.h>
+#include <Qt3DRender/qmaterial.h>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qphongmaterial.cpp b/src/extras/defaults/qphongmaterial.cpp
index c294984b6..449eb7351 100644
--- a/src/extras/defaults/qphongmaterial.cpp
+++ b/src/extras/defaults/qphongmaterial.cpp
@@ -39,6 +39,7 @@
#include "qphongmaterial.h"
#include "qphongmaterial_p.h"
+
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qeffect.h>
@@ -47,9 +48,10 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
-#include <QUrl>
-#include <QVector3D>
-#include <QVector4D>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
+
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qphongmaterial.h b/src/extras/defaults/qphongmaterial.h
index d4b8a0f0e..d78c8c2ff 100644
--- a/src/extras/defaults/qphongmaterial.h
+++ b/src/extras/defaults/qphongmaterial.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
-#include <QColor>
+#include <QtGui/QColor>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/defaults/qskyboxentity.cpp b/src/extras/defaults/qskyboxentity.cpp
index 32e68e6fc..3c7b0dd4e 100644
--- a/src/extras/defaults/qskyboxentity.cpp
+++ b/src/extras/defaults/qskyboxentity.cpp
@@ -51,6 +51,7 @@
#include <Qt3DExtras/qcuboidmesh.h>
#include <Qt3DRender/qrenderpass.h>
#include <Qt3DRender/qgraphicsapifilter.h>
+#include <Qt3DRender/qseamlesscubemap.h>
#include <Qt3DRender/qshaderprogram.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +66,7 @@ QSkyboxEntityPrivate::QSkyboxEntityPrivate()
, m_effect(new QEffect())
, m_material(new QMaterial())
, m_skyboxTexture(new QTextureCubeMap())
+ , m_loadedTexture(new QTextureLoader())
, m_gl3Shader(new QShaderProgram())
, m_gl2es2Shader(new QShaderProgram())
, m_gl2Technique(new QTechnique())
@@ -75,6 +77,7 @@ QSkyboxEntityPrivate::QSkyboxEntityPrivate()
, m_es2RenderPass(new QRenderPass())
, m_gl3RenderPass(new QRenderPass())
, m_mesh(new QCuboidMesh())
+ , m_gammaStrengthParameter(new QParameter(QStringLiteral("gammaStrength"), 0.0f))
, m_textureParameter(new QParameter(QStringLiteral("skyboxTexture"), m_skyboxTexture))
, m_posXImage(new QTextureImage())
, m_posYImage(new QTextureImage())
@@ -84,6 +87,7 @@ QSkyboxEntityPrivate::QSkyboxEntityPrivate()
, m_negZImage(new QTextureImage())
, m_extension(QStringLiteral(".png"))
{
+ m_loadedTexture->setGenerateMipMaps(false);
}
/*!
@@ -127,9 +131,11 @@ void QSkyboxEntityPrivate::init()
cullFront->setMode(QCullFace::Front);
QDepthTest *depthTest = new QDepthTest();
depthTest->setDepthFunction(QDepthTest::LessOrEqual);
+ QSeamlessCubemap *seamlessCubemap = new QSeamlessCubemap();
m_gl3RenderPass->addRenderState(cullFront);
m_gl3RenderPass->addRenderState(depthTest);
+ m_gl3RenderPass->addRenderState(seamlessCubemap);
m_gl2RenderPass->addRenderState(cullFront);
m_gl2RenderPass->addRenderState(depthTest);
m_es2RenderPass->addRenderState(cullFront);
@@ -144,6 +150,7 @@ void QSkyboxEntityPrivate::init()
m_effect->addTechnique(m_es2Technique);
m_material->setEffect(m_effect);
+ m_material->addParameter(m_gammaStrengthParameter);
m_material->addParameter(m_textureParameter);
m_mesh->setXYMeshResolution(QSize(2, 2));
@@ -151,11 +158,17 @@ void QSkyboxEntityPrivate::init()
m_mesh->setYZMeshResolution(QSize(2, 2));
m_posXImage->setFace(QTextureCubeMap::CubeMapPositiveX);
+ m_posXImage->setMirrored(false);
m_posYImage->setFace(QTextureCubeMap::CubeMapPositiveY);
+ m_posYImage->setMirrored(false);
m_posZImage->setFace(QTextureCubeMap::CubeMapPositiveZ);
+ m_posZImage->setMirrored(false);
m_negXImage->setFace(QTextureCubeMap::CubeMapNegativeX);
+ m_negXImage->setMirrored(false);
m_negYImage->setFace(QTextureCubeMap::CubeMapNegativeY);
+ m_negYImage->setMirrored(false);
m_negZImage->setFace(QTextureCubeMap::CubeMapNegativeZ);
+ m_negZImage->setMirrored(false);
m_skyboxTexture->setMagnificationFilter(QTextureCubeMap::Linear);
m_skyboxTexture->setMinificationFilter(QTextureCubeMap::Linear);
@@ -178,12 +191,18 @@ void QSkyboxEntityPrivate::init()
*/
void QSkyboxEntityPrivate::reloadTexture()
{
- m_posXImage->setSource(QUrl(m_baseName + QStringLiteral("_posx") + m_extension));
- m_posYImage->setSource(QUrl(m_baseName + QStringLiteral("_posy") + m_extension));
- m_posZImage->setSource(QUrl(m_baseName + QStringLiteral("_posz") + m_extension));
- m_negXImage->setSource(QUrl(m_baseName + QStringLiteral("_negx") + m_extension));
- m_negYImage->setSource(QUrl(m_baseName + QStringLiteral("_negy") + m_extension));
- m_negZImage->setSource(QUrl(m_baseName + QStringLiteral("_negz") + m_extension));
+ if (m_extension == QStringLiteral(".dds")) {
+ m_loadedTexture->setSource(QUrl(m_baseName + m_extension));
+ m_textureParameter->setValue(QVariant::fromValue(m_loadedTexture));
+ } else {
+ m_posXImage->setSource(QUrl(m_baseName + QStringLiteral("_posx") + m_extension));
+ m_posYImage->setSource(QUrl(m_baseName + QStringLiteral("_posy") + m_extension));
+ m_posZImage->setSource(QUrl(m_baseName + QStringLiteral("_posz") + m_extension));
+ m_negXImage->setSource(QUrl(m_baseName + QStringLiteral("_negx") + m_extension));
+ m_negYImage->setSource(QUrl(m_baseName + QStringLiteral("_negy") + m_extension));
+ m_negZImage->setSource(QUrl(m_baseName + QStringLiteral("_negz") + m_extension));
+ m_textureParameter->setValue(QVariant::fromValue(m_skyboxTexture));
+ }
}
/*!
@@ -232,7 +251,7 @@ void QSkyboxEntity::setBaseName(const QString &baseName)
Q_D(QSkyboxEntity);
if (baseName != d->m_baseName) {
d->m_baseName = baseName;
- emit sourceDirectoryChanged(baseName);
+ emit baseNameChanged(baseName);
d->reloadTexture();
}
}
@@ -267,6 +286,29 @@ QString QSkyboxEntity::extension() const
return d->m_extension;
}
+/*!
+ * Sets the gamma correction enable state to \a enabled.
+ * \since 5.9
+ */
+void QSkyboxEntity::setGammaCorrectEnabled(bool enabled)
+{
+ Q_D(QSkyboxEntity);
+ if (enabled != isGammaCorrectEnabled()) {
+ d->m_gammaStrengthParameter->setValue(enabled ? 1.0f : 0.0f);
+ emit gammaCorrectEnabledChanged(enabled);
+ }
+}
+
+/*!
+ * Returns true if gamma correction is enabled for this skybox.
+ * \since 5.9
+ */
+bool QSkyboxEntity::isGammaCorrectEnabled() const
+{
+ Q_D(const QSkyboxEntity);
+ return !qFuzzyIsNull(d->m_gammaStrengthParameter->value().toFloat());
+}
+
} // namespace Qt3DExtras
QT_END_NAMESPACE
diff --git a/src/extras/defaults/qskyboxentity.h b/src/extras/defaults/qskyboxentity.h
index a11d2f0a0..e49782dc2 100644
--- a/src/extras/defaults/qskyboxentity.h
+++ b/src/extras/defaults/qskyboxentity.h
@@ -52,19 +52,26 @@ class QSkyboxEntityPrivate;
class QT3DEXTRASSHARED_EXPORT QSkyboxEntity : public Qt3DCore::QEntity
{
Q_OBJECT
+ Q_PROPERTY(QString baseName READ baseName WRITE setBaseName NOTIFY baseNameChanged)
+ Q_PROPERTY(QString extension READ extension WRITE setExtension NOTIFY extensionChanged)
+ Q_PROPERTY(bool gammaCorrect READ isGammaCorrectEnabled WRITE setGammaCorrectEnabled NOTIFY gammaCorrectEnabledChanged REVISION 9)
public:
explicit QSkyboxEntity(Qt3DCore::QNode *parent = nullptr);
~QSkyboxEntity();
- void setBaseName(const QString &path);
QString baseName() const;
+ QString extension() const;
+ bool isGammaCorrectEnabled() const;
+public Q_SLOTS:
+ void setBaseName(const QString &path);
void setExtension(const QString &extension);
- QString extension() const;
+ void setGammaCorrectEnabled(bool enabled);
Q_SIGNALS:
- void sourceDirectoryChanged(const QString &path);
+ void baseNameChanged(const QString &path);
void extensionChanged(const QString &extension);
+ void gammaCorrectEnabledChanged(bool enabled);
private:
Q_DECLARE_PRIVATE(QSkyboxEntity)
diff --git a/src/extras/defaults/qskyboxentity_p.h b/src/extras/defaults/qskyboxentity_p.h
index effe97fce..88a40e2eb 100644
--- a/src/extras/defaults/qskyboxentity_p.h
+++ b/src/extras/defaults/qskyboxentity_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
+#include <QtGui/QVector3D>
+
#include <Qt3DCore/private/qentity_p.h>
-#include <QVector3D>
QT_BEGIN_NAMESPACE
@@ -60,6 +61,7 @@ namespace Qt3DRender {
class QFilterKey;
class QTextureCubeMap;
+class QTextureLoader;
class QShaderProgram;
class QSkyboxEntity;
class QTextureImage;
@@ -87,6 +89,7 @@ class QSkyboxEntityPrivate : public Qt3DCore::QEntityPrivate
Qt3DRender::QEffect *m_effect;
Qt3DRender::QMaterial *m_material;
Qt3DRender::QTextureCubeMap *m_skyboxTexture;
+ Qt3DRender::QTextureLoader *m_loadedTexture;
Qt3DRender::QShaderProgram *m_gl3Shader;
Qt3DRender::QShaderProgram *m_gl2es2Shader;
Qt3DRender::QTechnique *m_gl2Technique;
@@ -97,6 +100,7 @@ class QSkyboxEntityPrivate : public Qt3DCore::QEntityPrivate
Qt3DRender::QRenderPass *m_es2RenderPass;
Qt3DRender::QRenderPass *m_gl3RenderPass;
QCuboidMesh *m_mesh;
+ Qt3DRender::QParameter *m_gammaStrengthParameter;
Qt3DRender::QParameter *m_textureParameter;
Qt3DRender::QTextureImage *m_posXImage;
Qt3DRender:: QTextureImage *m_posYImage;
diff --git a/src/extras/defaults/qt3dwindow.cpp b/src/extras/defaults/qt3dwindow.cpp
index 06ff14212..635d81956 100644
--- a/src/extras/defaults/qt3dwindow.cpp
+++ b/src/extras/defaults/qt3dwindow.cpp
@@ -49,27 +49,25 @@
****************************************************************************/
#include "qt3dwindow.h"
+#include "qt3dwindow_p.h"
+#include <Qt3DCore/qaspectengine.h>
+#include <Qt3DCore/qentity.h>
#include <Qt3DExtras/qforwardrenderer.h>
#include <Qt3DRender/qrendersettings.h>
#include <Qt3DRender/qrenderaspect.h>
#include <Qt3DInput/qinputaspect.h>
#include <Qt3DInput/qinputsettings.h>
#include <Qt3DLogic/qlogicaspect.h>
-
-#include <Qt3DCore/qaspectengine.h>
#include <Qt3DRender/qcamera.h>
-#include <Qt3DCore/qentity.h>
-
#include <QtGui/qopenglcontext.h>
QT_BEGIN_NAMESPACE
namespace Qt3DExtras {
-Qt3DWindow::Qt3DWindow(QScreen *screen)
- : QWindow(screen)
- , m_aspectEngine(new Qt3DCore::QAspectEngine)
+Qt3DWindowPrivate::Qt3DWindowPrivate()
+ : m_aspectEngine(new Qt3DCore::QAspectEngine)
, m_renderAspect(new Qt3DRender::QRenderAspect)
, m_inputAspect(new Qt3DInput::QInputAspect)
, m_logicAspect(new Qt3DLogic::QLogicAspect)
@@ -81,6 +79,16 @@ Qt3DWindow::Qt3DWindow(QScreen *screen)
, m_userRoot(nullptr)
, m_initialized(false)
{
+}
+
+Qt3DWindow::Qt3DWindow(QScreen *screen)
+ : QWindow(*new Qt3DWindowPrivate(), nullptr)
+{
+ Q_D(Qt3DWindow);
+
+ if (!d->parentWindow)
+ d->connectToScreen(screen ? screen : d->topLevelScreen.data());
+
setSurfaceType(QSurface::OpenGLSurface);
resize(1024, 768);
@@ -99,74 +107,89 @@ Qt3DWindow::Qt3DWindow(QScreen *screen)
format.setStencilBufferSize(8);
setFormat(format);
QSurfaceFormat::setDefaultFormat(format);
- create();
- m_aspectEngine->registerAspect(m_renderAspect);
- m_aspectEngine->registerAspect(m_inputAspect);
- m_aspectEngine->registerAspect(m_logicAspect);
+ d->m_aspectEngine->registerAspect(d->m_renderAspect);
+ d->m_aspectEngine->registerAspect(d->m_inputAspect);
+ d->m_aspectEngine->registerAspect(d->m_logicAspect);
- m_defaultCamera->setParent(m_root);
- m_forwardRenderer->setCamera(m_defaultCamera);
- m_forwardRenderer->setSurface(this);
- m_renderSettings->setActiveFrameGraph(m_forwardRenderer);
- m_inputSettings->setEventSource(this);
+ d->m_defaultCamera->setParent(d->m_root);
+ d->m_forwardRenderer->setCamera(d->m_defaultCamera);
+ d->m_forwardRenderer->setSurface(this);
+ d->m_renderSettings->setActiveFrameGraph(d->m_forwardRenderer);
+ d->m_inputSettings->setEventSource(this);
}
Qt3DWindow::~Qt3DWindow()
{
+ Q_D(Qt3DWindow);
+ delete d->m_aspectEngine;
}
void Qt3DWindow::registerAspect(Qt3DCore::QAbstractAspect *aspect)
{
Q_ASSERT(!isVisible());
- m_aspectEngine->registerAspect(aspect);
+ Q_D(Qt3DWindow);
+ d->m_aspectEngine->registerAspect(aspect);
}
void Qt3DWindow::registerAspect(const QString &name)
{
Q_ASSERT(!isVisible());
- m_aspectEngine->registerAspect(name);
+ Q_D(Qt3DWindow);
+ d->m_aspectEngine->registerAspect(name);
}
void Qt3DWindow::setRootEntity(Qt3DCore::QEntity *root)
{
- if (m_userRoot != root) {
- if (m_userRoot != nullptr)
- m_userRoot->setParent(static_cast<Qt3DCore::QNode*>(nullptr));
+ Q_D(Qt3DWindow);
+ if (d->m_userRoot != root) {
+ if (d->m_userRoot != nullptr)
+ d->m_userRoot->setParent(static_cast<Qt3DCore::QNode*>(nullptr));
if (root != nullptr)
- root->setParent(m_root);
- m_userRoot = root;
+ root->setParent(d->m_root);
+ d->m_userRoot = root;
}
}
void Qt3DWindow::setActiveFrameGraph(Qt3DRender::QFrameGraphNode *activeFrameGraph)
{
- m_renderSettings->setActiveFrameGraph(activeFrameGraph);
+ Q_D(Qt3DWindow);
+ d->m_renderSettings->setActiveFrameGraph(activeFrameGraph);
}
Qt3DRender::QFrameGraphNode *Qt3DWindow::activeFrameGraph() const
{
- return m_renderSettings->activeFrameGraph();
+ Q_D(const Qt3DWindow);
+ return d->m_renderSettings->activeFrameGraph();
}
Qt3DExtras::QForwardRenderer *Qt3DWindow::defaultFrameGraph() const
{
- return m_forwardRenderer;
+ Q_D(const Qt3DWindow);
+ return d->m_forwardRenderer;
}
Qt3DRender::QCamera *Qt3DWindow::camera() const
{
- return m_defaultCamera;
+ Q_D(const Qt3DWindow);
+ return d->m_defaultCamera;
+}
+
+Qt3DRender::QRenderSettings *Qt3DWindow::renderSettings() const
+{
+ Q_D(const Qt3DWindow);
+ return d->m_renderSettings;
}
void Qt3DWindow::showEvent(QShowEvent *e)
{
- if (!m_initialized) {
- m_root->addComponent(m_renderSettings);
- m_root->addComponent(m_inputSettings);
- m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr(m_root));
+ Q_D(Qt3DWindow);
+ if (!d->m_initialized) {
+ d->m_root->addComponent(d->m_renderSettings);
+ d->m_root->addComponent(d->m_inputSettings);
+ d->m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr(d->m_root));
- m_initialized = true;
+ d->m_initialized = true;
}
QWindow::showEvent(e);
@@ -174,7 +197,8 @@ void Qt3DWindow::showEvent(QShowEvent *e)
void Qt3DWindow::resizeEvent(QResizeEvent *)
{
- m_defaultCamera->setAspectRatio(float(width()) / float(height()));
+ Q_D(Qt3DWindow);
+ d->m_defaultCamera->setAspectRatio(float(width()) / float(height()));
}
} // Qt3DExtras
diff --git a/src/extras/defaults/qt3dwindow.h b/src/extras/defaults/qt3dwindow.h
index 109e1be75..6ec1bbf8b 100644
--- a/src/extras/defaults/qt3dwindow.h
+++ b/src/extras/defaults/qt3dwindow.h
@@ -51,8 +51,8 @@
#ifndef QT3DWINDOW_H
#define QT3DWINDOW_H
-#include <QWindow>
#include <Qt3DExtras/qt3dextras_global.h>
+#include <QtGui/QWindow>
QT_BEGIN_NAMESPACE
@@ -84,6 +84,8 @@ class QLogicAspect;
namespace Qt3DExtras {
+class Qt3DWindowPrivate;
+
class QT3DEXTRASSHARED_EXPORT Qt3DWindow : public QWindow
{
Q_OBJECT
@@ -101,6 +103,7 @@ public:
Qt3DExtras::QForwardRenderer *defaultFrameGraph() const;
Qt3DRender::QCamera *camera() const;
+ Qt3DRender::QRenderSettings *renderSettings() const;
public Q_SLOTS:
@@ -111,28 +114,7 @@ protected:
void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;
private:
- QScopedPointer<Qt3DCore::QAspectEngine> m_aspectEngine;
-
- // Aspects
- Qt3DRender::QRenderAspect *m_renderAspect;
- Qt3DInput::QInputAspect *m_inputAspect;
- Qt3DLogic::QLogicAspect *m_logicAspect;
-
- // Renderer configuration
- Qt3DRender::QRenderSettings *m_renderSettings;
- Qt3DExtras::QForwardRenderer *m_forwardRenderer;
- Qt3DRender::QCamera *m_defaultCamera;
-
- // Input configuration
- Qt3DInput::QInputSettings *m_inputSettings;
-
- // Logic configuration
-
- // Scene
- Qt3DCore::QEntity *m_root;
- Qt3DCore::QEntity *m_userRoot;
-
- bool m_initialized;
+ Q_DECLARE_PRIVATE(Qt3DWindow)
};
} // Qt3DExtras
diff --git a/src/extras/defaults/qt3dwindow_p.h b/src/extras/defaults/qt3dwindow_p.h
new file mode 100644
index 000000000..731d5298e
--- /dev/null
+++ b/src/extras/defaults/qt3dwindow_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DWINDOW_P_H
+#define QT3DWINDOW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qwindow_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class Qt3DWindowPrivate : public QWindowPrivate
+{
+public:
+ Qt3DWindowPrivate();
+
+ Qt3DCore::QAspectEngine *m_aspectEngine;
+
+ // Aspects
+ Qt3DRender::QRenderAspect *m_renderAspect;
+ Qt3DInput::QInputAspect *m_inputAspect;
+ Qt3DLogic::QLogicAspect *m_logicAspect;
+
+ // Renderer configuration
+ Qt3DRender::QRenderSettings *m_renderSettings;
+ Qt3DExtras::QForwardRenderer *m_forwardRenderer;
+ Qt3DRender::QCamera *m_defaultCamera;
+
+ // Input configuration
+ Qt3DInput::QInputSettings *m_inputSettings;
+
+ // Logic configuration
+
+ // Scene
+ Qt3DCore::QEntity *m_root;
+ Qt3DCore::QEntity *m_userRoot;
+
+ bool m_initialized;
+
+ Q_DECLARE_PUBLIC(Qt3DWindow)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DWINDOW_P_H
diff --git a/src/extras/defaults/qtexturedmetalroughmaterial.cpp b/src/extras/defaults/qtexturedmetalroughmaterial.cpp
new file mode 100644
index 000000000..e09517866
--- /dev/null
+++ b/src/extras/defaults/qtexturedmetalroughmaterial.cpp
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexturedmetalroughmaterial.h"
+#include "qtexturedmetalroughmaterial_p.h"
+#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
+#include <QUrl>
+#include <QVector3D>
+#include <QVector4D>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DRender;
+
+namespace Qt3DExtras {
+
+QTexturedMetalRoughMaterialPrivate::QTexturedMetalRoughMaterialPrivate()
+ : QMaterialPrivate()
+ , m_baseColorTexture(new QTexture2D())
+ , m_metalnessTexture(new QTexture2D())
+ , m_roughnessTexture(new QTexture2D())
+ , m_ambientOcclusionTexture(new QTexture2D())
+ , m_normalTexture(new QTexture2D())
+ , m_environmentIrradianceTexture(new QTexture2D())
+ , m_environmentSpecularTexture(new QTexture2D())
+ , m_baseColorParameter(new QParameter(QStringLiteral("baseColorMap"), m_baseColorTexture))
+ , m_metalnessParameter(new QParameter(QStringLiteral("metalnessMap"), m_metalnessTexture))
+ , m_roughnessParameter(new QParameter(QStringLiteral("roughnessMap"), m_roughnessTexture))
+ , m_ambientOcclusionParameter(new QParameter(QStringLiteral("ambientOcclusionMap"), m_ambientOcclusionTexture))
+ , m_normalParameter(new QParameter(QStringLiteral("normalMap"), m_normalTexture))
+ , m_environmentIrradianceParameter(new QParameter(QStringLiteral("envLight.irradiance"), m_environmentIrradianceTexture))
+ , m_environmentSpecularParameter(new QParameter(QStringLiteral("envLight.specular"), m_environmentSpecularTexture))
+ , m_metalRoughEffect(new QEffect())
+ , m_metalRoughGL3Technique(new QTechnique())
+ , m_metalRoughGL3RenderPass(new QRenderPass())
+ , m_metalRoughGL3Shader(new QShaderProgram())
+ , m_filterKey(new QFilterKey)
+{
+ m_baseColorTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_baseColorTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_baseColorTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_baseColorTexture->setGenerateMipMaps(true);
+ m_baseColorTexture->setMaximumAnisotropy(16.0f);
+
+ m_metalnessTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_metalnessTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_metalnessTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_metalnessTexture->setGenerateMipMaps(true);
+ m_metalnessTexture->setMaximumAnisotropy(16.0f);
+
+ m_roughnessTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_roughnessTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_roughnessTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_roughnessTexture->setGenerateMipMaps(true);
+ m_roughnessTexture->setMaximumAnisotropy(16.0f);
+
+ m_ambientOcclusionTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_ambientOcclusionTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_ambientOcclusionTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_ambientOcclusionTexture->setGenerateMipMaps(true);
+ m_ambientOcclusionTexture->setMaximumAnisotropy(16.0f);
+
+ m_normalTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_normalTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_normalTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_normalTexture->setGenerateMipMaps(true);
+ m_normalTexture->setMaximumAnisotropy(16.0f);
+
+ m_environmentIrradianceTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_environmentIrradianceTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_environmentIrradianceTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_environmentIrradianceTexture->setGenerateMipMaps(true);
+ m_environmentIrradianceTexture->setMaximumAnisotropy(16.0f);
+
+ m_environmentSpecularTexture->setMagnificationFilter(QAbstractTexture::Linear);
+ m_environmentSpecularTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
+ m_environmentSpecularTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_environmentSpecularTexture->setGenerateMipMaps(true);
+ m_environmentSpecularTexture->setMaximumAnisotropy(16.0f);
+}
+
+void QTexturedMetalRoughMaterialPrivate::init()
+{
+ connect(m_baseColorParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTexturedMetalRoughMaterialPrivate::handleBaseColorChanged);
+ connect(m_metalnessParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTexturedMetalRoughMaterialPrivate::handleMetallicChanged);
+ connect(m_roughnessParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTexturedMetalRoughMaterialPrivate::handleRoughnessChanged);
+ connect(m_ambientOcclusionParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTexturedMetalRoughMaterialPrivate::handleAmbientOcclusionChanged);
+ connect(m_normalParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTexturedMetalRoughMaterialPrivate::handleNormalChanged);
+
+ m_metalRoughGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalrough.vert"))));
+ m_metalRoughGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalrough.frag"))));
+
+ m_metalRoughGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_metalRoughGL3Technique->graphicsApiFilter()->setMajorVersion(3);
+ m_metalRoughGL3Technique->graphicsApiFilter()->setMinorVersion(1);
+ m_metalRoughGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ Q_Q(QTexturedMetalRoughMaterial);
+ m_filterKey->setParent(q);
+ m_filterKey->setName(QStringLiteral("renderingStyle"));
+ m_filterKey->setValue(QStringLiteral("forward"));
+
+ m_metalRoughGL3Technique->addFilterKey(m_filterKey);
+ m_metalRoughGL3RenderPass->setShaderProgram(m_metalRoughGL3Shader);
+ m_metalRoughGL3Technique->addRenderPass(m_metalRoughGL3RenderPass);
+ m_metalRoughEffect->addTechnique(m_metalRoughGL3Technique);
+
+ m_metalRoughEffect->addParameter(m_baseColorParameter);
+ m_metalRoughEffect->addParameter(m_metalnessParameter);
+ m_metalRoughEffect->addParameter(m_roughnessParameter);
+ m_metalRoughEffect->addParameter(m_ambientOcclusionParameter);
+ m_metalRoughEffect->addParameter(m_normalParameter);
+
+ // Note that even though those parameters are not exposed in the API,
+ // they need to be kept around for now due to a bug in some drivers/GPUs
+ // (at least Intel) which cause issues with unbound textures even if you
+ // don't try to sample from them.
+ // Can probably go away once we generate the shaders and deal in this
+ // case in a better way.
+ m_metalRoughEffect->addParameter(m_environmentIrradianceParameter);
+ m_metalRoughEffect->addParameter(m_environmentSpecularParameter);
+
+ q->setEffect(m_metalRoughEffect);
+}
+
+void QTexturedMetalRoughMaterialPrivate::handleBaseColorChanged(const QVariant &var)
+{
+ Q_Q(QTexturedMetalRoughMaterial);
+ emit q->baseColorChanged(var.value<QAbstractTexture *>());
+}
+
+void QTexturedMetalRoughMaterialPrivate::handleMetallicChanged(const QVariant &var)
+{
+ Q_Q(QTexturedMetalRoughMaterial);
+ emit q->metalnessChanged(var.value<QAbstractTexture *>());
+}
+void QTexturedMetalRoughMaterialPrivate::handleRoughnessChanged(const QVariant &var)
+{
+ Q_Q(QTexturedMetalRoughMaterial);
+ emit q->roughnessChanged(var.value<QAbstractTexture *>());
+}
+void QTexturedMetalRoughMaterialPrivate::handleAmbientOcclusionChanged(const QVariant &var)
+{
+ Q_Q(QTexturedMetalRoughMaterial);
+ emit q->ambientOcclusionChanged(var.value<QAbstractTexture *>());
+}
+
+void QTexturedMetalRoughMaterialPrivate::handleNormalChanged(const QVariant &var)
+{
+ Q_Q(QTexturedMetalRoughMaterial);
+ emit q->normalChanged(var.value<QAbstractTexture *>());
+}
+
+/*!
+ \class Qt3DExtras::QTexturedMetalRoughMaterial
+ \brief The QTexturedMetalRoughMaterial provides a default implementation of PBR
+ lighting, environment maps and bump effect where the components are read from texture
+ maps (including normal maps).
+ \inmodule Qt3DExtras
+ \since 5.9
+ \inherits Qt3DRender::QMaterial
+
+ This material uses an effect with a single render pass approach and performs per fragment
+ lighting. Techniques are provided for OpenGL 3 only.
+*/
+
+/*!
+ Constructs a new QTexturedMetalRoughMaterial instance with parent object \a parent.
+*/
+QTexturedMetalRoughMaterial::QTexturedMetalRoughMaterial(QNode *parent)
+ : QMaterial(*new QTexturedMetalRoughMaterialPrivate, parent)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->init();
+}
+
+/*! \internal */
+QTexturedMetalRoughMaterial::QTexturedMetalRoughMaterial(QTexturedMetalRoughMaterialPrivate &dd, QNode *parent)
+ : QMaterial(dd, parent)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->init();
+}
+
+/*!
+ Destroys the QTexturedMetalRoughMaterial instance.
+*/
+QTexturedMetalRoughMaterial::~QTexturedMetalRoughMaterial()
+{
+}
+
+/*!
+ \property QTexturedMetalRoughMaterial::baseColor
+
+ Holds the current base color map texture.
+
+ By default, the base color texture has the following properties:
+
+ \list
+ \li Linear minification and magnification filters
+ \li Linear mipmap with mipmapping enabled
+ \li Repeat wrap mode
+ \li Maximum anisotropy of 16.0
+ \endlist
+*/
+QAbstractTexture *QTexturedMetalRoughMaterial::baseColor() const
+{
+ Q_D(const QTexturedMetalRoughMaterial);
+ return d->m_baseColorParameter->value().value<QAbstractTexture *>();
+}
+
+/*!
+ \property QTexturedMetalRoughMaterial::metalness
+
+ Holds the current metalness map texture.
+
+ By default, the metalness texture has the following properties:
+
+ \list
+ \li Linear minification and magnification filters
+ \li Linear mipmap with mipmapping enabled
+ \li Repeat wrap mode
+ \li Maximum anisotropy of 16.0
+ \endlist
+*/
+QAbstractTexture *QTexturedMetalRoughMaterial::metalness() const
+{
+ Q_D(const QTexturedMetalRoughMaterial);
+ return d->m_metalnessParameter->value().value<QAbstractTexture *>();
+}
+
+/*!
+ \property QTexturedMetalRoughMaterial::roughness
+
+ Holds the current roughness map texture.
+
+ By default, the roughness texture has the following properties:
+
+ \list
+ \li Linear minification and magnification filters
+ \li Linear mipmap with mipmapping enabled
+ \li Repeat wrap mode
+ \li Maximum anisotropy of 16.0
+ \endlist
+*/
+QAbstractTexture *QTexturedMetalRoughMaterial::roughness() const
+{
+ Q_D(const QTexturedMetalRoughMaterial);
+ return d->m_roughnessParameter->value().value<QAbstractTexture *>();
+}
+
+/*!
+ \property QTexturedMetalRoughMaterial::ambientOcclusion
+
+ Holds the current ambient occlusion map texture.
+
+ By default, the ambient occlusion texture has the following properties:
+
+ \list
+ \li Linear minification and magnification filters
+ \li Linear mipmap with mipmapping enabled
+ \li Repeat wrap mode
+ \li Maximum anisotropy of 16.0
+ \endlist
+*/
+QAbstractTexture *QTexturedMetalRoughMaterial::ambientOcclusion() const
+{
+ Q_D(const QTexturedMetalRoughMaterial);
+ return d->m_ambientOcclusionParameter->value().value<QAbstractTexture *>();
+}
+
+/*!
+ \property QTexturedMetalRoughMaterial::normal
+
+ Holds the current normal map texture.
+
+ By default, the normal texture has the following properties:
+
+ \list
+ \li Linear minification and magnification filters
+ \li Repeat wrap mode
+ \li Maximum anisotropy of 16.0
+ \endlist
+*/
+QAbstractTexture *QTexturedMetalRoughMaterial::normal() const
+{
+ Q_D(const QTexturedMetalRoughMaterial);
+ return d->m_normalParameter->value().value<QAbstractTexture *>();
+}
+
+
+void QTexturedMetalRoughMaterial::setBaseColor(QAbstractTexture *baseColor)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->m_baseColorParameter->setValue(QVariant::fromValue(baseColor));
+}
+
+void QTexturedMetalRoughMaterial::setMetalness(QAbstractTexture *metalness)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->m_metalnessParameter->setValue(QVariant::fromValue(metalness));
+}
+
+void QTexturedMetalRoughMaterial::setRoughness(QAbstractTexture *roughness)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->m_roughnessParameter->setValue(QVariant::fromValue(roughness));
+}
+
+void QTexturedMetalRoughMaterial::setAmbientOcclusion(QAbstractTexture *ambientOcclusion)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->m_ambientOcclusionParameter->setValue(QVariant::fromValue(ambientOcclusion));
+}
+
+void QTexturedMetalRoughMaterial::setNormal(QAbstractTexture *normal)
+{
+ Q_D(QTexturedMetalRoughMaterial);
+ d->m_normalParameter->setValue(QVariant::fromValue(normal));
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/defaults/qtexturedmetalroughmaterial.h b/src/extras/defaults/qtexturedmetalroughmaterial.h
new file mode 100644
index 000000000..62755a781
--- /dev/null
+++ b/src/extras/defaults/qtexturedmetalroughmaterial.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXTUREDMETALROUGHMATERIAL_H
+#define QT3DEXTRAS_QTEXTUREDMETALROUGHMATERIAL_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qmaterial.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QTexturedMetalRoughMaterialPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QTexturedMetalRoughMaterial : public Qt3DRender::QMaterial
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged)
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *metalness READ metalness WRITE setMetalness NOTIFY metalnessChanged)
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *roughness READ roughness WRITE setRoughness NOTIFY roughnessChanged)
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *ambientOcclusion READ ambientOcclusion WRITE setAmbientOcclusion NOTIFY ambientOcclusionChanged)
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *normal READ normal WRITE setNormal NOTIFY normalChanged)
+
+public:
+ explicit QTexturedMetalRoughMaterial(Qt3DCore::QNode *parent = nullptr);
+ ~QTexturedMetalRoughMaterial();
+
+ Qt3DRender::QAbstractTexture *baseColor() const;
+ Qt3DRender::QAbstractTexture *metalness() const;
+ Qt3DRender::QAbstractTexture *roughness() const;
+ Qt3DRender::QAbstractTexture *ambientOcclusion() const;
+ Qt3DRender::QAbstractTexture *normal() const;
+
+public Q_SLOTS:
+ void setBaseColor(Qt3DRender::QAbstractTexture *baseColor);
+ void setMetalness(Qt3DRender::QAbstractTexture *metalness);
+ void setRoughness(Qt3DRender::QAbstractTexture *roughness);
+ void setAmbientOcclusion(Qt3DRender::QAbstractTexture *ambientOcclusion);
+ void setNormal(Qt3DRender::QAbstractTexture *normal);
+
+Q_SIGNALS:
+ void baseColorChanged(Qt3DRender::QAbstractTexture *baseColor);
+ void metalnessChanged(Qt3DRender::QAbstractTexture *metalness);
+ void roughnessChanged(Qt3DRender::QAbstractTexture *roughness);
+ void ambientOcclusionChanged(Qt3DRender::QAbstractTexture *ambientOcclusion);
+ void normalChanged(Qt3DRender::QAbstractTexture *normal);
+
+protected:
+ explicit QTexturedMetalRoughMaterial(QTexturedMetalRoughMaterialPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QTexturedMetalRoughMaterial)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXTUREDMETALROUGHMATERIAL_H
diff --git a/src/extras/defaults/qtexturedmetalroughmaterial_p.h b/src/extras/defaults/qtexturedmetalroughmaterial_p.h
new file mode 100644
index 000000000..8972726e5
--- /dev/null
+++ b/src/extras/defaults/qtexturedmetalroughmaterial_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXTUREDMETALROUGHMATERIAL_P_H
+#define QT3DEXTRAS_QTEXTUREDMETALROUGHMATERIAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qmaterial_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QFilterKey;
+class QEffect;
+class QAbstractTexture;
+class QTechnique;
+class QParameter;
+class QShaderProgram;
+class QRenderPass;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QTexturedMetalRoughMaterial;
+
+class QTexturedMetalRoughMaterialPrivate : public Qt3DRender::QMaterialPrivate
+{
+public:
+ QTexturedMetalRoughMaterialPrivate();
+
+ void init();
+
+ void handleBaseColorChanged(const QVariant &var);
+ void handleMetallicChanged(const QVariant &var);
+ void handleRoughnessChanged(const QVariant &var);
+ void handleAmbientOcclusionChanged(const QVariant &var);
+ void handleNormalChanged(const QVariant &var);
+
+ Qt3DRender::QAbstractTexture *m_baseColorTexture;
+ Qt3DRender::QAbstractTexture *m_metalnessTexture;
+ Qt3DRender::QAbstractTexture *m_roughnessTexture;
+ Qt3DRender::QAbstractTexture *m_ambientOcclusionTexture;
+ Qt3DRender::QAbstractTexture *m_normalTexture;
+ Qt3DRender::QAbstractTexture *m_environmentIrradianceTexture;
+ Qt3DRender::QAbstractTexture *m_environmentSpecularTexture;
+ Qt3DRender::QParameter *m_baseColorParameter;
+ Qt3DRender::QParameter *m_metalnessParameter;
+ Qt3DRender::QParameter *m_roughnessParameter;
+ Qt3DRender::QParameter *m_ambientOcclusionParameter;
+ Qt3DRender::QParameter *m_normalParameter;
+ Qt3DRender::QParameter *m_environmentIrradianceParameter;
+ Qt3DRender::QParameter *m_environmentSpecularParameter;
+ Qt3DRender::QEffect *m_metalRoughEffect;
+ Qt3DRender::QTechnique *m_metalRoughGL3Technique;
+ Qt3DRender::QRenderPass *m_metalRoughGL3RenderPass;
+ Qt3DRender::QShaderProgram *m_metalRoughGL3Shader;
+ Qt3DRender::QFilterKey *m_filterKey;
+
+ Q_DECLARE_PUBLIC(QTexturedMetalRoughMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXTUREDMETALROUGHMATERIAL_P_H
+
diff --git a/src/extras/defaults/qtexturematerial.cpp b/src/extras/defaults/qtexturematerial.cpp
new file mode 100644
index 000000000..0038dd44a
--- /dev/null
+++ b/src/extras/defaults/qtexturematerial.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexturematerial.h"
+#include "qtexturematerial_p.h"
+#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
+#include <QUrl>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DRender;
+
+namespace Qt3DExtras {
+
+QTextureMaterialPrivate::QTextureMaterialPrivate()
+ : QMaterialPrivate()
+ , m_textureEffect(new QEffect)
+ , m_textureParameter(new QParameter(QStringLiteral("diffuseTexture"), new QTexture2D))
+ , m_textureOffsetParameter(new QParameter(QStringLiteral("texCoordOffset"), QVector2D(0.0f, 0.0f)))
+ , m_textureGL3Technique(new QTechnique)
+ , m_textureGL2Technique(new QTechnique)
+ , m_textureES2Technique(new QTechnique)
+ , m_textureGL3RenderPass(new QRenderPass)
+ , m_textureGL2RenderPass(new QRenderPass)
+ , m_textureES2RenderPass(new QRenderPass)
+ , m_textureGL3Shader(new QShaderProgram)
+ , m_textureGL2ES2Shader(new QShaderProgram)
+ , m_filterKey(new QFilterKey)
+{
+}
+
+void QTextureMaterialPrivate::init()
+{
+ connect(m_textureParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTextureMaterialPrivate::handleTextureChanged);
+ connect(m_textureOffsetParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QTextureMaterialPrivate::handleTextureOffsetChanged);
+
+ m_textureGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/unlittexture.vert"))));
+ m_textureGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/unlittexture.frag"))));
+ m_textureGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/unlittexture.vert"))));
+ m_textureGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/unlittexture.frag"))));
+
+ m_textureGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_textureGL3Technique->graphicsApiFilter()->setMajorVersion(3);
+ m_textureGL3Technique->graphicsApiFilter()->setMinorVersion(1);
+ m_textureGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ m_textureGL2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_textureGL2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_textureGL2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_textureGL2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+ m_textureES2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
+ m_textureES2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_textureES2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_textureES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+ Q_Q(QTextureMaterial);
+ m_filterKey->setParent(q);
+ m_filterKey->setName(QStringLiteral("renderingStyle"));
+ m_filterKey->setValue(QStringLiteral("forward"));
+
+ m_textureGL3Technique->addFilterKey(m_filterKey);
+ m_textureGL2Technique->addFilterKey(m_filterKey);
+ m_textureES2Technique->addFilterKey(m_filterKey);
+
+ m_textureGL3RenderPass->setShaderProgram(m_textureGL3Shader);
+ m_textureGL2RenderPass->setShaderProgram(m_textureGL2ES2Shader);
+ m_textureES2RenderPass->setShaderProgram(m_textureGL2ES2Shader);
+
+ m_textureGL3Technique->addRenderPass(m_textureGL3RenderPass);
+ m_textureGL2Technique->addRenderPass(m_textureGL2RenderPass);
+ m_textureES2Technique->addRenderPass(m_textureES2RenderPass);
+
+ m_textureEffect->addTechnique(m_textureGL3Technique);
+ m_textureEffect->addTechnique(m_textureGL2Technique);
+ m_textureEffect->addTechnique(m_textureES2Technique);
+
+ m_textureEffect->addParameter(m_textureParameter);
+ m_textureEffect->addParameter(m_textureOffsetParameter);
+
+ q->setEffect(m_textureEffect);
+}
+
+void QTextureMaterialPrivate::handleTextureChanged(const QVariant &var)
+{
+ Q_Q(QTextureMaterial);
+ emit q->textureChanged(var.value<QAbstractTexture *>());
+}
+
+void QTextureMaterialPrivate::handleTextureOffsetChanged(const QVariant &var)
+{
+ Q_Q(QTextureMaterial);
+ emit q->textureOffsetChanged(var.value<QVector2D>());
+}
+
+/*!
+ \class Qt3DExtras::QTextureMaterial
+ \brief The QTextureMaterial provides a default implementation of a simple unlit
+ texture material.
+ \inmodule Qt3DExtras
+ \since 5.9
+ \inherits Qt3DRender::QMaterial
+
+ This material uses an effect with a single render pass approach. Techniques are provided
+ for OpenGL 2, OpenGL 3 or above as well as OpenGL ES 2.
+*/
+
+/*!
+ Constructs a new QTextureMaterial instance with parent object \a parent.
+ */
+QTextureMaterial::QTextureMaterial(QNode *parent)
+ : QMaterial(*new QTextureMaterialPrivate, parent)
+{
+ Q_D(QTextureMaterial);
+ d->init();
+}
+
+/*!
+ Destroys the QTextureMaterial instance.
+*/
+QTextureMaterial::~QTextureMaterial()
+{
+}
+
+/*!
+ \property QTextureMaterial::texture
+
+ Holds the current texture used by the material.
+*/
+QAbstractTexture *QTextureMaterial::texture() const
+{
+ Q_D(const QTextureMaterial);
+ return d->m_textureParameter->value().value<QAbstractTexture *>();
+}
+
+/*!
+ \property QTextureMaterial::textureOffset
+
+ Holds the current texture offset. It is applied to texture
+ coordinates at render time. Defaults to (0.0, 0.0).
+
+*/
+QVector2D QTextureMaterial::textureOffset() const
+{
+ Q_D(const QTextureMaterial);
+ return d->m_textureOffsetParameter->value().value<QVector2D>();
+}
+
+void QTextureMaterial::setTexture(QAbstractTexture *texture)
+{
+ Q_D(QTextureMaterial);
+ d->m_textureParameter->setValue(QVariant::fromValue(texture));
+}
+
+void QTextureMaterial::setTextureOffset(QVector2D textureOffset)
+{
+ Q_D(QTextureMaterial);
+ d->m_textureOffsetParameter->setValue(QVariant::fromValue(textureOffset));
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/defaults/qtexturematerial.h b/src/extras/defaults/qtexturematerial.h
new file mode 100644
index 000000000..3101b9a1b
--- /dev/null
+++ b/src/extras/defaults/qtexturematerial.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXTUREMATERIAL_H
+#define QT3DEXTRAS_QTEXTUREMATERIAL_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qmaterial.h>
+#include <QVector2D>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAbstractTexture;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QTextureMaterialPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QTextureMaterial : public Qt3DRender::QMaterial
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *texture READ texture WRITE setTexture NOTIFY textureChanged)
+ Q_PROPERTY(QVector2D textureOffset READ textureOffset WRITE setTextureOffset NOTIFY textureOffsetChanged)
+public:
+ explicit QTextureMaterial(Qt3DCore::QNode *parent = nullptr);
+ ~QTextureMaterial();
+
+ Qt3DRender::QAbstractTexture *texture() const;
+ QVector2D textureOffset() const;
+
+public Q_SLOTS:
+ void setTexture(Qt3DRender::QAbstractTexture *texture);
+ void setTextureOffset(QVector2D textureOffset);
+
+Q_SIGNALS:
+ void textureChanged(Qt3DRender::QAbstractTexture *texture);
+ void textureOffsetChanged(QVector2D textureOffset);
+
+private:
+ Q_DECLARE_PRIVATE(QTextureMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXTUREMATERIAL_H
diff --git a/src/extras/defaults/qtexturematerial_p.h b/src/extras/defaults/qtexturematerial_p.h
new file mode 100644
index 000000000..5a8e78154
--- /dev/null
+++ b/src/extras/defaults/qtexturematerial_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXTUREMATERIAL_P_H
+#define QT3DEXTRAS_QTEXTUREMATERIAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qmaterial_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QFilterKey;
+class QEffect;
+class QAbstractTexture;
+class QTechnique;
+class QParameter;
+class QShaderProgram;
+class QRenderPass;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QTextureMaterial;
+
+class QTextureMaterialPrivate : public Qt3DRender::QMaterialPrivate
+{
+ QTextureMaterialPrivate();
+
+ void init();
+
+ void handleTextureChanged(const QVariant &var);
+ void handleTextureOffsetChanged(const QVariant &var);
+
+ Qt3DRender::QEffect *m_textureEffect;
+ Qt3DRender::QParameter *m_textureParameter;
+ Qt3DRender::QParameter *m_textureOffsetParameter;
+ Qt3DRender::QTechnique *m_textureGL3Technique;
+ Qt3DRender::QTechnique *m_textureGL2Technique;
+ Qt3DRender::QTechnique *m_textureES2Technique;
+ Qt3DRender::QRenderPass *m_textureGL3RenderPass;
+ Qt3DRender::QRenderPass *m_textureGL2RenderPass;
+ Qt3DRender::QRenderPass *m_textureES2RenderPass;
+ Qt3DRender::QShaderProgram *m_textureGL3Shader;
+ Qt3DRender::QShaderProgram *m_textureGL2ES2Shader;
+ Qt3DRender::QFilterKey *m_filterKey;
+
+ Q_DECLARE_PUBLIC(QTextureMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXTUREMATERIAL_P_H
+
diff --git a/src/extras/extras.pro b/src/extras/extras.pro
index d11172005..22c9fcb93 100644
--- a/src/extras/extras.pro
+++ b/src/extras/extras.pro
@@ -9,10 +9,10 @@ DEFINES += QT_NO_FOREACH
load(qt_module)
-include (animations/animations.pri)
include (geometries/geometries.pri)
include (3dtext/3dtext.pri)
include (defaults/defaults.pri)
+include (text/text.pri)
HEADERS += \
qt3dextras_global.h
diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc
index 121bfd029..9fce08a9f 100644
--- a/src/extras/extras.qrc
+++ b/src/extras/extras.qrc
@@ -39,6 +39,13 @@
<file>shaders/gl3/unlittexture.frag</file>
<file>shaders/es2/unlittexture.frag</file>
<file>shaders/es2/unlittexture.vert</file>
+ <file>shaders/gl3/metalrough.vert</file>
+ <file>shaders/gl3/metalrough.frag</file>
+ <file>shaders/gl3/metalroughuniform.frag</file>
+ <file>shaders/gl3/distancefieldtext.vert</file>
+ <file>shaders/gl3/distancefieldtext.frag</file>
+ <file>shaders/es2/distancefieldtext.frag</file>
+ <file>shaders/es2/distancefieldtext.vert</file>
<file>shaders/gl3/morphphong.vert</file>
<file>shaders/es2/morphphong.vert</file>
</qresource>
diff --git a/src/extras/geometries/qconegeometry.cpp b/src/extras/geometries/qconegeometry.cpp
index a86d10f6b..12bbf7ce3 100644
--- a/src/extras/geometries/qconegeometry.cpp
+++ b/src/extras/geometries/qconegeometry.cpp
@@ -57,10 +57,12 @@
#include "qconegeometry.h"
#include "qconegeometry_p.h"
+
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qattribute.h>
-#include <QVector3D>
+#include <QtGui/QVector3D>
+
#include <cmath>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qconemesh.cpp b/src/extras/geometries/qconemesh.cpp
index 8baa19217..5e327df03 100644
--- a/src/extras/geometries/qconemesh.cpp
+++ b/src/extras/geometries/qconemesh.cpp
@@ -41,13 +41,15 @@
# define _USE_MATH_DEFINES // For MSVC
#endif
-#include "qconemesh.h"
#include "qconegeometry.h"
+
+#include <Qt3DExtras/qconemesh.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qattribute.h>
+#include <QtGui/QVector3D>
+
#include <qmath.h>
-#include <QVector3D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qcuboidgeometry.cpp b/src/extras/geometries/qcuboidgeometry.cpp
index 28743858a..3bb68a500 100644
--- a/src/extras/geometries/qcuboidgeometry.cpp
+++ b/src/extras/geometries/qcuboidgeometry.cpp
@@ -39,12 +39,15 @@
#include "qcuboidgeometry.h"
#include "qcuboidgeometry_p.h"
+
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/private/renderlogging_p.h>
+
#include <limits>
+
QT_BEGIN_NAMESPACE
using namespace Qt3DRender;
diff --git a/src/extras/geometries/qcuboidgeometry.h b/src/extras/geometries/qcuboidgeometry.h
index fad5dcf9f..2c295d6c4 100644
--- a/src/extras/geometries/qcuboidgeometry.h
+++ b/src/extras/geometries/qcuboidgeometry.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qgeometry.h>
-#include <QSize>
+#include <QtCore/QSize>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qcuboidgeometry_p.h b/src/extras/geometries/qcuboidgeometry_p.h
index 212be19b4..cfabc0388 100644
--- a/src/extras/geometries/qcuboidgeometry_p.h
+++ b/src/extras/geometries/qcuboidgeometry_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
+#include <QtCore/QSize>
+
#include <Qt3DRender/private/qgeometry_p.h>
-#include <QSize>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qcuboidmesh.cpp b/src/extras/geometries/qcuboidmesh.cpp
index 88c735746..9e10d93a4 100644
--- a/src/extras/geometries/qcuboidmesh.cpp
+++ b/src/extras/geometries/qcuboidmesh.cpp
@@ -38,7 +38,8 @@
****************************************************************************/
#include "qcuboidmesh.h"
-#include "qcuboidgeometry.h"
+
+#include <Qt3DExtras/qcuboidgeometry.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qcuboidmesh.h b/src/extras/geometries/qcuboidmesh.h
index f709703c5..ca33c5f2d 100644
--- a/src/extras/geometries/qcuboidmesh.h
+++ b/src/extras/geometries/qcuboidmesh.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qgeometryrenderer.h>
-#include <QSize>
+#include <QtCore/QSize>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qcylindergeometry.cpp b/src/extras/geometries/qcylindergeometry.cpp
index 29f7ea7e0..4051477a6 100644
--- a/src/extras/geometries/qcylindergeometry.cpp
+++ b/src/extras/geometries/qcylindergeometry.cpp
@@ -43,11 +43,14 @@
#include "qcylindergeometry.h"
#include "qcylindergeometry_p.h"
+
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qattribute.h>
+#include <QtGui/QVector3D>
+
#include <qmath.h>
-#include <QVector3D>
+
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qcylindermesh.cpp b/src/extras/geometries/qcylindermesh.cpp
index 9b0ded28b..02df6295f 100644
--- a/src/extras/geometries/qcylindermesh.cpp
+++ b/src/extras/geometries/qcylindermesh.cpp
@@ -43,12 +43,14 @@
#endif
#include "qcylindermesh.h"
-#include "qcylindergeometry.h"
+
+#include <Qt3DExtras/qcylindergeometry.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qattribute.h>
+#include <QtGui/QVector3D>
+
#include <qmath.h>
-#include <QVector3D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qplanegeometry.cpp b/src/extras/geometries/qplanegeometry.cpp
index 16b401d3d..14ddb25e6 100644
--- a/src/extras/geometries/qplanegeometry.cpp
+++ b/src/extras/geometries/qplanegeometry.cpp
@@ -39,9 +39,11 @@
#include "qplanegeometry.h"
#include "qplanegeometry_p.h"
+
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
+
#include <limits>
QT_BEGIN_NAMESPACE
@@ -52,7 +54,7 @@ namespace Qt3DExtras {
namespace {
-QByteArray createPlaneVertexData(float w, float h, const QSize &resolution)
+QByteArray createPlaneVertexData(float w, float h, const QSize &resolution, bool mirrored)
{
Q_ASSERT(w > 0.0f);
Q_ASSERT(h > 0.0f);
@@ -93,7 +95,7 @@ QByteArray createPlaneVertexData(float w, float h, const QSize &resolution)
// texture coordinates
*fptr++ = u;
- *fptr++ = v;
+ *fptr++ = mirrored ? 1.0f - v : v;
// normal
*fptr++ = 0.0f;
@@ -147,17 +149,18 @@ QByteArray createPlaneIndexData(const QSize &resolution)
class PlaneVertexBufferFunctor : public QBufferDataGenerator
{
public:
- explicit PlaneVertexBufferFunctor(float w, float h, const QSize &resolution)
+ explicit PlaneVertexBufferFunctor(float w, float h, const QSize &resolution, bool mirrored)
: m_width(w)
, m_height(h)
, m_resolution(resolution)
+ , m_mirrored(mirrored)
{}
~PlaneVertexBufferFunctor() {}
QByteArray operator()() Q_DECL_FINAL
{
- return createPlaneVertexData(m_width, m_height, m_resolution);
+ return createPlaneVertexData(m_width, m_height, m_resolution, m_mirrored);
}
bool operator ==(const QBufferDataGenerator &other) const Q_DECL_FINAL
@@ -166,7 +169,8 @@ public:
if (otherFunctor != nullptr)
return (otherFunctor->m_width == m_width &&
otherFunctor->m_height == m_height &&
- otherFunctor->m_resolution == m_resolution);
+ otherFunctor->m_resolution == m_resolution &&
+ otherFunctor->m_mirrored == m_mirrored);
return false;
}
@@ -176,6 +180,7 @@ public:
float m_width;
float m_height;
QSize m_resolution;
+ bool m_mirrored;
};
class PlaneIndexBufferFunctor : public QBufferDataGenerator
@@ -235,6 +240,13 @@ public:
*/
/*!
+ * \qmlproperty bool PlaneGeometry::mirrored
+ * \since 5.9
+ *
+ * Controls if the UV coordinates of the plane should be flipped vertically.
+ */
+
+/*!
* \qmlproperty Attribute PlaneGeometry::positionAttribute
*
* Holds the geometry position attribute.
@@ -316,7 +328,7 @@ void QPlaneGeometry::updateVertices()
d->m_normalAttribute->setCount(nVerts);
d->m_texCoordAttribute->setCount(nVerts);
d->m_tangentAttribute->setCount(nVerts);
- d->m_vertexBuffer->setDataGenerator(QSharedPointer<PlaneVertexBufferFunctor>::create(d->m_width, d->m_height, d->m_meshResolution));
+ d->m_vertexBuffer->setDataGenerator(QSharedPointer<PlaneVertexBufferFunctor>::create(d->m_width, d->m_height, d->m_meshResolution, d->m_mirrored));
}
/*!
@@ -363,6 +375,16 @@ void QPlaneGeometry::setHeight(float height)
emit heightChanged(height);
}
+void QPlaneGeometry::setMirrored(bool mirrored)
+{
+ Q_D(QPlaneGeometry);
+ if (mirrored == d->m_mirrored)
+ return;
+ d->m_mirrored = mirrored;
+ updateVertices();
+ emit mirroredChanged(mirrored);
+}
+
/*!
* \property QPlaneGeometry::resolution
*
@@ -397,6 +419,18 @@ float QPlaneGeometry::height() const
}
/*!
+ * \property QPlaneGeometry::mirrored
+ * \since 5.9
+ *
+ * Controls if the UV coordinates of the plane should be flipped vertically.
+ */
+bool QPlaneGeometry::mirrored() const
+{
+ Q_D(const QPlaneGeometry);
+ return d->m_mirrored;
+}
+
+/*!
* \property QPlaneGeometry::positionAttribute
*
* Holds the geometry position attribute.
@@ -456,6 +490,7 @@ QPlaneGeometryPrivate::QPlaneGeometryPrivate()
, m_width(1.0f)
, m_height(1.0f)
, m_meshResolution(QSize(2, 2))
+ , m_mirrored(false)
, m_positionAttribute(nullptr)
, m_normalAttribute(nullptr)
, m_texCoordAttribute(nullptr)
@@ -523,7 +558,7 @@ void QPlaneGeometryPrivate::init()
// Each primitive has 3 vertives
m_indexAttribute->setCount(faces * 3);
- m_vertexBuffer->setDataGenerator(QSharedPointer<PlaneVertexBufferFunctor>::create(m_width, m_height, m_meshResolution));
+ m_vertexBuffer->setDataGenerator(QSharedPointer<PlaneVertexBufferFunctor>::create(m_width, m_height, m_meshResolution, m_mirrored));
m_indexBuffer->setDataGenerator(QSharedPointer<PlaneIndexBufferFunctor>::create(m_meshResolution));
q->addAttribute(m_positionAttribute);
diff --git a/src/extras/geometries/qplanegeometry.h b/src/extras/geometries/qplanegeometry.h
index 7ec5cba43..4a4efe6eb 100644
--- a/src/extras/geometries/qplanegeometry.h
+++ b/src/extras/geometries/qplanegeometry.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qgeometry.h>
-#include <QSize>
+#include <QtCore/QSize>
QT_BEGIN_NAMESPACE
@@ -62,6 +62,7 @@ class QT3DEXTRASSHARED_EXPORT QPlaneGeometry : public Qt3DRender::QGeometry
Q_PROPERTY(float width READ width WRITE setWidth NOTIFY widthChanged)
Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged)
Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
+ Q_PROPERTY(bool mirrored READ mirrored WRITE setMirrored NOTIFY mirroredChanged REVISION 9)
Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT)
Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT)
Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT)
@@ -78,6 +79,7 @@ public:
QSize resolution() const;
float width() const;
float height() const;
+ bool mirrored() const;
Qt3DRender::QAttribute *positionAttribute() const;
Qt3DRender::QAttribute *normalAttribute() const;
@@ -89,11 +91,13 @@ public Q_SLOTS:
void setResolution(const QSize &resolution);
void setWidth(float width);
void setHeight(float height);
+ void setMirrored(bool mirrored);
Q_SIGNALS:
void resolutionChanged(const QSize &resolution);
void widthChanged(float width);
void heightChanged(float height);
+ void mirroredChanged(bool mirrored);
protected:
QPlaneGeometry(QPlaneGeometryPrivate &dd, QNode *parent = nullptr);
diff --git a/src/extras/geometries/qplanegeometry_p.h b/src/extras/geometries/qplanegeometry_p.h
index d0a4e88e4..68d979895 100644
--- a/src/extras/geometries/qplanegeometry_p.h
+++ b/src/extras/geometries/qplanegeometry_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
+#include <QtCore/QSize>
+
#include <Qt3DRender/private/qgeometry_p.h>
-#include <QSize>
QT_BEGIN_NAMESPACE
@@ -74,6 +75,7 @@ public:
float m_width;
float m_height;
QSize m_meshResolution;
+ bool m_mirrored;
Qt3DRender::QAttribute *m_positionAttribute;
Qt3DRender::QAttribute *m_normalAttribute;
Qt3DRender::QAttribute *m_texCoordAttribute;
diff --git a/src/extras/geometries/qplanemesh.cpp b/src/extras/geometries/qplanemesh.cpp
index 120aed6df..4804df024 100644
--- a/src/extras/geometries/qplanemesh.cpp
+++ b/src/extras/geometries/qplanemesh.cpp
@@ -38,7 +38,8 @@
****************************************************************************/
#include "qplanemesh.h"
-#include "qplanegeometry.h"
+
+#include <Qt3DExtras/qplanegeometry.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +73,13 @@ namespace Qt3DExtras {
*/
/*!
+ * \qmlproperty bool PlaneMesh::mirrored
+ * \since 5.9
+ *
+ * Controls if the UV coordinates of the plane should be flipped vertically.
+ */
+
+/*!
* \class Qt3DExtras::QPlaneMesh
* \inheaderfile Qt3DExtras/QPlaneMesh
* \inmodule Qt3DExtras
@@ -91,6 +99,7 @@ QPlaneMesh::QPlaneMesh(QNode *parent)
QObject::connect(geometry, &QPlaneGeometry::widthChanged, this, &QPlaneMesh::widthChanged);
QObject::connect(geometry, &QPlaneGeometry::heightChanged, this, &QPlaneMesh::heightChanged);
QObject::connect(geometry, &QPlaneGeometry::resolutionChanged, this, &QPlaneMesh::meshResolutionChanged);
+ QObject::connect(geometry, &QPlaneGeometry::mirroredChanged, this, &QPlaneMesh::mirroredChanged);
QGeometryRenderer::setGeometry(geometry);
}
@@ -146,6 +155,22 @@ QSize QPlaneMesh::meshResolution() const
return static_cast<QPlaneGeometry *>(geometry())->resolution();
}
+void QPlaneMesh::setMirrored(bool mirrored)
+{
+ static_cast<QPlaneGeometry *>(geometry())->setMirrored(mirrored);
+}
+
+/*!
+ * \property QPlaneMesh::mirrored
+ * \since 5.9
+ *
+ * Controls if the UV coordinates of the plane should be flipped vertically.
+ */
+bool QPlaneMesh::mirrored() const
+{
+ return static_cast<QPlaneGeometry *>(geometry())->mirrored();
+}
+
} // namespace Qt3DExtras
QT_END_NAMESPACE
diff --git a/src/extras/geometries/qplanemesh.h b/src/extras/geometries/qplanemesh.h
index b1505db17..1cf2ae79e 100644
--- a/src/extras/geometries/qplanemesh.h
+++ b/src/extras/geometries/qplanemesh.h
@@ -42,7 +42,7 @@
#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qgeometryrenderer.h>
-#include <QSize>
+#include <QtCore/QSize>
QT_BEGIN_NAMESPACE
@@ -54,6 +54,7 @@ class QT3DEXTRASSHARED_EXPORT QPlaneMesh : public Qt3DRender::QGeometryRenderer
Q_PROPERTY(float width READ width WRITE setWidth NOTIFY widthChanged)
Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged)
Q_PROPERTY(QSize meshResolution READ meshResolution WRITE setMeshResolution NOTIFY meshResolutionChanged)
+ Q_PROPERTY(bool mirrored READ mirrored WRITE setMirrored NOTIFY mirroredChanged REVISION 9)
public:
explicit QPlaneMesh(Qt3DCore::QNode *parent = nullptr);
@@ -62,16 +63,19 @@ public:
float width() const;
float height() const;
QSize meshResolution() const;
+ bool mirrored() const;
public Q_SLOTS:
void setWidth(float width);
void setHeight(float height);
void setMeshResolution(const QSize &resolution);
+ void setMirrored(bool mirrored);
Q_SIGNALS:
void meshResolutionChanged(const QSize &meshResolution);
void widthChanged(float width);
void heightChanged(float height);
+ void mirroredChanged(bool mirrored);
private:
// As this is a default provided geometry renderer, no one should be able
diff --git a/src/extras/geometries/qspheregeometry.cpp b/src/extras/geometries/qspheregeometry.cpp
index a79eb8074..eae12ef39 100644
--- a/src/extras/geometries/qspheregeometry.cpp
+++ b/src/extras/geometries/qspheregeometry.cpp
@@ -39,15 +39,17 @@
#include "qspheregeometry.h"
#include "qspheregeometry_p.h"
+
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qattribute.h>
+#include <qmath.h>
+
#ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES // For MSVC
#endif
-#include <qmath.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qspheremesh.cpp b/src/extras/geometries/qspheremesh.cpp
index 988a95990..22089d7ab 100644
--- a/src/extras/geometries/qspheremesh.cpp
+++ b/src/extras/geometries/qspheremesh.cpp
@@ -39,7 +39,8 @@
****************************************************************************/
#include "qspheremesh.h"
-#include "qspheregeometry.h"
+
+#include <Qt3DExtras/qspheregeometry.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qtorusgeometry.cpp b/src/extras/geometries/qtorusgeometry.cpp
index 08afce1b0..57c94ec95 100644
--- a/src/extras/geometries/qtorusgeometry.cpp
+++ b/src/extras/geometries/qtorusgeometry.cpp
@@ -39,12 +39,14 @@
#include "qtorusgeometry.h"
#include "qtorusgeometry_p.h"
+
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qbufferdatagenerator.h>
#include <Qt3DRender/qattribute.h>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
+
#include <qmath.h>
-#include <QVector3D>
-#include <QVector4D>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/geometries/qtorusmesh.cpp b/src/extras/geometries/qtorusmesh.cpp
index 96fce9ec0..8e7c678db 100644
--- a/src/extras/geometries/qtorusmesh.cpp
+++ b/src/extras/geometries/qtorusmesh.cpp
@@ -43,7 +43,8 @@
#endif
#include "qtorusmesh.h"
-#include "qtorusgeometry.h"
+
+#include <Qt3DExtras/qtorusgeometry.h>
QT_BEGIN_NAMESPACE
diff --git a/src/extras/shaders/es2/distancefieldtext.frag b/src/extras/shaders/es2/distancefieldtext.frag
new file mode 100644
index 000000000..88ead1f68
--- /dev/null
+++ b/src/extras/shaders/es2/distancefieldtext.frag
@@ -0,0 +1,36 @@
+#define FP highp
+
+uniform FP sampler2D distanceFieldTexture;
+uniform FP float minAlpha;
+uniform FP float maxAlpha;
+uniform FP float textureSize;
+uniform FP vec4 color;
+
+varying FP vec3 position;
+varying FP vec2 texCoord;
+
+void main()
+{
+ // determine the scale of the glyph texture within pixel-space coordinates
+ // (that is, how many pixels are drawn for each texel)
+ FP vec2 texelDeltaX = abs(dFdx(texCoord));
+ FP vec2 texelDeltaY = abs(dFdy(texCoord));
+ FP float avgTexelDelta = textureSize * 0.5 * (texelDeltaX.x + texelDeltaX.y + texelDeltaY.x + texelDeltaY.y);
+ FP float texScale = 1.0 / avgTexelDelta;
+
+ // scaled to interval [0.0, 0.15]
+ FP float devScaleMin = 0.00;
+ FP float devScaleMax = 0.15;
+ FP float scaled = (clamp(texScale, devScaleMin, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin);
+
+ // thickness of glyphs should increase a lot for very small glyphs to make them readable
+ FP float base = 0.5;
+ FP float threshold = base * scaled;
+ FP float range = 0.06 / texScale;
+
+ FP float minAlpha = threshold - range;
+ FP float maxAlpha = threshold + range;
+
+ FP float distVal = texture2D(distanceFieldTexture, texCoord).r;
+ gl_FragColor = color * smoothstep(minAlpha, maxAlpha, distVal);
+}
diff --git a/src/extras/shaders/es2/distancefieldtext.vert b/src/extras/shaders/es2/distancefieldtext.vert
new file mode 100644
index 000000000..f7fc5327b
--- /dev/null
+++ b/src/extras/shaders/es2/distancefieldtext.vert
@@ -0,0 +1,17 @@
+attribute vec3 vertexPosition;
+attribute vec2 vertexTexCoord;
+
+varying vec3 position;
+varying vec2 texCoord;
+
+uniform mat4 modelView;
+uniform mat4 mvp;
+
+void main()
+{
+ texCoord = vertexTexCoord;
+ position = vec3(modelView * vec4(vertexPosition, 1.0));
+
+ gl_Position = mvp * vec4(vertexPosition, 1.0);
+}
+
diff --git a/src/extras/shaders/es2/light.inc.frag b/src/extras/shaders/es2/light.inc.frag
index 02660f008..074af5799 100644
--- a/src/extras/shaders/es2/light.inc.frag
+++ b/src/extras/shaders/es2/light.inc.frag
@@ -26,27 +26,45 @@ void adsModelNormalMapped(const in FP vec3 vpos, const in FP vec3 vnormal, const
FP vec3 n = normalize( vnormal );
FP vec3 s, ts;
+ Light light;
for (int i = 0; i < lightCount; ++i) {
+ if (i == 0)
+ light = lights[0];
+ else if (i == 1)
+ light = lights[1];
+ else if (i == 2)
+ light = lights[2];
+ else if (i == 3)
+ light = lights[3];
+ else if (i == 4)
+ light = lights[4];
+ else if (i == 5)
+ light = lights[5];
+ else if (i == 6)
+ light = lights[6];
+ else if (i == 7)
+ light = lights[7];
+
FP float att = 1.0;
- if ( lights[i].type != TYPE_DIRECTIONAL ) {
- s = lights[i].position - vpos;
+ if ( light.type != TYPE_DIRECTIONAL ) {
+ s = light.position - vpos;
if ( dot(snormal, s) < 0.0 )
att = 0.0;
else {
ts = normalize( tangentMatrix * s );
- if (length( lights[i].attenuation ) != 0.0) {
+ if (length( light.attenuation ) != 0.0) {
FP float dist = length(s);
- att = 1.0 / (lights[i].attenuation.x + lights[i].attenuation.y * dist + lights[i].attenuation.z * dist * dist);
+ att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);
}
s = normalize( s );
- if ( lights[i].type == TYPE_SPOT ) {
- if ( degrees(acos(dot(-s, normalize(lights[i].direction))) ) > lights[i].cutOffAngle)
+ if ( light.type == TYPE_SPOT ) {
+ if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle)
att = 0.0;
}
}
} else {
- if ( dot(snormal, -lights[i].direction) > 0.0 )
- s = normalize( tangentMatrix * -lights[i].direction );
+ if ( dot(snormal, -light.direction) > 0.0 )
+ s = normalize( tangentMatrix * -light.direction );
else
att = 0.0;
}
@@ -61,8 +79,8 @@ void adsModelNormalMapped(const in FP vec3 vpos, const in FP vec3 vnormal, const
specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
}
- diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
- specularColor += att * lights[i].intensity * specular * lights[i].color;
+ diffuseColor += att * light.intensity * diffuse * light.color;
+ specularColor += att * light.intensity * specular * light.color;
}
}
@@ -75,21 +93,39 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3
FP vec3 n = normalize( vnormal );
FP vec3 s;
+ Light light;
for (int i = 0; i < lightCount; ++i) {
+ if (i == 0)
+ light = lights[0];
+ else if (i == 1)
+ light = lights[1];
+ else if (i == 2)
+ light = lights[2];
+ else if (i == 3)
+ light = lights[3];
+ else if (i == 4)
+ light = lights[4];
+ else if (i == 5)
+ light = lights[5];
+ else if (i == 6)
+ light = lights[6];
+ else if (i == 7)
+ light = lights[7];
+
FP float att = 1.0;
- if ( lights[i].type != TYPE_DIRECTIONAL ) {
- s = lights[i].position - vpos;
- if (length( lights[i].attenuation ) != 0.0) {
+ if ( light.type != TYPE_DIRECTIONAL ) {
+ s = light.position - vpos;
+ if (length( light.attenuation ) != 0.0) {
FP float dist = length(s);
- att = 1.0 / (lights[i].attenuation.x + lights[i].attenuation.y * dist + lights[i].attenuation.z * dist * dist);
+ att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);
}
s = normalize( s );
- if ( lights[i].type == TYPE_SPOT ) {
- if ( degrees(acos(dot(-s, normalize(lights[i].direction))) ) > lights[i].cutOffAngle)
+ if ( light.type == TYPE_SPOT ) {
+ if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle)
att = 0.0;
}
} else {
- s = normalize( -lights[i].direction );
+ s = normalize( -light.direction );
}
FP float diffuse = max( dot( s, n ), 0.0 );
@@ -102,8 +138,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3
specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess );
}
- diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
- specularColor += att * lights[i].intensity * specular * lights[i].color;
+ diffuseColor += att * light.intensity * diffuse * light.color;
+ specularColor += att * light.intensity * specular * light.color;
}
}
@@ -114,25 +150,43 @@ void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffus
FP vec3 n = normalize( vnormal );
FP vec3 s;
+ Light light;
for (int i = 0; i < lightCount; ++i) {
+ if (i == 0)
+ light = lights[0];
+ else if (i == 1)
+ light = lights[1];
+ else if (i == 2)
+ light = lights[2];
+ else if (i == 3)
+ light = lights[3];
+ else if (i == 4)
+ light = lights[4];
+ else if (i == 5)
+ light = lights[5];
+ else if (i == 6)
+ light = lights[6];
+ else if (i == 7)
+ light = lights[7];
+
FP float att = 1.0;
- if ( lights[i].type != TYPE_DIRECTIONAL ) {
- s = lights[i].position - vpos;
- if (length( lights[i].attenuation ) != 0.0) {
+ if ( light.type != TYPE_DIRECTIONAL ) {
+ s = light.position - vpos;
+ if (length( light.attenuation ) != 0.0) {
FP float dist = length(s);
- att = 1.0 / (lights[i].attenuation.x + lights[i].attenuation.y * dist + lights[i].attenuation.z * dist * dist);
+ att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);
}
s = normalize( s );
- if ( lights[i].type == TYPE_SPOT ) {
- if ( degrees(acos(dot(-s, normalize(lights[i].direction))) ) > lights[i].cutOffAngle)
+ if ( light.type == TYPE_SPOT ) {
+ if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle)
att = 0.0;
}
} else {
- s = normalize( -lights[i].direction );
+ s = normalize( -light.direction );
}
FP float diffuse = max( dot( s, n ), 0.0 );
- diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
+ diffuseColor += att * light.intensity * diffuse * light.color;
}
}
diff --git a/src/extras/shaders/gl3/distancefieldtext.frag b/src/extras/shaders/gl3/distancefieldtext.frag
new file mode 100644
index 000000000..4f0c9cac0
--- /dev/null
+++ b/src/extras/shaders/gl3/distancefieldtext.frag
@@ -0,0 +1,38 @@
+#version 150 core
+
+uniform sampler2D distanceFieldTexture;
+uniform float minAlpha;
+uniform float maxAlpha;
+uniform float textureSize;
+uniform vec4 color;
+
+in vec3 position;
+in vec2 texCoord;
+
+out vec4 fragColor;
+
+void main()
+{
+ // determine the scale of the glyph texture within pixel-space coordinates
+ // (that is, how many pixels are drawn for each texel)
+ vec2 texelDeltaX = abs(dFdx(texCoord));
+ vec2 texelDeltaY = abs(dFdy(texCoord));
+ float avgTexelDelta = textureSize * 0.5 * (texelDeltaX.x + texelDeltaX.y + texelDeltaY.x + texelDeltaY.y);
+ float texScale = 1.0 / avgTexelDelta;
+
+ // scaled to interval [0.0, 0.15]
+ float devScaleMin = 0.00;
+ float devScaleMax = 0.15;
+ float scaled = (clamp(texScale, devScaleMin, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin);
+
+ // thickness of glyphs should increase a lot for very small glyphs to make them readable
+ float base = 0.5;
+ float threshold = base * scaled;
+ float range = 0.06 / texScale;
+
+ float minAlpha = threshold - range;
+ float maxAlpha = threshold + range;
+
+ float distVal = texture(distanceFieldTexture, texCoord).r;
+ fragColor = color * smoothstep(minAlpha, maxAlpha, distVal);
+}
diff --git a/src/extras/shaders/gl3/distancefieldtext.vert b/src/extras/shaders/gl3/distancefieldtext.vert
new file mode 100644
index 000000000..9bd2a0a90
--- /dev/null
+++ b/src/extras/shaders/gl3/distancefieldtext.vert
@@ -0,0 +1,19 @@
+#version 150 core
+
+in vec3 vertexPosition;
+in vec2 vertexTexCoord;
+
+out vec3 position;
+out vec2 texCoord;
+
+uniform mat4 modelView;
+uniform mat4 mvp;
+
+void main()
+{
+ texCoord = vertexTexCoord;
+ position = vec3(modelView * vec4(vertexPosition, 1.0));
+
+ gl_Position = mvp * vec4(vertexPosition, 1.0);
+}
+
diff --git a/src/extras/shaders/gl3/light.inc.frag b/src/extras/shaders/gl3/light.inc.frag
index 3047bdb3c..ce5c581cf 100644
--- a/src/extras/shaders/gl3/light.inc.frag
+++ b/src/extras/shaders/gl3/light.inc.frag
@@ -16,6 +16,14 @@ struct Light {
uniform Light lights[MAX_LIGHTS];
uniform int lightCount;
+// Pre-convolved environment maps
+struct EnvironmentLight {
+ samplerCube irradiance; // For diffuse contribution
+ samplerCube specular; // For specular contribution
+};
+uniform EnvironmentLight envLight;
+uniform int envLightCount = 0;
+
void adsModelNormalMapped(const in vec3 worldPos,
const in vec3 tsNormal,
const in vec3 worldEye,
diff --git a/src/extras/shaders/gl3/metalrough.frag b/src/extras/shaders/gl3/metalrough.frag
new file mode 100644
index 000000000..7f2f3d20e
--- /dev/null
+++ b/src/extras/shaders/gl3/metalrough.frag
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#version 150
+
+in vec2 texCoord;
+in vec3 worldPosition;
+in vec3 worldNormal;
+in vec4 worldTangent;
+
+out vec4 fragColor;
+
+// Qt 3D built in uniforms
+uniform vec3 eyePosition; // World space eye position
+uniform float time; // Time in seconds
+
+// PBR Material maps
+uniform sampler2D baseColorMap;
+uniform sampler2D metalnessMap;
+uniform sampler2D roughnessMap;
+uniform sampler2D normalMap;
+uniform sampler2D ambientOcclusionMap;
+
+// User control parameters
+uniform float metalFactor = 1.0;
+
+// Exposure correction
+uniform float exposure = 0.0;
+// Gamma correction
+uniform float gamma = 2.2;
+
+#pragma include light.inc.frag
+
+int mipLevelCount(const in samplerCube cube)
+{
+ int baseSize = textureSize(cube, 0).x;
+ int nMips = int(log2(float(baseSize>0 ? baseSize : 1))) + 1;
+ return nMips;
+}
+
+float remapRoughness(const in float roughness)
+{
+ // As per page 14 of
+ // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ // we remap the roughness to give a more perceptually linear response
+ // of "bluriness" as a function of the roughness specified by the user.
+ // r = roughness^2
+ const float maxSpecPower = 999999.0;
+ const float minRoughness = sqrt(2.0 / (maxSpecPower + 2));
+ return max(roughness * roughness, minRoughness);
+}
+
+mat3 calcWorldSpaceToTangentSpaceMatrix(const in vec3 wNormal, const in vec4 wTangent)
+{
+ // Make the tangent truly orthogonal to the normal by using Gram-Schmidt.
+ // This allows to build the tangentMatrix below by simply transposing the
+ // tangent -> eyespace matrix (which would now be orthogonal)
+ vec3 wFixedTangent = normalize(wTangent.xyz - dot(wTangent.xyz, wNormal) * wNormal);
+
+ // Calculate binormal vector. No "real" need to renormalize it,
+ // as built by crossing two normal vectors.
+ // To orient the binormal correctly, use the fourth coordinate of the tangent,
+ // which is +1 for a right hand system, and -1 for a left hand system.
+ vec3 wBinormal = cross(wNormal, wFixedTangent.xyz) * wTangent.w;
+
+ // Construct matrix to transform from world space to tangent space
+ // This is the transpose of the tangentToWorld transformation matrix
+ mat3 tangentToWorldMatrix = mat3(wFixedTangent, wBinormal, wNormal);
+ mat3 worldToTangentMatrix = transpose(tangentToWorldMatrix);
+ return worldToTangentMatrix;
+}
+
+float alphaToMipLevel(float alpha)
+{
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
+
+ // We use the mip level calculation from Lys' default power drop, which in
+ // turn is a slight modification of that used in Marmoset Toolbag. See
+ // https://docs.knaldtech.com/doku.php?id=specular_lys for details.
+ // For now we assume a max specular power of 999999 which gives
+ // maxGlossiness = 1.
+ const float k0 = 0.00098;
+ const float k1 = 0.9921;
+ float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1;
+
+ // TODO: Optimize by doing this on CPU and set as
+ // uniform int envLight.specularMipLevels say (if present in shader).
+ // Lookup the number of mips in the specular envmap
+ int mipLevels = mipLevelCount(envLight.specular);
+
+ // Offset of smallest miplevel we should use (corresponds to specular
+ // power of 1). I.e. in the 32x32 sized mip.
+ const float mipOffset = 5.0;
+
+ // The final factor is really 1 - g / g_max but as mentioned above g_max
+ // is 1 by definition here so we can avoid the division. If we make the
+ // max specular power for the spec map configurable, this will need to
+ // be handled properly.
+ float mipLevel = (mipLevels - 1.0 - mipOffset) * (1.0 - glossiness);
+ return mipLevel;
+}
+
+float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha)
+{
+ // Blinn-Phong approximation - see
+ // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
+ return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower);
+}
+
+vec3 fresnelFactor(const in vec3 color, const in float cosineFactor)
+{
+ // Calculate the Fresnel effect value
+ vec3 f = color;
+ vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
+ return clamp(F, f, vec3(1.0));
+}
+
+float geometricModel(const in float lDotN,
+ const in float vDotN,
+ const in vec3 h)
+{
+ // Implicit geometric model (equal to denominator in specular model).
+ // This currently assumes that there is no attenuation by geometric shadowing or
+ // masking according to the microfacet theory.
+ return lDotN * vDotN;
+}
+
+vec3 specularModel(const in vec3 F0,
+ const in float sDotH,
+ const in float sDotN,
+ const in float vDotN,
+ const in vec3 n,
+ const in vec3 h)
+{
+ // Clamp sDotN and vDotN to small positive value to prevent the
+ // denominator in the reflection equation going to infinity. Balance this
+ // by using the clamped values in the geometric factor function to
+ // avoid ugly seams in the specular lighting.
+ float sDotNPrime = max(sDotN, 0.001);
+ float vDotNPrime = max(vDotN, 0.001);
+
+ vec3 F = fresnelFactor(F0, sDotH);
+ float G = geometricModel(sDotNPrime, vDotNPrime, h);
+
+ vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
+ return clamp(cSpec, vec3(0.0), vec3(1.0));
+}
+
+vec3 pbrModel(const in int lightIndex,
+ const in vec3 wPosition,
+ const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha,
+ const in float ambientOcclusion)
+{
+ // Calculate some useful quantities
+ vec3 n = wNormal;
+ vec3 s = vec3(0.0);
+ vec3 v = wView;
+ vec3 h = vec3(0.0);
+
+ float vDotN = dot(v, n);
+ float sDotN = 0.0;
+ float sDotH = 0.0;
+ float att = 1.0;
+
+ if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
+ // Point and Spot lights
+ vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
+ s = normalize(sUnnormalized);
+
+ // Calculate the attenuation factor
+ sDotN = dot(s, n);
+ if (sDotN > 0.0) {
+ if (lights[lightIndex].constantAttenuation != 0.0
+ || lights[lightIndex].linearAttenuation != 0.0
+ || lights[lightIndex].quadraticAttenuation != 0.0) {
+ float dist = length(sUnnormalized);
+ att = 1.0 / (lights[lightIndex].constantAttenuation +
+ lights[lightIndex].linearAttenuation * dist +
+ lights[lightIndex].quadraticAttenuation * dist * dist);
+ }
+
+ // The light direction is in world space already
+ if (lights[lightIndex].type == TYPE_SPOT) {
+ // Check if fragment is inside or outside of the spot light cone
+ if (degrees(acos(dot(-s, lights[lightIndex].direction))) > lights[lightIndex].cutOffAngle)
+ sDotN = 0.0;
+ }
+ }
+ } else {
+ // Directional lights
+ // The light direction is in world space already
+ s = normalize(-lights[lightIndex].direction);
+ sDotN = dot(s, n);
+ }
+
+ h = normalize(s + v);
+ sDotH = dot(s, h);
+
+ // Calculate diffuse component
+ vec3 diffuseColor = (1.0 - metalness) * baseColor;
+ vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
+
+ // Calculate specular component
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = vec3(0.0);
+ if (sDotN > 0.0) {
+ specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
+ specularFactor *= normalDistribution(n, h, alpha);
+ }
+ vec3 specularColor = lights[lightIndex].color;
+ vec3 specular = specularColor * specularFactor;
+
+ // Blend between diffuse and specular to conserver energy
+ vec3 color = lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
+
+ // Reduce by ambient occlusion amount
+ color *= ambientOcclusion;
+
+ return color;
+}
+
+vec3 pbrIblModel(const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha,
+ const in float ambientOcclusion)
+{
+ // Calculate reflection direction of view vector about surface normal
+ // vector in world space. This is used in the fragment shader to sample
+ // from the environment textures for a light source. This is equivalent
+ // to the l vector for punctual light sources. Armed with this, calculate
+ // the usual factors needed
+ vec3 n = wNormal;
+ vec3 l = reflect(-wView, n);
+ vec3 v = wView;
+ vec3 h = normalize(l + v);
+ float vDotN = dot(v, n);
+ float lDotN = dot(l, n);
+ float lDotH = dot(l, h);
+
+ // Calculate diffuse component
+ vec3 diffuseColor = (1.0 - metalness) * baseColor;
+ vec3 diffuse = diffuseColor * texture(envLight.irradiance, l).rgb;
+
+ // Calculate specular component
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h);
+
+ float lod = alphaToMipLevel(alpha);
+//#define DEBUG_SPECULAR_LODS
+#ifdef DEBUG_SPECULAR_LODS
+ if (lod > 7.0)
+ return vec3(1.0, 0.0, 0.0);
+ else if (lod > 6.0)
+ return vec3(1.0, 0.333, 0.0);
+ else if (lod > 5.0)
+ return vec3(1.0, 1.0, 0.0);
+ else if (lod > 4.0)
+ return vec3(0.666, 1.0, 0.0);
+ else if (lod > 3.0)
+ return vec3(0.0, 1.0, 0.666);
+ else if (lod > 2.0)
+ return vec3(0.0, 0.666, 1.0);
+ else if (lod > 1.0)
+ return vec3(0.0, 0.0, 1.0);
+ else if (lod > 0.0)
+ return vec3(1.0, 0.0, 1.0);
+#endif
+ vec3 specularSkyColor = textureLod(envLight.specular, l, lod).rgb;
+ vec3 specular = specularSkyColor * specularFactor;
+
+ // Blend between diffuse and specular to conserve energy
+ vec3 iblColor = specular + diffuse * (vec3(1.0) - specularFactor);
+
+ // Reduce by ambient occlusion amount
+ iblColor *= ambientOcclusion;
+
+ return iblColor;
+}
+
+vec3 toneMap(const in vec3 c)
+{
+ return c / (c + vec3(1.0));
+}
+
+vec3 gammaCorrect(const in vec3 color)
+{
+ return pow(color, vec3(1.0 / gamma));
+}
+
+void main()
+{
+ vec3 cLinear = vec3(0.0);
+
+ // Calculate the perturbed texture coordinates from parallax occlusion mapping
+ mat3 worldToTangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent);
+ vec3 wView = normalize(eyePosition - worldPosition);
+ vec3 tView = worldToTangentMatrix * wView;
+
+ // Sample the inputs needed for the metal-roughness PBR BRDF
+ vec3 baseColor = texture(baseColorMap, texCoord).rgb;
+ float metalness = texture(metalnessMap, texCoord).r * metalFactor;
+ float roughness = texture(roughnessMap, texCoord).r;
+ float ambientOcclusion = texture(ambientOcclusionMap, texCoord).r;
+ vec3 tNormal = 2.0 * texture(normalMap, texCoord).rgb - vec3(1.0);
+ vec3 wNormal = normalize(transpose(worldToTangentMatrix) * tNormal);
+
+ // Remap roughness for a perceptually more linear correspondence
+ float alpha = remapRoughness(roughness);
+
+ for (int i = 0; i < envLightCount; ++i) {
+ cLinear += pbrIblModel(wNormal,
+ wView,
+ baseColor,
+ metalness,
+ alpha,
+ ambientOcclusion);
+ }
+
+ for (int i = 0; i < lightCount; ++i) {
+ cLinear += pbrModel(i,
+ worldPosition,
+ wNormal,
+ wView,
+ baseColor.rgb,
+ metalness,
+ alpha,
+ ambientOcclusion);
+ }
+
+ // Apply exposure correction
+ cLinear *= pow(2.0, exposure);
+
+ // Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1]
+ vec3 cToneMapped = toneMap(cLinear);
+
+ // Apply gamma correction prior to display
+ vec3 cGamma = gammaCorrect(cToneMapped);
+ fragColor = vec4(cGamma, 1.0);
+}
diff --git a/src/quick3d/imports/extras/defaults/qml/LevelOfDetailLoader.qml b/src/extras/shaders/gl3/metalrough.vert
index 83655a7bc..6d3a60ef6 100644
--- a/src/quick3d/imports/extras/defaults/qml/LevelOfDetailLoader.qml
+++ b/src/extras/shaders/gl3/metalrough.vert
@@ -48,33 +48,32 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.2
+#version 150
-Entity {
- id:root
+in vec3 vertexPosition;
+in vec3 vertexNormal;
+in vec4 vertexTangent;
+in vec2 vertexTexCoord;
- property var sources: []
- readonly property alias entity: loader.entity
- readonly property alias source: loader.source
+out vec3 worldPosition;
+out vec3 worldNormal;
+out vec4 worldTangent;
+out vec2 texCoord;
- property alias camera: lod.camera
- property alias currentIndex: lod.currentIndex
- property alias thresholdType: lod.thresholdType
- property alias thresholds: lod.thresholds
- property alias volumeOverride: lod.volumeOverride
+uniform mat4 modelMatrix;
+uniform mat3 modelNormalMatrix;
+uniform mat4 mvp;
- EntityLoader {
- id: loader
- components: [
- LevelOfDetail {
- id: lod
- enabled: root.enabled
- currentIndex: -1
- onCurrentIndexChanged: if (currentIndex >= 0 && currentIndex < root.sources.length)
- loader.source = root.sources[currentIndex]
- }
- ]
- }
-}
+void main()
+{
+ // Pass the texture coordinates through
+ texCoord = vertexTexCoord;
+
+ // Transform position, normal, and tangent to world space
+ worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0));
+ worldNormal = normalize(modelNormalMatrix * vertexNormal);
+ worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0)));
+ worldTangent.w = vertexTangent.w;
+ gl_Position = mvp * vec4(vertexPosition, 1.0);
+}
diff --git a/src/extras/shaders/gl3/metalroughuniform.frag b/src/extras/shaders/gl3/metalroughuniform.frag
new file mode 100644
index 000000000..f4bad0a00
--- /dev/null
+++ b/src/extras/shaders/gl3/metalroughuniform.frag
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#version 150
+
+in vec2 texCoord;
+in vec3 worldPosition;
+in vec3 worldNormal;
+in vec4 worldTangent;
+
+out vec4 fragColor;
+
+// Qt 3D built in uniforms
+uniform vec3 eyePosition; // World space eye position
+uniform float time; // Time in seconds
+
+// PBR Material maps
+uniform vec4 baseColor;
+uniform float metalness;
+uniform float roughness;
+
+// Exposure correction
+uniform float exposure = 0.0;
+// Gamma correction
+uniform float gamma = 2.2;
+
+#pragma include light.inc.frag
+
+int mipLevelCount(const in samplerCube cube)
+{
+ int baseSize = textureSize(cube, 0).x;
+ int nMips = int(log2(float(baseSize>0 ? baseSize : 1))) + 1;
+ return nMips;
+}
+
+float remapRoughness(const in float roughness)
+{
+ // As per page 14 of
+ // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ // we remap the roughness to give a more perceptually linear response
+ // of "bluriness" as a function of the roughness specified by the user.
+ // r = roughness^2
+ const float maxSpecPower = 999999.0;
+ const float minRoughness = sqrt(2.0 / (maxSpecPower + 2));
+ return max(roughness * roughness, minRoughness);
+}
+
+mat3 calcWorldSpaceToTangentSpaceMatrix(const in vec3 wNormal, const in vec4 wTangent)
+{
+ // Make the tangent truly orthogonal to the normal by using Gram-Schmidt.
+ // This allows to build the tangentMatrix below by simply transposing the
+ // tangent -> eyespace matrix (which would now be orthogonal)
+ vec3 wFixedTangent = normalize(wTangent.xyz - dot(wTangent.xyz, wNormal) * wNormal);
+
+ // Calculate binormal vector. No "real" need to renormalize it,
+ // as built by crossing two normal vectors.
+ // To orient the binormal correctly, use the fourth coordinate of the tangent,
+ // which is +1 for a right hand system, and -1 for a left hand system.
+ vec3 wBinormal = cross(wNormal, wFixedTangent.xyz) * wTangent.w;
+
+ // Construct matrix to transform from world space to tangent space
+ // This is the transpose of the tangentToWorld transformation matrix
+ mat3 tangentToWorldMatrix = mat3(wFixedTangent, wBinormal, wNormal);
+ mat3 worldToTangentMatrix = transpose(tangentToWorldMatrix);
+ return worldToTangentMatrix;
+}
+
+float alphaToMipLevel(float alpha)
+{
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
+
+ // We use the mip level calculation from Lys' default power drop, which in
+ // turn is a slight modification of that used in Marmoset Toolbag. See
+ // https://docs.knaldtech.com/doku.php?id=specular_lys for details.
+ // For now we assume a max specular power of 999999 which gives
+ // maxGlossiness = 1.
+ const float k0 = 0.00098;
+ const float k1 = 0.9921;
+ float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1;
+
+ // TODO: Optimize by doing this on CPU and set as
+ // uniform int envLight.specularMipLevels say (if present in shader).
+ // Lookup the number of mips in the specular envmap
+ int mipLevels = mipLevelCount(envLight.specular);
+
+ // Offset of smallest miplevel we should use (corresponds to specular
+ // power of 1). I.e. in the 32x32 sized mip.
+ const float mipOffset = 5.0;
+
+ // The final factor is really 1 - g / g_max but as mentioned above g_max
+ // is 1 by definition here so we can avoid the division. If we make the
+ // max specular power for the spec map configurable, this will need to
+ // be handled properly.
+ float mipLevel = (mipLevels - 1.0 - mipOffset) * (1.0 - glossiness);
+ return mipLevel;
+}
+
+float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha)
+{
+ // Blinn-Phong approximation - see
+ // http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
+ return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower);
+}
+
+vec3 fresnelFactor(const in vec3 color, const in float cosineFactor)
+{
+ // Calculate the Fresnel effect value
+ vec3 f = color;
+ vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
+ return clamp(F, f, vec3(1.0));
+}
+
+float geometricModel(const in float lDotN,
+ const in float vDotN,
+ const in vec3 h)
+{
+ // Implicit geometric model (equal to denominator in specular model).
+ // This currently assumes that there is no attenuation by geometric shadowing or
+ // masking according to the microfacet theory.
+ return lDotN * vDotN;
+}
+
+vec3 specularModel(const in vec3 F0,
+ const in float sDotH,
+ const in float sDotN,
+ const in float vDotN,
+ const in vec3 n,
+ const in vec3 h)
+{
+ // Clamp sDotN and vDotN to small positive value to prevent the
+ // denominator in the reflection equation going to infinity. Balance this
+ // by using the clamped values in the geometric factor function to
+ // avoid ugly seams in the specular lighting.
+ float sDotNPrime = max(sDotN, 0.001);
+ float vDotNPrime = max(vDotN, 0.001);
+
+ vec3 F = fresnelFactor(F0, sDotH);
+ float G = geometricModel(sDotNPrime, vDotNPrime, h);
+
+ vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
+ return clamp(cSpec, vec3(0.0), vec3(1.0));
+}
+
+vec3 pbrModel(const in int lightIndex,
+ const in vec3 wPosition,
+ const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha)
+{
+ // Calculate some useful quantities
+ vec3 n = wNormal;
+ vec3 s = vec3(0.0);
+ vec3 v = wView;
+ vec3 h = vec3(0.0);
+
+ float vDotN = dot(v, n);
+ float sDotN = 0.0;
+ float sDotH = 0.0;
+ float att = 1.0;
+
+ if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
+ // Point and Spot lights
+ vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
+ s = normalize(sUnnormalized);
+
+ // Calculate the attenuation factor
+ sDotN = dot(s, n);
+ if (sDotN > 0.0) {
+ if (lights[lightIndex].constantAttenuation != 0.0
+ || lights[lightIndex].linearAttenuation != 0.0
+ || lights[lightIndex].quadraticAttenuation != 0.0) {
+ float dist = length(sUnnormalized);
+ att = 1.0 / (lights[lightIndex].constantAttenuation +
+ lights[lightIndex].linearAttenuation * dist +
+ lights[lightIndex].quadraticAttenuation * dist * dist);
+ }
+
+ // The light direction is in world space already
+ if (lights[lightIndex].type == TYPE_SPOT) {
+ // Check if fragment is inside or outside of the spot light cone
+ if (degrees(acos(dot(-s, lights[lightIndex].direction))) > lights[lightIndex].cutOffAngle)
+ sDotN = 0.0;
+ }
+ }
+ } else {
+ // Directional lights
+ // The light direction is in world space already
+ s = normalize(-lights[lightIndex].direction);
+ sDotN = dot(s, n);
+ }
+
+ h = normalize(s + v);
+ sDotH = dot(s, h);
+
+ // Calculate diffuse component
+ vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
+ vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
+
+ // Calculate specular component
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = vec3(0.0);
+ if (sDotN > 0.0) {
+ specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
+ specularFactor *= normalDistribution(n, h, alpha);
+ }
+ vec3 specularColor = lights[lightIndex].color;
+ vec3 specular = specularColor * specularFactor;
+
+ // Blend between diffuse and specular to conserver energy
+ return att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
+}
+
+vec3 pbrIblModel(const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha)
+{
+ // Calculate reflection direction of view vector about surface normal
+ // vector in world space. This is used in the fragment shader to sample
+ // from the environment textures for a light source. This is equivalent
+ // to the l vector for punctual light sources. Armed with this, calculate
+ // the usual factors needed
+ vec3 n = wNormal;
+ vec3 l = reflect(-wView, n);
+ vec3 v = wView;
+ vec3 h = normalize(l + v);
+ float vDotN = dot(v, n);
+ float lDotN = dot(l, n);
+ float lDotH = dot(l, h);
+
+ // Calculate diffuse component
+ vec3 diffuseColor = (1.0 - metalness) * baseColor;
+ vec3 diffuse = diffuseColor * texture(envLight.irradiance, l).rgb;
+
+ // Calculate specular component
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h);
+
+ // As per page 14 of
+ // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ // we remap the roughness to give a more perceptually linear response
+ // of "bluriness" as a function of the roughness specified by the user.
+ // r = roughness^2
+ float lod = alphaToMipLevel(alpha);
+//#define DEBUG_SPECULAR_LODS
+#ifdef DEBUG_SPECULAR_LODS
+ if (lod > 7.0)
+ return vec3(1.0, 0.0, 0.0);
+ else if (lod > 6.0)
+ return vec3(1.0, 0.333, 0.0);
+ else if (lod > 5.0)
+ return vec3(1.0, 1.0, 0.0);
+ else if (lod > 4.0)
+ return vec3(0.666, 1.0, 0.0);
+ else if (lod > 3.0)
+ return vec3(0.0, 1.0, 0.666);
+ else if (lod > 2.0)
+ return vec3(0.0, 0.666, 1.0);
+ else if (lod > 1.0)
+ return vec3(0.0, 0.0, 1.0);
+ else if (lod > 0.0)
+ return vec3(1.0, 0.0, 1.0);
+#endif
+ vec3 specularSkyColor = textureLod(envLight.specular, l, lod).rgb;
+ vec3 specular = specularSkyColor * specularFactor;
+
+ // Blend between diffuse and specular to conserve energy
+ return specular + diffuse * (vec3(1.0) - specularFactor);
+}
+
+vec3 toneMap(const in vec3 c)
+{
+ return c / (c + vec3(1.0));
+}
+
+vec3 gammaCorrect(const in vec3 color)
+{
+ return pow(color, vec3(1.0 / gamma));
+}
+
+void main()
+{
+ vec3 cLinear = vec3(0.0);
+
+ // Remap roughness for a perceptually more linear correspondence
+ float alpha = remapRoughness(roughness);
+
+
+ vec3 wNormal = normalize(worldNormal);
+ vec3 worldView = normalize(eyePosition - worldPosition);
+ for (int i = 0; i < envLightCount; ++i) {
+ cLinear += pbrIblModel(wNormal,
+ worldView,
+ baseColor.rgb,
+ metalness,
+ alpha);
+ }
+
+ for (int i = 0; i < lightCount; ++i) {
+ cLinear += pbrModel(i,
+ worldPosition,
+ wNormal,
+ worldView,
+ baseColor.rgb,
+ metalness,
+ alpha);
+ }
+
+ // Apply exposure correction
+ cLinear *= pow(2.0, exposure);
+
+ // Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1]
+ vec3 cToneMapped = toneMap(cLinear);
+
+ // Apply gamma correction prior to display
+ vec3 cGamma = gammaCorrect(cToneMapped);
+ fragColor = vec4(cGamma, 1.0);
+}
diff --git a/src/extras/shaders/gl3/skybox.frag b/src/extras/shaders/gl3/skybox.frag
index 99c8f111b..931e20343 100644
--- a/src/extras/shaders/gl3/skybox.frag
+++ b/src/extras/shaders/gl3/skybox.frag
@@ -4,7 +4,21 @@ in vec3 texCoord0;
out vec4 fragColor;
uniform samplerCube skyboxTexture;
+// Gamma correction
+uniform float gamma = 2.2;
+
+uniform float gammaStrength;
+
+vec3 gammaCorrect(const in vec3 color)
+{
+ return pow(color, vec3(1.0 / gamma));
+}
+
void main()
{
- fragColor = texture(skyboxTexture, texCoord0);
+ vec4 baseColor = texture(skyboxTexture, texCoord0);
+ vec4 gammaColor = vec4(gammaCorrect(baseColor.rgb), 1.0);
+ // This is an odd way to enable or not gamma correction,
+ // but this is a way to avoid branching until we can generate shaders
+ fragColor = mix(baseColor, gammaColor, gammaStrength);
}
diff --git a/src/extras/text/areaallocator.cpp b/src/extras/text/areaallocator.cpp
new file mode 100644
index 000000000..61f1d5bc6
--- /dev/null
+++ b/src/extras/text/areaallocator.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "areaallocator_p.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+
+//
+// This file is copied from qtdeclarative/src/quick/scenegraph/util/qsgareaallocator.cpp
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+namespace
+{
+ enum SplitType
+ {
+ VerticalSplit,
+ HorizontalSplit
+ };
+
+ static const int maxMargin = 2;
+}
+
+struct AreaAllocatorNode
+{
+ AreaAllocatorNode(AreaAllocatorNode *parent);
+ ~AreaAllocatorNode();
+ inline bool isLeaf();
+
+ AreaAllocatorNode *parent;
+ AreaAllocatorNode *left;
+ AreaAllocatorNode *right;
+ int split; // only valid for inner nodes.
+ SplitType splitType;
+ bool isOccupied; // only valid for leaf nodes.
+};
+
+AreaAllocatorNode::AreaAllocatorNode(AreaAllocatorNode *parent)
+ : parent(parent)
+ , left(0)
+ , right(0)
+ , isOccupied(false)
+{
+}
+
+AreaAllocatorNode::~AreaAllocatorNode()
+{
+ delete left;
+ delete right;
+}
+
+bool AreaAllocatorNode::isLeaf()
+{
+ Q_ASSERT((left != 0) == (right != 0));
+ return !left;
+}
+
+
+AreaAllocator::AreaAllocator(const QSize &size) : m_size(size)
+{
+ m_root = new AreaAllocatorNode(0);
+}
+
+AreaAllocator::~AreaAllocator()
+{
+ delete m_root;
+}
+
+QRect AreaAllocator::allocate(const QSize &size)
+{
+ QPoint point;
+ bool result = allocateInNode(size, point, QRect(QPoint(0, 0), m_size), m_root);
+ return result ? QRect(point, size) : QRect();
+}
+
+bool AreaAllocator::deallocate(const QRect &rect)
+{
+ return deallocateInNode(rect.topLeft(), m_root);
+}
+
+bool AreaAllocator::allocateInNode(const QSize &size, QPoint &result, const QRect &currentRect, AreaAllocatorNode *node)
+{
+ if (size.width() > currentRect.width() || size.height() > currentRect.height())
+ return false;
+
+ if (node->isLeaf()) {
+ if (node->isOccupied)
+ return false;
+ if (size.width() + maxMargin >= currentRect.width() && size.height() + maxMargin >= currentRect.height()) {
+ //Snug fit, occupy entire rectangle.
+ node->isOccupied = true;
+ result = currentRect.topLeft();
+ return true;
+ }
+ // TODO: Reuse nodes.
+ // Split node.
+ node->left = new AreaAllocatorNode(node);
+ node->right = new AreaAllocatorNode(node);
+ QRect splitRect = currentRect;
+ if ((currentRect.width() - size.width()) * currentRect.height() < (currentRect.height() - size.height()) * currentRect.width()) {
+ node->splitType = HorizontalSplit;
+ node->split = currentRect.top() + size.height();
+ splitRect.setHeight(size.height());
+ } else {
+ node->splitType = VerticalSplit;
+ node->split = currentRect.left() + size.width();
+ splitRect.setWidth(size.width());
+ }
+ return allocateInNode(size, result, splitRect, node->left);
+ } else {
+ // TODO: avoid unnecessary recursion.
+ // has been split.
+ QRect leftRect = currentRect;
+ QRect rightRect = currentRect;
+ if (node->splitType == HorizontalSplit) {
+ leftRect.setHeight(node->split - leftRect.top());
+ rightRect.setTop(node->split);
+ } else {
+ leftRect.setWidth(node->split - leftRect.left());
+ rightRect.setLeft(node->split);
+ }
+ if (allocateInNode(size, result, leftRect, node->left))
+ return true;
+ if (allocateInNode(size, result, rightRect, node->right))
+ return true;
+ return false;
+ }
+}
+
+bool AreaAllocator::deallocateInNode(const QPoint &pos, AreaAllocatorNode *node)
+{
+ while (!node->isLeaf()) {
+ // has been split.
+ int cmp = node->splitType == HorizontalSplit ? pos.y() : pos.x();
+ node = cmp < node->split ? node->left : node->right;
+ }
+ if (!node->isOccupied)
+ return false;
+ node->isOccupied = false;
+ mergeNodeWithNeighbors(node);
+ return true;
+}
+
+void AreaAllocator::mergeNodeWithNeighbors(AreaAllocatorNode *node)
+{
+ bool done = false;
+ AreaAllocatorNode *parent = 0;
+ AreaAllocatorNode *current = 0;
+ AreaAllocatorNode *sibling;
+ while (!done) {
+ Q_ASSERT(node->isLeaf());
+ Q_ASSERT(!node->isOccupied);
+ if (node->parent == 0)
+ return; // No neighbors.
+
+ SplitType splitType = SplitType(node->parent->splitType);
+ done = true;
+
+ /* Special case. Might be faster than going through the general code path.
+ // Merge with sibling.
+ parent = node->parent;
+ sibling = (node == parent->left ? parent->right : parent->left);
+ if (sibling->isLeaf() && !sibling->isOccupied) {
+ Q_ASSERT(!sibling->right);
+ node = parent;
+ parent->isOccupied = false;
+ delete parent->left;
+ delete parent->right;
+ parent->left = parent->right = 0;
+ done = false;
+ continue;
+ }
+ */
+
+ // Merge with left neighbor.
+ current = node;
+ parent = current->parent;
+ while (parent && current == parent->left && parent->splitType == splitType) {
+ current = parent;
+ parent = parent->parent;
+ }
+
+ if (parent && parent->splitType == splitType) {
+ Q_ASSERT(current == parent->right);
+ Q_ASSERT(parent->left);
+
+ AreaAllocatorNode *neighbor = parent->left;
+ while (neighbor->right && neighbor->splitType == splitType)
+ neighbor = neighbor->right;
+
+ if (neighbor->isLeaf() && neighbor->parent->splitType == splitType && !neighbor->isOccupied) {
+ // Left neighbor can be merged.
+ parent->split = neighbor->parent->split;
+
+ parent = neighbor->parent;
+ sibling = neighbor == parent->left ? parent->right : parent->left;
+ AreaAllocatorNode **nodeRef = &m_root;
+ if (parent->parent) {
+ if (parent == parent->parent->left)
+ nodeRef = &parent->parent->left;
+ else
+ nodeRef = &parent->parent->right;
+ }
+ sibling->parent = parent->parent;
+ *nodeRef = sibling;
+ parent->left = parent->right = 0;
+ delete parent;
+ delete neighbor;
+ done = false;
+ }
+ }
+
+ // Merge with right neighbor.
+ current = node;
+ parent = current->parent;
+ while (parent && current == parent->right && parent->splitType == splitType) {
+ current = parent;
+ parent = parent->parent;
+ }
+
+ if (parent && parent->splitType == splitType) {
+ Q_ASSERT(current == parent->left);
+ Q_ASSERT(parent->right);
+
+ AreaAllocatorNode *neighbor = parent->right;
+ while (neighbor->left && neighbor->splitType == splitType)
+ neighbor = neighbor->left;
+
+ if (neighbor->isLeaf() && neighbor->parent->splitType == splitType && !neighbor->isOccupied) {
+ // Right neighbor can be merged.
+ parent->split = neighbor->parent->split;
+
+ parent = neighbor->parent;
+ sibling = neighbor == parent->left ? parent->right : parent->left;
+ AreaAllocatorNode **nodeRef = &m_root;
+ if (parent->parent) {
+ if (parent == parent->parent->left)
+ nodeRef = &parent->parent->left;
+ else
+ nodeRef = &parent->parent->right;
+ }
+ sibling->parent = parent->parent;
+ *nodeRef = sibling;
+ parent->left = parent->right = 0;
+ delete parent;
+ delete neighbor;
+ done = false;
+ }
+ }
+ } // end while (!done)
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/text/areaallocator_p.h b/src/extras/text/areaallocator_p.h
new file mode 100644
index 000000000..809c5c698
--- /dev/null
+++ b/src/extras/text/areaallocator_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_AREAALLOCATOR_P_H
+#define QT3DEXTRAS_AREAALLOCATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// This file is copied from qtdeclarative/src/quick/scenegraph/util/qsgareaallocator_p.h
+//
+
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRect;
+class QPoint;
+
+namespace Qt3DExtras {
+
+struct AreaAllocatorNode;
+
+class AreaAllocator
+{
+public:
+ AreaAllocator(const QSize &size);
+ ~AreaAllocator();
+
+ QRect allocate(const QSize &size);
+ bool deallocate(const QRect &rect);
+ bool isEmpty() const { return m_root == 0; }
+ QSize size() const { return m_size; }
+private:
+ bool allocateInNode(const QSize &size, QPoint &result, const QRect &currentRect, AreaAllocatorNode *node);
+ bool deallocateInNode(const QPoint &pos, AreaAllocatorNode *node);
+ void mergeNodeWithNeighbors(AreaAllocatorNode *node);
+
+ AreaAllocatorNode *m_root;
+ QSize m_size;
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_AREAALLOCATOR_P_H
diff --git a/src/extras/text/distancefieldtextrenderer.cpp b/src/extras/text/distancefieldtextrenderer.cpp
new file mode 100644
index 000000000..9f390e8da
--- /dev/null
+++ b/src/extras/text/distancefieldtextrenderer.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qbuffer.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qgeometry.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+
+#include <Qt3DExtras/private/qtext2dmaterial_p.h>
+
+#include "distancefieldtextrenderer_p.h"
+#include "distancefieldtextrenderer_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+using namespace Qt3DCore;
+
+DistanceFieldTextRendererPrivate::DistanceFieldTextRendererPrivate()
+ : m_renderer(nullptr)
+ , m_geometry(nullptr)
+ , m_positionAttr(nullptr)
+ , m_texCoordAttr(nullptr)
+ , m_indexAttr(nullptr)
+ , m_vertexBuffer(nullptr)
+ , m_indexBuffer(nullptr)
+ , m_material(nullptr)
+{
+}
+
+DistanceFieldTextRendererPrivate::~DistanceFieldTextRendererPrivate()
+{
+}
+
+void DistanceFieldTextRendererPrivate::init()
+{
+ Q_Q(DistanceFieldTextRenderer);
+
+ m_renderer = new Qt3DRender::QGeometryRenderer(q);
+ m_renderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
+
+ m_geometry = new Qt3DRender::QGeometry(m_renderer);
+ m_renderer->setGeometry(m_geometry);
+
+ m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, m_geometry);
+ m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, m_geometry);
+
+ m_positionAttr = new Qt3DRender::QAttribute(m_geometry);
+ m_positionAttr->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ m_positionAttr->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ m_positionAttr->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ m_positionAttr->setVertexSize(3);
+ m_positionAttr->setByteStride(5 * sizeof(float));
+ m_positionAttr->setByteOffset(0);
+ m_positionAttr->setBuffer(m_vertexBuffer);
+
+ m_texCoordAttr = new Qt3DRender::QAttribute(m_geometry);
+ m_texCoordAttr->setName(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName());
+ m_texCoordAttr->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ m_texCoordAttr->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ m_texCoordAttr->setVertexSize(2);
+ m_texCoordAttr->setByteStride(5 * sizeof(float));
+ m_texCoordAttr->setByteOffset(3 * sizeof(float));
+ m_texCoordAttr->setBuffer(m_vertexBuffer);
+
+ m_indexAttr = new Qt3DRender::QAttribute(m_geometry);
+ m_indexAttr->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+ m_indexAttr->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
+ m_indexAttr->setBuffer(m_indexBuffer);
+
+ m_geometry->addAttribute(m_positionAttr);
+ m_geometry->setBoundingVolumePositionAttribute(m_positionAttr);
+ m_geometry->addAttribute(m_texCoordAttr);
+ m_geometry->addAttribute(m_indexAttr);
+
+ m_material = new QText2DMaterial(q);
+
+ q->addComponent(m_renderer);
+ q->addComponent(m_material);
+}
+
+DistanceFieldTextRenderer::DistanceFieldTextRenderer(QNode *parent)
+ : QEntity(*new DistanceFieldTextRendererPrivate(), parent)
+{
+ Q_D(DistanceFieldTextRenderer);
+ d->init();
+}
+
+DistanceFieldTextRenderer::~DistanceFieldTextRenderer()
+{
+}
+
+void DistanceFieldTextRenderer::setGlyphData(Qt3DRender::QAbstractTexture *glyphTexture,
+ const QVector<float> &vertexData,
+ const QVector<quint16> &indexData)
+{
+ Q_D(DistanceFieldTextRenderer);
+
+ const int vertexCount = vertexData.size() / 5;
+
+ d->m_vertexBuffer->setData(QByteArray((char*) vertexData.data(), vertexData.size() * sizeof(float)));
+ d->m_indexBuffer->setData(QByteArray((char*) indexData.data(), indexData.size() * sizeof(quint16)));
+ d->m_positionAttr->setCount(vertexCount);
+ d->m_texCoordAttr->setCount(vertexCount);
+ d->m_indexAttr->setCount(indexData.size());
+
+ d->m_material->setDistanceFieldTexture(glyphTexture);
+}
+
+void DistanceFieldTextRenderer::setColor(const QColor &color)
+{
+ Q_D(DistanceFieldTextRenderer);
+ d->m_material->setColor(color);
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/text/distancefieldtextrenderer_p.h b/src/extras/text/distancefieldtextrenderer_p.h
new file mode 100644
index 000000000..fdb9a836f
--- /dev/null
+++ b/src/extras/text/distancefieldtextrenderer_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_DISTANCEFIELDTEXTRENDERER_P_H
+#define QT3DEXTRAS_DISTANCEFIELDTEXTRENDERER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QRectF>
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/qentity.h>
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QAbstractTexture;
+}
+
+namespace Qt3DExtras {
+
+class DistanceFieldTextRendererPrivate;
+
+class DistanceFieldTextRenderer : public Qt3DCore::QEntity
+{
+ Q_OBJECT
+
+public:
+ DistanceFieldTextRenderer(Qt3DCore::QNode *parent = nullptr);
+ ~DistanceFieldTextRenderer();
+
+ void setGlyphData(Qt3DRender::QAbstractTexture *glyphTexture,
+ const QVector<float> &vertexData,
+ const QVector<quint16> &indexData);
+
+ void setColor(const QColor &color);
+
+ Q_DECLARE_PRIVATE(DistanceFieldTextRenderer)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_DISTANCEFIELDTEXTRENDERER_P_H
diff --git a/src/extras/text/distancefieldtextrenderer_p_p.h b/src/extras/text/distancefieldtextrenderer_p_p.h
new file mode 100644
index 000000000..af4bc4723
--- /dev/null
+++ b/src/extras/text/distancefieldtextrenderer_p_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_DISTANCEFIELDTEXTRENDERER_P_P_H
+#define QT3DEXTRAS_DISTANCEFIELDTEXTRENDERER_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qentity_p.h>
+#include <Qt3DExtras/private/distancefieldtextrenderer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QGeometryRenderer;
+class QGeometry;
+class QMaterial;
+class QAttribute;
+class QBuffer;
+}
+
+namespace Qt3DExtras {
+
+class QText2DMaterial;
+
+class DistanceFieldTextRendererPrivate : public Qt3DCore::QEntityPrivate
+{
+public:
+ DistanceFieldTextRendererPrivate();
+ ~DistanceFieldTextRendererPrivate();
+
+ Q_DECLARE_PUBLIC(DistanceFieldTextRenderer)
+
+ void init();
+
+ Qt3DRender::QGeometryRenderer *m_renderer;
+ Qt3DRender::QGeometry *m_geometry;
+ Qt3DRender::QAttribute *m_positionAttr;
+ Qt3DRender::QAttribute *m_texCoordAttr;
+ Qt3DRender::QAttribute *m_indexAttr;
+ Qt3DRender::QBuffer *m_vertexBuffer;
+ Qt3DRender::QBuffer *m_indexBuffer;
+ QText2DMaterial *m_material;
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_DISTANCEFIELDTEXTRENDERER_P_P_H
diff --git a/src/extras/text/qdistancefieldglyphcache.cpp b/src/extras/text/qdistancefieldglyphcache.cpp
new file mode 100644
index 000000000..99085f378
--- /dev/null
+++ b/src/extras/text/qdistancefieldglyphcache.cpp
@@ -0,0 +1,370 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qrawfont.h>
+#include <QtGui/qglyphrun.h>
+#include <QtGui/private/qrawfont_p.h>
+
+#include "qdistancefieldglyphcache_p.h"
+#include "qtextureatlas_p.h"
+
+#include <QtGui/qfont.h>
+#include <QtGui/private/qdistancefield_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DExtras/private/qtextureatlas_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define DEFAULT_IMAGE_PADDING 1
+
+using namespace Qt3DCore;
+
+namespace Qt3DExtras {
+
+// ref-count glyphs and keep track of where they are stored
+class StoredGlyph {
+public:
+ StoredGlyph() = default;
+ StoredGlyph(const StoredGlyph &) = default;
+ StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution);
+
+ int refCount() const { return m_ref; }
+ void ref() { ++m_ref; }
+ int deref() { return m_ref = std::max(m_ref - 1, (quint32) 0); }
+
+ bool addToTextureAtlas(QTextureAtlas *atlas);
+ void removeFromTextureAtlas();
+
+ QTextureAtlas *atlas() const { return m_atlas; }
+ QRectF glyphPathBoundingRect() const { return m_glyphPathBoundingRect; }
+ QRectF texCoords() const;
+
+private:
+ quint32 m_glyph = (quint32) -1;
+ quint32 m_ref = 0;
+ QTextureAtlas *m_atlas = nullptr;
+ QTextureAtlas::TextureId m_atlasEntry = QTextureAtlas::InvalidTexture;
+ QRectF m_glyphPathBoundingRect;
+ QImage m_distanceFieldImage; // only used until added to texture atlas
+};
+
+// A DistanceFieldFont stores all glyphs for a given QRawFont.
+// it will use multiple QTextureAtlasess to store the distance
+// fields and uses ref-counting for each glyph to ensure that
+// unused glyphs are removed from the texture atlasses.
+class DistanceFieldFont
+{
+public:
+ DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DCore::QNode *parent);
+ ~DistanceFieldFont();
+
+ StoredGlyph findGlyph(quint32 glyph) const;
+ StoredGlyph refGlyph(quint32 glyph);
+ void derefGlyph(quint32 glyph);
+
+ bool doubleGlyphResolution() const { return m_doubleGlyphResolution; }
+
+private:
+ QRawFont m_font;
+ bool m_doubleGlyphResolution;
+ Qt3DCore::QNode *m_parentNode; // parent node for the QTextureAtlasses
+
+ QHash<quint32, StoredGlyph> m_glyphs;
+
+ QVector<QTextureAtlas*> m_atlasses;
+};
+
+StoredGlyph::StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution)
+ : m_glyph(glyph)
+ , m_ref(1)
+ , m_atlas(nullptr)
+ , m_atlasEntry(QTextureAtlas::InvalidTexture)
+{
+ // create new single-channel distance field image for given glyph
+ const QPainterPath path = font.pathForGlyph(glyph);
+ const QDistanceField dfield(font, glyph, doubleResolution);
+ m_distanceFieldImage = dfield.toImage(QImage::Format_Alpha8);
+
+ // scale bounding rect down (as in QSGDistanceFieldGlyphCache::glyphData())
+ const QRectF pathBound = path.boundingRect();
+ float f = 1.0f / QT_DISTANCEFIELD_SCALE(doubleResolution);
+ m_glyphPathBoundingRect = QRectF(pathBound.left() * f, -pathBound.top() * f, pathBound.width() * f, pathBound.height() * f);
+}
+
+bool StoredGlyph::addToTextureAtlas(QTextureAtlas *atlas)
+{
+ if (m_atlas || m_distanceFieldImage.isNull())
+ return false;
+
+ const auto texId = atlas->addImage(m_distanceFieldImage, DEFAULT_IMAGE_PADDING);
+ if (texId != QTextureAtlas::InvalidTexture) {
+ m_atlas = atlas;
+ m_atlasEntry = texId;
+ m_distanceFieldImage = QImage(); // free glyph image data
+ return true;
+ }
+
+ return false;
+}
+
+void StoredGlyph::removeFromTextureAtlas()
+{
+ if (m_atlas) {
+ m_atlas->removeImage(m_atlasEntry);
+ m_atlas = nullptr;
+ m_atlasEntry = QTextureAtlas::InvalidTexture;
+ }
+}
+
+QRectF StoredGlyph::texCoords() const
+{
+ return m_atlas ? m_atlas->imageTexCoords(m_atlasEntry) : QRectF();
+}
+
+DistanceFieldFont::DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DCore::QNode *parent)
+ : m_font(font)
+ , m_doubleGlyphResolution(doubleRes)
+ , m_parentNode(parent)
+{
+}
+
+DistanceFieldFont::~DistanceFieldFont()
+{
+ qDeleteAll(m_atlasses);
+}
+
+StoredGlyph DistanceFieldFont::findGlyph(quint32 glyph) const
+{
+ const auto it = m_glyphs.find(glyph);
+ return (it != m_glyphs.cend()) ? it.value() : StoredGlyph();
+}
+
+StoredGlyph DistanceFieldFont::refGlyph(quint32 glyph)
+{
+ // if glyph already exists, just increase ref-count
+ auto it = m_glyphs.find(glyph);
+ if (it != m_glyphs.end()) {
+ it.value().ref();
+ return it.value();
+ }
+
+ // need to create new glyph
+ StoredGlyph storedGlyph(m_font, glyph, m_doubleGlyphResolution);
+
+ // see if one of the existing atlasses can hold the distance field image
+ for (int i = 0; i < m_atlasses.size(); i++)
+ if (storedGlyph.addToTextureAtlas(m_atlasses[i]))
+ break;
+
+ // if no texture atlas is big enough (or no exists yet), allocate a new one
+ if (!storedGlyph.atlas()) {
+ // this should be enough to store 40-60 glyphs, which should be sufficient for most
+ // scenarios
+ const int size = m_doubleGlyphResolution ? 512 : 256;
+
+ QTextureAtlas *atlas = new QTextureAtlas(m_parentNode);
+ atlas->setWidth(size);
+ atlas->setHeight(size);
+ atlas->setFormat(Qt3DRender::QAbstractTexture::R8_UNorm);
+ atlas->setPixelFormat(QOpenGLTexture::Red);
+ atlas->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ atlas->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ m_atlasses << atlas;
+
+ if (!storedGlyph.addToTextureAtlas(atlas))
+ qWarning() << Q_FUNC_INFO << "Couldn't add glyph to newly allocated atlas. Glyph could be huge?";
+ }
+
+ m_glyphs.insert(glyph, storedGlyph);
+ return storedGlyph;
+}
+
+void DistanceFieldFont::derefGlyph(quint32 glyph)
+{
+ auto it = m_glyphs.find(glyph);
+ if (it == m_glyphs.end())
+ return;
+
+ // TODO
+ // possible optimization: keep unreferenced glyphs as the texture atlas
+ // still has space. only if a new glyph needs to be allocated, and there
+ // is no more space within the atlas, then we can actually remove the glyphs
+ // from the atlasses.
+
+ // remove glyph if no refs anymore
+ if (it.value().deref() <= 0) {
+ QTextureAtlas *atlas = it.value().atlas();
+ it.value().removeFromTextureAtlas();
+
+ // remove atlas, if it contains no glyphs anymore
+ if (atlas && atlas->imageCount() == 0) {
+ Q_ASSERT(m_atlasses.contains(atlas));
+
+ m_atlasses.removeAll(atlas);
+ delete atlas;
+ }
+
+ m_glyphs.erase(it);
+ }
+}
+
+// copied from QSGDistanceFieldGlyphCacheManager::fontKey
+// we use this function to compare QRawFonts, as QRawFont doesn't
+// implement a stable comparison function
+QString QDistanceFieldGlyphCache::fontKey(const QRawFont &font)
+{
+ QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
+ if (!fe->faceId().filename.isEmpty()) {
+ QByteArray keyName = fe->faceId().filename;
+ if (font.style() != QFont::StyleNormal)
+ keyName += QByteArray(" I");
+ if (font.weight() != QFont::Normal)
+ keyName += ' ' + QByteArray::number(font.weight());
+ keyName += QByteArray(" DF");
+ return QString::fromUtf8(keyName);
+ } else {
+ return QString::fromLatin1("%1_%2_%3_%4")
+ .arg(font.familyName())
+ .arg(font.styleName())
+ .arg(font.weight())
+ .arg(font.style());
+ }
+}
+
+DistanceFieldFont* QDistanceFieldGlyphCache::getOrCreateDistanceFieldFont(const QRawFont &font)
+{
+ // return, if font already exists (make sure to only create one DistanceFieldFont for
+ // each unique QRawFont, by building a hash on the QRawFont that ignores the font size)
+ const QString key = fontKey(font);
+ const auto it = m_fonts.constFind(key);
+ if (it != m_fonts.cend())
+ return it.value();
+
+ // logic taken from QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+ const int glyphCount = fontD->fontEngine->glyphCount();
+ const bool useDoubleRes = qt_fontHasNarrowOutlines(font) && glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT();
+
+ // only keep one FontCache with a fixed pixel size for each distinct font type
+ QRawFont actualFont = font;
+ actualFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(useDoubleRes) * QT_DISTANCEFIELD_SCALE(useDoubleRes));
+
+ // create new font cache
+ DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, m_rootNode);
+ m_fonts.insert(key, dff);
+ return dff;
+}
+
+QDistanceFieldGlyphCache::QDistanceFieldGlyphCache()
+ : m_rootNode(nullptr)
+{
+}
+
+QDistanceFieldGlyphCache::~QDistanceFieldGlyphCache()
+{
+}
+
+void QDistanceFieldGlyphCache::setRootNode(QNode *rootNode)
+{
+ m_rootNode = rootNode;
+}
+
+QNode *QDistanceFieldGlyphCache::rootNode() const
+{
+ return m_rootNode;
+}
+
+bool QDistanceFieldGlyphCache::doubleGlyphResolution(const QRawFont &font)
+{
+ return getOrCreateDistanceFieldFont(font)->doubleGlyphResolution();
+}
+
+namespace {
+QDistanceFieldGlyphCache::Glyph refAndGetGlyph(DistanceFieldFont *dff, quint32 glyph)
+{
+ QDistanceFieldGlyphCache::Glyph ret;
+
+ if (dff) {
+ const auto entry = dff->refGlyph(glyph);
+
+ if (entry.atlas()) {
+ ret.glyphPathBoundingRect = entry.glyphPathBoundingRect();
+ ret.texCoords = entry.texCoords();
+ ret.texture = entry.atlas();
+ }
+ }
+
+ return ret;
+}
+} // anonymous
+
+QVector<QDistanceFieldGlyphCache::Glyph> QDistanceFieldGlyphCache::refGlyphs(const QGlyphRun &run)
+{
+ DistanceFieldFont *dff = getOrCreateDistanceFieldFont(run.rawFont());
+ QVector<QDistanceFieldGlyphCache::Glyph> ret;
+
+ const QVector<quint32> glyphs = run.glyphIndexes();
+ for (quint32 glyph : glyphs)
+ ret << refAndGetGlyph(dff, glyph);
+
+ return ret;
+}
+
+QDistanceFieldGlyphCache::Glyph QDistanceFieldGlyphCache::refGlyph(const QRawFont &font, quint32 glyph)
+{
+ return refAndGetGlyph(getOrCreateDistanceFieldFont(font), glyph);
+}
+
+void QDistanceFieldGlyphCache::derefGlyphs(const QGlyphRun &run)
+{
+ DistanceFieldFont *dff = getOrCreateDistanceFieldFont(run.rawFont());
+
+ const QVector<quint32> glyphs = run.glyphIndexes();
+ for (quint32 glyph : glyphs)
+ dff->derefGlyph(glyph);
+}
+
+void QDistanceFieldGlyphCache::derefGlyph(const QRawFont &font, quint32 glyph)
+{
+ getOrCreateDistanceFieldFont(font)->derefGlyph(glyph);
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/text/qdistancefieldglyphcache_p.h b/src/extras/text/qdistancefieldglyphcache_p.h
new file mode 100644
index 000000000..6ca011c76
--- /dev/null
+++ b/src/extras/text/qdistancefieldglyphcache_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QDISTANCEFIELDGLYPHCACHE_P_H
+#define QT3DEXTRAS_QDISTANCEFIELDGLYPHCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QRectF>
+#include <Qt3DCore/qnode.h>
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRawFont;
+class QGlyphRun;
+
+namespace Qt3DCore {
+class QNode;
+}
+
+namespace Qt3DRender {
+class QAbstractTexture;
+}
+
+namespace Qt3DExtras {
+
+class DistanceFieldFont;
+class QDistanceFieldGlyphCachePrivate;
+
+class QDistanceFieldGlyphCache
+{
+public:
+ QDistanceFieldGlyphCache();
+ ~QDistanceFieldGlyphCache();
+
+ void setRootNode(Qt3DCore::QNode *rootNode);
+ Qt3DCore::QNode *rootNode() const;
+
+ struct Glyph {
+ Qt3DRender::QAbstractTexture *texture = nullptr;
+ QRectF glyphPathBoundingRect; // bounding rect of the QPainterPath used to draw the glyph
+ QRectF texCoords; // texture coordinates within texture
+ };
+
+ bool doubleGlyphResolution(const QRawFont &font);
+
+ QVector<Glyph> refGlyphs(const QGlyphRun &run);
+ Glyph refGlyph(const QRawFont &font, quint32 glyph);
+
+ void derefGlyphs(const QGlyphRun &run);
+ void derefGlyph(const QRawFont &font, quint32 glyph);
+
+private:
+ DistanceFieldFont* getOrCreateDistanceFieldFont(const QRawFont &font);
+ static QString fontKey(const QRawFont &font);
+
+ QHash<QString, DistanceFieldFont*> m_fonts;
+ Qt3DCore::QNode *m_rootNode;
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QDISTANCEFIELDGLYPHCACHE_P_H
diff --git a/src/extras/text/qtext2dentity.cpp b/src/extras/text/qtext2dentity.cpp
new file mode 100644
index 000000000..dbd4368bc
--- /dev/null
+++ b/src/extras/text/qtext2dentity.cpp
@@ -0,0 +1,381 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtext2dentity.h"
+#include "qtext2dentity_p.h"
+#include "qtext2dmaterial_p.h"
+
+#include <QtGui/qtextlayout.h>
+#include <QtGui/qglyphrun.h>
+#include <QtGui/private/qdistancefield_p.h>
+#include <QtGui/private/qtextureglyphcache_p.h>
+#include <QtGui/private/qfont_p.h>
+#include <QtGui/private/qdistancefield_p.h>
+
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qbuffer.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qgeometry.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+
+#include <Qt3DCore/private/qscene_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+inline Q_DECL_CONSTEXPR QRectF scaleRectF(const QRectF &rect, float scale)
+{
+ return QRectF(rect.left() * scale, rect.top() * scale, rect.width() * scale, rect.height() * scale);
+}
+
+} // anonymous
+
+namespace Qt3DExtras {
+
+QHash<Qt3DCore::QScene *, QText2DEntityPrivate::CacheEntry> QText2DEntityPrivate::m_glyphCacheInstances;
+
+QText2DEntityPrivate::QText2DEntityPrivate()
+ : m_glyphCache(nullptr)
+ , m_font(QLatin1String("Times"), 10)
+ , m_scaledFont(QLatin1String("Times"), 10)
+ , m_color(QColor(255, 255, 255, 255))
+ , m_width(0.0f)
+ , m_height(0.0f)
+{
+}
+
+QText2DEntityPrivate::~QText2DEntityPrivate()
+{
+}
+
+void QText2DEntityPrivate::setScene(Qt3DCore::QScene *scene)
+{
+ if (scene == m_scene)
+ return;
+
+ // Unref old glyph cache if it exists
+ if (m_scene != nullptr) {
+ m_glyphCache = nullptr;
+ QText2DEntityPrivate::CacheEntry &entry = QText2DEntityPrivate::m_glyphCacheInstances[m_scene];
+ --entry.count;
+ if (entry.count == 0 && entry.glyphCache != nullptr) {
+ delete entry.glyphCache;
+ entry.glyphCache = nullptr;
+ }
+ }
+
+ QEntityPrivate::setScene(scene);
+
+ // Ref new glyph cache is scene is valid
+ if (scene != nullptr) {
+ QText2DEntityPrivate::CacheEntry &entry = QText2DEntityPrivate::m_glyphCacheInstances[scene];
+ if (entry.glyphCache == nullptr) {
+ entry.glyphCache = new QDistanceFieldGlyphCache();
+ entry.glyphCache->setRootNode(scene->rootNode());
+ }
+ m_glyphCache = entry.glyphCache;
+ ++entry.count;
+ // Update to populate glyphCache if needed
+ update();
+ }
+}
+
+QText2DEntity::QText2DEntity(QNode *parent)
+ : Qt3DCore::QEntity(*new QText2DEntityPrivate(), parent)
+{
+}
+
+QText2DEntity::~QText2DEntity()
+{
+}
+
+float QText2DEntityPrivate::computeActualScale() const
+{
+ // scale font based on fontScale property and given QFont
+ float scale = 1.0f;
+ if (m_font.pointSizeF() > 0)
+ scale *= m_font.pointSizeF() / m_scaledFont.pointSizeF();
+ return scale;
+}
+
+struct RenderData {
+ int vertexCount = 0;
+ QVector<float> vertex;
+ QVector<quint16> index;
+};
+
+void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs)
+{
+ if (runs.isEmpty())
+ return;
+
+ // For each distinct texture, we need a separate DistanceFieldTextRenderer,
+ // for which we need vertex and index data
+ QHash<Qt3DRender::QAbstractTexture*, RenderData> renderData;
+
+ const float scale = computeActualScale();
+
+ // process glyph runs
+ for (const QGlyphRun &run : runs) {
+ const QVector<quint32> glyphs = run.glyphIndexes();
+ const QVector<QPointF> pos = run.positions();
+
+ Q_ASSERT(glyphs.size() == pos.size());
+
+ const bool doubleGlyphResolution = m_glyphCache->doubleGlyphResolution(run.rawFont());
+
+ // faithfully copied from QSGDistanceFieldGlyphNode::updateGeometry()
+ const float pixelSize = run.rawFont().pixelSize();
+ const float fontScale = pixelSize / QT_DISTANCEFIELD_BASEFONTSIZE(doubleGlyphResolution);
+ const float margin = QT_DISTANCEFIELD_RADIUS(doubleGlyphResolution) / QT_DISTANCEFIELD_SCALE(doubleGlyphResolution) * fontScale;
+
+ for (int i = 0; i < glyphs.size(); i++) {
+ const QDistanceFieldGlyphCache::Glyph &dfield = m_glyphCache->refGlyph(run.rawFont(), glyphs[i]);
+
+ if (!dfield.texture)
+ continue;
+
+ RenderData &data = renderData[dfield.texture];
+
+ // faithfully copied from QSGDistanceFieldGlyphNode::updateGeometry()
+ QRectF metrics = scaleRectF(dfield.glyphPathBoundingRect, fontScale);
+ metrics.adjust(-margin, margin, margin, 3*margin);
+
+ const float top = 0.0f;
+ const float left = 0.0f;
+ const float right = m_width;
+ const float bottom = m_height;
+
+ float x1 = left + scale * (pos[i].x() + metrics.left());
+ float y2 = bottom - scale * (pos[i].y() - metrics.top());
+ float x2 = x1 + scale * metrics.width();
+ float y1 = y2 - scale * metrics.height();
+
+ // only draw glyphs that are at least partly visible
+ if (y2 < top || x1 > right)
+ continue;
+
+ QRectF texCoords = dfield.texCoords;
+
+ // if a glyph is only partly visible within the given rectangle,
+ // cut it in half and adjust tex coords
+ if (y1 < top) {
+ const float insideRatio = (top - y2) / (y1 - y2);
+ y1 = top;
+ texCoords.setHeight(texCoords.height() * insideRatio);
+ }
+
+ // do the same thing horizontally
+ if (x2 > right) {
+ const float insideRatio = (right - x1) / (x2 - x1);
+ x2 = right;
+ texCoords.setWidth(texCoords.width() * insideRatio);
+ }
+
+ data.vertex << x1 << y1 << 0.f << texCoords.left() << texCoords.bottom();
+ data.vertex << x1 << y2 << 0.f << texCoords.left() << texCoords.top();
+ data.vertex << x2 << y1 << 0.f << texCoords.right() << texCoords.bottom();
+ data.vertex << x2 << y2 << 0.f << texCoords.right() << texCoords.top();
+
+ data.index << data.vertexCount << data.vertexCount+3 << data.vertexCount+1;
+ data.index << data.vertexCount << data.vertexCount+2 << data.vertexCount+3;
+
+ data.vertexCount += 4;
+ }
+ }
+
+ // make sure we have the correct number of DistanceFieldTextRenderers
+ // TODO: we might keep one renderer at all times, so we won't delete and
+ // re-allocate one every time the text changes from an empty to a non-empty string
+ // and vice-versa
+ while (m_renderers.size() > renderData.size())
+ delete m_renderers.takeLast();
+
+ while (m_renderers.size() < renderData.size()) {
+ DistanceFieldTextRenderer *renderer = new DistanceFieldTextRenderer(q_func());
+ renderer->setColor(m_color);
+ m_renderers << renderer;
+ }
+
+ Q_ASSERT(m_renderers.size() == renderData.size());
+
+ // assign vertex data for all textures to the renderers
+ int rendererIdx = 0;
+ for (auto it = renderData.begin(); it != renderData.end(); ++it) {
+ m_renderers[rendererIdx++]->setGlyphData(it.key(), it.value().vertex, it.value().index);
+ }
+
+ // de-ref all glyphs for previous QGlyphRuns
+ for (int i = 0; i < m_currentGlyphRuns.size(); i++)
+ m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]);
+ m_currentGlyphRuns = runs;
+}
+
+void QText2DEntityPrivate::update()
+{
+ if (m_glyphCache == nullptr)
+ return;
+
+ QVector<QGlyphRun> glyphRuns;
+
+ // collect all GlyphRuns generated by the QTextLayout
+ if ((m_width > 0.0f || m_height > 0.0f) && !m_text.isEmpty()) {
+ QTextLayout layout(m_text, m_scaledFont);
+ const float lineWidth = m_width / computeActualScale();
+ float height = 0;
+ layout.beginLayout();
+
+ while (true) {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+
+ // position current line
+ line.setLineWidth(lineWidth);
+ line.setPosition(QPointF(0, height));
+ height += line.height();
+
+ // add glyph runs created by line
+ const QList<QGlyphRun> runs = line.glyphRuns();
+ for (const QGlyphRun &run : runs)
+ glyphRuns << run;
+ }
+
+ layout.endLayout();
+ }
+
+ setCurrentGlyphRuns(glyphRuns);
+}
+
+QFont QText2DEntity::font() const
+{
+ Q_D(const QText2DEntity);
+ return d->m_font;
+}
+
+void QText2DEntity::setFont(const QFont &font)
+{
+ Q_D(QText2DEntity);
+ if (d->m_font != font) {
+ // ignore the point size of the font, just make it a default value.
+ // still we want to make sure that font() returns the same value
+ // that was passed to setFont(), so we store it nevertheless
+ d->m_font = font;
+ d->m_scaledFont = font;
+ d->m_scaledFont.setPointSize(10);
+
+ emit fontChanged(font);
+
+ if (!d->m_text.isEmpty())
+ d->update();
+ }
+}
+
+QColor QText2DEntity::color() const
+{
+ Q_D(const QText2DEntity);
+ return d->m_color;
+}
+
+void QText2DEntity::setColor(const QColor &color)
+{
+ Q_D(QText2DEntity);
+ if (d->m_color != color) {
+ d->m_color = color;
+
+ emit colorChanged(color);
+
+ for (DistanceFieldTextRenderer *renderer : qAsConst(d->m_renderers))
+ renderer->setColor(color);
+ }
+}
+
+QString QText2DEntity::text() const
+{
+ Q_D(const QText2DEntity);
+ return d->m_text;
+}
+
+void QText2DEntity::setText(const QString &text)
+{
+ Q_D(QText2DEntity);
+ if (d->m_text != text) {
+ d->m_text = text;
+ emit textChanged(text);
+
+ d->update();
+ }
+}
+
+float QText2DEntity::width() const
+{
+ Q_D(const QText2DEntity);
+ return d->m_width;
+}
+
+float QText2DEntity::height() const
+{
+ Q_D(const QText2DEntity);
+ return d->m_height;
+}
+
+void QText2DEntity::setWidth(float width)
+{
+ Q_D(QText2DEntity);
+ if (width != d->m_width) {
+ d->m_width = width;
+ emit widthChanged(width);
+ d->update();
+ }
+}
+
+void QText2DEntity::setHeight(float height)
+{
+ Q_D(QText2DEntity);
+ if (height != d->m_height) {
+ d->m_height = height;
+ emit heightChanged(height);
+ d->update();
+ }
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qconductedclipanimator.cpp b/src/extras/text/qtext2dentity.h
index 29bdefe37..39be91a0f 100644
--- a/src/animation/frontend/qconductedclipanimator.cpp
+++ b/src/extras/text/qtext2dentity.h
@@ -36,41 +36,63 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "qconductedclipanimator.h"
-#include "qconductedclipanimator_p.h"
+
+#ifndef QT3DEXTRAS_QTEXT2DENTITY_H
+#define QT3DEXTRAS_QTEXT2DENTITY_H
+
+#include <QtCore/qrect.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qfont.h>
+#include <Qt3DCore/qentity.h>
+#include <Qt3DExtras/qt3dextras_global.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DAnimation {
+namespace Qt3DExtras {
-QConductedClipAnimatorPrivate::QConductedClipAnimatorPrivate()
- : Qt3DCore::QComponentPrivate()
-{
-}
+class QText2DEntityPrivate;
-QConductedClipAnimator::QConductedClipAnimator(Qt3DCore::QNode *parent)
- : Qt3DCore::QComponent(*new QConductedClipAnimatorPrivate, parent)
+class QT3DEXTRASSHARED_EXPORT QText2DEntity : public Qt3DCore::QEntity
{
-}
+ Q_OBJECT
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(float width READ width WRITE setWidth NOTIFY widthChanged)
+ Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged)
-QConductedClipAnimator::QConductedClipAnimator(QConductedClipAnimatorPrivate &dd, Qt3DCore::QNode *parent)
- : Qt3DCore::QComponent(dd, parent)
-{
-}
+public:
+ explicit QText2DEntity(Qt3DCore::QNode *parent = nullptr);
+ ~QText2DEntity();
-QConductedClipAnimator::~QConductedClipAnimator()
-{
-}
+ QFont font() const;
+ void setFont(const QFont &font);
-Qt3DCore::QNodeCreatedChangeBasePtr QConductedClipAnimator::createNodeCreationChange() const
-{
- auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QConductedClipAnimatorData>::create(this);
- auto &data = creationChange->data;
- Q_D(const QConductedClipAnimator);
- // TODO: Send data members in creation change
- return creationChange;
-}
+ QColor color() const;
+ void setColor(const QColor &color);
-} // namespace Qt3DAnimation
+ QString text() const;
+ void setText(const QString &text);
+
+ float width() const;
+ float height() const;
+
+ void setWidth(float width);
+ void setHeight(float height);
+
+Q_SIGNALS:
+ void fontChanged(const QFont &font);
+ void colorChanged(const QColor &color);
+ void textChanged(const QString &text);
+ void widthChanged(float width);
+ void heightChanged(float height);
+
+private:
+ Q_DECLARE_PRIVATE(QText2DEntity)
+};
+
+} // namespace Qt3DExtras
QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXT2DENTITY_H
diff --git a/src/extras/text/qtext2dentity_p.h b/src/extras/text/qtext2dentity_p.h
new file mode 100644
index 000000000..863431091
--- /dev/null
+++ b/src/extras/text/qtext2dentity_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXT2DENTITY_P_H
+#define QT3DEXTRAS_QTEXT2DENTITY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qentity_p.h>
+#include <Qt3DExtras/private/distancefieldtextrenderer_p.h>
+#include <Qt3DExtras/private/qdistancefieldglyphcache_p.h>
+#include <QFont>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QScene;
+}
+
+namespace Qt3DRender {
+class QGeometryRenderer;
+class QGeometry;
+class QMaterial;
+class QAttribute;
+class QBuffer;
+}
+
+namespace Qt3DExtras {
+
+class QText2DMaterial;
+class QText2DEntity;
+
+class QText2DEntityPrivate : public Qt3DCore::QEntityPrivate
+{
+public:
+ QText2DEntityPrivate();
+ ~QText2DEntityPrivate();
+
+ Q_DECLARE_PUBLIC(QText2DEntity)
+
+ // keep track of the glyphs currently being displayed,
+ // to guarantee proper glyph ref-counting in the
+ // QDistanceFieldGlyphCache
+ QVector<QGlyphRun> m_currentGlyphRuns;
+ QDistanceFieldGlyphCache *m_glyphCache;
+
+ void setScene(Qt3DCore::QScene *scene) Q_DECL_OVERRIDE;
+
+ QFont m_font;
+ QFont m_scaledFont; // ignore point or pixel size, set to default value
+
+ QColor m_color;
+ QString m_text;
+ float m_width;
+ float m_height;
+
+ QVector<DistanceFieldTextRenderer*> m_renderers;
+
+ float computeActualScale() const;
+
+ void setCurrentGlyphRuns(const QVector<QGlyphRun> &runs);
+ void update();
+
+ struct CacheEntry
+ {
+ QDistanceFieldGlyphCache *glyphCache = nullptr;
+ int count = 0;
+ };
+
+ static QHash<Qt3DCore::QScene *, CacheEntry> m_glyphCacheInstances;
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXT2DENTITY_P_H
diff --git a/src/extras/text/qtext2dmaterial.cpp b/src/extras/text/qtext2dmaterial.cpp
new file mode 100644
index 000000000..d8bf312c4
--- /dev/null
+++ b/src/extras/text/qtext2dmaterial.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtext2dmaterial_p.h"
+#include "qtext2dmaterial_p_p.h"
+#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
+#include <Qt3DRender/qblendequation.h>
+#include <Qt3DRender/qblendequationarguments.h>
+#include <Qt3DRender/qdepthtest.h>
+#include <Qt3DRender/qabstracttexture.h>
+#include <QUrl>
+#include <QVector3D>
+#include <QVector4D>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QText2DMaterialPrivate::QText2DMaterialPrivate()
+ : QMaterialPrivate()
+ , m_effect(new Qt3DRender::QEffect())
+ , m_distanceFieldTexture(nullptr)
+ , m_textureParameter(new Qt3DRender::QParameter(QStringLiteral("distanceFieldTexture"), QVariant(0)))
+ , m_textureSizeParameter(new Qt3DRender::QParameter(QStringLiteral("textureSize"), QVariant(256.f)))
+ , m_colorParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(255, 255, 255, 255))))
+ , m_gl3Technique(new Qt3DRender::QTechnique())
+ , m_gl2Technique(new Qt3DRender::QTechnique())
+ , m_es2Technique(new Qt3DRender::QTechnique())
+ , m_gl3RenderPass(new Qt3DRender::QRenderPass())
+ , m_gl2RenderPass(new Qt3DRender::QRenderPass())
+ , m_es2RenderPass(new Qt3DRender::QRenderPass())
+ , m_gl3ShaderProgram(new Qt3DRender::QShaderProgram())
+ , m_gl2es2ShaderProgram(new Qt3DRender::QShaderProgram())
+ , m_blend(new Qt3DRender::QBlendEquation())
+ , m_blendArgs(new Qt3DRender::QBlendEquationArguments())
+ , m_depthTest(new Qt3DRender::QDepthTest())
+{
+}
+
+void QText2DMaterialPrivate::init()
+{
+ m_gl3ShaderProgram->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/distancefieldtext.vert"))));
+ m_gl3ShaderProgram->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/distancefieldtext.frag"))));
+
+ m_gl2es2ShaderProgram->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/distancefieldtext.vert"))));
+ m_gl2es2ShaderProgram->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/distancefieldtext.frag"))));
+
+ m_blend->setBlendFunction(Qt3DRender::QBlendEquation::Add);
+ m_blendArgs->setSourceRgba(Qt3DRender::QBlendEquationArguments::SourceAlpha);
+ m_blendArgs->setDestinationRgba(Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha);
+ m_depthTest->setDepthFunction(Qt3DRender::QDepthTest::LessOrEqual);
+
+ m_gl3RenderPass->setShaderProgram(m_gl3ShaderProgram);
+ m_gl3RenderPass->addRenderState(m_blend);
+ m_gl3RenderPass->addRenderState(m_blendArgs);
+ m_gl3RenderPass->addRenderState(m_depthTest);
+
+ m_gl2RenderPass->setShaderProgram(m_gl2es2ShaderProgram);
+ m_gl2RenderPass->addRenderState(m_blend);
+ m_gl2RenderPass->addRenderState(m_blendArgs);
+ m_gl2RenderPass->addRenderState(m_depthTest);
+
+ m_es2RenderPass->setShaderProgram(m_gl2es2ShaderProgram);
+ m_es2RenderPass->addRenderState(m_blend);
+ m_es2RenderPass->addRenderState(m_blendArgs);
+ m_es2RenderPass->addRenderState(m_depthTest);
+
+ m_gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL);
+ m_gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ m_gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ m_gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile);
+ m_gl3Technique->addRenderPass(m_gl3RenderPass);
+
+ m_gl2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL);
+ m_gl2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_gl2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_gl2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile);
+ m_gl2Technique->addRenderPass(m_gl2RenderPass);
+
+ m_es2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES);
+ m_es2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_es2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_es2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile);
+ m_es2Technique->addRenderPass(m_es2RenderPass);
+
+ Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey(q_func());
+ filterKey->setName(QStringLiteral("renderingStyle"));
+ filterKey->setValue(QStringLiteral("forward"));
+ m_gl3Technique->addFilterKey(filterKey);
+ m_gl2Technique->addFilterKey(filterKey);
+ m_es2Technique->addFilterKey(filterKey);
+
+ m_effect->addTechnique(m_gl3Technique);
+ m_effect->addTechnique(m_gl2Technique);
+ m_effect->addTechnique(m_es2Technique);
+ m_effect->addParameter(m_textureParameter);
+ m_effect->addParameter(m_textureSizeParameter);
+ m_effect->addParameter(m_colorParameter);
+
+ q_func()->setEffect(m_effect);
+}
+
+QText2DMaterial::QText2DMaterial(Qt3DCore::QNode *parent)
+ : QMaterial(*new QText2DMaterialPrivate(), parent)
+{
+ Q_D(QText2DMaterial);
+ d->init();
+}
+
+QText2DMaterial::~QText2DMaterial()
+{
+}
+
+void QText2DMaterial::setColor(const QColor &color)
+{
+ Q_D(QText2DMaterial);
+ d->m_colorParameter->setValue(QVariant::fromValue(color));
+}
+
+void QText2DMaterial::setDistanceFieldTexture(Qt3DRender::QAbstractTexture *tex)
+{
+ Q_D(QText2DMaterial);
+ d->m_distanceFieldTexture = tex;
+
+ if (tex) {
+ d->m_textureParameter->setValue(QVariant::fromValue(tex));
+ d->m_textureSizeParameter->setValue(QVariant::fromValue(static_cast<float>(tex->width())));
+ } else {
+ d->m_textureParameter->setValue(0);
+ d->m_textureSizeParameter->setValue(QVariant::fromValue(1.f));
+ }
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qconductedclipanimator.h b/src/extras/text/qtext2dmaterial_p.h
index 4364f6774..cf967b02b 100644
--- a/src/animation/frontend/qconductedclipanimator.h
+++ b/src/extras/text/qtext2dmaterial_p.h
@@ -37,40 +37,47 @@
**
****************************************************************************/
-#ifndef QT3DANIMATION_QCONDUCTEDCLIPANIMATOR_H
-#define QT3DANIMATION_QCONDUCTEDCLIPANIMATOR_H
+#ifndef QT3DEXTRAS_QTEXT2DMATERIAL_P_H
+#define QT3DEXTRAS_QTEXT2DMATERIAL_P_H
-#include <Qt3DAnimation/qt3danimation_global.h>
-#include <Qt3DCore/qcomponent.h>
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qmaterial.h>
+#include <QColor>
QT_BEGIN_NAMESPACE
-namespace Qt3DAnimation {
+namespace Qt3DExtras {
-class QConductedClipAnimatorPrivate;
+class QText2DMaterialPrivate;
-class QT3DANIMATIONSHARED_EXPORT QConductedClipAnimator : public Qt3DCore::QComponent
+class QText2DMaterial : public Qt3DRender::QMaterial
{
Q_OBJECT
- // TODO: Add property declarations
-public:
- explicit QConductedClipAnimator(Qt3DCore::QNode *parent = nullptr);
- ~QConductedClipAnimator();
-public Q_SLOTS:
-
-Q_SIGNALS:
+public:
+ explicit QText2DMaterial(Qt3DCore::QNode *parent = nullptr);
+ ~QText2DMaterial();
-protected:
- QConductedClipAnimator(QConductedClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ void setColor(const QColor &color);
+ void setDistanceFieldTexture(Qt3DRender::QAbstractTexture *tex);
private:
- Q_DECLARE_PRIVATE(QConductedClipAnimator)
- Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+ Q_DECLARE_PRIVATE(QText2DMaterial)
};
-} // namespace Qt3DAnimation
+} // namespace Qt3DExtras
QT_END_NAMESPACE
-#endif // QT3DANIMATION_QCONDUCTEDCLIPANIMATOR_H
+#endif // QT3DEXTRAS_QTEXT2DMATERIAL_P_H
diff --git a/src/extras/text/qtext2dmaterial_p_p.h b/src/extras/text/qtext2dmaterial_p_p.h
new file mode 100644
index 000000000..90f0a71f1
--- /dev/null
+++ b/src/extras/text/qtext2dmaterial_p_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXT2DMATERIAL_P_P_H
+#define QT3DEXTRAS_QTEXT2DMATERIAL_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qmaterial_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QAbstractTexture;
+class QEffect;
+class QTechnique;
+class QParameter;
+class QRenderPass;
+class QShaderProgram;
+class QBlendEquation;
+class QBlendEquationArguments;
+class QDepthTest;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QText2DMaterial;
+
+class QText2DMaterialPrivate : public Qt3DRender::QMaterialPrivate
+{
+public:
+ QText2DMaterialPrivate();
+
+ Qt3DRender::QEffect *m_effect;
+ Qt3DRender::QAbstractTexture *m_distanceFieldTexture;
+ Qt3DRender::QParameter *m_textureParameter;
+ Qt3DRender::QParameter *m_textureSizeParameter;
+ Qt3DRender::QParameter *m_colorParameter;
+ Qt3DRender::QTechnique *m_gl3Technique;
+ Qt3DRender::QTechnique *m_gl2Technique;
+ Qt3DRender::QTechnique *m_es2Technique;
+ Qt3DRender::QRenderPass *m_gl3RenderPass;
+ Qt3DRender::QRenderPass *m_gl2RenderPass;
+ Qt3DRender::QRenderPass *m_es2RenderPass;
+ Qt3DRender::QShaderProgram *m_gl3ShaderProgram;
+ Qt3DRender::QShaderProgram *m_gl2es2ShaderProgram;
+ Qt3DRender::QBlendEquation *m_blend;
+ Qt3DRender::QBlendEquationArguments *m_blendArgs;
+ Qt3DRender::QDepthTest *m_depthTest;
+
+ void init();
+
+ Q_DECLARE_PUBLIC(QText2DMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXT2DMATERIAL_P_P_H
diff --git a/src/extras/text/qtextureatlas.cpp b/src/extras/text/qtextureatlas.cpp
new file mode 100644
index 000000000..2b82010a6
--- /dev/null
+++ b/src/extras/text/qtextureatlas.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtextureatlas_p.h"
+#include "qtextureatlas_p_p.h"
+#include <Qt3DRender/qtexturedata.h>
+#include <Qt3DRender/qabstracttextureimage.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qpropertynodeaddedchange.h>
+#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DExtras {
+
+QTextureAtlasData::QTextureAtlasData(int w, int h, QImage::Format fmt)
+ : m_image(w, h, fmt)
+{
+}
+
+QTextureAtlasData::~QTextureAtlasData()
+{
+}
+
+void QTextureAtlasData::addImage(const AtlasTexture &texture, const QImage &image)
+{
+ QMutexLocker lock(&m_mutex);
+
+ Update update;
+ update.textureInfo = texture;
+ update.image = image;
+ m_updates << update;
+}
+
+QByteArray QTextureAtlasData::createUpdatedImageData()
+{
+ m_mutex.lock();
+ const QVector<Update> updates = std::move(m_updates);
+ m_mutex.unlock();
+
+ // copy sub-images into the actual texture image
+ for (const Update &update : updates) {
+ const QImage &image = update.image;
+
+ const int padding = update.textureInfo.padding;
+ const QRect imgRect = update.textureInfo.position;
+ const QRect alloc = imgRect.adjusted(-padding, -padding, padding, padding);
+
+ // bytes per pixel
+ if (image.depth() != m_image.depth()) {
+ qWarning() << "[QTextureAtlas] Image depth does not match. Original =" << m_image.depth() << ", Sub-Image =" << image.depth();
+ continue;
+ }
+ int bpp = image.depth() / 8;
+
+ // copy image contents into texture image
+ // use image border pixels to fill the padding region
+ for (int y = alloc.top(); y <= alloc.bottom(); y++) {
+ const int ySrc = qBound(0, y - imgRect.top(), image.height()-1);
+
+ const uchar *srcLine = image.scanLine(ySrc);
+ const uchar *srcLastPx = &srcLine[bpp * (image.width()-1)];
+
+ uchar *dstLine = m_image.scanLine(y);
+
+ uchar *dstPadL = &dstLine[bpp * alloc.left()];
+ uchar *dstPadR = &dstLine[bpp * imgRect.right()];
+ uchar *dstImg = &dstLine[bpp * imgRect.left()];
+
+ // copy left and right padding pixels
+ for (int pad = 0; pad < padding; pad++) {
+ for (int px = 0; px < bpp; px++) {
+ dstPadL[bpp * pad + px] = srcLine[px];
+ dstPadR[bpp * pad + px] = srcLastPx[px];
+ }
+ }
+
+ // copy image scanline
+ memcpy(dstImg, srcLine, bpp * imgRect.width());
+ }
+ }
+
+ return QByteArray(reinterpret_cast<const char*>(m_image.constBits()), m_image.byteCount());
+}
+
+QTextureAtlasPrivate::QTextureAtlasPrivate()
+ : Qt3DRender::QAbstractTexturePrivate()
+{
+ m_target = Qt3DRender::QAbstractTexture::TargetAutomatic;
+ m_format = Qt3DRender::QAbstractTexture::RGBA8_UNorm;
+ m_width = 256;
+ m_height = 256;
+ m_depth = 1;
+}
+
+QTextureAtlasPrivate::~QTextureAtlasPrivate()
+{
+}
+
+QTextureAtlasGenerator::QTextureAtlasGenerator(const QTextureAtlasPrivate *texAtlas)
+ : m_data(texAtlas->m_data)
+ , m_format(texAtlas->m_format)
+ , m_pixelFormat(texAtlas->m_pixelFormat)
+ , m_generation(texAtlas->m_currGen)
+ , m_atlasId(texAtlas->m_id)
+{
+}
+
+QTextureAtlasGenerator::~QTextureAtlasGenerator()
+{
+}
+
+Qt3DRender::QTextureDataPtr QTextureAtlasGenerator::operator()()
+{
+ Qt3DRender::QTextureImageDataPtr texImage = Qt3DRender::QTextureImageDataPtr::create();
+ texImage->setTarget(QOpenGLTexture::Target2D);
+ texImage->setWidth(m_data->width());
+ texImage->setHeight(m_data->height());
+ texImage->setDepth(1);
+ texImage->setFaces(1);
+ texImage->setLayers(1);
+ texImage->setMipLevels(1);
+ texImage->setFormat(static_cast<QOpenGLTexture::TextureFormat>(m_format));
+ texImage->setPixelFormat(m_pixelFormat);
+ texImage->setPixelType(QOpenGLTexture::UInt8);
+
+ const QByteArray bytes = m_data->createUpdatedImageData();
+ texImage->setData(bytes, 1);
+
+ Qt3DRender::QTextureDataPtr generatedData = Qt3DRender::QTextureDataPtr::create();
+ generatedData->setTarget(Qt3DRender::QAbstractTexture::Target2D);
+ generatedData->setFormat(m_format);
+ generatedData->setWidth(m_data->width());
+ generatedData->setHeight(m_data->height());
+ generatedData->setDepth(1);
+ generatedData->setLayers(1);
+ generatedData->addImageData(texImage);
+
+ return generatedData;
+}
+
+bool QTextureAtlasGenerator::operator==(const QTextureGenerator &other) const
+{
+ const QTextureAtlasGenerator *otherFunctor = Qt3DRender::functor_cast<QTextureAtlasGenerator>(&other);
+ return (otherFunctor != nullptr
+ && otherFunctor->m_data == m_data
+ && otherFunctor->m_atlasId == m_atlasId
+ && otherFunctor->m_generation == m_generation);
+}
+
+QTextureAtlas::QTextureAtlas(Qt3DCore::QNode *parent)
+ : QAbstractTexture(*new QTextureAtlasPrivate(), parent)
+{
+}
+
+QOpenGLTexture::PixelFormat QTextureAtlas::pixelFormat() const
+{
+ Q_D(const QTextureAtlas);
+ return d->m_pixelFormat;
+}
+
+void QTextureAtlas::setPixelFormat(QOpenGLTexture::PixelFormat fmt)
+{
+ Q_D(QTextureAtlas);
+ d->m_pixelFormat = fmt;
+}
+
+QTextureAtlas::~QTextureAtlas()
+{
+}
+
+QTextureAtlas::TextureId QTextureAtlas::addImage(const QImage &image, int padding)
+{
+ Q_D(QTextureAtlas);
+
+ // lazily create image and allocator to allow setWidth/setHeight after object construction
+ if (!d->m_allocator) {
+ Q_ASSERT(d->m_data.isNull());
+
+ d->m_allocator.reset(new AreaAllocator(QSize(width(), height())));
+ d->m_data = QTextureAtlasDataPtr::create(width(), height(), image.format());
+ }
+
+ const QSize allocSz = image.size() + QSize(2 * padding, 2 * padding);
+
+ // try to allocate space within image space
+ const QRect alloc = d->m_allocator->allocate(allocSz);
+ if (alloc.isEmpty())
+ return InvalidTexture;
+
+ const QRect imgRect = alloc.adjusted(padding, padding, -padding, -padding);
+ AtlasTexture tex;
+ tex.position = imgRect;
+ tex.padding = padding;
+
+ // store texture
+ TextureId id = d->m_currId++;
+ d->m_textures[id] = tex;
+ d->m_data->addImage(tex, image);
+
+ // update data functor
+ d->m_currGen++;
+ d->setDataFunctor(QTextureAtlasGeneratorPtr::create(d));
+
+ return id;
+}
+
+void QTextureAtlas::removeImage(TextureId id)
+{
+ Q_D(QTextureAtlas);
+ auto it = d->m_textures.find(id);
+ if (it != d->m_textures.end()) {
+ QRect imgRect = it->position;
+ imgRect.adjust(-it->padding, -it->padding, 2*it->padding, 2*it->padding);
+
+ if (d->m_allocator)
+ d->m_allocator->deallocate(imgRect);
+ d->m_textures.erase(it);
+ }
+}
+
+bool QTextureAtlas::hasImage(TextureId id) const
+{
+ Q_D(const QTextureAtlas);
+ return d->m_textures.contains(id);
+}
+
+int QTextureAtlas::imageCount() const
+{
+ Q_D(const QTextureAtlas);
+ return d->m_textures.size();
+}
+
+QRect QTextureAtlas::imagePosition(TextureId id) const
+{
+ Q_D(const QTextureAtlas);
+ const auto it = d->m_textures.find(id);
+ return (it != d->m_textures.cend()) ? it->position : QRect();
+}
+
+QRectF QTextureAtlas::imageTexCoords(TextureId id) const
+{
+ Q_D(const QTextureAtlas);
+ const auto it = d->m_textures.find(id);
+ if (it != d->m_textures.cend()) {
+ const float w = d->m_data->width();
+ const float h = d->m_data->height();
+ return QRectF(static_cast<float>(it->position.x()) / w,
+ static_cast<float>(it->position.y()) / h,
+ static_cast<float>(it->position.width()) / w,
+ static_cast<float>(it->position.height()) / h);
+ }
+ return QRectF();
+}
+
+int QTextureAtlas::imagePadding(TextureId id) const
+{
+ Q_D(const QTextureAtlas);
+ const auto it = d->m_textures.find(id);
+ return (it != d->m_textures.cend()) ? it->padding : -1;
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/text/qtextureatlas_p.h b/src/extras/text/qtextureatlas_p.h
new file mode 100644
index 000000000..8dc9e19b3
--- /dev/null
+++ b/src/extras/text/qtextureatlas_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXTUREATLAS_P_H
+#define QT3DEXTRAS_QTEXTUREATLAS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qabstracttexture.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QTextureAtlasPrivate;
+
+class QTextureAtlas : public Qt3DRender::QAbstractTexture
+{
+ Q_OBJECT
+
+public:
+ typedef int TextureId;
+ static Q_CONSTEXPR TextureId InvalidTexture = -1;
+
+ QTextureAtlas(Qt3DCore::QNode *parent = nullptr);
+ ~QTextureAtlas();
+
+ QOpenGLTexture::PixelFormat pixelFormat() const;
+ void setPixelFormat(QOpenGLTexture::PixelFormat fmt);
+
+ TextureId addImage(const QImage &image, int padding);
+ void removeImage(TextureId id);
+
+ int imageCount() const;
+
+ bool hasImage(TextureId id) const;
+ QRect imagePosition(TextureId id) const;
+ QRectF imageTexCoords(TextureId id) const;
+ int imagePadding(TextureId id) const;
+
+private:
+ Q_DECLARE_PRIVATE(QTextureAtlas)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXTUREATLAS_P_H
diff --git a/src/extras/text/qtextureatlas_p_p.h b/src/extras/text/qtextureatlas_p_p.h
new file mode 100644
index 000000000..ca18a263a
--- /dev/null
+++ b/src/extras/text/qtextureatlas_p_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QTEXTUREATLAS_P_P_H
+#define QT3DEXTRAS_QTEXTUREATLAS_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qscopedpointer.h>
+#include <Qt3DRender/private/qabstracttexture_p.h>
+#include <Qt3DRender/qtexturegenerator.h>
+#include <Qt3DExtras/private/areaallocator_p.h>
+#include <Qt3DExtras/private/qtextureatlas_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+// Used to store texture info within atlas
+struct AtlasTexture
+{
+ QRect position;
+ int padding = 0;
+};
+
+// data shared between QTextureAtlasPrivate and the QTextureGenerators
+// we use this extra indirection so we can lazily copy the sub-images
+// into the actual texture image in the backend texture loader thread.
+class QTextureAtlasData
+{
+public:
+ QTextureAtlasData(int w, int h, QImage::Format fmt);
+ ~QTextureAtlasData();
+
+ int width() const { return m_image.width(); }
+ int height() const { return m_image.height(); }
+
+ void addImage(const AtlasTexture &texture, const QImage &image);
+ QByteArray createUpdatedImageData();
+
+private:
+ struct Update {
+ AtlasTexture textureInfo;
+ QImage image;
+ };
+
+ QMutex m_mutex;
+ QImage m_image;
+ QVector<Update> m_updates;
+};
+
+typedef QSharedPointer<QTextureAtlasData> QTextureAtlasDataPtr;
+
+class QTextureAtlasPrivate : public Qt3DRender::QAbstractTexturePrivate
+{
+public:
+ QTextureAtlasPrivate();
+ ~QTextureAtlasPrivate();
+
+ Q_DECLARE_PUBLIC(QTextureAtlas)
+
+ QTextureAtlas::TextureId m_currId = 1; // IDs for new sub-textures
+ int m_currGen = 0;
+
+ QTextureAtlasDataPtr m_data;
+ QScopedPointer<AreaAllocator> m_allocator;
+ QOpenGLTexture::PixelFormat m_pixelFormat;
+ QHash<QTextureAtlas::TextureId, AtlasTexture> m_textures;
+};
+
+class QTextureAtlasGenerator : public Qt3DRender::QTextureGenerator
+{
+public:
+ QTextureAtlasGenerator(const QTextureAtlasPrivate *texAtlas);
+ ~QTextureAtlasGenerator();
+ Qt3DRender::QTextureDataPtr operator()() Q_DECL_OVERRIDE;
+ bool operator==(const QTextureGenerator &other) const Q_DECL_OVERRIDE;
+
+ QT3D_FUNCTOR(QTextureAtlasGenerator)
+
+private:
+ QTextureAtlasDataPtr m_data;
+ Qt3DRender::QAbstractTexture::TextureFormat m_format;
+ QOpenGLTexture::PixelFormat m_pixelFormat;
+ int m_generation;
+ Qt3DCore::QNodeId m_atlasId;
+};
+typedef QSharedPointer<QTextureAtlasGenerator> QTextureAtlasGeneratorPtr;
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QTEXTUREATLAS_P_P_H
diff --git a/src/extras/text/text.pri b/src/extras/text/text.pri
new file mode 100644
index 000000000..1d2cb793c
--- /dev/null
+++ b/src/extras/text/text.pri
@@ -0,0 +1,21 @@
+HEADERS += \
+ $$PWD/distancefieldtextrenderer_p.h \
+ $$PWD/distancefieldtextrenderer_p_p.h \
+ $$PWD/areaallocator_p.h \
+ $$PWD/qdistancefieldglyphcache_p.h \
+ $$PWD/qtextureatlas_p_p.h \
+ $$PWD/qtextureatlas_p.h \
+ $$PWD/qtext2dentity_p.h \
+ $$PWD/qtext2dentity.h \
+ $$PWD/qtext2dmaterial_p_p.h \
+ $$PWD/qtext2dmaterial_p.h
+
+SOURCES += \
+ $$PWD/qtextureatlas.cpp \
+ $$PWD/qdistancefieldglyphcache.cpp \
+ $$PWD/distancefieldtextrenderer.cpp \
+ $$PWD/areaallocator.cpp \
+ $$PWD/qtext2dentity.cpp \
+ $$PWD/qtext2dmaterial.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/input/backend/abstractaxisinput.cpp b/src/input/backend/abstractaxisinput.cpp
index 5cb209f25..aae165a7e 100644
--- a/src/input/backend/abstractaxisinput.cpp
+++ b/src/input/backend/abstractaxisinput.cpp
@@ -37,13 +37,15 @@
**
****************************************************************************/
-#include "abstractaxisinput_p.h"
-#include <Qt3DInput/qabstractaxisinput.h>
+#include "qabstractaxisinput.h"
+#include "qabstractaxisinput_p.h"
+
#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+#include <Qt3DInput/private/abstractaxisinput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
-#include <Qt3DInput/private/qabstractaxisinput_p.h>
#include <Qt3DInput/private/qinputdeviceintegration_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/action.cpp b/src/input/backend/action.cpp
index 2b8ada042..601961dd9 100644
--- a/src/input/backend/action.cpp
+++ b/src/input/backend/action.cpp
@@ -38,13 +38,14 @@
****************************************************************************/
#include "action_p.h"
+
#include <Qt3DInput/qaction.h>
#include <Qt3DInput/qabstractactioninput.h>
-#include <Qt3DInput/private/qaction_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
+
+#include <Qt3DInput/private/qaction_p.h>
QT_BEGIN_NAMESPACE
@@ -82,7 +83,6 @@ void Action::setActionTriggered(bool actionTriggered)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("active");
e->setValue(m_actionTriggered);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
diff --git a/src/input/backend/actioninput.cpp b/src/input/backend/actioninput.cpp
index b120c789e..46dc7f584 100644
--- a/src/input/backend/actioninput.cpp
+++ b/src/input/backend/actioninput.cpp
@@ -38,10 +38,12 @@
****************************************************************************/
#include "actioninput_p.h"
+
#include <Qt3DInput/qactioninput.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DInput/private/qactioninput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/utils_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/actioninput_p.h b/src/input/backend/actioninput_p.h
index da99c985e..3059f66cf 100644
--- a/src/input/backend/actioninput_p.h
+++ b/src/input/backend/actioninput_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DInput/private/abstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DInput/private/abstractactioninput_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/backend/analogaxisinput.cpp b/src/input/backend/analogaxisinput.cpp
index 914604e33..4a801baec 100644
--- a/src/input/backend/analogaxisinput.cpp
+++ b/src/input/backend/analogaxisinput.cpp
@@ -38,11 +38,13 @@
****************************************************************************/
#include "analogaxisinput_p.h"
+
#include <Qt3DInput/qanalogaxisinput.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
#include <Qt3DInput/private/qanalogaxisinput_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/utils_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/assignkeyboardfocusjob.cpp b/src/input/backend/assignkeyboardfocusjob.cpp
index ae845beaf..216c914d4 100644
--- a/src/input/backend/assignkeyboardfocusjob.cpp
+++ b/src/input/backend/assignkeyboardfocusjob.cpp
@@ -38,11 +38,12 @@
****************************************************************************/
#include "assignkeyboardfocusjob_p.h"
-#include "keyboarddevice_p.h"
-#include "keyboardhandler_p.h"
-#include "inputhandler_p.h"
-#include "inputmanagers_p.h"
-#include "job_common_p.h"
+
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/job_common_p.h>
+#include <Qt3DInput/private/keyboarddevice_p.h>
+#include <Qt3DInput/private/keyboardhandler_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/axis.cpp b/src/input/backend/axis.cpp
index 579c9fe7d..6ba4e2b34 100644
--- a/src/input/backend/axis.cpp
+++ b/src/input/backend/axis.cpp
@@ -38,13 +38,14 @@
****************************************************************************/
#include "axis_p.h"
+
#include <Qt3DInput/qaxis.h>
#include <Qt3DInput/qabstractaxisinput.h>
-#include <Qt3DInput/private/qaxis_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
+
+#include <Qt3DInput/private/qaxis_p.h>
QT_BEGIN_NAMESPACE
@@ -82,7 +83,6 @@ void Axis::setAxisValue(float axisValue)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("value");
e->setValue(m_axisValue);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
diff --git a/src/input/backend/axisaccumulator.cpp b/src/input/backend/axisaccumulator.cpp
index 815c25cb0..edc282bec 100644
--- a/src/input/backend/axisaccumulator.cpp
+++ b/src/input/backend/axisaccumulator.cpp
@@ -38,10 +38,11 @@
****************************************************************************/
#include "axisaccumulator_p.h"
-#include <Qt3DInput/private/qaxisaccumulator_p.h>
-#include <Qt3DInput/private/inputmanagers_p.h>
+
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
+
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/qaxisaccumulator_p.h>
QT_BEGIN_NAMESPACE
@@ -88,7 +89,6 @@ void AxisAccumulator::setValue(float value)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("value");
e->setValue(m_value);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
@@ -103,7 +103,6 @@ void AxisAccumulator::setVelocity(float velocity)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("velocity");
e->setValue(m_velocity);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
diff --git a/src/input/backend/axisaccumulator_p.h b/src/input/backend/axisaccumulator_p.h
index 67eb3906a..7d6799eb0 100644
--- a/src/input/backend/axisaccumulator_p.h
+++ b/src/input/backend/axisaccumulator_p.h
@@ -51,11 +51,10 @@
// We mean it.
//
+#include <Qt3DInput/qaxisaccumulator.h>
#include <Qt3DCore/qbackendnode.h>
#include <Qt3DCore/qnodeid.h>
-#include <Qt3DInput/qaxisaccumulator.h>
-
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/backend/axisaccumulatorjob.cpp b/src/input/backend/axisaccumulatorjob.cpp
index 133f9713a..7ea2d063d 100644
--- a/src/input/backend/axisaccumulatorjob.cpp
+++ b/src/input/backend/axisaccumulatorjob.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "axisaccumulatorjob_p.h"
+
#include <Qt3DInput/private/axisaccumulator_p.h>
#include <Qt3DInput/private/job_common_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
diff --git a/src/input/backend/axisaccumulatorjob_p.h b/src/input/backend/axisaccumulatorjob_p.h
index d8ced8a3a..4d38fd70f 100644
--- a/src/input/backend/axisaccumulatorjob_p.h
+++ b/src/input/backend/axisaccumulatorjob_p.h
@@ -51,9 +51,9 @@
// We mean it.
//
+#include <Qt3DInput/private/handle_types_p.h>
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
-#include <Qt3DInput/private/handle_types_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/axissetting.cpp b/src/input/backend/axissetting.cpp
index 10892f861..b3c81f84d 100644
--- a/src/input/backend/axissetting.cpp
+++ b/src/input/backend/axissetting.cpp
@@ -38,10 +38,12 @@
****************************************************************************/
#include "axissetting_p.h"
+
#include <Qt3DInput/qaxissetting.h>
-#include <Qt3DInput/private/qaxissetting_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DInput/private/qaxissetting_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/backend/buttonaxisinput.cpp b/src/input/backend/buttonaxisinput.cpp
index 99fa99852..fef8f6d41 100644
--- a/src/input/backend/buttonaxisinput.cpp
+++ b/src/input/backend/buttonaxisinput.cpp
@@ -38,11 +38,13 @@
****************************************************************************/
#include "buttonaxisinput_p.h"
+
#include <Qt3DInput/qbuttonaxisinput.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
#include <Qt3DInput/private/qbuttonaxisinput_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/utils_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/eventsourcesetterhelper.cpp b/src/input/backend/eventsourcesetterhelper.cpp
index 4ae6cebae..5c11ada38 100644
--- a/src/input/backend/eventsourcesetterhelper.cpp
+++ b/src/input/backend/eventsourcesetterhelper.cpp
@@ -38,7 +38,8 @@
****************************************************************************/
#include "eventsourcesetterhelper_p.h"
-#include "inputhandler_p.h"
+
+#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/eventsourcesetterhelper_p.h b/src/input/backend/eventsourcesetterhelper_p.h
index 97776dc9b..48418f1b9 100644
--- a/src/input/backend/eventsourcesetterhelper_p.h
+++ b/src/input/backend/eventsourcesetterhelper_p.h
@@ -51,8 +51,8 @@
// We mean it.
//
-#include <QObject>
-#include <QMutex>
+#include <QtCore/QMutex>
+#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/genericdevicebackendnode.cpp b/src/input/backend/genericdevicebackendnode.cpp
index 093acd966..40202b4a5 100644
--- a/src/input/backend/genericdevicebackendnode.cpp
+++ b/src/input/backend/genericdevicebackendnode.cpp
@@ -38,11 +38,12 @@
****************************************************************************/
#include "genericdevicebackendnode_p.h"
-#include "inputhandler_p.h"
-#include "inputmanagers_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/genericdevicebackendnode_p.h b/src/input/backend/genericdevicebackendnode_p.h
index 8c0ffcfde..16aaf3e5b 100644
--- a/src/input/backend/genericdevicebackendnode_p.h
+++ b/src/input/backend/genericdevicebackendnode_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
+#include <QtCore/QHash>
+#include <QtCore/QMutex>
+
#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
-#include <QHash>
-#include <QMutex>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/inputchord.cpp b/src/input/backend/inputchord.cpp
index ebcf79737..731fd91e3 100644
--- a/src/input/backend/inputchord.cpp
+++ b/src/input/backend/inputchord.cpp
@@ -38,13 +38,15 @@
****************************************************************************/
#include "inputchord_p.h"
+
#include <Qt3DInput/qinputchord.h>
-#include <Qt3DInput/private/qinputchord_p.h>
-#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DInput/private/qinputchord_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/backend/inputchord_p.h b/src/input/backend/inputchord_p.h
index 7f51f5d96..95557a00d 100644
--- a/src/input/backend/inputchord_p.h
+++ b/src/input/backend/inputchord_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DInput/private/abstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DInput/private/abstractactioninput_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/backend/inputhandler.cpp b/src/input/backend/inputhandler.cpp
index aebf2c8f1..525a45b6c 100644
--- a/src/input/backend/inputhandler.cpp
+++ b/src/input/backend/inputhandler.cpp
@@ -38,16 +38,17 @@
****************************************************************************/
#include "inputhandler_p.h"
-#include "inputmanagers_p.h"
-#include "keyboardeventfilter_p.h"
-#include "mouseeventfilter_p.h"
-#include "assignkeyboardfocusjob_p.h"
-#include "keyeventdispatcherjob_p.h"
-#include "mouseeventdispatcherjob_p.h"
-#include <Qt3DCore/private/qeventfilterservice_p.h>
-#include "inputsettings_p.h"
-#include "eventsourcesetterhelper_p.h"
+
+#include <Qt3DInput/private/assignkeyboardfocusjob_p.h>
+#include <Qt3DInput/private/eventsourcesetterhelper_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/inputsettings_p.h>
+#include <Qt3DInput/private/keyboardeventfilter_p.h>
+#include <Qt3DInput/private/keyeventdispatcherjob_p.h>
+#include <Qt3DInput/private/mouseeventdispatcherjob_p.h>
+#include <Qt3DInput/private/mouseeventfilter_p.h>
#include <Qt3DInput/private/qinputdeviceintegration_p.h>
+#include <Qt3DCore/private/qeventfilterservice_p.h>
QT_BEGIN_NAMESPACE
@@ -162,6 +163,7 @@ void InputHandler::clearPendingMouseEvents()
m_pendingMouseEvents.clear();
}
+#if QT_CONFIG(wheelevent)
void InputHandler::appendWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &event)
{
QMutexLocker lock(&m_mutex);
@@ -179,7 +181,7 @@ void InputHandler::clearPendingWheelEvents()
QMutexLocker lock(&m_mutex);
m_pendingWheelEvents.clear();
}
-
+#endif
void InputHandler::appendKeyboardDevice(HKeyboardDevice device)
{
@@ -248,15 +250,23 @@ QVector<Qt3DCore::QAspectJobPtr> InputHandler::mouseJobs()
{
QVector<QAspectJobPtr> jobs;
const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> mouseEvents = pendingMouseEvents();
+#if QT_CONFIG(wheelevent)
const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> wheelEvents = pendingWheelEvents();
+#endif
for (const HMouseDevice cHandle : qAsConst(m_activeMouseDevices)) {
MouseDevice *controller = m_mouseDeviceManager->data(cHandle);
controller->updateMouseEvents(mouseEvents);
+#if QT_CONFIG(wheelevent)
controller->updateWheelEvents(wheelEvents);
+#endif
// Event dispacthing job
- if (!mouseEvents.isEmpty() || !wheelEvents.empty()) {
+ if (!mouseEvents.isEmpty()
+#if QT_CONFIG(wheelevent)
+ || !wheelEvents.empty()
+#endif
+ ) {
// Send the events to the mouse handlers that have for sourceDevice controller
const QVector<HMouseHandler> activeMouseHandlers = m_mouseInputManager->activeHandles();
for (HMouseHandler mouseHandlerHandle : activeMouseHandlers) {
@@ -266,8 +276,11 @@ QVector<Qt3DCore::QAspectJobPtr> InputHandler::mouseJobs()
if (mouseHandler->mouseDevice() == controller->peerId()) {
MouseEventDispatcherJob *job = new MouseEventDispatcherJob(mouseHandler->peerId(),
- mouseEvents,
- wheelEvents);
+ mouseEvents
+#if QT_CONFIG(wheelevent)
+ , wheelEvents
+#endif
+ );
job->setInputHandler(this);
jobs.append(QAspectJobPtr(job));
}
diff --git a/src/input/backend/inputhandler_p.h b/src/input/backend/inputhandler_p.h
index eff0c0c24..a2a38262d 100644
--- a/src/input/backend/inputhandler_p.h
+++ b/src/input/backend/inputhandler_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
+#include <Qt3DInput/QKeyEvent>
#include <Qt3DInput/qt3dinput_global.h>
-#include <Qt3DInput/private/handle_types_p.h>
#include <Qt3DCore/qaspectjob.h>
-#include <QKeyEvent>
-#include <QMutex>
+#include <QtCore/QMutex>
+
+#include <Qt3DInput/private/handle_types_p.h>
QT_BEGIN_NAMESPACE
@@ -126,9 +127,11 @@ public:
QList<QT_PREPEND_NAMESPACE(QMouseEvent)> pendingMouseEvents();
void clearPendingMouseEvents();
+#if QT_CONFIG(wheelevent)
void appendWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &event);
QList<QT_PREPEND_NAMESPACE(QWheelEvent)> pendingWheelEvents();
void clearPendingWheelEvents();
+#endif
void appendKeyboardDevice(HKeyboardDevice device);
void removeKeyboardDevice(HKeyboardDevice device);
@@ -169,7 +172,9 @@ private:
QList<QT_PREPEND_NAMESPACE(QKeyEvent)> m_pendingKeyEvents;
QList<QT_PREPEND_NAMESPACE(QMouseEvent)> m_pendingMouseEvents;
+#if QT_CONFIG(wheelevent)
QList<QT_PREPEND_NAMESPACE(QWheelEvent)> m_pendingWheelEvents;
+#endif
mutable QMutex m_mutex;
AxisManager *m_axisManager;
diff --git a/src/input/backend/inputmanagers_p.h b/src/input/backend/inputmanagers_p.h
index 473042867..a0cb127b1 100644
--- a/src/input/backend/inputmanagers_p.h
+++ b/src/input/backend/inputmanagers_p.h
@@ -51,13 +51,13 @@
// We mean it.
//
-#include <QtGlobal>
+#include <QtCore/QtGlobal>
+
#include <Qt3DInput/private/handle_types_p.h>
#include <Qt3DInput/private/keyboarddevice_p.h>
#include <Qt3DInput/private/keyboardhandler_p.h>
#include <Qt3DInput/private/mousehandler_p.h>
#include <Qt3DInput/private/mousedevice_p.h>
-#include <Qt3DCore/private/qresourcemanager_p.h>
#include <Qt3DInput/private/actioninput_p.h>
#include <Qt3DInput/private/inputsequence_p.h>
#include <Qt3DInput/private/inputchord_p.h>
@@ -70,6 +70,7 @@
#include <Qt3DInput/private/logicaldevice_p.h>
#include <Qt3DInput/private/genericdevicebackendnode_p.h>
#include <Qt3DInput/private/physicaldeviceproxy_p.h>
+#include <Qt3DCore/private/qresourcemanager_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/inputsequence.cpp b/src/input/backend/inputsequence.cpp
index ee31cb1de..e45fae364 100644
--- a/src/input/backend/inputsequence.cpp
+++ b/src/input/backend/inputsequence.cpp
@@ -38,14 +38,16 @@
****************************************************************************/
#include "inputsequence_p.h"
-#include <Qt3DInput/qinputsequence.h>
+
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DInput/private/qinputsequence_p.h>
-#include <Qt3DInput/private/inputhandler_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DInput/qinputsequence.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <QDateTime>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <QtCore/QDateTime>
+
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/qinputsequence_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/inputsequence_p.h b/src/input/backend/inputsequence_p.h
index 28cb1c0e1..a9fa2dd2f 100644
--- a/src/input/backend/inputsequence_p.h
+++ b/src/input/backend/inputsequence_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DInput/private/abstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DInput/private/abstractactioninput_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/backend/inputsettings.cpp b/src/input/backend/inputsettings.cpp
index 587e4ce1a..b695ed600 100644
--- a/src/input/backend/inputsettings.cpp
+++ b/src/input/backend/inputsettings.cpp
@@ -38,10 +38,12 @@
****************************************************************************/
#include "inputsettings_p.h"
+
#include <Qt3DInput/qinputsettings.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/qinputsettings_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/inputsettings_p.h b/src/input/backend/inputsettings_p.h
index 386716bc5..2fee6c946 100644
--- a/src/input/backend/inputsettings_p.h
+++ b/src/input/backend/inputsettings_p.h
@@ -51,8 +51,8 @@
// We mean it.
//
-#include <QPointer>
#include <Qt3DCore/qbackendnode.h>
+#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyboarddevice.cpp b/src/input/backend/keyboarddevice.cpp
index 2566dacd2..33578bdad 100644
--- a/src/input/backend/keyboarddevice.cpp
+++ b/src/input/backend/keyboarddevice.cpp
@@ -38,11 +38,13 @@
****************************************************************************/
#include "keyboarddevice_p.h"
-#include "inputhandler_p.h"
-#include "inputmanagers_p.h"
+
+#include <Qt3DInput/QKeyEvent>
#include <Qt3DCore/qnode.h>
-#include <QKeyEvent>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyboarddevice_p.h b/src/input/backend/keyboarddevice_p.h
index 0ab7d22e8..611a06233 100644
--- a/src/input/backend/keyboarddevice_p.h
+++ b/src/input/backend/keyboarddevice_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
+#include <Qt3DInput/QKeyEvent>
#include <Qt3DCore/qnodeid.h>
+
#include <Qt3DInput/private/handle_types_p.h>
-#include <QKeyEvent>
+#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyboardeventfilter.cpp b/src/input/backend/keyboardeventfilter.cpp
index e94af9ade..bd3bac5a7 100644
--- a/src/input/backend/keyboardeventfilter.cpp
+++ b/src/input/backend/keyboardeventfilter.cpp
@@ -38,9 +38,11 @@
****************************************************************************/
#include "keyboardeventfilter_p.h"
-#include "inputhandler_p.h"
-#include <QEvent>
-#include <QKeyEvent>
+
+#include <Qt3DInput/QKeyEvent>
+#include <QtCore/QEvent>
+
+#include <Qt3DInput/private/inputhandler_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyboardeventfilter_p.h b/src/input/backend/keyboardeventfilter_p.h
index a06b4cdd5..46b8071cd 100644
--- a/src/input/backend/keyboardeventfilter_p.h
+++ b/src/input/backend/keyboardeventfilter_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QObject>
+#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyboardhandler.cpp b/src/input/backend/keyboardhandler.cpp
index b674ac372..ae1e6d03c 100644
--- a/src/input/backend/keyboardhandler.cpp
+++ b/src/input/backend/keyboardhandler.cpp
@@ -38,14 +38,15 @@
****************************************************************************/
#include "keyboardhandler_p.h"
+
+#include <Qt3DInput/qkeyboarddevice.h>
#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DInput/private/qkeyboardhandler_p.h>
-#include "qkeyboarddevice.h"
-#include "inputhandler_p.h"
-#include "inputmanagers_p.h"
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
-#include <QVariant>
+#include <QtCore/QVariant>
+
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/qkeyboardhandler_p.h>
QT_BEGIN_NAMESPACE
@@ -91,7 +92,6 @@ void KeyboardHandler::setFocus(bool focus)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("focus");
e->setValue(m_focus);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
@@ -102,7 +102,6 @@ void KeyboardHandler::keyEvent(const QKeyEventPtr &event)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("event");
e->setValue(QVariant::fromValue(event));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
diff --git a/src/input/backend/keyboardhandler_p.h b/src/input/backend/keyboardhandler_p.h
index 6dd3a2c5e..e2aeab4f3 100644
--- a/src/input/backend/keyboardhandler_p.h
+++ b/src/input/backend/keyboardhandler_p.h
@@ -51,9 +51,9 @@
// We mean it.
//
+#include <Qt3DInput/qkeyevent.h>
#include <Qt3DCore/qbackendnode.h>
#include <Qt3DCore/qnodeid.h>
-#include <Qt3DInput/qkeyevent.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyboardmousegenericdeviceintegration.cpp b/src/input/backend/keyboardmousegenericdeviceintegration.cpp
index 31d0ea981..05430b0e8 100644
--- a/src/input/backend/keyboardmousegenericdeviceintegration.cpp
+++ b/src/input/backend/keyboardmousegenericdeviceintegration.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "keyboardmousegenericdeviceintegration_p.h"
+
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
diff --git a/src/input/backend/keyeventdispatcherjob.cpp b/src/input/backend/keyeventdispatcherjob.cpp
index bbf703a56..ac90e9e37 100644
--- a/src/input/backend/keyeventdispatcherjob.cpp
+++ b/src/input/backend/keyeventdispatcherjob.cpp
@@ -38,10 +38,11 @@
****************************************************************************/
#include "keyeventdispatcherjob_p.h"
-#include "inputhandler_p.h"
-#include "keyboardhandler_p.h"
-#include "inputmanagers_p.h"
-#include "job_common_p.h"
+
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/job_common_p.h>
+#include <Qt3DInput/private/keyboardhandler_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/keyeventdispatcherjob_p.h b/src/input/backend/keyeventdispatcherjob_p.h
index b89d8ced2..1456f0878 100644
--- a/src/input/backend/keyeventdispatcherjob_p.h
+++ b/src/input/backend/keyeventdispatcherjob_p.h
@@ -51,9 +51,9 @@
// We mean it.
//
+#include <Qt3DInput/QKeyEvent>
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
-#include <QKeyEvent>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/loadproxydevicejob.cpp b/src/input/backend/loadproxydevicejob.cpp
index 622d7ab83..2ea29b4a9 100644
--- a/src/input/backend/loadproxydevicejob.cpp
+++ b/src/input/backend/loadproxydevicejob.cpp
@@ -38,9 +38,10 @@
****************************************************************************/
#include "loadproxydevicejob_p.h"
+
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
-#include "job_common_p.h"
+#include <Qt3DInput/private/job_common_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/logicaldevice.cpp b/src/input/backend/logicaldevice.cpp
index fd4a637f2..5fcfb07bb 100644
--- a/src/input/backend/logicaldevice.cpp
+++ b/src/input/backend/logicaldevice.cpp
@@ -38,14 +38,16 @@
****************************************************************************/
#include "logicaldevice_p.h"
-#include <Qt3DInput/qlogicaldevice.h>
-#include <Qt3DInput/qaxis.h>
+
#include <Qt3DInput/qaction.h>
-#include <Qt3DInput/private/inputmanagers_p.h>
-#include <Qt3DInput/private/qlogicaldevice_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DInput/qaxis.h>
+#include <Qt3DInput/qlogicaldevice.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/qlogicaldevice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/mousedevice.cpp b/src/input/backend/mousedevice.cpp
index 918fdecb0..128988637 100644
--- a/src/input/backend/mousedevice.cpp
+++ b/src/input/backend/mousedevice.cpp
@@ -38,15 +38,16 @@
****************************************************************************/
#include "mousedevice_p.h"
-#include "inputmanagers_p.h"
-#include "inputhandler_p.h"
-#include "qmousedevice.h"
-#include <Qt3DInput/private/qmousedevice_p.h>
-#include <Qt3DCore/qnode.h>
+#include <Qt3DInput/qmousedevice.h>
#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qnode.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/qmousedevice_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
@@ -134,6 +135,7 @@ float MouseDevice::sensitivity() const
return m_sensitivity;
}
+#if QT_CONFIG(wheelevent)
void MouseDevice::updateWheelEvents(const QList<QT_PREPEND_NAMESPACE (QWheelEvent)> &events)
{
// Reset axis values before we accumulate new values for this frame
@@ -146,6 +148,7 @@ void MouseDevice::updateWheelEvents(const QList<QT_PREPEND_NAMESPACE (QWheelEven
}
}
}
+#endif
void MouseDevice::updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &events)
{
diff --git a/src/input/backend/mousedevice_p.h b/src/input/backend/mousedevice_p.h
index 8b85ee34a..a085194ff 100644
--- a/src/input/backend/mousedevice_p.h
+++ b/src/input/backend/mousedevice_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
+#include <Qt3DInput/QMouseEvent>
+
#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
-#include <QMouseEvent>
QT_BEGIN_NAMESPACE
@@ -98,7 +99,9 @@ public:
bool isButtonPressed(int buttonIdentifier) const Q_DECL_OVERRIDE;
void updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &events);
+#if QT_CONFIG(wheelevent)
void updateWheelEvents(const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> &events);
+#endif
MouseState mouseState() const;
QPointF previousPos() const;
diff --git a/src/input/backend/mouseeventdispatcherjob.cpp b/src/input/backend/mouseeventdispatcherjob.cpp
index 167560e39..11653d8a8 100644
--- a/src/input/backend/mouseeventdispatcherjob.cpp
+++ b/src/input/backend/mouseeventdispatcherjob.cpp
@@ -38,10 +38,11 @@
****************************************************************************/
#include "mouseeventdispatcherjob_p.h"
-#include "inputhandler_p.h"
-#include "mousehandler_p.h"
-#include "inputmanagers_p.h"
-#include "job_common_p.h"
+
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/job_common_p.h>
+#include <Qt3DInput/private/mousehandler_p.h>
QT_BEGIN_NAMESPACE
@@ -49,13 +50,18 @@ namespace Qt3DInput {
namespace Input {
MouseEventDispatcherJob::MouseEventDispatcherJob(Qt3DCore::QNodeId input,
- const QList<QT_PREPEND_NAMESPACE (QMouseEvent)> &mouseEvents,
- const QList<QT_PREPEND_NAMESPACE (QWheelEvent)> &wheelEvents)
+ const QList<QT_PREPEND_NAMESPACE (QMouseEvent)> &mouseEvents
+#if QT_CONFIG(wheelevent)
+ , const QList<QT_PREPEND_NAMESPACE (QWheelEvent)> &wheelEvents
+#endif
+ )
: QAspectJob()
, m_inputHandler(nullptr)
, m_mouseInput(input)
, m_mouseEvents(mouseEvents)
+#if QT_CONFIG(wheelevent)
, m_wheelEvents(wheelEvents)
+#endif
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::MouseEventDispatcher, 0);
}
@@ -72,8 +78,10 @@ void MouseEventDispatcherJob::run()
// Send mouse and wheel events to frontend
for (const QT_PREPEND_NAMESPACE(QMouseEvent) &e : m_mouseEvents)
input->mouseEvent(QMouseEventPtr(new QMouseEvent(e)));
+#if QT_CONFIG(wheelevent)
for (const QT_PREPEND_NAMESPACE(QWheelEvent) &e : m_wheelEvents)
input->wheelEvent(QWheelEventPtr(new QWheelEvent(e)));
+#endif
}
}
diff --git a/src/input/backend/mouseeventdispatcherjob_p.h b/src/input/backend/mouseeventdispatcherjob_p.h
index defe3c3a3..366774005 100644
--- a/src/input/backend/mouseeventdispatcherjob_p.h
+++ b/src/input/backend/mouseeventdispatcherjob_p.h
@@ -51,9 +51,9 @@
// We mean it.
//
+#include <Qt3DInput/QMouseEvent>
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
-#include <QMouseEvent>
QT_BEGIN_NAMESPACE
@@ -66,8 +66,11 @@ class MouseEventDispatcherJob : public Qt3DCore::QAspectJob
{
public:
explicit MouseEventDispatcherJob(Qt3DCore::QNodeId input,
- const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &mouseEvents,
- const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> &wheelEvents);
+ const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &mouseEvents
+#if QT_CONFIG(wheelevent)
+ , const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> &wheelEvents
+#endif
+ );
void setInputHandler(InputHandler *handler);
void run() Q_DECL_FINAL;
@@ -75,7 +78,9 @@ private:
InputHandler *m_inputHandler;
const Qt3DCore::QNodeId m_mouseInput;
const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> m_mouseEvents;
+#if QT_CONFIG(wheelevent)
const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> m_wheelEvents;
+#endif
};
} // namespace Input
diff --git a/src/input/backend/mouseeventfilter.cpp b/src/input/backend/mouseeventfilter.cpp
index f12127c3b..618a64b15 100644
--- a/src/input/backend/mouseeventfilter.cpp
+++ b/src/input/backend/mouseeventfilter.cpp
@@ -38,9 +38,11 @@
****************************************************************************/
#include "mouseeventfilter_p.h"
-#include "inputhandler_p.h"
-#include <QEvent>
-#include <QKeyEvent>
+
+#include <Qt3DInput/QKeyEvent>
+#include <QtCore/QEvent>
+
+#include <Qt3DInput/private/inputhandler_p.h>
QT_BEGIN_NAMESPACE
@@ -78,10 +80,12 @@ bool MouseEventFilter::eventFilter(QObject *obj, QEvent *e)
// Creates copy and store event to be processed later on in an InputAspect job
m_inputHandler->appendMouseEvent(QMouseEvent(*static_cast<QMouseEvent *>(e)));
break;
+#if QT_CONFIG(wheelevent)
case QEvent::Wheel:
// Creates copy and store event to be processed later on in an InputAspect job
m_inputHandler->appendWheelEvent(QWheelEvent(*static_cast<QWheelEvent *>(e)));
break;
+#endif
default:
break;
}
diff --git a/src/input/backend/mouseeventfilter_p.h b/src/input/backend/mouseeventfilter_p.h
index a733b3ad1..340524a61 100644
--- a/src/input/backend/mouseeventfilter_p.h
+++ b/src/input/backend/mouseeventfilter_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QObject>
+#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/mousehandler.cpp b/src/input/backend/mousehandler.cpp
index 770c318e1..c492dcf28 100644
--- a/src/input/backend/mousehandler.cpp
+++ b/src/input/backend/mousehandler.cpp
@@ -38,15 +38,15 @@
****************************************************************************/
#include "mousehandler_p.h"
-#include "inputmanagers_p.h"
-#include "inputhandler_p.h"
-#include "mousedevice_p.h"
#include <Qt3DInput/qmousehandler.h>
-#include <Qt3DInput/private/qmousehandler_p.h>
#include <Qt3DInput/qmousedevice.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
+
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/mousedevice_p.h>
+#include <Qt3DInput/private/qmousehandler_p.h>
QT_BEGIN_NAMESPACE
@@ -88,19 +88,19 @@ void MouseHandler::mouseEvent(const QMouseEventPtr &event)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("mouse");
e->setValue(QVariant::fromValue(event));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
+#if QT_CONFIG(wheelevent)
void MouseHandler::wheelEvent(const QWheelEventPtr &event)
{
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("wheel");
e->setValue(QVariant::fromValue(event));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
+#endif
void MouseHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
diff --git a/src/input/backend/mousehandler_p.h b/src/input/backend/mousehandler_p.h
index b2ae4f9ed..ae484d8d6 100644
--- a/src/input/backend/mousehandler_p.h
+++ b/src/input/backend/mousehandler_p.h
@@ -51,8 +51,8 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
#include <Qt3DInput/qmouseevent.h>
+#include <Qt3DCore/qbackendnode.h>
QT_BEGIN_NAMESPACE
@@ -70,7 +70,9 @@ public:
Qt3DCore::QNodeId mouseDevice() const;
void setInputHandler(InputHandler *handler);
void mouseEvent(const QMouseEventPtr &event);
+#if QT_CONFIG(wheelevent)
void wheelEvent(const QWheelEventPtr &event);
+#endif
protected:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
diff --git a/src/input/backend/physicaldeviceproxy.cpp b/src/input/backend/physicaldeviceproxy.cpp
index 083f2438a..9512296b8 100644
--- a/src/input/backend/physicaldeviceproxy.cpp
+++ b/src/input/backend/physicaldeviceproxy.cpp
@@ -38,12 +38,13 @@
****************************************************************************/
#include "physicaldeviceproxy_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <QtCore/QCoreApplication>
+
#include <Qt3DInput/private/inputmanagers_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
-#include <QCoreApplication>
+#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h>
QT_BEGIN_NAMESPACE
@@ -93,7 +94,6 @@ void PhysicalDeviceProxy::setDevice(QAbstractPhysicalDevice *device)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("device");
e->setValue(QVariant::fromValue(device));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
diff --git a/src/input/backend/qabstractphysicaldevicebackendnode.cpp b/src/input/backend/qabstractphysicaldevicebackendnode.cpp
index 45f228e1a..5006d702a 100644
--- a/src/input/backend/qabstractphysicaldevicebackendnode.cpp
+++ b/src/input/backend/qabstractphysicaldevicebackendnode.cpp
@@ -39,22 +39,22 @@
#include "qabstractphysicaldevicebackendnode_p.h"
#include "qabstractphysicaldevicebackendnode_p_p.h"
-#include "qabstractphysicaldevice.h"
-#include "qaxissetting.h"
-#include "inputhandler_p.h"
-#include "inputmanagers_p.h"
+#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DInput/qaxissetting.h>
#include <Qt3DInput/qinputaspect.h>
#include <Qt3DInput/qphysicaldevicecreatedchange.h>
-#include <Qt3DInput/private/qinputaspect_p.h>
-
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/private/qabstractaspect_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <cmath>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/qinputaspect_p.h>
+#include <Qt3DCore/private/qabstractaspect_p.h>
+
QT_BEGIN_NAMESPACE
namespace {
diff --git a/src/input/backend/qabstractphysicaldevicebackendnode_p.h b/src/input/backend/qabstractphysicaldevicebackendnode_p.h
index aa789fe27..272143c45 100644
--- a/src/input/backend/qabstractphysicaldevicebackendnode_p.h
+++ b/src/input/backend/qabstractphysicaldevicebackendnode_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qbackendnode.h>
+
#include <Qt3DInput/private/qt3dinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h b/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h
index 8d9ee0617..d6928aced 100644
--- a/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h
+++ b/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/qnodeid.h>
#include <QtCore/qvector.h>
-#include <Qt3DInput/private/qt3dinput_global_p.h>
+#include <Qt3DCore/qnodeid.h>
+
#include <Qt3DInput/private/movingaverage_p.h>
+#include <Qt3DInput/private/qt3dinput_global_p.h>
+#include <Qt3DCore/private/qbackendnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/updateaxisactionjob.cpp b/src/input/backend/updateaxisactionjob.cpp
index 4e990ff0e..03690479a 100644
--- a/src/input/backend/updateaxisactionjob.cpp
+++ b/src/input/backend/updateaxisactionjob.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "updateaxisactionjob_p.h"
+
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/job_common_p.h>
diff --git a/src/input/backend/updateaxisactionjob_p.h b/src/input/backend/updateaxisactionjob_p.h
index ea590a1b2..b65cbec87 100644
--- a/src/input/backend/updateaxisactionjob_p.h
+++ b/src/input/backend/updateaxisactionjob_p.h
@@ -53,6 +53,7 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
+
#include <Qt3DInput/private/handle_types_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractactioninput.cpp b/src/input/frontend/qabstractactioninput.cpp
index f5e9ff33e..5d7af72f8 100644
--- a/src/input/frontend/qabstractactioninput.cpp
+++ b/src/input/frontend/qabstractactioninput.cpp
@@ -37,6 +37,7 @@
****************************************************************************/
#include "qabstractactioninput_p.h"
+
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractactioninput_p.h b/src/input/frontend/qabstractactioninput_p.h
index 6741bc4dc..b7494ee38 100644
--- a/src/input/frontend/qabstractactioninput_p.h
+++ b/src/input/frontend/qabstractactioninput_p.h
@@ -50,7 +50,8 @@
// We mean it.
//
-#include <Qt3DInput/qabstractactioninput.h>
+#include "qabstractactioninput.h"
+
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractaxisinput.cpp b/src/input/frontend/qabstractaxisinput.cpp
index bcce50a33..e3974421a 100644
--- a/src/input/frontend/qabstractaxisinput.cpp
+++ b/src/input/frontend/qabstractaxisinput.cpp
@@ -37,8 +37,9 @@
**
****************************************************************************/
-#include "qabstractaxisinput.h"
#include "qabstractaxisinput_p.h"
+
+#include <Qt3DInput/qabstractaxisinput.h>
#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractaxisinput.h b/src/input/frontend/qabstractaxisinput.h
index b26d3249a..c0a93da31 100644
--- a/src/input/frontend/qabstractaxisinput.h
+++ b/src/input/frontend/qabstractaxisinput.h
@@ -40,9 +40,9 @@
#ifndef QT3DINPUT_QABSTRACTAXISINPUT_H
#define QT3DINPUT_QABSTRACTAXISINPUT_H
+#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/qt3dinput_global.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DInput/qabstractphysicaldevice.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractaxisinput_p.h b/src/input/frontend/qabstractaxisinput_p.h
index f64a140f4..91e02719e 100644
--- a/src/input/frontend/qabstractaxisinput_p.h
+++ b/src/input/frontend/qabstractaxisinput_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/qnodeid.h>
#include <QtCore/qvariant.h>
+#include <Qt3DCore/private/qnode_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qabstractphysicaldevice.cpp b/src/input/frontend/qabstractphysicaldevice.cpp
index 4984b4300..8a0e81e0c 100644
--- a/src/input/frontend/qabstractphysicaldevice.cpp
+++ b/src/input/frontend/qabstractphysicaldevice.cpp
@@ -39,11 +39,13 @@
#include "qabstractphysicaldevice.h"
#include "qabstractphysicaldevice_p.h"
-#include <Qt3DInput/qphysicaldevicecreatedchange.h>
+
#include <Qt3DInput/qaxissetting.h>
+#include <Qt3DInput/qphysicaldevicecreatedchange.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractphysicaldevice_p.h b/src/input/frontend/qabstractphysicaldevice_p.h
index 55e98723c..e2b67a815 100644
--- a/src/input/frontend/qabstractphysicaldevice_p.h
+++ b/src/input/frontend/qabstractphysicaldevice_p.h
@@ -52,11 +52,12 @@
//
#include <Qt3DInput/qt3dinput_global.h>
-#include <Qt3DCore/private/qnode_p.h>
#include <QtCore/qhash.h>
#include <QtCore/qmutex.h>
#include <QtCore/qvector.h>
+
#include <Qt3DInput/private/qt3dinput_global_p.h>
+#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qabstractphysicaldeviceproxy.cpp b/src/input/frontend/qabstractphysicaldeviceproxy.cpp
index 03e59761b..34b7db2a4 100644
--- a/src/input/frontend/qabstractphysicaldeviceproxy.cpp
+++ b/src/input/frontend/qabstractphysicaldeviceproxy.cpp
@@ -39,9 +39,11 @@
#include "qabstractphysicaldeviceproxy_p.h"
#include "qabstractphysicaldeviceproxy_p_p.h"
+
#include <Qt3DInput/qphysicaldevicecreatedchange.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qabstractphysicaldeviceproxy_p.h b/src/input/frontend/qabstractphysicaldeviceproxy_p.h
index 1175f53bb..6d44ad2cd 100644
--- a/src/input/frontend/qabstractphysicaldeviceproxy_p.h
+++ b/src/input/frontend/qabstractphysicaldeviceproxy_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DInput/qabstractphysicaldevice.h>
+
#include <Qt3DInput/private/qt3dinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qaction.cpp b/src/input/frontend/qaction.cpp
index 3a6e6dc4f..1006c0cec 100644
--- a/src/input/frontend/qaction.cpp
+++ b/src/input/frontend/qaction.cpp
@@ -39,12 +39,14 @@
#include "qaction.h"
#include "qaction_p.h"
-#include <Qt3DCore/private/qnode_p.h>
+
+#include <Qt3DInput/qabstractactioninput.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DInput/qabstractactioninput.h>
+
+#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qactioninput.cpp b/src/input/frontend/qactioninput.cpp
index 5bee62cb9..b8db101d8 100644
--- a/src/input/frontend/qactioninput.cpp
+++ b/src/input/frontend/qactioninput.cpp
@@ -38,8 +38,9 @@
#include "qactioninput.h"
#include "qactioninput_p.h"
+
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DInput/QAbstractActionInput>
+#include <Qt3DInput/qabstractactioninput.h>
#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qactioninput.h b/src/input/frontend/qactioninput.h
index 9b06047b2..580afaf2e 100644
--- a/src/input/frontend/qactioninput.h
+++ b/src/input/frontend/qactioninput.h
@@ -40,9 +40,9 @@
#ifndef QT3DINPUT_QACTIONINPUT_H
#define QT3DINPUT_QACTIONINPUT_H
+#include <Qt3DInput/qabstractactioninput.h>
#include <Qt3DInput/qt3dinput_global.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DInput/qabstractactioninput.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qactioninput_p.h b/src/input/frontend/qactioninput_p.h
index d1e9f88dc..74a69d68c 100644
--- a/src/input/frontend/qactioninput_p.h
+++ b/src/input/frontend/qactioninput_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DInput/private/qabstractactioninput_p.h>
#include <QtCore/qvariant.h>
+#include <Qt3DInput/private/qabstractactioninput_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qanalogaxisinput.cpp b/src/input/frontend/qanalogaxisinput.cpp
index 6d50af45c..7b85983e3 100644
--- a/src/input/frontend/qanalogaxisinput.cpp
+++ b/src/input/frontend/qanalogaxisinput.cpp
@@ -39,6 +39,7 @@
#include "qanalogaxisinput.h"
#include "qanalogaxisinput_p.h"
+
#include <Qt3DInput/qabstractphysicaldevice.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qaxis.cpp b/src/input/frontend/qaxis.cpp
index 6b19e43fe..01e28e9cf 100644
--- a/src/input/frontend/qaxis.cpp
+++ b/src/input/frontend/qaxis.cpp
@@ -38,6 +38,7 @@
#include "qaxis.h"
#include "qaxis_p.h"
+
#include <Qt3DInput/qabstractaxisinput.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
diff --git a/src/input/frontend/qaxisaccumulator.cpp b/src/input/frontend/qaxisaccumulator.cpp
index 758faaa37..5f10d81a7 100644
--- a/src/input/frontend/qaxisaccumulator.cpp
+++ b/src/input/frontend/qaxisaccumulator.cpp
@@ -39,6 +39,7 @@
#include "qaxisaccumulator.h"
#include "qaxisaccumulator_p.h"
+
#include <Qt3DInput/qaxis.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
@@ -88,7 +89,7 @@ namespace Qt3DInput {
*/
/*!
- \qmlproperty int Qt3D.Inpit::Axis::value
+ \qmlproperty int Qt3D.Input::Axis::value
\readonly
Holds the value accumulated from the sourceAxis.
@@ -183,11 +184,13 @@ QAxisAccumulator::SourceAxisType QAxisAccumulator::sourceAxisType() const
/*!
\qmlproperty real Qt3D.Input::AxisAccumulator::value
- The accumulated (integrated) value.
+ The amount to scale the axis value by when accumulating. This can be
+ thought of as the maximum velocity or acceleration the axis can
+ control.
*/
/*!
- \return the accumulated (integrated) value.
+ Returns the accumulated (integrated) value.
*/
float QAxisAccumulator::value() const
{
@@ -208,14 +211,6 @@ float QAxisAccumulator::velocity() const
}
/*!
- \qmlproperty real Qt3D.Input::AxisAccumulator::value
-
- The amount to scale the axis value by when accumulating. This can be
- thought of as the maximum velocity or acceleration the axis can
- control.
- */
-
-/*!
The amount to scale the axis value by when accumulating. This can be
thought of as the maximum velocity or acceleration the axis can
control.
@@ -254,7 +249,7 @@ void QAxisAccumulator::setSourceAxis(QAxis *sourceAxis)
}
/*!
- Sets how the accumulator treats the values originating from the source axis.
+ Sets how the accumulator treats the values originating from the \a sourceAxisType.
*/
void QAxisAccumulator::setSourceAxisType(QAxisAccumulator::SourceAxisType sourceAxisType)
{
diff --git a/src/input/frontend/qaxisaccumulator_p.h b/src/input/frontend/qaxisaccumulator_p.h
index 532f01b6b..a936f54aa 100644
--- a/src/input/frontend/qaxisaccumulator_p.h
+++ b/src/input/frontend/qaxisaccumulator_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DInput/qaxisaccumulator.h>
+#include <Qt3DCore/private/qcomponent_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qaxissetting.cpp b/src/input/frontend/qaxissetting.cpp
index 987cd246a..8f1a8d797 100644
--- a/src/input/frontend/qaxissetting.cpp
+++ b/src/input/frontend/qaxissetting.cpp
@@ -39,6 +39,7 @@
#include "qaxissetting.h"
#include "qaxissetting_p.h"
+
#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qaxissetting.h b/src/input/frontend/qaxissetting.h
index 483c6c2a0..b3d244e15 100644
--- a/src/input/frontend/qaxissetting.h
+++ b/src/input/frontend/qaxissetting.h
@@ -40,9 +40,8 @@
#ifndef QT3DINPUT_QAXISSETTING_H
#define QT3DINPUT_QAXISSETTING_H
-#include <Qt3DCore/qnode.h>
#include <Qt3DInput/qt3dinput_global.h>
-
+#include <Qt3DCore/qnode.h>
#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qbuttonaxisinput.cpp b/src/input/frontend/qbuttonaxisinput.cpp
index e6bfe4f8c..fb74b8efd 100644
--- a/src/input/frontend/qbuttonaxisinput.cpp
+++ b/src/input/frontend/qbuttonaxisinput.cpp
@@ -39,6 +39,7 @@
#include "qbuttonaxisinput.h"
#include "qbuttonaxisinput_p.h"
+
#include <Qt3DInput/qabstractphysicaldevice.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qgamepadinput.cpp b/src/input/frontend/qgamepadinput.cpp
index faf62ae88..a0efecfc0 100644
--- a/src/input/frontend/qgamepadinput.cpp
+++ b/src/input/frontend/qgamepadinput.cpp
@@ -35,10 +35,11 @@
****************************************************************************/
#include "qgamepadinput_p.h"
-#include "qabstractphysicaldevice_p.h"
-#include <QGamepadManager>
-#include <QMetaEnum>
+#include <QtCore/QMetaEnum>
+#include <QtGamepad/QGamepadManager>
+
+#include <Qt3DInput/private/qabstractphysicaldevice_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qgamepadinput_p.h b/src/input/frontend/qgamepadinput_p.h
index c1990030e..c064f1c94 100644
--- a/src/input/frontend/qgamepadinput_p.h
+++ b/src/input/frontend/qgamepadinput_p.h
@@ -49,6 +49,7 @@
//
#include <Qt3DInput/qabstractphysicaldevice.h>
+
#include <Qt3DInput/private/qt3dinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qgenericinputdevice.cpp b/src/input/frontend/qgenericinputdevice.cpp
index 8c4b44992..84a1699fc 100644
--- a/src/input/frontend/qgenericinputdevice.cpp
+++ b/src/input/frontend/qgenericinputdevice.cpp
@@ -39,7 +39,7 @@
#include "qgenericinputdevice_p.h"
-#include "qabstractphysicaldevice_p.h"
+#include <Qt3DInput/private/qabstractphysicaldevice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qgenericinputdevice_p.h b/src/input/frontend/qgenericinputdevice_p.h
index f4af03975..b46eada67 100644
--- a/src/input/frontend/qgenericinputdevice_p.h
+++ b/src/input/frontend/qgenericinputdevice_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DInput/qabstractphysicaldevice.h>
+
#include <Qt3DInput/private/qt3dinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputaspect.cpp b/src/input/frontend/qinputaspect.cpp
index 5c5fd3b06..a3bf58f08 100644
--- a/src/input/frontend/qinputaspect.cpp
+++ b/src/input/frontend/qinputaspect.cpp
@@ -39,56 +39,60 @@
#include "qinputaspect.h"
#include "qinputaspect_p.h"
-#include "inputhandler_p.h"
-#include "buttonaxisinput_p.h"
-#include "keyboarddevice_p.h"
-#include "keyboardhandler_p.h"
-#include "mousedevice_p.h"
-#include "mousehandler_p.h"
-#include <Qt3DInput/qkeyboarddevice.h>
-#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DInput/qmousedevice.h>
-#include <Qt3DInput/qmousehandler.h>
-#include <Qt3DInput/private/qinputdeviceintegration_p.h>
-#include <Qt3DInput/qinputsettings.h>
-#include <Qt3DInput/private/qgenericinputdevice_p.h>
-#include <Qt3DInput/private/qinputdeviceintegrationfactory_p.h>
-#include <Qt3DCore/private/qservicelocator_p.h>
-#include <Qt3DCore/private/qeventfilterservice_p.h>
-#include <QDir>
-#include <QLibrary>
-#include <QLibraryInfo>
-#include <QPluginLoader>
-#include <Qt3DInput/qaxis.h>
-#include <Qt3DInput/qaxisaccumulator.h>
+#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/qaction.h>
-#include <Qt3DInput/qaxissetting.h>
#include <Qt3DInput/qactioninput.h>
#include <Qt3DInput/qanalogaxisinput.h>
+#include <Qt3DInput/qaxis.h>
+#include <Qt3DInput/qaxisaccumulator.h>
+#include <Qt3DInput/qaxissetting.h>
#include <Qt3DInput/qbuttonaxisinput.h>
#include <Qt3DInput/qinputchord.h>
#include <Qt3DInput/qinputsequence.h>
+#include <Qt3DInput/qinputsettings.h>
+#include <Qt3DInput/qkeyboarddevice.h>
+#include <Qt3DInput/qkeyboardhandler.h>
#include <Qt3DInput/qlogicaldevice.h>
-#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p.h>
+#include <Qt3DInput/qmousedevice.h>
+#include <Qt3DInput/qmousehandler.h>
+#include <QtCore/QDir>
+
+#if QT_CONFIG(library)
+#include <QtCore/QLibrary>
+#endif
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QPluginLoader>
+
+#include <Qt3DInput/private/action_p.h>
+#include <Qt3DInput/private/actioninput_p.h>
#include <Qt3DInput/private/axis_p.h>
#include <Qt3DInput/private/axisaccumulator_p.h>
-#include <Qt3DInput/private/action_p.h>
+#include <Qt3DInput/private/axisaccumulatorjob_p.h>
#include <Qt3DInput/private/axissetting_p.h>
-#include <Qt3DInput/private/actioninput_p.h>
-#include <Qt3DInput/private/inputchord_p.h>
-#include <Qt3DInput/private/inputsequence_p.h>
-#include <Qt3DInput/private/logicaldevice_p.h>
+#include <Qt3DInput/private/buttonaxisinput_p.h>
+#include <Qt3DInput/private/eventsourcesetterhelper_p.h>
+#include <Qt3DInput/private/genericdevicebackendnode_p.h>
#include <Qt3DInput/private/inputbackendnodefunctor_p.h>
+#include <Qt3DInput/private/inputchord_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
-#include <Qt3DInput/private/updateaxisactionjob_p.h>
-#include <Qt3DInput/private/keyboardmousegenericdeviceintegration_p.h>
-#include <Qt3DInput/private/genericdevicebackendnode_p.h>
+#include <Qt3DInput/private/inputsequence_p.h>
#include <Qt3DInput/private/inputsettings_p.h>
-#include <Qt3DInput/private/eventsourcesetterhelper_p.h>
+#include <Qt3DInput/private/keyboarddevice_p.h>
+#include <Qt3DInput/private/keyboardhandler_p.h>
+#include <Qt3DInput/private/keyboardmousegenericdeviceintegration_p.h>
#include <Qt3DInput/private/loadproxydevicejob_p.h>
-#include <Qt3DInput/private/axisaccumulatorjob_p.h>
+#include <Qt3DInput/private/logicaldevice_p.h>
+#include <Qt3DInput/private/mousedevice_p.h>
+#include <Qt3DInput/private/mousehandler_p.h>
+#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p.h>
+#include <Qt3DInput/private/qgenericinputdevice_p.h>
+#include <Qt3DInput/private/qinputdeviceintegration_p.h>
+#include <Qt3DInput/private/qinputdeviceintegrationfactory_p.h>
+#include <Qt3DInput/private/updateaxisactionjob_p.h>
+#include <Qt3DCore/private/qeventfilterservice_p.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
#ifdef HAVE_QGAMEPAD
# include <Qt3DInput/private/qgamepadinput_p.h>
diff --git a/src/input/frontend/qinputaspect_p.h b/src/input/frontend/qinputaspect_p.h
index 35a4ffa02..bcdd8d4ed 100644
--- a/src/input/frontend/qinputaspect_p.h
+++ b/src/input/frontend/qinputaspect_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qabstractaspect_p.h>
+#include <Qt3DCore/private/qabstractaspect_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputchord.cpp b/src/input/frontend/qinputchord.cpp
index 372c61990..7c986f297 100644
--- a/src/input/frontend/qinputchord.cpp
+++ b/src/input/frontend/qinputchord.cpp
@@ -38,8 +38,9 @@
#include "qinputchord.h"
#include "qinputchord_p.h"
-#include <Qt3DCore/qnodecreatedchange.h>
+
#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
diff --git a/src/input/frontend/qinputchord.h b/src/input/frontend/qinputchord.h
index f3e603eb5..1fc69bd1b 100644
--- a/src/input/frontend/qinputchord.h
+++ b/src/input/frontend/qinputchord.h
@@ -40,9 +40,9 @@
#ifndef QT3DINPUT_QINPUTCHORD_H
#define QT3DINPUT_QINPUTCHORD_H
+#include <Qt3DInput/qabstractactioninput.h>
#include <Qt3DInput/qt3dinput_global.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DInput/qabstractactioninput.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputchord_p.h b/src/input/frontend/qinputchord_p.h
index bd49f93d6..37cbbd9f2 100644
--- a/src/input/frontend/qinputchord_p.h
+++ b/src/input/frontend/qinputchord_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DInput/private/qabstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DInput/private/qabstractactioninput_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qinputdeviceintegration_p.h b/src/input/frontend/qinputdeviceintegration_p.h
index 248243fa2..a066d7629 100644
--- a/src/input/frontend/qinputdeviceintegration_p.h
+++ b/src/input/frontend/qinputdeviceintegration_p.h
@@ -51,12 +51,12 @@
// We mean it.
//
-#include <QObject>
#include <Qt3DInput/qt3dinput_global.h>
-#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
-
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
+#include <QtCore/QObject>
+
+#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputdeviceintegration_p_p.h b/src/input/frontend/qinputdeviceintegration_p_p.h
index c8557eac5..31eea4cdf 100644
--- a/src/input/frontend/qinputdeviceintegration_p_p.h
+++ b/src/input/frontend/qinputdeviceintegration_p_p.h
@@ -51,8 +51,8 @@
// We mean it.
//
-#include <private/qobject_p.h>
-#include <private/qt3dinput_global_p.h>
+#include <Qt3DInput/private/qt3dinput_global_p.h>
+#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputdeviceintegrationfactory.cpp b/src/input/frontend/qinputdeviceintegrationfactory.cpp
index 22e93294e..957b33542 100644
--- a/src/input/frontend/qinputdeviceintegrationfactory.cpp
+++ b/src/input/frontend/qinputdeviceintegrationfactory.cpp
@@ -38,11 +38,13 @@
****************************************************************************/
#include "qinputdeviceintegrationfactory_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+
#include <Qt3DInput/private/qinputdeviceintegration_p.h>
#include <Qt3DInput/private/qinputdeviceplugin_p.h>
#include <QtCore/private/qfactoryloader_p.h>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDir>
QT_BEGIN_NAMESPACE
@@ -72,6 +74,7 @@ QStringList QInputDeviceIntegrationFactory::keys(const QString &pluginPath)
list.append(loader()->keyMap().values());
return list;
#else
+ Q_UNUSED(pluginPath);
return QStringList();
#endif
}
@@ -86,6 +89,10 @@ QInputDeviceIntegration *QInputDeviceIntegrationFactory::create(const QString &n
}
if (QInputDeviceIntegration *ret = qLoadPlugin<QInputDeviceIntegration, QInputDevicePlugin>(loader(), name, args))
return ret;
+#else
+ Q_UNUSED(name);
+ Q_UNUSED(args);
+ Q_UNUSED(pluginPath);
#endif
return nullptr;
}
diff --git a/src/input/frontend/qinputdeviceplugin_p.h b/src/input/frontend/qinputdeviceplugin_p.h
index ca77441af..a2f93eb3f 100644
--- a/src/input/frontend/qinputdeviceplugin_p.h
+++ b/src/input/frontend/qinputdeviceplugin_p.h
@@ -52,8 +52,8 @@
//
#include <QtCore/QObject>
-#include <QtCore/QtPlugin>
#include <QtCore/QFactoryInterface>
+#include <QtCore/QtPlugin>
#include <Qt3DInput/private/qt3dinput_global_p.h>
diff --git a/src/input/frontend/qinputsequence.cpp b/src/input/frontend/qinputsequence.cpp
index 99eff289b..766674840 100644
--- a/src/input/frontend/qinputsequence.cpp
+++ b/src/input/frontend/qinputsequence.cpp
@@ -38,13 +38,15 @@
#include "qinputsequence.h"
#include "qinputsequence_p.h"
-#include <Qt3DCore/private/qnode_p.h>
-#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DInput/qabstractphysicaldevice.h>
+
#include <Qt3DInput/qabstractactioninput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
@@ -74,7 +76,7 @@ QInputSequencePrivate::QInputSequencePrivate()
Represents a set of QAbstractActionInput's that must be triggerd one after the other.
- The following example shows a chord that will be triggered by pressing the A and S keys together with a tolerence of 10 miliseconds between presses.
+ The following example shows a chord that will be triggered by pressing the A and S keys together with a tolerance of 10 miliseconds between presses.
\qml
InputChord {
tolerance: 10
diff --git a/src/input/frontend/qinputsequence.h b/src/input/frontend/qinputsequence.h
index 2baeb40b8..6e08bc649 100644
--- a/src/input/frontend/qinputsequence.h
+++ b/src/input/frontend/qinputsequence.h
@@ -40,9 +40,9 @@
#ifndef QT3DINPUT_QINPUTSEQUENCE_H
#define QT3DINPUT_QINPUTSEQUENCE_H
+#include <Qt3DInput/qabstractactioninput.h>
#include <Qt3DInput/qt3dinput_global.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DInput/qabstractactioninput.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputsequence_p.h b/src/input/frontend/qinputsequence_p.h
index 3290e4dcc..b2807b2d5 100644
--- a/src/input/frontend/qinputsequence_p.h
+++ b/src/input/frontend/qinputsequence_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DInput/private/qabstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DInput/private/qabstractactioninput_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qinputsettings.cpp b/src/input/frontend/qinputsettings.cpp
index 47c835cea..ccc53e47b 100644
--- a/src/input/frontend/qinputsettings.cpp
+++ b/src/input/frontend/qinputsettings.cpp
@@ -39,6 +39,7 @@
#include "qinputsettings.h"
#include "qinputsettings_p.h"
+
#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputsettings.h b/src/input/frontend/qinputsettings.h
index 9e0ea7b6b..4f4d746f6 100644
--- a/src/input/frontend/qinputsettings.h
+++ b/src/input/frontend/qinputsettings.h
@@ -40,8 +40,8 @@
#ifndef QT3DINPUT_QINPUTSETTINGS_H
#define QT3DINPUT_QINPUTSETTINGS_H
-#include <Qt3DCore/qcomponent.h>
#include <Qt3DInput/qt3dinput_global.h>
+#include <Qt3DCore/qcomponent.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qinputsettings_p.h b/src/input/frontend/qinputsettings_p.h
index 13757ac0b..584e597ba 100644
--- a/src/input/frontend/qinputsettings_p.h
+++ b/src/input/frontend/qinputsettings_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qcomponent_p.h>
#include <QtCore/qpointer.h>
+#include <Qt3DCore/private/qcomponent_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qkeyboarddevice.cpp b/src/input/frontend/qkeyboarddevice.cpp
index b2c0975ee..257a5be8c 100644
--- a/src/input/frontend/qkeyboarddevice.cpp
+++ b/src/input/frontend/qkeyboarddevice.cpp
@@ -39,10 +39,12 @@
#include "qkeyboarddevice.h"
#include "qkeyboarddevice_p.h"
-#include "qkeyboardhandler.h"
-#include <Qt3DCore/private/qscene_p.h>
+
+#include <Qt3DInput/qkeyboardhandler.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qscene_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qkeyboarddevice.h b/src/input/frontend/qkeyboarddevice.h
index a86687769..a0baf255e 100644
--- a/src/input/frontend/qkeyboarddevice.h
+++ b/src/input/frontend/qkeyboarddevice.h
@@ -40,9 +40,9 @@
#ifndef QT3DINPUT_INPUT_QKEYBOARDDEVICE_H
#define QT3DINPUT_INPUT_QKEYBOARDDEVICE_H
+#include <Qt3DInput/QKeyboardHandler>
#include <Qt3DInput/qt3dinput_global.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DInput/QKeyboardHandler>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qkeyboarddevice_p.h b/src/input/frontend/qkeyboarddevice_p.h
index e05f7549b..8399b061b 100644
--- a/src/input/frontend/qkeyboarddevice_p.h
+++ b/src/input/frontend/qkeyboarddevice_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <private/qabstractphysicaldevice_p.h>
#include <Qt3DCore/qnodeid.h>
#include <QtCore/qhash.h>
#include <QtCore/qstring.h>
+#include <Qt3DInput/private/qabstractphysicaldevice_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qkeyboardhandler.cpp b/src/input/frontend/qkeyboardhandler.cpp
index e45609f74..5854a047d 100644
--- a/src/input/frontend/qkeyboardhandler.cpp
+++ b/src/input/frontend/qkeyboardhandler.cpp
@@ -39,7 +39,8 @@
#include "qkeyboardhandler.h"
#include "qkeyboardhandler_p.h"
-#include "qkeyboarddevice.h"
+
+#include <Qt3DInput/qkeyboarddevice.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qkeyboardhandler_p.h b/src/input/frontend/qkeyboardhandler_p.h
index 339d36d26..9de55f9d0 100644
--- a/src/input/frontend/qkeyboardhandler_p.h
+++ b/src/input/frontend/qkeyboardhandler_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qcomponent_p.h>
+#include <Qt3DCore/private/qcomponent_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qkeyevent.h b/src/input/frontend/qkeyevent.h
index 0978a45e7..e028438ce 100644
--- a/src/input/frontend/qkeyevent.h
+++ b/src/input/frontend/qkeyevent.h
@@ -40,9 +40,9 @@
#ifndef QT3DINPUT_QKEYEVENT_H
#define QT3DINPUT_QKEYEVENT_H
-#include <QObject>
-#include <QtGui/QKeyEvent>
#include <Qt3DInput/qt3dinput_global.h>
+#include <QtCore/QObject>
+#include <QtGui/QKeyEvent>
QT_BEGIN_NAMESPACE
@@ -78,7 +78,9 @@ public:
inline bool isAccepted() const { return m_event.isAccepted(); }
inline void setAccepted(bool accepted) { m_event.setAccepted(accepted); }
inline QEvent::Type type() const { return m_event.type(); }
+#if QT_CONFIG(shortcut)
Q_INVOKABLE bool matches(QKeySequence::StandardKey key_) const { return m_event.matches(key_); }
+#endif
private:
QT_PREPEND_NAMESPACE(QKeyEvent) m_event;
diff --git a/src/input/frontend/qlogicaldevice.cpp b/src/input/frontend/qlogicaldevice.cpp
index 4794431b8..1e7033962 100644
--- a/src/input/frontend/qlogicaldevice.cpp
+++ b/src/input/frontend/qlogicaldevice.cpp
@@ -39,12 +39,13 @@
#include "qlogicaldevice.h"
#include "qlogicaldevice_p.h"
-#include <Qt3DInput/qaction.h>
-#include <Qt3DInput/qaxis.h>
+
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DInput/qaction.h>
+#include <Qt3DInput/qaxis.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qlogicaldevice_p.h b/src/input/frontend/qlogicaldevice_p.h
index c8940e6b9..e04d238c5 100644
--- a/src/input/frontend/qlogicaldevice_p.h
+++ b/src/input/frontend/qlogicaldevice_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/private/qcomponent_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/input/frontend/qmousedevice.cpp b/src/input/frontend/qmousedevice.cpp
index 744d289f3..b5123533f 100644
--- a/src/input/frontend/qmousedevice.cpp
+++ b/src/input/frontend/qmousedevice.cpp
@@ -39,8 +39,9 @@
#include "qmousedevice.h"
#include "qmousedevice_p.h"
-#include <Qt3DInput/qphysicaldevicecreatedchange.h>
+
#include <Qt3DInput/qmouseevent.h>
+#include <Qt3DInput/qphysicaldevicecreatedchange.h>
#include <Qt3DCore/qentity.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qmousedevice.h b/src/input/frontend/qmousedevice.h
index 620c41edc..93ee99256 100644
--- a/src/input/frontend/qmousedevice.h
+++ b/src/input/frontend/qmousedevice.h
@@ -40,8 +40,8 @@
#ifndef QT3DINPUT_QMOUSEDEVICE_H
#define QT3DINPUT_QMOUSEDEVICE_H
-#include <Qt3DInput/qt3dinput_global.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DInput/qt3dinput_global.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qmousedevice_p.h b/src/input/frontend/qmousedevice_p.h
index 92718dffa..49c1c6191 100644
--- a/src/input/frontend/qmousedevice_p.h
+++ b/src/input/frontend/qmousedevice_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qabstractphysicaldevice_p.h>
+#include <Qt3DInput/private/qabstractphysicaldevice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/frontend/qmouseevent.cpp b/src/input/frontend/qmouseevent.cpp
index b1574f623..62f7a097e 100644
--- a/src/input/frontend/qmouseevent.cpp
+++ b/src/input/frontend/qmouseevent.cpp
@@ -455,6 +455,7 @@ QMouseEvent::Modifiers QMouseEvent::modifiers() const
* Returns the QEvent::Type of the event.
*/
+#if QT_CONFIG(wheelevent)
/*!
* Constructs a new QWheelEvent instance from the QWheelEvent \a e.
*/
@@ -497,6 +498,7 @@ QWheelEvent::Modifiers QWheelEvent::modifiers() const
return QWheelEvent::NoModifier;
}
}
+#endif // QT_CONFIG(wheelevent)
} // namespace Qt3DInput
diff --git a/src/input/frontend/qmouseevent.h b/src/input/frontend/qmouseevent.h
index c1051dc1f..63786ac28 100644
--- a/src/input/frontend/qmouseevent.h
+++ b/src/input/frontend/qmouseevent.h
@@ -41,9 +41,9 @@
#define QT3DINPUT_QMOUSEEVENT_H
#include <Qt3DInput/qt3dinput_global.h>
-#include <QObject>
+#include <QtCore/QtGlobal>
+#include <QtCore/QObject>
#include <QtGui/QMouseEvent>
-#include <QtGlobal>
QT_BEGIN_NAMESPACE
@@ -85,7 +85,13 @@ public:
inline int x() const { return m_event.x(); }
inline int y() const { return m_event.y(); }
- inline bool wasHeld() const { return static_cast<Qt::GestureType>(m_event.type()) == Qt::TapAndHoldGesture; }
+ inline bool wasHeld() const {
+#if QT_CONFIG(gestures)
+ return static_cast<Qt::GestureType>(m_event.type()) == Qt::TapAndHoldGesture;
+#else
+ return false;
+#endif
+ }
Buttons button() const;
int buttons() const;
Modifiers modifiers() const;
@@ -100,6 +106,7 @@ private:
typedef QSharedPointer<QMouseEvent> QMouseEventPtr;
+#if QT_CONFIG(wheelevent)
class QT3DINPUTSHARED_EXPORT QWheelEvent : public QObject
{
Q_OBJECT
@@ -148,12 +155,16 @@ private:
};
typedef QSharedPointer<QWheelEvent> QWheelEventPtr;
+#endif
} // namespace Qt3DInput
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Qt3DInput::QMouseEvent*) // LCOV_EXCL_LINE
+
+#if QT_CONFIG(wheelevent)
Q_DECLARE_METATYPE(Qt3DInput::QWheelEvent*) // LCOV_EXCL_LINE
+#endif
#endif // QT3DINPUT_QMOUSEEVENT_H
diff --git a/src/input/frontend/qmousehandler.cpp b/src/input/frontend/qmousehandler.cpp
index 75e68b819..419052d8a 100644
--- a/src/input/frontend/qmousehandler.cpp
+++ b/src/input/frontend/qmousehandler.cpp
@@ -39,10 +39,11 @@
#include "qmousehandler.h"
#include "qmousehandler_p.h"
-#include "qmousedevice.h"
-#include "qmouseevent.h"
+
+#include <Qt3DInput/qmousedevice.h>
+#include <Qt3DInput/qmouseevent.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <QTimer>
+#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
@@ -82,9 +83,11 @@ void QMouseHandlerPrivate::mouseEvent(const QMouseEventPtr &event)
m_pressAndHoldTimer->stop();
emit q->released(event.data());
break;
+#if QT_CONFIG(gestures)
case Qt::TapGesture:
emit q->clicked(event.data());
break;
+#endif
case QEvent::MouseButtonDblClick:
emit q->doubleClicked(event.data());
break;
@@ -310,9 +313,11 @@ void QMouseHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
if (e->propertyName() == QByteArrayLiteral("mouse")) {
QMouseEventPtr ev = e->value().value<QMouseEventPtr>();
d->mouseEvent(ev);
+#if QT_CONFIG(wheelevent)
} else if (e->propertyName() == QByteArrayLiteral("wheel")) {
QWheelEventPtr ev = e->value().value<QWheelEventPtr>();
emit wheel(ev.data());
+#endif
}
}
}
diff --git a/src/input/frontend/qmousehandler.h b/src/input/frontend/qmousehandler.h
index 750ed394d..ef4267c5c 100644
--- a/src/input/frontend/qmousehandler.h
+++ b/src/input/frontend/qmousehandler.h
@@ -82,7 +82,9 @@ Q_SIGNALS:
void pressAndHold(Qt3DInput::QMouseEvent *mouse);
void positionChanged(Qt3DInput::QMouseEvent *mouse);
+#if QT_CONFIG(wheelevent)
void wheel(Qt3DInput::QWheelEvent *wheel);
+#endif
protected:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
diff --git a/src/input/frontend/qmousehandler_p.h b/src/input/frontend/qmousehandler_p.h
index 2d82ca1ad..bb82334a0 100644
--- a/src/input/frontend/qmousehandler_p.h
+++ b/src/input/frontend/qmousehandler_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <private/qcomponent_p.h>
#include <Qt3DInput/qmouseevent.h>
+#include <Qt3DCore/private/qcomponent_p.h>
+
QT_BEGIN_NAMESPACE
class QTimer;
diff --git a/src/input/frontend/qphysicaldevicecreatedchange.cpp b/src/input/frontend/qphysicaldevicecreatedchange.cpp
index 17edde76a..2f2452187 100644
--- a/src/input/frontend/qphysicaldevicecreatedchange.cpp
+++ b/src/input/frontend/qphysicaldevicecreatedchange.cpp
@@ -36,10 +36,12 @@
#include "qphysicaldevicecreatedchange.h"
#include "qphysicaldevicecreatedchange_p.h"
+
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/qaxissetting.h>
#include <Qt3DCore/qnodeid.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
diff --git a/src/logic/callbackjob.cpp b/src/logic/callbackjob.cpp
index bc974c792..5c04d8838 100644
--- a/src/logic/callbackjob.cpp
+++ b/src/logic/callbackjob.cpp
@@ -38,8 +38,9 @@
****************************************************************************/
#include "callbackjob_p.h"
-#include "manager_p.h"
-#include "job_common_p.h"
+
+#include <Qt3DLogic/private/job_common_p.h>
+#include <Qt3DLogic/private/manager_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/logic/executor.cpp b/src/logic/executor.cpp
index 74267379e..6134e801e 100644
--- a/src/logic/executor.cpp
+++ b/src/logic/executor.cpp
@@ -38,11 +38,13 @@
****************************************************************************/
#include "executor_p.h"
+
#include <Qt3DLogic/qframeaction.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DCore/private/qscene_p.h>
#include <QtCore/qsemaphore.h>
+#include <Qt3DCore/private/qscene_p.h>
+
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -94,7 +96,7 @@ void Executor::processLogicFrameUpdates(float dt)
const QVector<QNode *> nodes = m_scene->lookupNodes(m_nodeIds);
for (QNode *node : nodes) {
QFrameAction *frameAction = qobject_cast<QFrameAction *>(node);
- if (frameAction)
+ if (frameAction && frameAction->isEnabled())
frameAction->onTriggered(dt);
}
diff --git a/src/logic/handler.cpp b/src/logic/handler.cpp
index 777637640..884d5f582 100644
--- a/src/logic/handler.cpp
+++ b/src/logic/handler.cpp
@@ -38,10 +38,12 @@
****************************************************************************/
#include "handler_p.h"
-#include "manager_p.h"
-#include "managers_p.h"
+
#include <Qt3DCore/qnode.h>
+#include <Qt3DLogic/private/manager_p.h>
+#include <Qt3DLogic/private/managers_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DLogic {
diff --git a/src/logic/manager.cpp b/src/logic/manager.cpp
index 7f0a6b4eb..7b654ccd4 100644
--- a/src/logic/manager.cpp
+++ b/src/logic/manager.cpp
@@ -38,15 +38,16 @@
****************************************************************************/
#include "manager_p.h"
-#include "qlogicaspect.h"
+
+#include <Qt3DLogic/qlogicaspect.h>
+#include <QtCore/QDebug>
+#include <QtCore/QThread>
+#include <QtCore/qcoreapplication.h>
+
#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DLogic/private/executor_p.h>
#include <Qt3DLogic/private/managers_p.h>
-#include <QtCore/qcoreapplication.h>
-
-#include <QDebug>
-#include <QThread>
QT_BEGIN_NAMESPACE
diff --git a/src/logic/manager_p.h b/src/logic/manager_p.h
index 58e6e655b..39c0b5342 100644
--- a/src/logic/manager_p.h
+++ b/src/logic/manager_p.h
@@ -52,12 +52,13 @@
//
#include <Qt3DLogic/qt3dlogic_global.h>
-#include <Qt3DLogic/private/handle_types_p.h>
#include <Qt3DCore/qnodeid.h>
#include <QtCore/qmutex.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qsemaphore.h>
+#include <Qt3DLogic/private/handle_types_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DLogic {
diff --git a/src/logic/managers_p.h b/src/logic/managers_p.h
index b09104850..6194d260a 100644
--- a/src/logic/managers_p.h
+++ b/src/logic/managers_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <QtGlobal>
+#include <QtCore/QtGlobal>
+
+#include <Qt3DCore/private/qresourcemanager_p.h>
#include <Qt3DLogic/private/handle_types_p.h>
#include <Qt3DLogic/private/handler_p.h>
-#include <Qt3DCore/private/qresourcemanager_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/logic/qframeaction.cpp b/src/logic/qframeaction.cpp
index fa4cefe06..f6ae70516 100644
--- a/src/logic/qframeaction.cpp
+++ b/src/logic/qframeaction.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qframeaction.h"
+
#include "qframeaction_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/logic/qframeaction_p.h b/src/logic/qframeaction_p.h
index 17155ffd3..a83efe77a 100644
--- a/src/logic/qframeaction_p.h
+++ b/src/logic/qframeaction_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <private/qcomponent_p.h>
+#include <Qt3DCore/private/qcomponent_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/logic/qlogicaspect.cpp b/src/logic/qlogicaspect.cpp
index 369410585..04add1408 100644
--- a/src/logic/qlogicaspect.cpp
+++ b/src/logic/qlogicaspect.cpp
@@ -37,21 +37,22 @@
**
****************************************************************************/
+
#include "qlogicaspect.h"
#include "qlogicaspect_p.h"
-#include "executor_p.h"
-#include "handler_p.h"
-#include "manager_p.h"
-#include "qframeaction.h"
+#include <Qt3DLogic/qframeaction.h>
#include <Qt3DCore/qnode.h>
+#include <QtCore/QThread>
+#include <QtGui/QWindow>
+
+#include <Qt3DLogic/private/executor_p.h>
+#include <Qt3DLogic/private/handler_p.h>
+#include <Qt3DLogic/private/manager_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
-#include <QThread>
-#include <QWindow>
-
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -121,7 +122,7 @@ QVector<QAspectJobPtr> QLogicAspect::jobsToExecute(qint64 time)
d->m_manager->setDeltaTime(dt);
d->m_time = time;
- // Create jobs that will get exectued by the threadpool
+ // Create jobs that will get executed by the threadpool
QVector<QAspectJobPtr> jobs;
jobs.append(d->m_callbackJob);
return jobs;
diff --git a/src/logic/qlogicaspect_p.h b/src/logic/qlogicaspect_p.h
index 052fdb244..ee7131a3e 100644
--- a/src/logic/qlogicaspect_p.h
+++ b/src/logic/qlogicaspect_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
+#include <QtCore/qsharedpointer.h>
+
#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DLogic/private/callbackjob_p.h>
-#include <QtCore/qsharedpointer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/geometryloaders/default/basegeometryloader.cpp b/src/plugins/geometryloaders/default/basegeometryloader.cpp
index 687c39e6a..2943eec2b 100644
--- a/src/plugins/geometryloaders/default/basegeometryloader.cpp
+++ b/src/plugins/geometryloaders/default/basegeometryloader.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(BaseGeometryLoaderLog, "Qt3D.BaseGeometryLoader")
+Q_LOGGING_CATEGORY(BaseGeometryLoaderLog, "Qt3D.BaseGeometryLoader", QtWarningMsg)
BaseGeometryLoader::BaseGeometryLoader()
: m_loadTextureCoords(true)
diff --git a/src/plugins/geometryloaders/default/basegeometryloader_p.h b/src/plugins/geometryloaders/default/basegeometryloader_p.h
index 56bdb23a9..fb1ffc6b0 100644
--- a/src/plugins/geometryloaders/default/basegeometryloader_p.h
+++ b/src/plugins/geometryloaders/default/basegeometryloader_p.h
@@ -154,6 +154,13 @@ struct FaceIndices
};
QT3D_DECLARE_TYPEINFO(Qt3DRender, FaceIndices, Q_PRIMITIVE_TYPE)
+struct ByteArraySplitterEntry
+{
+ int start;
+ int size;
+};
+QT3D_DECLARE_TYPEINFO(Qt3DRender, ByteArraySplitterEntry, Q_PRIMITIVE_TYPE)
+
/*
* A helper class to split a QByteArray and access its sections without
* additional memory allocations.
@@ -169,7 +176,7 @@ public:
for (auto it = begin; it != end; ++it) {
if (*it == delimiter) {
if (position > lastPosition || splitBehavior == QString::KeepEmptyParts) { // skip multiple consecutive delimiters
- const Entry entry = { lastPosition, position - lastPosition };
+ const ByteArraySplitterEntry entry = { lastPosition, position - lastPosition };
m_entries.append(entry);
}
lastPosition = position + 1;
@@ -178,7 +185,7 @@ public:
++position;
}
- const Entry entry = { lastPosition, position - lastPosition };
+ const ByteArraySplitterEntry entry = { lastPosition, position - lastPosition };
m_entries.append(entry);
}
@@ -212,17 +219,10 @@ public:
return ByteArraySplitter(m_input + m_entries[index].start, m_input + m_entries[index].start + m_entries[index].size, delimiter, splitBehavior);
}
- struct Entry
- {
- int start;
- int size;
- };
-
private:
- QVarLengthArray<Entry, 16> m_entries;
+ QVarLengthArray<ByteArraySplitterEntry, 16> m_entries;
const char *m_input;
};
-QT3D_DECLARE_TYPEINFO(Qt3DRender, ByteArraySplitter::Entry, Q_PRIMITIVE_TYPE)
} // namespace Qt3DRender
diff --git a/src/plugins/geometryloaders/default/objgeometryloader.cpp b/src/plugins/geometryloaders/default/objgeometryloader.cpp
index ad1bde7d4..b1fb1f931 100644
--- a/src/plugins/geometryloaders/default/objgeometryloader.cpp
+++ b/src/plugins/geometryloaders/default/objgeometryloader.cpp
@@ -40,12 +40,13 @@
#include "objgeometryloader.h"
#include <QtCore/QLoggingCategory>
+#include <QtCore/QRegularExpression>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(ObjGeometryLoaderLog, "Qt3D.ObjGeometryLoader")
+Q_LOGGING_CATEGORY(ObjGeometryLoaderLog, "Qt3D.ObjGeometryLoader", QtWarningMsg)
static void addFaceVertex(const FaceIndices &faceIndices,
QVector<FaceIndices>& faceIndexVector,
@@ -77,7 +78,7 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh)
int normalsOffset = 0;
int texCoordsOffset = 0;
- QRegExp subMeshMatch(subMesh);
+ QRegularExpression subMeshMatch(subMesh);
if (!subMeshMatch.isValid())
subMeshMatch.setPattern(QLatin1String("^(") + subMesh + QLatin1String(")$"));
Q_ASSERT(subMeshMatch.isValid());
@@ -196,7 +197,8 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh)
} else {
if (!subMesh.isEmpty() ) {
const QString objName = tokens.stringAt(1);
- skipping = subMeshMatch.indexIn(objName) < 0;
+ QRegularExpressionMatch match = subMeshMatch.match(objName);
+ skipping = !match.hasMatch();
}
}
}
@@ -217,7 +219,7 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh)
if (hasNormals)
m_normals.resize(vertexCount);
- for (QHash<FaceIndices, unsigned int>::const_iterator it = faceIndexMap.begin(), endIt = faceIndexMap.end(); it != endIt; ++it) {
+ for (auto it = faceIndexMap.cbegin(), endIt = faceIndexMap.cend(); it != endIt; ++it) {
m_points[it.value()] = positions[it.key().positionIndex];
if (hasTexCoords)
m_texCoords[it.value()] = std::numeric_limits<unsigned int>::max() != it.key().texCoordIndex ? texCoords[it.key().texCoordIndex] : QVector2D();
@@ -229,7 +231,7 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh)
const int indexCount = faceIndexVector.size();
m_indices.clear();
m_indices.reserve(indexCount);
- for (const FaceIndices faceIndices : faceIndexVector) {
+ for (const FaceIndices faceIndices : qAsConst(faceIndexVector)) {
const unsigned int i = faceIndexMap.value(faceIndices);
m_indices.append(i);
}
diff --git a/src/plugins/geometryloaders/default/plygeometryloader.cpp b/src/plugins/geometryloaders/default/plygeometryloader.cpp
index a7c252174..a51c991af 100644
--- a/src/plugins/geometryloaders/default/plygeometryloader.cpp
+++ b/src/plugins/geometryloaders/default/plygeometryloader.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(PlyGeometryLoaderLog, "Qt3D.PlyGeometryLoader")
+Q_LOGGING_CATEGORY(PlyGeometryLoaderLog, "Qt3D.PlyGeometryLoader", QtWarningMsg)
namespace {
diff --git a/src/plugins/geometryloaders/default/stlgeometryloader.cpp b/src/plugins/geometryloaders/default/stlgeometryloader.cpp
index b76698cc7..b4b5333cb 100644
--- a/src/plugins/geometryloaders/default/stlgeometryloader.cpp
+++ b/src/plugins/geometryloaders/default/stlgeometryloader.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(StlGeometryLoaderLog, "Qt3D.StlGeometryLoader")
+Q_LOGGING_CATEGORY(StlGeometryLoaderLog, "Qt3D.StlGeometryLoader", QtWarningMsg)
bool StlGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh)
{
diff --git a/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp b/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp
index cb0b57d50..7b1b8e4ee 100644
--- a/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp
+++ b/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(FbxGeometryLoaderLog, "Qt3D.FbxGeometryLoader")
+Q_LOGGING_CATEGORY(FbxGeometryLoaderLog, "Qt3D.FbxGeometryLoader", QtWarningMsg)
class FbxStreamWrapper : public FbxStream
{
diff --git a/src/plugins/geometryloaders/geometryloaders.pro b/src/plugins/geometryloaders/geometryloaders.pro
index 8dd99deb5..764c615da 100644
--- a/src/plugins/geometryloaders/geometryloaders.pro
+++ b/src/plugins/geometryloaders/geometryloaders.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS += default
+qtConfig(regularexpression) : SUBDIRS += default
SUBDIRS += gltf
qtConfig(qt3d-fbxsdk) : SUBDIRS += fbx
diff --git a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
index 20e0bef5f..3ebb6bec2 100644
--- a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
+++ b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(GLTFGeometryLoaderLog, "Qt3D.GLTFGeometryLoader")
+Q_LOGGING_CATEGORY(GLTFGeometryLoaderLog, "Qt3D.GLTFGeometryLoader", QtWarningMsg)
#define KEY_ACCESSORS QLatin1String("accessors")
#define KEY_ATTRIBUTES QLatin1String("attributes")
diff --git a/src/plugins/renderplugins/renderplugins.pro b/src/plugins/renderplugins/renderplugins.pro
new file mode 100644
index 000000000..1bc2f6c6c
--- /dev/null
+++ b/src/plugins/renderplugins/renderplugins.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += scene2d
diff --git a/src/quick3d/imports/extras/defaults/qml/TextureMaterial.qml b/src/plugins/renderplugins/scene2d/main.cpp
index 387d8d4aa..00a3db734 100644
--- a/src/quick3d/imports/extras/defaults/qml/TextureMaterial.qml
+++ b/src/plugins/renderplugins/scene2d/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,32 +37,27 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
+#include "scene2dplugin.h"
-Material {
- id: root
+#include <private/qrenderpluginfactoryif_p.h>
+#include <private/qrenderplugin_p.h>
- property Texture2D texture: Texture2D {}
- property alias textureOffset: texCoordOffset.offset
+QT_BEGIN_NAMESPACE
- parameters: [
- Parameter {
- name: "diffuseTexture"
- value: root.texture
- },
- Parameter {
- id: texCoordOffset
- property vector2d offset: Qt.vector2d(0, 0)
- name: "texCoordOffset"
- value: offset
- }
- ]
+class Scene2DPlugin : public Qt3DRender::Render::QRenderPluginFactoryIf
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QRenderPluginFactoryInterface_iid FILE "scene2dplugin.json")
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/unlittexture.vert"
- fragmentES: "qrc:/shaders/es2/unlittexture.frag"
- vertex: "qrc:/shaders/gl3/unlittexture.vert"
- fragment: "qrc:/shaders/gl3/unlittexture.frag"
+ Qt3DRender::Render::QRenderPlugin *create(const QString &key,
+ const QStringList &paramList) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(key)
+ Q_UNUSED(paramList)
+ return new Qt3DRender::Render::Scene2DPlugin();
}
-}
+};
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/renderplugins/scene2d/scene2d.pro b/src/plugins/renderplugins/scene2d/scene2d.pro
new file mode 100644
index 000000000..4f7ae6ea9
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2d.pro
@@ -0,0 +1,19 @@
+TARGET = scene2d
+QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras 3dquickscene2d 3dquickscene2d-private
+
+# Qt3D is free of Q_FOREACH - make sure it stays that way:
+DEFINES += QT_NO_FOREACH
+
+HEADERS += \
+ scene2dplugin.h
+
+SOURCES += \
+ main.cpp \
+ scene2dplugin.cpp
+
+DISTFILES += \
+ scene2dplugin.json
+
+PLUGIN_TYPE = renderplugins
+PLUGIN_CLASS_NAME = Scene2DPlugin
+load(qt_plugin)
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.cpp b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
new file mode 100644
index 000000000..83e002473
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene2dplugin.h"
+
+#include <Qt3DRender/qrenderaspect.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+template <typename Backend>
+class Scene2DBackendNodeMapper : public Qt3DCore::QBackendNodeMapper
+{
+public:
+ explicit Scene2DBackendNodeMapper(Render::AbstractRenderer *renderer,
+ Render::Scene2DNodeManager *manager)
+ : m_manager(manager)
+ , m_renderer(renderer)
+ {
+ }
+
+ Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const Q_DECL_FINAL
+ {
+ Backend *backend = m_manager->getOrCreateResource(change->subjectId());
+ backend->setRenderer(m_renderer);
+ return backend;
+ }
+
+ Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const Q_DECL_FINAL
+ {
+ return m_manager->lookupResource(id);
+ }
+
+ void destroy(Qt3DCore::QNodeId id) const Q_DECL_FINAL
+ {
+ m_manager->releaseResource(id);
+ }
+
+private:
+ Render::Scene2DNodeManager *m_manager;
+ Render::AbstractRenderer *m_renderer;
+};
+
+Scene2DPlugin::Scene2DPlugin()
+ : m_scene2dNodeManager(new Render::Scene2DNodeManager())
+{
+
+}
+
+Scene2DPlugin::~Scene2DPlugin()
+{
+ delete m_scene2dNodeManager;
+}
+
+bool Scene2DPlugin::registerBackendTypes(QRenderAspect *aspect,
+ AbstractRenderer *renderer)
+{
+ registerBackendType(aspect, Qt3DRender::Quick::QScene2D::staticMetaObject,
+ QSharedPointer<Scene2DBackendNodeMapper<Render::Quick::Scene2D> >
+ ::create(renderer, m_scene2dNodeManager));
+ return true;
+}
+bool Scene2DPlugin::unregisterBackendTypes(QRenderAspect *aspect)
+{
+ unregisterBackendType(aspect, Qt3DRender::Quick::QScene2D::staticMetaObject);
+ return true;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.h b/src/plugins/renderplugins/scene2d/scene2dplugin.h
new file mode 100644
index 000000000..f19093c7e
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_SCENE2DPLUGIN_H
+#define QT3DRENDER_SCENE2DPLUGIN_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrenderaspect_p.h>
+#include <private/qrenderplugin_p.h>
+#include <private/abstractrenderer_p.h>
+#include <private/qresourcemanager_p.h>
+#include <private/scene2d_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+class Scene2DNode;
+
+class Scene2DNodeManager : public Qt3DCore::QResourceManager<
+ Render::Quick::Scene2D,
+ Qt3DCore::QNodeId,
+ 16,
+ Qt3DCore::ArrayAllocatingPolicy,
+ Qt3DCore::ObjectLevelLockingPolicy>
+{
+};
+
+class Scene2DPlugin : public QRenderPlugin
+{
+public:
+ Scene2DPlugin();
+ ~Scene2DPlugin();
+ bool registerBackendTypes(QRenderAspect *aspect, AbstractRenderer *renderer) Q_DECL_OVERRIDE;
+ bool unregisterBackendTypes(QRenderAspect *aspect) Q_DECL_OVERRIDE;
+private:
+ Render::Scene2DNodeManager *m_scene2dNodeManager;
+};
+
+} // Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_SCENE2DPLUGIN_H
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.json b/src/plugins/renderplugins/scene2d/scene2dplugin.json
new file mode 100644
index 000000000..2eece1046
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.json
@@ -0,0 +1,3 @@
+{
+ "Keys": ["scene2d"]
+}
diff --git a/src/plugins/sceneparsers/assimp/assimp.pro b/src/plugins/sceneparsers/assimp/assimp.pro
index da8393f0c..28abef2b8 100644
--- a/src/plugins/sceneparsers/assimp/assimp.pro
+++ b/src/plugins/sceneparsers/assimp/assimp.pro
@@ -1,5 +1,5 @@
TARGET = assimpsceneimport
-QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras
+QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras 3danimation
include(../../../3rdparty/assimp/assimp_dependency.pri)
diff --git a/src/plugins/sceneparsers/assimp/assimphelpers.cpp b/src/plugins/sceneparsers/assimp/assimphelpers.cpp
index 02799beaf..ce6619541 100644
--- a/src/plugins/sceneparsers/assimp/assimphelpers.cpp
+++ b/src/plugins/sceneparsers/assimp/assimphelpers.cpp
@@ -39,11 +39,11 @@
#include "assimphelpers.h"
-#include <QFileDevice>
-#include <QFileInfo>
-#include <QUrl>
-#include <QDir>
-#include <QDebug>
+#include <QtCore/QFileDevice>
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrl>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/sceneparsers/assimp/assimphelpers.h b/src/plugins/sceneparsers/assimp/assimphelpers.h
index 21ac1b1ef..64a6d4abe 100644
--- a/src/plugins/sceneparsers/assimp/assimphelpers.h
+++ b/src/plugins/sceneparsers/assimp/assimphelpers.h
@@ -54,9 +54,8 @@
// ASSIMP INCLUDES
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
-
-#include <QIODevice>
-#include <QMap>
+#include <QtCore/QIODevice>
+#include <QtCore/QMap>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp
index 66c219fe9..4370ffe2b 100644
--- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp
+++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp
@@ -39,31 +39,36 @@
#include "assimpimporter.h"
-#include <Qt3DCore/private/qabstractnodefactory_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
+#include <Qt3DExtras/qdiffusemapmaterial.h>
+#include <Qt3DExtras/qdiffusespecularmapmaterial.h>
+#include <Qt3DExtras/qphongmaterial.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/qcameralens.h>
-#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qeffect.h>
-#include <Qt3DRender/qmesh.h>
+#include <Qt3DRender/qgeometry.h>
+#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/qmaterial.h>
-#include <Qt3DRender/qbuffer.h>
-#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qmesh.h>
+#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qtexture.h>
#include <Qt3DRender/qtextureimagedatagenerator.h>
#include <Qt3DExtras/qmorphphongmaterial.h>
#include <Qt3DExtras/qdiffusemapmaterial.h>
#include <Qt3DExtras/qdiffusespecularmapmaterial.h>
#include <Qt3DExtras/qphongmaterial.h>
-#include <Qt3DExtras/qkeyframeanimation.h>
-#include <Qt3DExtras/qmorphinganimation.h>
-#include <QFileInfo>
-#include <QColor>
+#include <Qt3DAnimation/qkeyframeanimation.h>
+#include <Qt3DAnimation/qmorphinganimation.h>
+#include <QtCore/QFileInfo>
+#include <QtGui/QColor>
+
#include <qmath.h>
+
+#include <Qt3DCore/private/qabstractnodefactory_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
-#include <Qt3DRender/qgeometryrenderer.h>
-#include <Qt3DRender/qgeometry.h>
QT_BEGIN_NAMESPACE
@@ -83,7 +88,7 @@ namespace Qt3DRender {
It should be noted that Assimp aiString is explicitly defined to be UTF-8.
*/
-Q_LOGGING_CATEGORY(AssimpImporterLog, "Qt3D.AssimpImporter")
+Q_LOGGING_CATEGORY(AssimpImporterLog, "Qt3D.AssimpImporter", QtWarningMsg)
namespace {
@@ -137,7 +142,7 @@ QMatrix4x4 aiMatrix4x4ToQMatrix4x4(const aiMatrix4x4 &matrix) Q_DECL_NOTHROW
/*!
* Returns a QString from \a str;
*/
-static inline QString aiStringToQString(const aiString &str)
+inline QString aiStringToQString(const aiString &str)
{
return QString::fromUtf8(str.data, int(str.length));
}
@@ -241,6 +246,21 @@ QAttribute *createAttribute(QBuffer *buffer,
return attribute;
}
+QTextureWrapMode::WrapMode wrapModeFromaiTextureMapMode(int mode)
+{
+ switch (mode) {
+ case aiTextureMapMode_Wrap:
+ return QTextureWrapMode::Repeat;
+ case aiTextureMapMode_Mirror:
+ return QTextureWrapMode::MirroredRepeat;
+ case aiTextureMapMode_Decal:
+ return QTextureWrapMode::ClampToBorder;
+ case aiTextureMapMode_Clamp:
+ default:
+ return QTextureWrapMode::ClampToEdge;
+ }
+}
+
} // anonymous
QStringList AssimpImporter::assimpSupportedFormatsList = AssimpImporter::assimpSupportedFormats();
@@ -260,6 +280,7 @@ QStringList AssimpImporter::assimpSupportedFormats()
formats.append(QStringLiteral("acc"));
formats.append(QStringLiteral("ase"));
formats.append(QStringLiteral("ask"));
+ formats.append(QStringLiteral("assbin"));
formats.append(QStringLiteral("b3d"));
formats.append(QStringLiteral("blend"));
formats.append(QStringLiteral("bvh"));
@@ -268,6 +289,7 @@ QStringList AssimpImporter::assimpSupportedFormats()
formats.append(QStringLiteral("dae"));
formats.append(QStringLiteral("dxf"));
formats.append(QStringLiteral("enff"));
+ formats.append(QStringLiteral("fbx"));
formats.append(QStringLiteral("hmp"));
formats.append(QStringLiteral("irr"));
formats.append(QStringLiteral("irrmesh"));
@@ -288,6 +310,7 @@ QStringList AssimpImporter::assimpSupportedFormats()
formats.append(QStringLiteral("nff"));
formats.append(QStringLiteral("obj"));
formats.append(QStringLiteral("off"));
+ formats.append(QStringLiteral("ogex"));
formats.append(QStringLiteral("pk3"));
formats.append(QStringLiteral("ply"));
formats.append(QStringLiteral("prj"));
@@ -295,6 +318,7 @@ QStringList AssimpImporter::assimpSupportedFormats()
formats.append(QStringLiteral("q3s"));
formats.append(QStringLiteral("raw"));
formats.append(QStringLiteral("scn"));
+ formats.append(QStringLiteral("sib"));
formats.append(QStringLiteral("smd"));
formats.append(QStringLiteral("stl"));
formats.append(QStringLiteral("ter"));
@@ -302,7 +326,6 @@ QStringList AssimpImporter::assimpSupportedFormats()
formats.append(QStringLiteral("vta"));
formats.append(QStringLiteral("x"));
formats.append(QStringLiteral("xml"));
- formats.append(QStringLiteral("fbx"));
return formats;
}
@@ -352,17 +375,15 @@ AssimpImporter::~AssimpImporter()
}
/*!
- * Returns \c true if the provided \a path has a suffix supported
+ * Returns \c true if the extensions are supported
* by the Assimp Assets importer.
*/
-bool AssimpImporter::isAssimpPath(const QString &path)
+bool AssimpImporter::areAssimpExtensions(const QStringList &extensions)
{
- QFileInfo fileInfo(path);
-
- if (!fileInfo.exists() ||
- !AssimpImporter::assimpSupportedFormatsList.contains(fileInfo.suffix().toLower()))
- return false;
- return true;
+ for (const auto ext : qAsConst(extensions))
+ if (AssimpImporter::assimpSupportedFormatsList.contains(ext.toLower()))
+ return true;
+ return false;
}
/*!
@@ -382,13 +403,21 @@ void AssimpImporter::setSource(const QUrl &source)
}
/*!
+ * Sets the \a source used by the parser to load the asset file.
+ * If the file is valid, this will trigger parsing of the file.
+ */
+void AssimpImporter::setData(const QByteArray &data, const QString &basePath)
+{
+ readSceneData(data, basePath);
+}
+
+/*!
* Returns \c true if the extension of \a source is supported by
* the assimp parser.
*/
-bool AssimpImporter::isFileTypeSupported(const QUrl &source) const
+bool AssimpImporter::areFileTypesSupported(const QStringList &extensions) const
{
- const QString path = QUrlHelper::urlToLocalFileOrQrc(source);
- return AssimpImporter::isAssimpPath(path);
+ return AssimpImporter::areAssimpExtensions(extensions);
}
/*!
@@ -420,7 +449,7 @@ Qt3DCore::QEntity *AssimpImporter::scene(const QString &id)
if (m_scene->m_animations.size() > 0) {
qWarning() << "No target found for " << m_scene->m_animations.size() << " animations!";
- for (Qt3DExtras::QKeyframeAnimation *anim : m_scene->m_animations)
+ for (Qt3DAnimation::QKeyframeAnimation *anim : qAsConst(m_scene->m_animations))
delete anim;
m_scene->m_animations.clear();
}
@@ -472,24 +501,24 @@ Qt3DCore::QEntity *AssimpImporter::node(aiNode *node)
if (m_scene->m_materials.contains(materialIndex))
material = m_scene->m_materials[materialIndex];
- QList<Qt3DExtras::QMorphingAnimation *> morphingAnimations
- = mesh->findChildren<Qt3DExtras::QMorphingAnimation *>();
+ QList<Qt3DAnimation::QMorphingAnimation *> morphingAnimations
+ = mesh->findChildren<Qt3DAnimation::QMorphingAnimation *>();
if (morphingAnimations.size() > 0) {
material = new Qt3DExtras::QMorphPhongMaterial(entityNode);
- QVector<Qt3DExtras::QMorphingAnimation *> animations;
- findAnimationsForNode<Qt3DExtras::QMorphingAnimation>(m_scene->m_morphAnimations,
+ QVector<Qt3DAnimation::QMorphingAnimation *> animations;
+ findAnimationsForNode<Qt3DAnimation::QMorphingAnimation>(m_scene->m_morphAnimations,
animations,
aiStringToQString(node->mName));
const auto morphTargetList = morphingAnimations.at(0)->morphTargetList();
- for (Qt3DExtras::QMorphingAnimation *anim : animations) {
+ for (Qt3DAnimation::QMorphingAnimation *anim : qAsConst(animations)) {
anim->setParent(entityNode);
anim->setTarget(mesh);
anim->setMorphTargets(morphTargetList);
}
for (int j = 0; j < animations.size(); ++j) {
- QObject::connect(animations[j], &Qt3DExtras::QMorphingAnimation::interpolatorChanged,
+ QObject::connect(animations[j], &Qt3DAnimation::QMorphingAnimation::interpolatorChanged,
(Qt3DExtras::QMorphPhongMaterial *)material,
&Qt3DExtras::QMorphPhongMaterial::setInterpolator);
}
@@ -530,12 +559,12 @@ Qt3DCore::QEntity *AssimpImporter::node(aiNode *node)
transform->setMatrix(qTransformMatrix);
entityNode->addComponent(transform);
- QVector<Qt3DExtras::QKeyframeAnimation *> animations;
- findAnimationsForNode<Qt3DExtras::QKeyframeAnimation>(m_scene->m_animations,
+ QVector<Qt3DAnimation::QKeyframeAnimation *> animations;
+ findAnimationsForNode<Qt3DAnimation::QKeyframeAnimation>(m_scene->m_animations,
animations,
aiStringToQString(node->mName));
- for (Qt3DExtras::QKeyframeAnimation *anim : animations) {
+ for (Qt3DAnimation::QKeyframeAnimation *anim : qAsConst(animations)) {
anim->setTarget(transform);
anim->setParent(entityNode);
}
@@ -580,6 +609,36 @@ void AssimpImporter::readSceneFile(const QString &path)
}
/*!
+ * Reads the scene file pointed by \a path and launches the parsing of
+ * the scene using Assimp, after having cleaned up previously saved values
+ * from eventual previous parsings.
+ */
+void AssimpImporter::readSceneData(const QByteArray& data, const QString &basePath)
+{
+ cleanup();
+
+ m_scene = new SceneImporter();
+
+ // SET THIS TO REMOVE POINTS AND LINES -> HAVE ONLY TRIANGLES
+ m_scene->m_importer->SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE|aiPrimitiveType_POINT);
+ // SET CUSTOM FILE HANDLER TO HANDLE FILE READING THROUGH QT (RESOURCES, SOCKET ...)
+ m_scene->m_importer->SetIOHandler(new AssimpHelper::AssimpIOSystem());
+
+ // type and aiProcess_Triangulate discompose polygons with more than 3 points in triangles
+ // aiProcess_SortByPType makes sure that meshes data are triangles
+ m_scene->m_aiScene = m_scene->m_importer->ReadFileFromMemory(data.data(), data.size(),
+ aiProcess_SortByPType|
+ aiProcess_Triangulate|
+ aiProcess_GenSmoothNormals|
+ aiProcess_FlipUVs);
+ if (m_scene->m_aiScene == nullptr) {
+ qCWarning(AssimpImporterLog) << "Assimp scene import failed";
+ return ;
+ }
+ parse();
+}
+
+/*!
* Cleans the various dictionaries holding the scene's information.
*/
void AssimpImporter::cleanup()
@@ -792,10 +851,10 @@ void AssimpImporter::loadMesh(uint meshIndex)
if (animesh->mNumVertices != mesh->mNumVertices)
return;
- Qt3DExtras::QMorphingAnimation *morphingAnimation
- = new Qt3DExtras::QMorphingAnimation(geometryRenderer);
+ Qt3DAnimation::QMorphingAnimation *morphingAnimation
+ = new Qt3DAnimation::QMorphingAnimation(geometryRenderer);
QVector<QString> names;
- QVector<Qt3DExtras::QMorphTarget *> targets;
+ QVector<Qt3DAnimation::QMorphTarget *> targets;
uint voff = 0;
uint noff = 0;
uint tanoff = 0;
@@ -835,7 +894,7 @@ void AssimpImporter::loadMesh(uint meshIndex)
for (uint i = 0; i < mesh->mNumAnimMeshes; i++) {
aiAnimMesh *animesh = mesh->mAnimMeshes[i];
- Qt3DExtras::QMorphTarget *target = new Qt3DExtras::QMorphTarget(geometryRenderer);
+ Qt3DAnimation::QMorphTarget *target = new Qt3DAnimation::QMorphTarget(geometryRenderer);
targets.push_back(target);
QVector<QAttribute *> attributes;
QByteArray targetBufferArray;
@@ -1029,7 +1088,7 @@ void AssimpImporter::loadAnimation(uint animationIndex)
aiNodeAnim *nodeAnim = assimpAnim->mChannels[i];
aiNode *targetNode = m_scene->m_aiScene->mRootNode->FindNode(nodeAnim->mNodeName);
- Qt3DExtras::QKeyframeAnimation *kfa = new Qt3DExtras::QKeyframeAnimation();
+ Qt3DAnimation::QKeyframeAnimation *kfa = new Qt3DAnimation::QKeyframeAnimation();
QVector<float> positions;
QVector<Qt3DCore::QTransform*> transforms;
if ((nodeAnim->mNumPositionKeys > 1)
@@ -1102,7 +1161,7 @@ void AssimpImporter::loadAnimation(uint animationIndex)
aiNode *targetNode = m_scene->m_aiScene->mRootNode->FindNode(morphAnim->mName);
aiMesh *mesh = m_scene->m_aiScene->mMeshes[targetNode->mMeshes[0]];
- Qt3DExtras::QMorphingAnimation *morphingAnimation = new Qt3DExtras::QMorphingAnimation;
+ Qt3DAnimation::QMorphingAnimation *morphingAnimation = new Qt3DAnimation::QMorphingAnimation;
QVector<float> positions;
positions.resize(morphAnim->mNumKeys);
// set so that weights array is allocated to correct size in morphingAnimation
@@ -1125,8 +1184,8 @@ void AssimpImporter::loadAnimation(uint animationIndex)
morphingAnimation->setAnimationName(QString(assimpAnim->mName.C_Str()));
morphingAnimation->setTargetName(QString(targetNode->mName.C_Str()));
morphingAnimation->setMethod((mesh->mMethod == aiMorphingMethod_MORPH_NORMALIZED)
- ? Qt3DExtras::QMorphingAnimation::Normalized
- : Qt3DExtras::QMorphingAnimation::Relative);
+ ? Qt3DAnimation::QMorphingAnimation::Normalized
+ : Qt3DAnimation::QMorphingAnimation::Relative);
m_scene->m_morphAnimations.push_back(morphingAnimation);
}
}
@@ -1229,18 +1288,28 @@ void AssimpImporter::copyMaterialTextures(QMaterial *material, aiMaterial *assim
for (unsigned int i = 0; i < sizeof(textureType)/sizeof(textureType[0]); i++) {
aiString path;
if (assimpMaterial->GetTexture(textureType[i], 0, &path) == AI_SUCCESS) {
- QString fullPath = m_sceneDir.absoluteFilePath(texturePath(path));
+ const QString fullPath = m_sceneDir.absoluteFilePath(texturePath(path));
// Load texture if not already loaded
- if (!m_scene->m_materialTextures.contains(fullPath)) {
- QAbstractTexture *tex = QAbstractNodeFactory::createNode<QTexture2D>("QTexture2D");
- QTextureImage *texImage = QAbstractNodeFactory::createNode<QTextureImage>("QTextureImage");
- texImage->setSource(QUrl::fromLocalFile(fullPath));
- tex->addTextureImage(texImage);
- m_scene->m_materialTextures.insert(fullPath, tex);
- qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Loaded Texture " << fullPath;
- }
+ QAbstractTexture *tex = QAbstractNodeFactory::createNode<QTexture2D>("QTexture2D");
+ QTextureImage *texImage = QAbstractNodeFactory::createNode<QTextureImage>("QTextureImage");
+ texImage->setSource(QUrl::fromLocalFile(fullPath));
+ tex->addTextureImage(texImage);
+
+ // Set proper wrapping mode
+ QTextureWrapMode wrapMode(QTextureWrapMode::Repeat);
+ int xMode = 0;
+ int yMode = 0;
+
+ if (assimpMaterial->Get(AI_MATKEY_MAPPINGMODE_U(textureType[i], 0), xMode) == aiReturn_SUCCESS)
+ wrapMode.setX(wrapModeFromaiTextureMapMode(xMode));
+ if (assimpMaterial->Get(AI_MATKEY_MAPPINGMODE_V(textureType[i], 0), yMode) == aiReturn_SUCCESS)
+ wrapMode.setY(wrapModeFromaiTextureMapMode(yMode));
+
+ tex->setWrapMode(wrapMode);
+
+ qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Loaded Texture " << fullPath;
setParameterValue(m_scene->m_textureToParameterName[textureType[i]],
- material, QVariant::fromValue(m_scene->m_materialTextures[fullPath]));
+ material, QVariant::fromValue(tex));
}
}
}
@@ -1289,8 +1358,9 @@ AssimpRawTextureImage::AssimpRawTextureImageFunctor::AssimpRawTextureImageFuncto
QTextureImageDataPtr AssimpRawTextureImage::AssimpRawTextureImageFunctor::operator()()
{
- QTextureImageDataPtr dataPtr;
- dataPtr->setData(m_data, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
+ QTextureImageDataPtr dataPtr = QTextureImageDataPtr::create();
+ // Note: we assume 4 components per pixel and not compressed for now
+ dataPtr->setData(m_data, 4, false);
return dataPtr;
}
diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.h b/src/plugins/sceneparsers/assimp/assimpimporter.h
index 0d2c0c9e5..3c0a41124 100644
--- a/src/plugins/sceneparsers/assimp/assimpimporter.h
+++ b/src/plugins/sceneparsers/assimp/assimpimporter.h
@@ -56,13 +56,15 @@
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
-#include <Qt3DRender/private/qsceneimporter_p.h>
+
+#include <QtCore/QMap>
+#include <QtCore/QDir>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QVector>
+
#include "assimphelpers.h"
-#include <QMap>
-#include <QDir>
-#include <QVector>
-#include <QLoggingCategory>
+#include <Qt3DRender/private/qsceneimporter_p.h>
QT_BEGIN_NAMESPACE
@@ -72,7 +74,7 @@ namespace Qt3DCore {
class QCamera;
}
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
class QKeyframeAnimation;
class QMorphingAnimation;
}
@@ -98,17 +100,19 @@ public:
// SceneParserInterface interface
void setSource(const QUrl& source) Q_DECL_OVERRIDE;
- bool isFileTypeSupported(const QUrl &source) const Q_DECL_OVERRIDE;
+ void setData(const QByteArray& data, const QString &basePath) Q_DECL_OVERRIDE;
+ bool areFileTypesSupported(const QStringList &extensions) const Q_DECL_OVERRIDE;
Qt3DCore::QEntity *scene(const QString &id = QString()) Q_DECL_OVERRIDE;
Qt3DCore::QEntity *node(const QString &id) Q_DECL_OVERRIDE;
private:
- static bool isAssimpPath(const QString &path);
+ static bool areAssimpExtensions(const QStringList &extensions);
static QStringList assimpSupportedFormats();
Qt3DCore::QEntity *node(aiNode *node);
void readSceneFile(const QString &file);
+ void readSceneData(const QByteArray& data, const QString &basePath);
void cleanup();
void parse();
@@ -141,11 +145,10 @@ private:
QMap<uint, QMaterial*> m_materials;
QMap<uint, QEffect *> m_effects;
QMap<uint, QAbstractTexture *> m_embeddedTextures;
- QMap<QString, QAbstractTexture *> m_materialTextures;
QMap<aiNode*, Qt3DCore::QEntity*> m_cameras;
QHash<aiTextureType, QString> m_textureToParameterName;
- QVector<Qt3DExtras::QKeyframeAnimation *> m_animations;
- QVector<Qt3DExtras::QMorphingAnimation *> m_morphAnimations;
+ QVector<Qt3DAnimation::QKeyframeAnimation *> m_animations;
+ QVector<Qt3DAnimation::QMorphingAnimation *> m_morphAnimations;
// QMap<aiNode*, Light*> m_lights;
};
diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.cpp b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
index c026594bf..a94a4f307 100644
--- a/src/plugins/sceneparsers/gltf/gltfimporter.cpp
+++ b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
@@ -255,7 +255,7 @@ Qt3DRender::QFilterKey *buildFilterKey(const QString &key, const QJsonValue &val
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(GLTFImporterLog, "Qt3D.GLTFImport")
+Q_LOGGING_CATEGORY(GLTFImporterLog, "Qt3D.GLTFImport", QtWarningMsg)
GLTFImporter::GLTFImporter() : QSceneImporter(),
@@ -314,13 +314,30 @@ void GLTFImporter::setSource(const QUrl &source)
}
/*!
- * Returns true if the extension of \a path is supported by the
+ * Sets the \a path used by the parser to load the scene file.
+ * If the file is valid, parsing is automatically triggered.
+ */
+void GLTFImporter::setData(const QByteArray& data, const QString &basePath)
+{
+ QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(data);
+ if (sceneDocument.isNull())
+ sceneDocument = QJsonDocument::fromJson(data);
+
+ if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ qCWarning(GLTFImporterLog, "not a JSON document");
+ return;
+ }
+
+ setBasePath(basePath);
+}
+
+/*!
+ * Returns true if the extensions are supported by the
* GLTF parser.
*/
-bool GLTFImporter::isFileTypeSupported(const QUrl &source) const
+bool GLTFImporter::areFileTypesSupported(const QStringList &extensions) const
{
- const QString path = QUrlHelper::urlToLocalFileOrQrc(source);
- return GLTFImporter::isGLTFPath(path);
+ return GLTFImporter::isGLTFSupported(extensions);
}
Qt3DCore::QEntity* GLTFImporter::node(const QString &id)
@@ -570,16 +587,14 @@ GLTFImporter::AccessorData::AccessorData(const QJsonObject &json)
stride = byteStride.toInt();
}
-bool GLTFImporter::isGLTFPath(const QString& path)
+bool GLTFImporter::isGLTFSupported(const QStringList &extensions)
{
- QFileInfo finfo(path);
- if (!finfo.exists())
- return false;
-
- // might need to detect other things in the future, but would
- // prefer to avoid doing a full parse.
- QString suffix = finfo.suffix().toLower();
- return suffix == QLatin1String("json") || suffix == QLatin1String("gltf") || suffix == QLatin1String("qgltf");
+ for (auto suffix: qAsConst(extensions)) {
+ suffix = suffix.toLower();
+ if (suffix == QLatin1String("json") || suffix == QLatin1String("gltf") || suffix == QLatin1String("qgltf"))
+ return true;
+ }
+ return false;
}
void GLTFImporter::renameFromJson(const QJsonObject &json, QObject * const object)
@@ -1072,7 +1087,7 @@ void GLTFImporter::cleanup()
m_shaderPaths.clear();
delete_if_without_parent(m_programs);
m_programs.clear();
- for (auto params : m_techniqueParameters.values())
+ for (auto params : qAsConst(m_techniqueParameters))
delete_if_without_parent(params);
m_techniqueParameters.clear();
delete_if_without_parent(m_techniques);
@@ -1546,7 +1561,7 @@ void GLTFImporter::processJSONExtensions(const QString &id, const QJsonObject &j
// level GLTF item.
if (id == KEY_COMMON_MAT) {
const auto lights = jsonObject.value(KEY_LIGHTS).toObject();
- for (auto lightKey : lights.keys()) {
+ for (const auto &lightKey : lights.keys()) {
const auto light = lights.value(lightKey).toObject();
auto lightType = light.value(KEY_TYPE).toString();
const auto lightValues = light.value(lightType).toObject();
diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.h b/src/plugins/sceneparsers/gltf/gltfimporter.h
index e97148600..8a8e1b3ee 100644
--- a/src/plugins/sceneparsers/gltf/gltfimporter.h
+++ b/src/plugins/sceneparsers/gltf/gltfimporter.h
@@ -52,13 +52,13 @@
// We mean it.
//
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qbuffer.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qhash.h>
-#include <Qt3DRender/qattribute.h>
-#include <Qt3DRender/qbuffer.h>
-#include <private/qsceneimporter_p.h>
+#include <Qt3DRender/private/qsceneimporter_p.h>
QT_BEGIN_NAMESPACE
@@ -98,7 +98,8 @@ public:
// SceneParserInterface interface
void setSource(const QUrl &source) Q_DECL_FINAL;
- bool isFileTypeSupported(const QUrl &source) const Q_DECL_FINAL;
+ void setData(const QByteArray& data, const QString &basePath) Q_DECL_FINAL;
+ bool areFileTypesSupported(const QStringList &extensions) const Q_DECL_FINAL;
Qt3DCore::QEntity *node(const QString &id) Q_DECL_FINAL;
Qt3DCore::QEntity *scene(const QString &id = QString()) Q_DECL_FINAL;
@@ -139,7 +140,7 @@ private:
int stride;
};
- static bool isGLTFPath(const QString &path);
+ static bool isGLTFSupported(const QStringList &extensions);
static void renameFromJson(const QJsonObject& json, QObject * const object );
static bool hasStandardUniformNameFromSemantic(const QString &semantic);
static QString standardAttributeNameFromSemantic(const QString &semantic);
diff --git a/src/plugins/sceneparsers/gltf/gltfio.cpp b/src/plugins/sceneparsers/gltf/gltfio.cpp
new file mode 100644
index 000000000..c7c7a00dd
--- /dev/null
+++ b/src/plugins/sceneparsers/gltf/gltfio.cpp
@@ -0,0 +1,1588 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DCore/QEntity>
+#include <Qt3DCore/QTransform>
+#include <Qt3DExtras/QDiffuseMapMaterial>
+#include <Qt3DExtras/QDiffuseSpecularMapMaterial>
+#include <Qt3DExtras/QNormalDiffuseMapMaterial>
+#include <Qt3DExtras/QNormalDiffuseSpecularMapMaterial>
+#include <Qt3DExtras/QPhongMaterial>
+#include <Qt3DRender/QAlphaCoverage>
+#include <Qt3DRender/QBlendEquation>
+#include <Qt3DRender/QBlendEquationArguments>
+#include <Qt3DRender/QCameraLens>
+#include <Qt3DRender/QColorMask>
+#include <Qt3DRender/QCullFace>
+#include <Qt3DRender/QDepthTest>
+#include <Qt3DRender/QEffect>
+#include <Qt3DRender/QFrontFace>
+#include <Qt3DRender/QGeometry>
+#include <Qt3DRender/QGeometryRenderer>
+#include <Qt3DRender/QGraphicsApiFilter>
+#include <Qt3DRender/QMaterial>
+#include <Qt3DRender/QNoDepthMask>
+#include <Qt3DRender/QParameter>
+#include <Qt3DRender/QPolygonOffset>
+#include <Qt3DRender/QRenderState>
+#include <Qt3DRender/QScissorTest>
+#include <Qt3DRender/QShaderProgram>
+#include <Qt3DRender/QTechnique>
+#include <Qt3DRender/QTexture>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonObject>
+#include <QtGui/QVector2D>
+
+#include "gltfio.h"
+
+#include <Qt3DRender/private/qurlhelper_p.h>
+
+#ifndef qUtf16PrintableImpl // -Impl is a Qt 5.8 feature
+# define qUtf16PrintableImpl(string) \
+ static_cast<const wchar_t*>(static_cast<const void*>(string.utf16()))
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+using namespace Qt3DExtras;
+
+namespace Qt3DRender {
+
+Q_LOGGING_CATEGORY(GLTFIOLog, "Qt3D.GLTFIO")
+
+#define KEY_CAMERA QLatin1String("camera")
+#define KEY_CAMERAS QLatin1String("cameras")
+#define KEY_SCENES QLatin1String("scenes")
+#define KEY_NODES QLatin1String("nodes")
+#define KEY_MESHES QLatin1String("meshes")
+#define KEY_CHILDREN QLatin1String("children")
+#define KEY_MATRIX QLatin1String("matrix")
+#define KEY_ROTATION QLatin1String("rotation")
+#define KEY_SCALE QLatin1String("scale")
+#define KEY_TRANSLATION QLatin1String("translation")
+#define KEY_TYPE QLatin1String("type")
+#define KEY_PERSPECTIVE QLatin1String("perspective")
+#define KEY_NAME QLatin1String("name")
+#define KEY_COUNT QLatin1String("count")
+#define KEY_YFOV QLatin1String("yfov")
+#define KEY_ZNEAR QLatin1String("znear")
+#define KEY_ZFAR QLatin1String("zfar")
+#define KEY_MATERIALS QLatin1String("materials")
+#define KEY_EXTENSIONS QLatin1String("extensions")
+#define KEY_COMMON_MAT QLatin1String("KHR_materials_common")
+#define KEY_TECHNIQUE QLatin1String("technique")
+#define KEY_VALUES QLatin1String("values")
+#define KEY_BUFFERS QLatin1String("buffers")
+#define KEY_SHADERS QLatin1String("shaders")
+#define KEY_PROGRAMS QLatin1String("programs")
+#define KEY_PROGRAM QLatin1String("program")
+#define KEY_TECHNIQUES QLatin1String("techniques")
+#define KEY_ACCESSORS QLatin1String("accessors")
+#define KEY_IMAGES QLatin1String("images")
+#define KEY_TEXTURES QLatin1String("textures")
+#define KEY_SCENE QLatin1String("scene")
+#define KEY_BUFFER QLatin1String("buffer")
+#define KEY_TARGET QLatin1String("target")
+#define KEY_BYTE_OFFSET QLatin1String("byteOffset")
+#define KEY_BYTE_LENGTH QLatin1String("byteLength")
+#define KEY_BYTE_STRIDE QLatin1String("byteStride")
+#define KEY_PRIMITIVES QLatin1String("primitives")
+#define KEY_MODE QLatin1String("mode")
+#define KEY_MATERIAL QLatin1String("material")
+#define KEY_ATTRIBUTES QLatin1String("attributes")
+#define KEY_INDICES QLatin1String("indices")
+#define KEY_URI QLatin1String("uri")
+#define KEY_FORMAT QLatin1String("format")
+#define KEY_PASSES QLatin1String("passes")
+#define KEY_SOURCE QLatin1String("source")
+#define KEY_SAMPLER QLatin1String("sampler")
+#define KEY_SAMPLERS QLatin1String("samplers")
+#define KEY_SEMANTIC QLatin1String("semantic")
+#define KEY_STATES QLatin1String("states")
+#define KEY_UNIFORMS QLatin1String("uniforms")
+#define KEY_PARAMETERS QLatin1String("parameters")
+#define KEY_WRAP_S QLatin1String("wrapS")
+#define KEY_MIN_FILTER QLatin1String("minFilter")
+#define KEY_MAG_FILTER QLatin1String("magFilter")
+
+#define KEY_INSTANCE_TECHNIQUE QLatin1String("instanceTechnique")
+#define KEY_INSTANCE_PROGRAM QLatin1String("instanceProgram")
+#define KEY_BUFFER_VIEWS QLatin1String("bufferViews")
+#define KEY_BUFFER_VIEW QLatin1String("bufferView")
+#define KEY_VERTEX_SHADER QLatin1String("vertexShader")
+#define KEY_FRAGMENT_SHADER QLatin1String("fragmentShader")
+#define KEY_INTERNAL_FORMAT QLatin1String("internalFormat")
+#define KEY_COMPONENT_TYPE QLatin1String("componentType")
+#define KEY_ASPECT_RATIO QLatin1String("aspect_ratio")
+#define KEY_VALUE QLatin1String("value")
+#define KEY_ENABLE QLatin1String("enable")
+#define KEY_FUNCTIONS QLatin1String("functions")
+#define KEY_TECHNIQUE_CORE QLatin1String("techniqueCore")
+#define KEY_TECHNIQUE_GL2 QLatin1String("techniqueGL2")
+
+GLTFIO::GLTFIO() : QSceneIOHandler(),
+ m_parseDone(false)
+{
+}
+
+GLTFIO::~GLTFIO()
+{
+
+}
+
+void GLTFIO::setBasePath(const QString& path)
+{
+ m_basePath = path;
+}
+
+bool GLTFIO::setJSON(const QJsonDocument &json )
+{
+ if ( !json.isObject() ) {
+ return false;
+ }
+
+ m_json = json;
+ m_parseDone = false;
+
+ cleanup();
+
+ return true;
+}
+
+/*!
+ * Sets the \a path used by the parser to load the scene file.
+ * If the file is valid, parsing is automatically triggered.
+ */
+void GLTFIO::setSource(const QUrl &source)
+{
+ const QString path = QUrlHelper::urlToLocalFileOrQrc(source);
+ QFileInfo finfo(path);
+ if (Q_UNLIKELY(!finfo.exists())) {
+ qCWarning(GLTFIOLog, "missing file: %ls", qUtf16PrintableImpl(path));
+ return;
+ }
+ QFile f(path);
+ f.open(QIODevice::ReadOnly);
+
+ QByteArray jsonData = f.readAll();
+ QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
+ if (sceneDocument.isNull())
+ sceneDocument = QJsonDocument::fromJson(jsonData);
+
+ if (Q_UNLIKELY(!setJSON(sceneDocument))) {
+ qCWarning(GLTFIOLog, "not a JSON document");
+ return;
+ }
+
+ setBasePath(finfo.dir().absolutePath());
+}
+
+/*!
+ * Returns true if the extension of \a path is supported by the
+ * GLTF parser.
+ */
+bool GLTFIO::isFileTypeSupported(const QUrl &source) const
+{
+ const QString path = QUrlHelper::urlToLocalFileOrQrc(source);
+ return GLTFIO::isGLTFPath(path);
+}
+
+Qt3DCore::QEntity* GLTFIO::node(const QString &id)
+{
+ QJsonObject nodes = m_json.object().value(KEY_NODES).toObject();
+ const auto jsonVal = nodes.value(id);
+ if (Q_UNLIKELY(jsonVal.isUndefined())) {
+ qCWarning(GLTFIOLog, "unknown node %ls in GLTF file %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ return NULL;
+ }
+
+ const QJsonObject jsonObj = jsonVal.toObject();
+ QEntity* result = nullptr;
+
+ // Qt3D has a limitation that a QEntity can only have 1 mesh and 1 material component
+ // So if the node has only 1 mesh, we only create 1 QEntity
+ // Otherwise if there are n meshes, there is 1 QEntity, with n children for each mesh/material combo
+ {
+ QVector<QEntity *> entities;
+
+ const auto meshes = jsonObj.value(KEY_MESHES).toArray();
+ for (const QJsonValue &mesh : meshes) {
+ const QString meshName = mesh.toString();
+ const auto geometryRenderers = qAsConst(m_meshDict).equal_range(meshName);
+ if (Q_UNLIKELY(geometryRenderers.first == geometryRenderers.second)) {
+ qCWarning(GLTFIOLog, "node %ls references unknown mesh %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(meshName));
+ continue;
+ }
+
+ for (auto it = geometryRenderers.first; it != geometryRenderers.second; ++it) {
+ QGeometryRenderer *geometryRenderer = it.value();
+ QEntity *entity = new QEntity;
+ entity->addComponent(geometryRenderer);
+ QMaterial *mat = material(m_meshMaterialDict[geometryRenderer]);
+ if (mat)
+ entity->addComponent(mat);
+ entities.append(entity);
+ }
+
+ }
+
+ switch (entities.size()) {
+ case 0:
+ break;
+ case 1:
+ result = qAsConst(entities).first();
+ break;
+ default:
+ result = new QEntity;
+ for (QEntity *entity : qAsConst(entities))
+ entity->setParent(result);
+ }
+ }
+
+ //If the entity contains no meshes, results will still be null here
+ if (result == nullptr)
+ result = new QEntity;
+
+ {
+ const auto children = jsonObj.value(KEY_CHILDREN).toArray();
+ for (const QJsonValue &c : children) {
+ QEntity* child = node(c.toString());
+ if (!child)
+ continue;
+ child->setParent(result);
+ }
+ }
+
+ renameFromJson(jsonObj, result);
+
+
+ // Node Transforms
+ Qt3DCore::QTransform *trans = nullptr;
+ const auto matrix = jsonObj.value(KEY_MATRIX);
+ if (!matrix.isUndefined()) {
+ QMatrix4x4 m(Qt::Uninitialized);
+
+ QJsonArray matrixValues = matrix.toArray();
+ for (int i=0; i<16; ++i) {
+ double v = matrixValues.at( i ).toDouble();
+ m(i % 4, i >> 2) = v;
+ }
+
+ // ADD MATRIX TRANSFORM COMPONENT TO ENTITY
+ if (trans == nullptr)
+ trans = new Qt3DCore::QTransform;
+ trans->setMatrix(m);
+ }
+
+ // Rotation quaternion
+ const auto rotation = jsonObj.value(KEY_ROTATION);
+ if (!rotation.isUndefined()) {
+ if (!trans)
+ trans = new Qt3DCore::QTransform;
+
+ const QJsonArray quaternionValues = rotation.toArray();
+ QQuaternion quaternion(quaternionValues[0].toDouble(),
+ quaternionValues[1].toDouble(),
+ quaternionValues[2].toDouble(),
+ quaternionValues[3].toDouble());
+ trans->setRotation(quaternion);
+ }
+
+ // Translation
+ const auto translation = jsonObj.value(KEY_TRANSLATION);
+ if (!translation.isUndefined()) {
+ if (!trans)
+ trans = new Qt3DCore::QTransform;
+
+ const QJsonArray translationValues = translation.toArray();
+ trans->setTranslation(QVector3D(translationValues[0].toDouble(),
+ translationValues[1].toDouble(),
+ translationValues[2].toDouble()));
+ }
+
+ // Scale
+ const auto scale = jsonObj.value(KEY_SCALE);
+ if (!scale.isUndefined()) {
+ if (!trans)
+ trans = new Qt3DCore::QTransform;
+
+ const QJsonArray scaleValues = scale.toArray();
+ trans->setScale3D(QVector3D(scaleValues[0].toDouble(),
+ scaleValues[1].toDouble(),
+ scaleValues[2].toDouble()));
+ }
+
+ // Add the Transform component
+ if (trans != nullptr)
+ result->addComponent(trans);
+
+ const auto cameraVal = jsonObj.value(KEY_CAMERA);
+ if (!cameraVal.isUndefined()) {
+ QCameraLens* cam = camera(cameraVal.toString());
+ if (Q_UNLIKELY(!cam)) {
+ qCWarning(GLTFIOLog) << "failed to build camera:" << cameraVal
+ << "on node" << id;
+ } else {
+ result->addComponent(cam);
+ }
+ } // of have camera attribute
+
+ return result;
+}
+
+Qt3DCore::QEntity* GLTFIO::scene(const QString &id)
+{
+ parse();
+
+ QJsonObject scenes = m_json.object().value(KEY_SCENES).toObject();
+ const auto sceneVal = scenes.value(id);
+ if (Q_UNLIKELY(sceneVal.isUndefined())) {
+ if (Q_UNLIKELY(!id.isNull()))
+ qCWarning(GLTFIOLog, "GLTF: no such scene %ls in file %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ return defaultScene();
+ }
+
+ QJsonObject sceneObj = sceneVal.toObject();
+ QEntity* sceneEntity = new QEntity;
+ const auto nodes = sceneObj.value(KEY_NODES).toArray();
+ for (const QJsonValue &nnv : nodes) {
+ QString nodeName = nnv.toString();
+ QEntity* child = node(nodeName);
+ if (!child)
+ continue;
+ child->setParent(sceneEntity);
+ }
+
+ return sceneEntity;
+}
+
+GLTFIO::BufferData::BufferData()
+ : length(0)
+ , data(nullptr)
+{
+}
+
+GLTFIO::BufferData::BufferData(const QJsonObject &json)
+ : length(json.value(KEY_BYTE_LENGTH).toInt()),
+ path(json.value(KEY_URI).toString()),
+ data(nullptr)
+{
+}
+
+GLTFIO::ParameterData::ParameterData() :
+ type(0)
+{
+
+}
+
+GLTFIO::ParameterData::ParameterData(const QJsonObject &json)
+ : semantic(json.value(KEY_SEMANTIC).toString()),
+ type(json.value(KEY_TYPE).toInt())
+{
+}
+
+GLTFIO::AccessorData::AccessorData()
+ : type(QAttribute::Float)
+ , dataSize(0)
+ , count(0)
+ , offset(0)
+ , stride(0)
+{
+
+}
+
+GLTFIO::AccessorData::AccessorData(const QJsonObject &json)
+ : bufferViewName(json.value(KEY_BUFFER_VIEW).toString()),
+ type(accessorTypeFromJSON(json.value(KEY_COMPONENT_TYPE).toInt())),
+ dataSize(accessorDataSizeFromJson(json.value(KEY_TYPE).toString())),
+ count(json.value(KEY_COUNT).toInt()),
+ offset(0),
+ stride(0)
+{
+ const auto byteOffset = json.value(KEY_BYTE_OFFSET);
+ if (!byteOffset.isUndefined())
+ offset = byteOffset.toInt();
+ const auto byteStride = json.value(KEY_BYTE_STRIDE);
+ if (!byteStride.isUndefined())
+ stride = byteStride.toInt();
+}
+
+bool GLTFIO::isGLTFPath(const QString& path)
+{
+ QFileInfo finfo(path);
+ if (!finfo.exists())
+ return false;
+
+ // might need to detect other things in the future, but would
+ // prefer to avoid doing a full parse.
+ QString suffix = finfo.suffix().toLower();
+ return suffix == QLatin1String("json") || suffix == QLatin1String("gltf") || suffix == QLatin1String("qgltf");
+}
+
+void GLTFIO::renameFromJson(const QJsonObject &json, QObject * const object)
+{
+ const auto name = json.value(KEY_NAME);
+ if (!name.isUndefined())
+ object->setObjectName(name.toString());
+}
+
+bool GLTFIO::hasStandardUniformNameFromSemantic(const QString &semantic)
+{
+ //Standard Uniforms
+ if (semantic.isEmpty())
+ return false;
+ switch (semantic.at(0).toLatin1()) {
+ case 'L':
+ // return semantic == QLatin1String("LOCAL");
+ return false;
+ case 'M':
+ return semantic == QLatin1String("MODEL")
+ || semantic == QLatin1String("MODELVIEW")
+ || semantic == QLatin1String("MODELVIEWPROJECTION")
+ || semantic == QLatin1String("MODELINVERSE")
+ || semantic == QLatin1String("MODELVIEWPROJECTIONINVERSE")
+ || semantic == QLatin1String("MODELINVERSETRANSPOSE")
+ || semantic == QLatin1String("MODELVIEWINVERSETRANSPOSE");
+ case 'V':
+ return semantic == QLatin1String("VIEW")
+ || semantic == QLatin1String("VIEWINVERSE")
+ || semantic == QLatin1String("VIEWPORT");
+ case 'P':
+ return semantic == QLatin1String("PROJECTION")
+ || semantic == QLatin1String("PROJECTIONINVERSE");
+ }
+ return false;
+}
+
+QString GLTFIO::standardAttributeNameFromSemantic(const QString &semantic)
+{
+ //Standard Attributes
+ if (semantic.startsWith(QLatin1String("POSITION")))
+ return QAttribute::defaultPositionAttributeName();
+ if (semantic.startsWith(QLatin1String("NORMAL")))
+ return QAttribute::defaultNormalAttributeName();
+ if (semantic.startsWith(QLatin1String("TEXCOORD")))
+ return QAttribute::defaultTextureCoordinateAttributeName();
+ if (semantic.startsWith(QLatin1String("COLOR")))
+ return QAttribute::defaultColorAttributeName();
+ if (semantic.startsWith(QLatin1String("TANGENT")))
+ return QAttribute::defaultTangentAttributeName();
+
+// if (semantic.startsWith(QLatin1String("JOINT")));
+// if (semantic.startsWith(QLatin1String("JOINTMATRIX")));
+// if (semantic.startsWith(QLatin1String("WEIGHT")));
+
+ return QString();
+}
+
+QParameter *GLTFIO::parameterFromTechnique(QTechnique *technique, const QString &parameterName)
+{
+ const auto parameters = technique->parameters();
+ for (QParameter *parameter : parameters) {
+ if (parameter->name() == parameterName) {
+ return parameter;
+ }
+ }
+
+ return nullptr;
+}
+
+Qt3DCore::QEntity* GLTFIO::defaultScene()
+{
+ if (Q_UNLIKELY(m_defaultScene.isEmpty())) {
+ qCWarning(GLTFIOLog, "no default scene");
+ return NULL;
+ }
+
+ return scene(m_defaultScene);
+}
+
+QMaterial *GLTFIO::materialWithCustomShader(const QString &id, const QJsonObject &jsonObj)
+{
+ //Default ES2 Technique
+ QString techniqueName = jsonObj.value(KEY_TECHNIQUE).toString();
+ const auto it = qAsConst(m_techniques).find(techniqueName);
+ if (Q_UNLIKELY(it == m_techniques.cend())) {
+ qCWarning(GLTFIOLog, "unknown technique %ls for material %ls in GLTF file %ls",
+ qUtf16PrintableImpl(techniqueName), qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ return NULL;
+ }
+ QTechnique *technique = *it;
+ technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
+ technique->graphicsApiFilter()->setMajorVersion(2);
+ technique->graphicsApiFilter()->setMinorVersion(0);
+ technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+
+ //Optional Core technique
+ QTechnique *coreTechnique = nullptr;
+ QTechnique *gl2Technique = nullptr;
+ QString coreTechniqueName = jsonObj.value(KEY_TECHNIQUE_CORE).toString();
+ if (!coreTechniqueName.isNull()) {
+ const auto it = qAsConst(m_techniques).find(coreTechniqueName);
+ if (Q_UNLIKELY(it == m_techniques.cend())) {
+ qCWarning(GLTFIOLog, "unknown technique %ls for material %ls in GLTF file %ls",
+ qUtf16PrintableImpl(coreTechniqueName), qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ } else {
+ coreTechnique = it.value();
+ coreTechnique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ coreTechnique->graphicsApiFilter()->setMajorVersion(3);
+ coreTechnique->graphicsApiFilter()->setMinorVersion(1);
+ coreTechnique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+ }
+ }
+ //Optional GL2 technique
+ QString gl2TechniqueName = jsonObj.value(KEY_TECHNIQUE_GL2).toString();
+ if (!gl2TechniqueName.isNull()) {
+ const auto it = qAsConst(m_techniques).find(gl2TechniqueName);
+ if (Q_UNLIKELY(it == m_techniques.cend())) {
+ qCWarning(GLTFIOLog, "unknown technique %ls for material %ls in GLTF file %ls",
+ qUtf16PrintableImpl(gl2TechniqueName), qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ } else {
+ gl2Technique = it.value();
+ gl2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl2Technique->graphicsApiFilter()->setMajorVersion(2);
+ gl2Technique->graphicsApiFilter()->setMinorVersion(0);
+ gl2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+ }
+ }
+
+
+ // glTF doesn't deal in effects, but we need a trivial one to wrap
+ // up our techniques
+ // However we need to create a unique effect for each material instead
+ // of caching because QMaterial does not keep up with effects
+ // its not the parent of.
+ QEffect* effect = new QEffect;
+ effect->setObjectName(techniqueName);
+ effect->addTechnique(technique);
+ if (coreTechnique != nullptr)
+ effect->addTechnique(coreTechnique);
+ if (gl2Technique != nullptr)
+ effect->addTechnique(gl2Technique);
+
+ QMaterial* mat = new QMaterial;
+ mat->setEffect(effect);
+
+ renameFromJson(jsonObj, mat);
+
+ const QJsonObject values = jsonObj.value(KEY_VALUES).toObject();
+ for (auto it = values.begin(), end = values.end(); it != end; ++it) {
+ const QString vName = it.key();
+ QParameter *param = parameterFromTechnique(technique, vName);
+
+ if (param == nullptr && coreTechnique != nullptr) {
+ param = parameterFromTechnique(coreTechnique, vName);
+ }
+
+ if (param == nullptr && gl2Technique != nullptr) {
+ param = parameterFromTechnique(gl2Technique, vName);
+ }
+
+ if (Q_UNLIKELY(!param)) {
+ qCWarning(GLTFIOLog, "unknown parameter: %ls in technique %ls processing material %ls",
+ qUtf16PrintableImpl(vName), qUtf16PrintableImpl(techniqueName), qUtf16PrintableImpl(id));
+ continue;
+ }
+
+ ParameterData paramData = m_parameterDataDict.value(param);
+ QVariant var = parameterValueFromJSON(paramData.type, it.value());
+
+ mat->addParameter(new QParameter(param->name(), var));
+ } // of material technique-instance values iteration
+
+ return mat;
+}
+
+static inline QVariant vec4ToRgb(const QVariant &vec4Var)
+{
+ const QVector4D v = vec4Var.value<QVector4D>();
+ return QVariant(QColor::fromRgbF(v.x(), v.y(), v.z()));
+}
+
+QMaterial *GLTFIO::commonMaterial(const QJsonObject &jsonObj)
+{
+ QVariantHash params;
+ bool hasDiffuseMap = false;
+ bool hasSpecularMap = false;
+ bool hasNormalMap = false;
+
+ const QJsonObject values = jsonObj.value(KEY_VALUES).toObject();
+ for (auto it = values.begin(), end = values.end(); it != end; ++it) {
+ const QString vName = it.key();
+ const QJsonValue val = it.value();
+ QVariant var;
+ QString propertyName = vName;
+ if (vName == QLatin1String("ambient") && val.isArray()) {
+ var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
+ } else if (vName == QLatin1String("diffuse")) {
+ if (val.isString()) {
+ var = parameterValueFromJSON(GL_SAMPLER_2D, val);
+ hasDiffuseMap = true;
+ } else if (val.isArray()) {
+ var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
+ }
+ } else if (vName == QLatin1String("specular")) {
+ if (val.isString()) {
+ var = parameterValueFromJSON(GL_SAMPLER_2D, val);
+ hasSpecularMap = true;
+ } else if (val.isArray()) {
+ var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
+ }
+ } else if (vName == QLatin1String("shininess") && val.isDouble()) {
+ var = parameterValueFromJSON(GL_FLOAT, val);
+ } else if (vName == QLatin1String("normalmap") && val.isString()) {
+ var = parameterValueFromJSON(GL_SAMPLER_2D, val);
+ propertyName = QStringLiteral("normal");
+ hasNormalMap = true;
+ } else if (vName == QLatin1String("transparency")) {
+ qCWarning(GLTFIOLog, "Semi-transparent common materials are not currently supported, ignoring alpha");
+ }
+ if (var.isValid())
+ params[propertyName] = var;
+ }
+
+ QMaterial *mat = nullptr;
+ if (hasNormalMap) {
+ if (hasSpecularMap) {
+ mat = new QNormalDiffuseSpecularMapMaterial;
+ } else {
+ if (Q_UNLIKELY(!hasDiffuseMap))
+ qCWarning(GLTFIOLog, "Common material with normal and specular maps needs a diffuse map as well");
+ else
+ mat = new QNormalDiffuseMapMaterial;
+ }
+ } else {
+ if (hasSpecularMap) {
+ if (Q_UNLIKELY(!hasDiffuseMap))
+ qCWarning(GLTFIOLog, "Common material with specular map needs a diffuse map as well");
+ else
+ mat = new QDiffuseSpecularMapMaterial;
+ } else if (hasDiffuseMap) {
+ mat = new QDiffuseMapMaterial;
+ } else {
+ mat = new QPhongMaterial;
+ }
+ }
+
+ if (Q_UNLIKELY(!mat)) {
+ qCWarning(GLTFIOLog, "Could not find a suitable built-in material for KHR_materials_common");
+ } else {
+ for (QVariantHash::const_iterator it = params.constBegin(), itEnd = params.constEnd(); it != itEnd; ++it)
+ mat->setProperty(it.key().toUtf8(), it.value());
+ }
+
+ return mat;
+}
+
+QMaterial* GLTFIO::material(const QString &id)
+{
+ const auto it = qAsConst(m_materialCache).find(id);
+ if (it != m_materialCache.cend())
+ return it.value();
+
+ QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject();
+ const auto jsonVal = mats.value(id);
+ if (Q_UNLIKELY(jsonVal.isUndefined())) {
+ qCWarning(GLTFIOLog, "unknown material %ls in GLTF file %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ return NULL;
+ }
+
+ const QJsonObject jsonObj = jsonVal.toObject();
+
+ QMaterial *mat = nullptr;
+
+ // Prefer common materials over custom shaders.
+ const auto extensionMat = jsonObj.value(KEY_EXTENSIONS).toObject().value(KEY_COMMON_MAT);
+ if (!extensionMat.isUndefined())
+ mat = commonMaterial(extensionMat.toObject());
+
+ if (!mat)
+ mat = materialWithCustomShader(id, jsonObj);
+
+ m_materialCache[id] = mat;
+ return mat;
+}
+
+QCameraLens* GLTFIO::camera(const QString &id) const
+{
+ const auto jsonVal = m_json.object().value(KEY_CAMERAS).toObject().value(id);
+ if (Q_UNLIKELY(jsonVal.isUndefined())) {
+ qCWarning(GLTFIOLog, "unknown camera %ls in GLTF file %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(m_basePath));
+ return nullptr;
+ }
+
+ QJsonObject jsonObj = jsonVal.toObject();
+ QString camTy = jsonObj.value(KEY_TYPE).toString();
+
+ if (camTy == QLatin1String("perspective")) {
+ const auto pVal = jsonObj.value(KEY_PERSPECTIVE);
+ if (Q_UNLIKELY(pVal.isUndefined())) {
+ qCWarning(GLTFIOLog, "camera: %ls missing 'perspective' object",
+ qUtf16PrintableImpl(id));
+ return nullptr;
+ }
+
+ const QJsonObject pObj = pVal.toObject();
+ double aspectRatio = pObj.value(KEY_ASPECT_RATIO).toDouble();
+ double yfov = pObj.value(KEY_YFOV).toDouble();
+ double frustumNear = pObj.value(KEY_ZNEAR).toDouble();
+ double frustumFar = pObj.value(KEY_ZFAR).toDouble();
+
+ QCameraLens* result = new QCameraLens;
+ result->setPerspectiveProjection(yfov, aspectRatio, frustumNear, frustumFar);
+ return result;
+ } else if (camTy == QLatin1String("orthographic")) {
+ qCWarning(GLTFIOLog, "implement me");
+
+ return nullptr;
+ } else {
+ qCWarning(GLTFIOLog, "camera: %ls has unsupported type: %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(camTy));
+ return nullptr;
+ }
+}
+
+
+void GLTFIO::parse()
+{
+ if (m_parseDone)
+ return;
+
+ const QJsonObject buffers = m_json.object().value(KEY_BUFFERS).toObject();
+ for (auto it = buffers.begin(), end = buffers.end(); it != end; ++it)
+ processJSONBuffer(it.key(), it.value().toObject());
+
+ const QJsonObject views = m_json.object().value(KEY_BUFFER_VIEWS).toObject();
+ loadBufferData();
+ for (auto it = views.begin(), end = views.end(); it != end; ++it)
+ processJSONBufferView(it.key(), it.value().toObject());
+ unloadBufferData();
+
+ const QJsonObject shaders = m_json.object().value(KEY_SHADERS).toObject();
+ for (auto it = shaders.begin(), end = shaders.end(); it != end; ++it)
+ processJSONShader(it.key(), it.value().toObject());
+
+ const QJsonObject programs = m_json.object().value(KEY_PROGRAMS).toObject();
+ for (auto it = programs.begin(), end = programs.end(); it != end; ++it)
+ processJSONProgram(it.key(), it.value().toObject());
+
+ const QJsonObject techniques = m_json.object().value(KEY_TECHNIQUES).toObject();
+ for (auto it = techniques.begin(), end = techniques.end(); it != end; ++it)
+ processJSONTechnique(it.key(), it.value().toObject());
+
+ const QJsonObject attrs = m_json.object().value(KEY_ACCESSORS).toObject();
+ for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it)
+ processJSONAccessor(it.key(), it.value().toObject());
+
+ const QJsonObject meshes = m_json.object().value(KEY_MESHES).toObject();
+ for (auto it = meshes.begin(), end = meshes.end(); it != end; ++it)
+ processJSONMesh(it.key(), it.value().toObject());
+
+ const QJsonObject images = m_json.object().value(KEY_IMAGES).toObject();
+ for (auto it = images.begin(), end = images.end(); it != end; ++it)
+ processJSONImage(it.key(), it.value().toObject());
+
+ const QJsonObject textures = m_json.object().value(KEY_TEXTURES).toObject();
+ for (auto it = textures.begin(), end = textures.end(); it != end; ++it)
+ processJSONTexture(it.key(), it.value().toObject());
+
+ m_defaultScene = m_json.object().value(KEY_SCENE).toString();
+ m_parseDone = true;
+}
+
+namespace {
+template <typename C>
+void delete_if_without_parent(const C &c)
+{
+ for (const auto *e : c) {
+ if (!e->parent())
+ delete e;
+ }
+}
+} // unnamed namespace
+
+void GLTFIO::cleanup()
+{
+ m_meshDict.clear();
+ m_meshMaterialDict.clear();
+ m_accessorDict.clear();
+ delete_if_without_parent(m_materialCache);
+ m_materialCache.clear();
+ m_bufferDatas.clear();
+ m_buffers.clear();
+ m_shaderPaths.clear();
+ delete_if_without_parent(m_programs);
+ m_programs.clear();
+ delete_if_without_parent(m_techniques);
+ m_techniques.clear();
+ delete_if_without_parent(m_textures);
+ m_textures.clear();
+ m_imagePaths.clear();
+ m_defaultScene.clear();
+ m_parameterDataDict.clear();
+}
+
+void GLTFIO::processJSONBuffer(const QString &id, const QJsonObject& json)
+{
+ // simply cache buffers for lookup by buffer-views
+ m_bufferDatas[id] = BufferData(json);
+}
+
+void GLTFIO::processJSONBufferView(const QString &id, const QJsonObject& json)
+{
+ QString bufName = json.value(KEY_BUFFER).toString();
+ const auto it = qAsConst(m_bufferDatas).find(bufName);
+ if (Q_UNLIKELY(it == m_bufferDatas.cend())) {
+ qCWarning(GLTFIOLog, "unknown buffer: %ls processing view: %ls",
+ qUtf16PrintableImpl(bufName), qUtf16PrintableImpl(id));
+ return;
+ }
+ const auto &bufferData = *it;
+
+ int target = json.value(KEY_TARGET).toInt();
+ Qt3DRender::QBuffer::BufferType ty(Qt3DRender::QBuffer::VertexBuffer);
+
+ switch (target) {
+ case GL_ARRAY_BUFFER: ty = Qt3DRender::QBuffer::VertexBuffer; break;
+ case GL_ELEMENT_ARRAY_BUFFER: ty = Qt3DRender::QBuffer::IndexBuffer; break;
+ default:
+ qCWarning(GLTFIOLog, "buffer %ls unsupported target: %d",
+ qUtf16PrintableImpl(id), target);
+ return;
+ }
+
+ quint64 offset = 0;
+ const auto byteOffset = json.value(KEY_BYTE_OFFSET);
+ if (!byteOffset.isUndefined()) {
+ offset = byteOffset.toInt();
+ qCDebug(GLTFIOLog, "bv: %ls has offset: %lld", qUtf16PrintableImpl(id), offset);
+ }
+
+ quint64 len = json.value(KEY_BYTE_LENGTH).toInt();
+
+ QByteArray bytes = bufferData.data->mid(offset, len);
+ if (Q_UNLIKELY(bytes.count() != int(len))) {
+ qCWarning(GLTFIOLog, "failed to read sufficient bytes from: %ls for view %ls",
+ qUtf16PrintableImpl(bufferData.path), qUtf16PrintableImpl(id));
+ }
+
+ Qt3DRender::QBuffer *b(new Qt3DRender::QBuffer(ty));
+ b->setData(bytes);
+ m_buffers[id] = b;
+}
+
+void GLTFIO::processJSONShader(const QString &id, const QJsonObject &jsonObject)
+{
+ // shaders are trivial for the moment, defer the real work
+ // to the program section
+ QString path = jsonObject.value(KEY_URI).toString();
+
+ QFileInfo info(m_basePath, path);
+ if (Q_UNLIKELY(!info.exists())) {
+ qCWarning(GLTFIOLog, "can't find shader %ls from path %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(path));
+ return;
+ }
+
+ m_shaderPaths[id] = info.absoluteFilePath();
+}
+
+void GLTFIO::processJSONProgram(const QString &id, const QJsonObject &jsonObject)
+{
+ QString fragName = jsonObject.value(KEY_FRAGMENT_SHADER).toString(),
+ vertName = jsonObject.value(KEY_VERTEX_SHADER).toString();
+ const auto fragIt = qAsConst(m_shaderPaths).find(fragName),
+ vertIt = qAsConst(m_shaderPaths).find(vertName);
+ if (Q_UNLIKELY(fragIt == m_shaderPaths.cend() || vertIt == m_shaderPaths.cend())) {
+ qCWarning(GLTFIOLog, "program: %ls missing shader: %ls %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(fragName), qUtf16PrintableImpl(vertName));
+ return;
+ }
+
+ QShaderProgram* prog = new QShaderProgram;
+ prog->setObjectName(id);
+ prog->setFragmentShaderCode(QShaderProgram::loadSource(QUrl::fromLocalFile(fragIt.value())));
+ prog->setVertexShaderCode(QShaderProgram::loadSource(QUrl::fromLocalFile(vertIt.value())));
+ m_programs[id] = prog;
+}
+
+void GLTFIO::processJSONTechnique(const QString &id, const QJsonObject &jsonObject )
+{
+ QTechnique *t = new QTechnique;
+ t->setObjectName(id);
+
+ // Parameters
+ QHash<QString, QParameter*> paramDict;
+ const QJsonObject params = jsonObject.value(KEY_PARAMETERS).toObject();
+ for (auto it = params.begin(), end = params.end(); it != end; ++it) {
+ const QString pname = it.key();
+ const QJsonObject po = it.value().toObject();
+
+ //QString semantic = po.value(KEY_SEMANTIC).toString();
+ QParameter *p = new QParameter(t);
+ p->setName(pname);
+ m_parameterDataDict.insert(p, ParameterData(po));
+
+ //If the parameter has default value, set it
+ QJsonValue value = po.value(KEY_VALUE);
+ if (!value.isUndefined()) {
+ int dataType = po.value(KEY_TYPE).toInt();
+ p->setValue(parameterValueFromJSON(dataType, value));
+ }
+
+ t->addParameter(p);
+
+ paramDict[pname] = p;
+ } // of parameters iteration
+
+ // Program
+ QRenderPass* pass = new QRenderPass;
+ QString programName = jsonObject.value(KEY_PROGRAM).toString();
+ const auto progIt = qAsConst(m_programs).find(programName);
+ if (Q_UNLIKELY(progIt == m_programs.cend())) {
+ qCWarning(GLTFIOLog, "technique %ls: missing program %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(programName));
+ } else {
+ pass->setShaderProgram(progIt.value());
+ }
+
+ // Attributes
+ const QJsonObject attrs = jsonObject.value(KEY_ATTRIBUTES).toObject();
+ for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it) {
+ QString pname = it.value().toString();
+ QParameter *parameter = paramDict.value(pname, nullptr);
+ QString attributeName = pname;
+ if (Q_UNLIKELY(!parameter)) {
+ qCWarning(GLTFIOLog, "attribute %ls defined in instanceProgram but not as parameter",
+ qUtf16PrintableImpl(pname));
+ continue;
+ }
+ //Check if the parameter has a standard attribute semantic
+ const auto paramDataIt = m_parameterDataDict.find(parameter);
+ QString standardAttributeName = standardAttributeNameFromSemantic(paramDataIt->semantic);
+ if (!standardAttributeName.isNull()) {
+ attributeName = standardAttributeName;
+ t->removeParameter(parameter);
+ m_parameterDataDict.erase(paramDataIt);
+ delete parameter;
+ }
+
+ } // of program-instance attributes
+
+ // Uniforms
+ const QJsonObject uniforms = jsonObject.value(KEY_UNIFORMS).toObject();
+ for (auto it = uniforms.begin(), end = uniforms.end(); it != end; ++it) {
+ const QString pname = it.value().toString();
+ QParameter *parameter = paramDict.value(pname, nullptr);
+ if (Q_UNLIKELY(!parameter)) {
+ qCWarning(GLTFIOLog, "uniform %ls defined in instanceProgram but not as parameter",
+ qUtf16PrintableImpl(pname));
+ continue;
+ }
+ //Check if the parameter has a standard uniform semantic
+ const auto paramDataIt = m_parameterDataDict.find(parameter);
+ if (hasStandardUniformNameFromSemantic(paramDataIt->semantic)) {
+ t->removeParameter(parameter);
+ m_parameterDataDict.erase(paramDataIt);
+ delete parameter;
+ }
+ } // of program-instance uniforms
+
+
+ // States
+ QJsonObject states = jsonObject.value(KEY_STATES).toObject();
+
+ //Process states to enable
+ const QJsonArray enableStatesArray = states.value(KEY_ENABLE).toArray();
+ QVector<int> enableStates;
+ for (const QJsonValue &enableValue : enableStatesArray)
+ enableStates.append(enableValue.toInt());
+
+ //Process the list of state functions
+ const QJsonObject functions = states.value(KEY_FUNCTIONS).toObject();
+ for (auto it = functions.begin(), end = functions.end(); it != end; ++it) {
+ int enableStateType = 0;
+ QRenderState *renderState = buildState(it.key(), it.value(), enableStateType);
+ if (renderState != nullptr) {
+ //Remove the need to set a default state values for enableStateType
+ enableStates.removeOne(enableStateType);
+ pass->addRenderState(renderState);
+ }
+ }
+
+ //Create render states with default values for any remaining enable states
+ for (int enableState : qAsConst(enableStates)) {
+ QRenderState *renderState = buildStateEnable(enableState);
+ if (renderState != nullptr)
+ pass->addRenderState(renderState);
+ }
+
+
+ t->addRenderPass(pass);
+
+ m_techniques[id] = t;
+}
+
+void GLTFIO::processJSONAccessor( const QString &id, const QJsonObject& json )
+{
+ m_accessorDict[id] = AccessorData(json);
+}
+
+void GLTFIO::processJSONMesh(const QString &id, const QJsonObject &json)
+{
+ const QJsonArray primitivesArray = json.value(KEY_PRIMITIVES).toArray();
+ for (const QJsonValue &primitiveValue : primitivesArray) {
+ QJsonObject primitiveObject = primitiveValue.toObject();
+ int type = primitiveObject.value(KEY_MODE).toInt();
+ QString material = primitiveObject.value(KEY_MATERIAL).toString();
+
+ if (Q_UNLIKELY(material.isEmpty())) {
+ qCWarning(GLTFIOLog, "malformed primitive on %ls, missing material value %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(material));
+ continue;
+ }
+
+ QGeometryRenderer *geometryRenderer = new QGeometryRenderer;
+ QGeometry *meshGeometry = new QGeometry(geometryRenderer);
+
+ //Set Primitive Type
+ geometryRenderer->setPrimitiveType(static_cast<QGeometryRenderer::PrimitiveType>(type));
+
+ //Save Material for mesh
+ m_meshMaterialDict[geometryRenderer] = material;
+
+ const QJsonObject attrs = primitiveObject.value(KEY_ATTRIBUTES).toObject();
+ for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it) {
+ QString k = it.value().toString();
+ const auto accessorIt = qAsConst(m_accessorDict).find(k);
+ if (Q_UNLIKELY(accessorIt == m_accessorDict.cend())) {
+ qCWarning(GLTFIOLog, "unknown attribute accessor: %ls on mesh %ls",
+ qUtf16PrintableImpl(k), qUtf16PrintableImpl(id));
+ continue;
+ }
+
+ const QString attrName = it.key();
+ QString attributeName = standardAttributeNameFromSemantic(attrName);
+ if (attributeName.isEmpty())
+ attributeName = attrName;
+
+ //Get buffer handle for accessor
+ Qt3DRender::QBuffer *buffer = m_buffers.value(accessorIt->bufferViewName, nullptr);
+ if (Q_UNLIKELY(!buffer)) {
+ qCWarning(GLTFIOLog, "unknown buffer-view: %ls processing accessor: %ls",
+ qUtf16PrintableImpl(accessorIt->bufferViewName), qUtf16PrintableImpl(id));
+ continue;
+ }
+
+ QAttribute *attribute = new QAttribute(buffer,
+ attributeName,
+ accessorIt->type,
+ accessorIt->dataSize,
+ accessorIt->count,
+ accessorIt->offset,
+ accessorIt->stride);
+ attribute->setAttributeType(QAttribute::VertexAttribute);
+ meshGeometry->addAttribute(attribute);
+ }
+
+ const auto indices = primitiveObject.value(KEY_INDICES);
+ if (!indices.isUndefined()) {
+ QString k = indices.toString();
+ const auto accessorIt = qAsConst(m_accessorDict).find(k);
+ if (Q_UNLIKELY(accessorIt == m_accessorDict.cend())) {
+ qCWarning(GLTFIOLog, "unknown index accessor: %ls on mesh %ls",
+ qUtf16PrintableImpl(k), qUtf16PrintableImpl(id));
+ } else {
+ //Get buffer handle for accessor
+ Qt3DRender::QBuffer *buffer = m_buffers.value(accessorIt->bufferViewName, nullptr);
+ if (Q_UNLIKELY(!buffer)) {
+ qCWarning(GLTFIOLog, "unknown buffer-view: %ls processing accessor: %ls",
+ qUtf16PrintableImpl(accessorIt->bufferViewName), qUtf16PrintableImpl(id));
+ continue;
+ }
+
+ QAttribute *attribute = new QAttribute(buffer,
+ accessorIt->type,
+ accessorIt->dataSize,
+ accessorIt->count,
+ accessorIt->offset,
+ accessorIt->stride);
+ attribute->setAttributeType(QAttribute::IndexAttribute);
+ meshGeometry->addAttribute(attribute);
+ }
+ } // of has indices
+
+ geometryRenderer->setGeometry(meshGeometry);
+
+ m_meshDict.insert( id, geometryRenderer);
+ } // of primitives iteration
+}
+
+void GLTFIO::processJSONImage(const QString &id, const QJsonObject &jsonObject)
+{
+ QString path = jsonObject.value(KEY_URI).toString();
+ QFileInfo info(m_basePath, path);
+ if (Q_UNLIKELY(!info.exists())) {
+ qCWarning(GLTFIOLog, "can't find image %ls from path %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(path));
+ return;
+ }
+
+ m_imagePaths[id] = info.absoluteFilePath();
+}
+
+void GLTFIO::processJSONTexture(const QString &id, const QJsonObject &jsonObject)
+{
+ int target = jsonObject.value(KEY_TARGET).toInt(GL_TEXTURE_2D);
+ //TODO: support other targets that GL_TEXTURE_2D (though the spec doesn't support anything else)
+ if (Q_UNLIKELY(target != GL_TEXTURE_2D)) {
+ qCWarning(GLTFIOLog, "unsupported texture target: %d", target);
+ return;
+ }
+
+ QTextureLoader* tex = new QTextureLoader;
+ tex->setMirrored(false);
+
+ QString samplerId = jsonObject.value(KEY_SAMPLER).toString();
+ QString source = jsonObject.value(KEY_SOURCE).toString();
+ const auto imagIt = qAsConst(m_imagePaths).find(source);
+ if (Q_UNLIKELY(imagIt == m_imagePaths.cend())) {
+ qCWarning(GLTFIOLog, "texture %ls references missing image %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(source));
+ return;
+ }
+
+ tex->setSource(QUrl::fromLocalFile(imagIt.value()));
+
+ const auto samplersDictValue = m_json.object().value(KEY_SAMPLERS).toObject().value(samplerId);
+ if (Q_UNLIKELY(samplersDictValue.isUndefined())) {
+ qCWarning(GLTFIOLog, "texture %ls references unknown sampler %ls",
+ qUtf16PrintableImpl(id), qUtf16PrintableImpl(samplerId));
+ return;
+ }
+
+ QJsonObject sampler = samplersDictValue.toObject();
+
+ tex->setWrapMode(QTextureWrapMode(static_cast<QTextureWrapMode::WrapMode>(sampler.value(KEY_WRAP_S).toInt())));
+ tex->setMinificationFilter(static_cast<QAbstractTexture::Filter>(sampler.value(KEY_MIN_FILTER).toInt()));
+ if (tex->minificationFilter() == QAbstractTexture::NearestMipMapLinear ||
+ tex->minificationFilter() == QAbstractTexture::LinearMipMapNearest ||
+ tex->minificationFilter() == QAbstractTexture::NearestMipMapNearest ||
+ tex->minificationFilter() == QAbstractTexture::LinearMipMapLinear) {
+
+ tex->setGenerateMipMaps(true);
+ }
+ tex->setMagnificationFilter(static_cast<QAbstractTexture::Filter>(sampler.value(KEY_MAG_FILTER).toInt()));
+
+ m_textures[id] = tex;
+}
+
+void GLTFIO::loadBufferData()
+{
+ for (auto &bufferData : m_bufferDatas) {
+ if (!bufferData.data) {
+ bufferData.data = new QByteArray(resolveLocalData(bufferData.path));
+ }
+ }
+}
+
+void GLTFIO::unloadBufferData()
+{
+ for (const auto &bufferData : qAsConst(m_bufferDatas)) {
+ QByteArray *data = bufferData.data;
+ delete data;
+ }
+}
+
+QByteArray GLTFIO::resolveLocalData(const QString &path) const
+{
+ QDir d(m_basePath);
+ Q_ASSERT(d.exists());
+
+ QString absPath = d.absoluteFilePath(path);
+ QFile f(absPath);
+ f.open(QIODevice::ReadOnly);
+ return f.readAll();
+}
+
+QVariant GLTFIO::parameterValueFromJSON(int type, const QJsonValue &value) const
+{
+ if (value.isBool()) {
+ if (type == GL_BOOL)
+ return QVariant(static_cast<GLboolean>(value.toBool()));
+ } else if (value.isString()) {
+ if (type == GL_SAMPLER_2D) {
+ //Textures are special because we need to do a lookup to return the
+ //QAbstractTexture
+ QString textureId = value.toString();
+ const auto it = m_textures.find(textureId);
+ if (Q_UNLIKELY(it == m_textures.end())) {
+ qCWarning(GLTFIOLog, "unknown texture %ls", qUtf16PrintableImpl(textureId));
+ return QVariant();
+ } else {
+ return QVariant::fromValue(it.value());
+ }
+ }
+ } else if (value.isDouble()) {
+ switch (type) {
+ case GL_BYTE:
+ return QVariant(static_cast<GLbyte>(value.toInt()));
+ case GL_UNSIGNED_BYTE:
+ return QVariant(static_cast<GLubyte>(value.toInt()));
+ case GL_SHORT:
+ return QVariant(static_cast<GLshort>(value.toInt()));
+ case GL_UNSIGNED_SHORT:
+ return QVariant(static_cast<GLushort>(value.toInt()));
+ case GL_INT:
+ return QVariant(static_cast<GLint>(value.toInt()));
+ case GL_UNSIGNED_INT:
+ return QVariant(static_cast<GLuint>(value.toInt()));
+ case GL_FLOAT:
+ return QVariant(static_cast<GLfloat>(value.toDouble()));
+ }
+ } else if (value.isArray()) {
+
+ const QJsonArray valueArray = value.toArray();
+
+ QVector2D vector2D;
+ QVector3D vector3D;
+ QVector4D vector4D;
+ QVector<float> dataMat2(4, 0.0f);
+ QVector<float> dataMat3(9, 0.0f);
+
+ switch (type) {
+ case GL_BYTE:
+ return QVariant(static_cast<GLbyte>(valueArray.first().toInt()));
+ case GL_UNSIGNED_BYTE:
+ return QVariant(static_cast<GLubyte>(valueArray.first().toInt()));
+ case GL_SHORT:
+ return QVariant(static_cast<GLshort>(valueArray.first().toInt()));
+ case GL_UNSIGNED_SHORT:
+ return QVariant(static_cast<GLushort>(valueArray.first().toInt()));
+ case GL_INT:
+ return QVariant(static_cast<GLint>(valueArray.first().toInt()));
+ case GL_UNSIGNED_INT:
+ return QVariant(static_cast<GLuint>(valueArray.first().toInt()));
+ case GL_FLOAT:
+ return QVariant(static_cast<GLfloat>(valueArray.first().toDouble()));
+ case GL_FLOAT_VEC2:
+ vector2D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble()));
+ vector2D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble()));
+ return QVariant(vector2D);
+ case GL_FLOAT_VEC3:
+ vector3D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble()));
+ vector3D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble()));
+ vector3D.setZ(static_cast<GLfloat>(valueArray.at(2).toDouble()));
+ return QVariant(vector3D);
+ case GL_FLOAT_VEC4:
+ vector4D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble()));
+ vector4D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble()));
+ vector4D.setZ(static_cast<GLfloat>(valueArray.at(2).toDouble()));
+ vector4D.setW(static_cast<GLfloat>(valueArray.at(3).toDouble()));
+ return QVariant(vector4D);
+ case GL_INT_VEC2:
+ vector2D.setX(static_cast<GLint>(valueArray.at(0).toInt()));
+ vector2D.setY(static_cast<GLint>(valueArray.at(1).toInt()));
+ return QVariant(vector2D);
+ case GL_INT_VEC3:
+ vector3D.setX(static_cast<GLint>(valueArray.at(0).toInt()));
+ vector3D.setY(static_cast<GLint>(valueArray.at(1).toInt()));
+ vector3D.setZ(static_cast<GLint>(valueArray.at(2).toInt()));
+ return QVariant(vector3D);
+ case GL_INT_VEC4:
+ vector4D.setX(static_cast<GLint>(valueArray.at(0).toInt()));
+ vector4D.setY(static_cast<GLint>(valueArray.at(1).toInt()));
+ vector4D.setZ(static_cast<GLint>(valueArray.at(2).toInt()));
+ vector4D.setW(static_cast<GLint>(valueArray.at(3).toInt()));
+ return QVariant(vector4D);
+ case GL_BOOL:
+ return QVariant(static_cast<GLboolean>(valueArray.first().toBool()));
+ case GL_BOOL_VEC2:
+ vector2D.setX(static_cast<GLboolean>(valueArray.at(0).toBool()));
+ vector2D.setY(static_cast<GLboolean>(valueArray.at(1).toBool()));
+ return QVariant(vector2D);
+ case GL_BOOL_VEC3:
+ vector3D.setX(static_cast<GLboolean>(valueArray.at(0).toBool()));
+ vector3D.setY(static_cast<GLboolean>(valueArray.at(1).toBool()));
+ vector3D.setZ(static_cast<GLboolean>(valueArray.at(2).toBool()));
+ return QVariant(vector3D);
+ case GL_BOOL_VEC4:
+ vector4D.setX(static_cast<GLboolean>(valueArray.at(0).toBool()));
+ vector4D.setY(static_cast<GLboolean>(valueArray.at(1).toBool()));
+ vector4D.setZ(static_cast<GLboolean>(valueArray.at(2).toBool()));
+ vector4D.setW(static_cast<GLboolean>(valueArray.at(3).toBool()));
+ return QVariant(vector4D);
+ case GL_FLOAT_MAT2:
+ //Matrix2x2 is in Row Major ordering (so we need to convert)
+ dataMat2[0] = static_cast<GLfloat>(valueArray.at(0).toDouble());
+ dataMat2[1] = static_cast<GLfloat>(valueArray.at(2).toDouble());
+ dataMat2[2] = static_cast<GLfloat>(valueArray.at(1).toDouble());
+ dataMat2[3] = static_cast<GLfloat>(valueArray.at(3).toDouble());
+ return QVariant::fromValue(QMatrix2x2(dataMat2.constData()));
+ case GL_FLOAT_MAT3:
+ //Matrix3x3 is in Row Major ordering (so we need to convert)
+ dataMat3[0] = static_cast<GLfloat>(valueArray.at(0).toDouble());
+ dataMat3[1] = static_cast<GLfloat>(valueArray.at(3).toDouble());
+ dataMat3[2] = static_cast<GLfloat>(valueArray.at(6).toDouble());
+ dataMat3[3] = static_cast<GLfloat>(valueArray.at(1).toDouble());
+ dataMat3[4] = static_cast<GLfloat>(valueArray.at(4).toDouble());
+ dataMat3[5] = static_cast<GLfloat>(valueArray.at(7).toDouble());
+ dataMat3[6] = static_cast<GLfloat>(valueArray.at(2).toDouble());
+ dataMat3[7] = static_cast<GLfloat>(valueArray.at(5).toDouble());
+ dataMat3[8] = static_cast<GLfloat>(valueArray.at(8).toDouble());
+ return QVariant::fromValue(QMatrix3x3(dataMat3.constData()));
+ case GL_FLOAT_MAT4:
+ //Matrix4x4 is Column Major ordering
+ return QVariant(QMatrix4x4(static_cast<GLfloat>(valueArray.at(0).toDouble()),
+ static_cast<GLfloat>(valueArray.at(1).toDouble()),
+ static_cast<GLfloat>(valueArray.at(2).toDouble()),
+ static_cast<GLfloat>(valueArray.at(3).toDouble()),
+ static_cast<GLfloat>(valueArray.at(4).toDouble()),
+ static_cast<GLfloat>(valueArray.at(5).toDouble()),
+ static_cast<GLfloat>(valueArray.at(6).toDouble()),
+ static_cast<GLfloat>(valueArray.at(7).toDouble()),
+ static_cast<GLfloat>(valueArray.at(8).toDouble()),
+ static_cast<GLfloat>(valueArray.at(9).toDouble()),
+ static_cast<GLfloat>(valueArray.at(10).toDouble()),
+ static_cast<GLfloat>(valueArray.at(11).toDouble()),
+ static_cast<GLfloat>(valueArray.at(12).toDouble()),
+ static_cast<GLfloat>(valueArray.at(13).toDouble()),
+ static_cast<GLfloat>(valueArray.at(14).toDouble()),
+ static_cast<GLfloat>(valueArray.at(15).toDouble())));
+ case GL_SAMPLER_2D:
+ return QVariant(valueArray.at(0).toString());
+ }
+ }
+ return QVariant();
+}
+
+QAttribute::VertexBaseType GLTFIO::accessorTypeFromJSON(int componentType)
+{
+ if (componentType == GL_BYTE) {
+ return QAttribute::Byte;
+ } else if (componentType == GL_UNSIGNED_BYTE) {
+ return QAttribute::UnsignedByte;
+ } else if (componentType == GL_SHORT) {
+ return QAttribute::Short;
+ } else if (componentType == GL_UNSIGNED_SHORT) {
+ return QAttribute::UnsignedShort;
+ } else if (componentType == GL_UNSIGNED_INT) {
+ return QAttribute::UnsignedInt;
+ } else if (componentType == GL_FLOAT) {
+ return QAttribute::Float;
+ }
+
+ //There shouldn't be an invalid case here
+ qCWarning(GLTFIOLog, "unsupported accessor type %d", componentType);
+ return QAttribute::Float;
+}
+
+uint GLTFIO::accessorDataSizeFromJson(const QString &type)
+{
+ QString typeName = type.toUpper();
+ if (typeName == QLatin1String("SCALAR"))
+ return 1;
+ if (typeName == QLatin1String("VEC2"))
+ return 2;
+ if (typeName == QLatin1String("VEC3"))
+ return 3;
+ if (typeName == QLatin1String("VEC4"))
+ return 4;
+ if (typeName == QLatin1String("MAT2"))
+ return 4;
+ if (typeName == QLatin1String("MAT3"))
+ return 9;
+ if (typeName == QLatin1String("MAT4"))
+ return 16;
+
+ return 0;
+}
+
+QRenderState *GLTFIO::buildStateEnable(int state)
+{
+ int type = 0;
+ //By calling buildState with QJsonValue(), a Render State with
+ //default values is created.
+
+ if (state == GL_BLEND) {
+ //It doesn't make sense to handle this state alone
+ return nullptr;
+ }
+
+ if (state == GL_CULL_FACE) {
+ return buildState(QStringLiteral("cullFace"), QJsonValue(), type);
+ }
+
+ if (state == GL_DEPTH_TEST) {
+ return buildState(QStringLiteral("depthFunc"), QJsonValue(), type);
+ }
+
+ if (state == GL_POLYGON_OFFSET_FILL) {
+ return buildState(QStringLiteral("polygonOffset"), QJsonValue(), type);
+ }
+
+ if (state == GL_SAMPLE_ALPHA_TO_COVERAGE) {
+ return new QAlphaCoverage();
+ }
+
+ if (state == GL_SCISSOR_TEST) {
+ return buildState(QStringLiteral("scissor"), QJsonValue(), type);
+ }
+
+ qCWarning(GLTFIOLog, "unsupported render state: %d", state);
+
+ return nullptr;
+}
+
+QRenderState* GLTFIO::buildState(const QString& functionName, const QJsonValue &value, int &type)
+{
+ type = -1;
+ QJsonArray values = value.toArray();
+
+ if (functionName == QLatin1String("blendColor")) {
+ type = GL_BLEND;
+ //TODO: support render state blendColor
+ qCWarning(GLTFIOLog, "unsupported render state: %ls", qUtf16PrintableImpl(functionName));
+ return nullptr;
+ }
+
+ if (functionName == QLatin1String("blendEquationSeparate")) {
+ type = GL_BLEND;
+ //TODO: support settings blendEquation alpha
+ QBlendEquation *blendEquation = new QBlendEquation;
+ blendEquation->setBlendFunction((QBlendEquation::BlendFunction)values.at(0).toInt(GL_FUNC_ADD));
+ return blendEquation;
+ }
+
+ if (functionName == QLatin1String("blendFuncSeparate")) {
+ type = GL_BLEND;
+ QBlendEquationArguments *blendArgs = new QBlendEquationArguments;
+ blendArgs->setSourceRgb((QBlendEquationArguments::Blending)values.at(0).toInt(GL_ONE));
+ blendArgs->setSourceAlpha((QBlendEquationArguments::Blending)values.at(1).toInt(GL_ONE));
+ blendArgs->setDestinationRgb((QBlendEquationArguments::Blending)values.at(2).toInt(GL_ZERO));
+ blendArgs->setDestinationAlpha((QBlendEquationArguments::Blending)values.at(3).toInt(GL_ZERO));
+ return blendArgs;
+ }
+
+ if (functionName == QLatin1String("colorMask")) {
+ QColorMask *colorMask = new QColorMask;
+ colorMask->setRedMasked(values.at(0).toBool(true));
+ colorMask->setGreenMasked(values.at(1).toBool(true));
+ colorMask->setBlueMasked(values.at(2).toBool(true));
+ colorMask->setAlphaMasked(values.at(3).toBool(true));
+ return colorMask;
+ }
+
+ if (functionName == QLatin1String("cullFace")) {
+ type = GL_CULL_FACE;
+ QCullFace *cullFace = new QCullFace;
+ cullFace->setMode((QCullFace::CullingMode)values.at(0).toInt(GL_BACK));
+ return cullFace;
+ }
+
+ if (functionName == QLatin1String("depthFunc")) {
+ type = GL_DEPTH_TEST;
+ QDepthTest *depthTest = new QDepthTest;
+ depthTest->setDepthFunction((QDepthTest::DepthFunction)values.at(0).toInt(GL_LESS));
+ return depthTest;
+ }
+
+ if (functionName == QLatin1String("depthMask")) {
+ if (!values.at(0).toBool(true)) {
+ QNoDepthMask *depthMask = new QNoDepthMask;
+ return depthMask;
+ }
+ return nullptr;
+ }
+
+ if (functionName == QLatin1String("depthRange")) {
+ //TODO: support render state depthRange
+ qCWarning(GLTFIOLog, "unsupported render state: %ls", qUtf16PrintableImpl(functionName));
+ return nullptr;
+ }
+
+ if (functionName == QLatin1String("frontFace")) {
+ QFrontFace *frontFace = new QFrontFace;
+ frontFace->setDirection((QFrontFace::WindingDirection)values.at(0).toInt(GL_CCW));
+ return frontFace;
+ }
+
+ if (functionName == QLatin1String("lineWidth")) {
+ //TODO: support render state lineWidth
+ qCWarning(GLTFIOLog, "unsupported render state: %ls", qUtf16PrintableImpl(functionName));
+ return nullptr;
+ }
+
+ if (functionName == QLatin1String("polygonOffset")) {
+ type = GL_POLYGON_OFFSET_FILL;
+ QPolygonOffset *polygonOffset = new QPolygonOffset;
+ polygonOffset->setScaleFactor((float)values.at(0).toDouble(0.0f));
+ polygonOffset->setDepthSteps((float)values.at(1).toDouble(0.0f));
+ return polygonOffset;
+ }
+
+ if (functionName == QLatin1String("scissor")) {
+ type = GL_SCISSOR_TEST;
+ QScissorTest *scissorTest = new QScissorTest;
+ scissorTest->setLeft(values.at(0).toDouble(0.0f));
+ scissorTest->setBottom(values.at(1).toDouble(0.0f));
+ scissorTest->setWidth(values.at(2).toDouble(0.0f));
+ scissorTest->setHeight(values.at(3).toDouble(0.0f));
+ return scissorTest;
+ }
+
+ qCWarning(GLTFIOLog, "unsupported render state: %ls", qUtf16PrintableImpl(functionName));
+ return nullptr;
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#include "moc_gltfio.cpp"
diff --git a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
index 7332fa6b5..7921fce64 100644
--- a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
+++ b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
@@ -168,6 +168,7 @@ inline QJsonArray vec2jsvec(const QVector4D &v)
return arr;
}
+#if 0 // unused for now
inline QJsonArray matrix2jsvec(const QMatrix2x2 &matrix)
{
QJsonArray jm;
@@ -185,6 +186,7 @@ inline QJsonArray matrix2jsvec(const QMatrix3x3 &matrix)
jm.append(*mtxp++);
return jm;
}
+#endif
inline QJsonArray matrix2jsvec(const QMatrix4x4 &matrix)
{
@@ -225,7 +227,7 @@ using namespace Qt3DExtras;
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(GLTFExporterLog, "Qt3D.GLTFExport")
+Q_LOGGING_CATEGORY(GLTFExporterLog, "Qt3D.GLTFExport", QtWarningMsg)
const QString MATERIAL_DIFFUSE_COLOR = QStringLiteral("kd");
const QString MATERIAL_SPECULAR_COLOR = QStringLiteral("ks");
@@ -368,7 +370,7 @@ bool GLTFExporter::exportScene(QEntity *sceneRoot, const QString &outDir,
QFile::Permissions targetPermissions = gltfFile.permissions();
// Copy exported scene to actual export directory
- for (auto sourceFileStr : m_exportedFiles) {
+ for (const auto &sourceFileStr : m_exportedFiles) {
QFileInfo fiSource(m_exportDir + sourceFileStr);
QFileInfo fiDestination(finalExportDir + sourceFileStr);
if (fiDestination.exists()) {
@@ -522,7 +524,7 @@ void GLTFExporter::copyTextures()
void GLTFExporter::createShaders()
{
qCDebug(GLTFExporterLog, "Creating shaders...");
- for (auto si : m_shaderInfo) {
+ for (const auto &si : m_shaderInfo) {
const QString fileName = m_exportDir + si.uri;
QFile f(fileName);
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
@@ -938,11 +940,11 @@ void GLTFExporter::parseMeshes()
qCDebug(GLTFExporterLog, " Vertex buffer size (bytes): %i", vertexBuf.size());
qCDebug(GLTFExporterLog, " Index buffer size (bytes): %i", indexBuf.size());
QStringList sl;
- for (auto bv : meshInfo.views)
+ for (const auto &bv : meshInfo.views)
sl << bv.name;
qCDebug(GLTFExporterLog) << " buffer views:" << sl;
sl.clear();
- for (auto acc : meshInfo.accessors)
+ for (const auto &acc : meshInfo.accessors)
sl << acc.name;
qCDebug(GLTFExporterLog) << " accessors:" << sl;
qCDebug(GLTFExporterLog, " material: '%ls'",
@@ -1127,7 +1129,7 @@ QString GLTFExporter::addShaderInfo(QShaderProgram::ShaderType type, QByteArray
if (code.isEmpty())
return QString();
- for (auto si : m_shaderInfo) {
+ for (const auto &si : m_shaderInfo) {
if (si.type == QShaderProgram::Vertex && code == si.code)
return si.name;
}
@@ -1151,10 +1153,11 @@ bool GLTFExporter::saveScene()
QVector<MeshInfo::BufferView> bvList;
QVector<MeshInfo::Accessor> accList;
- for (auto mi : m_meshInfo.values()) {
- for (auto v : mi.views)
+ for (auto it = m_meshInfo.begin(); it != m_meshInfo.end(); ++it) {
+ auto &mi = it.value();
+ for (auto &v : mi.views)
bvList << v;
- for (auto acc : mi.accessors)
+ for (auto &acc : mi.accessors)
accList << acc;
}
@@ -1191,7 +1194,7 @@ bool GLTFExporter::saveScene()
m_obj["buffers"] = buffers;
QJsonObject bufferViews;
- for (auto bv : bvList) {
+ for (const auto &bv : bvList) {
QJsonObject bufferView;
bufferView["buffer"] = QStringLiteral("buf");
bufferView["byteLength"] = int(bv.length);
@@ -1204,7 +1207,7 @@ bool GLTFExporter::saveScene()
m_obj["bufferViews"] = bufferViews;
QJsonObject accessors;
- for (auto acc : accList) {
+ for (const auto &acc : accList) {
QJsonObject accessor;
accessor["bufferView"] = acc.bufferView;
accessor["byteOffset"] = int(acc.offset);
@@ -1218,7 +1221,8 @@ bool GLTFExporter::saveScene()
m_obj["accessors"] = accessors;
QJsonObject meshes;
- for (auto meshInfo : m_meshInfo.values()) {
+ for (auto it = m_meshInfo.begin(); it != m_meshInfo.end(); ++it) {
+ auto &meshInfo = it.value();
QJsonObject mesh;
mesh["name"] = meshInfo.originalName;
if (meshInfo.meshType != TypeNone) {
@@ -1232,7 +1236,7 @@ bool GLTFExporter::saveScene()
QJsonObject prim;
prim["mode"] = 4; // triangles
QJsonObject attrs;
- for (auto acc : meshInfo.accessors) {
+ for (const auto &acc : meshInfo.accessors) {
if (acc.usage != QStringLiteral("INDEX"))
attrs[acc.usage] = acc.name;
else
@@ -1249,7 +1253,7 @@ bool GLTFExporter::saveScene()
m_obj["meshes"] = meshes;
QJsonObject cameras;
- for (auto camInfo : m_cameraInfo.values()) {
+ for (auto camInfo : qAsConst(m_cameraInfo)) {
QJsonObject camera;
QJsonObject proj;
proj["znear"] = camInfo.znear;
@@ -1281,7 +1285,7 @@ bool GLTFExporter::saveScene()
if (m_rootNodeEmpty) {
// Don't export the root node if it is there just to group the scene, so we don't get
// an extra empty node when we import the scene back.
- for (auto c : m_rootNode->children)
+ for (auto c : qAsConst(m_rootNode->children))
sceneNodes << exportNodes(c, nodes);
} else {
sceneNodes << exportNodes(m_rootNode, nodes);
@@ -1303,7 +1307,8 @@ bool GLTFExporter::saveScene()
// Lights must be declared as extensions to the top-level glTF object
QJsonObject lights;
- for (auto lightInfo : m_lightInfo.values()) {
+ for (auto it = m_lightInfo.begin(); it != m_lightInfo.end(); ++it) {
+ const auto &lightInfo = it.value();
QJsonObject light;
QJsonObject lightDetails;
QString type;
@@ -1404,7 +1409,7 @@ bool GLTFExporter::saveScene()
if (!gFilter->vendor().isEmpty())
graphicsApiFilterObj["vendor"] = gFilter->vendor();
QJsonArray extensions;
- for (auto extName : gFilter->extensions())
+ for (const auto &extName : gFilter->extensions())
extensions << extName;
if (!extensions.isEmpty())
graphicsApiFilterObj["extensions"] = extensions;
@@ -1483,7 +1488,7 @@ bool GLTFExporter::saveScene()
// Save shaders for custom materials
QJsonObject shaders;
- for (auto si : m_shaderInfo) {
+ for (const auto &si : m_shaderInfo) {
QJsonObject shaderObj;
shaderObj["uri"] = si.uri;
shaders[si.name] = shaderObj;
@@ -1570,7 +1575,7 @@ bool GLTFExporter::saveScene()
QByteArray pre = "<RCC><qresource prefix=\"/gltf_res\">\n";
QByteArray post = "</qresource></RCC>\n";
f.write(pre);
- for (auto file : m_exportedFiles) {
+ for (const auto &file : qAsConst(m_exportedFiles)) {
QString line = QString(QStringLiteral(" <file>%1</file>\n")).arg(file);
f.write(line.toUtf8());
}
@@ -1592,7 +1597,7 @@ void GLTFExporter::delNode(GLTFExporter::Node *n)
{
if (!n)
return;
- for (auto *c : n->children)
+ for (auto *c : qAsConst(n->children))
delNode(c);
delete n;
}
@@ -1602,7 +1607,7 @@ QString GLTFExporter::exportNodes(GLTFExporter::Node *n, QJsonObject &nodes)
QJsonObject node;
node["name"] = n->name;
QJsonArray children;
- for (auto c : n->children)
+ for (auto c : qAsConst(n->children))
children << exportNodes(c, nodes);
node["children"] = children;
if (auto transform = m_transformMap.value(n))
@@ -2058,7 +2063,7 @@ void GLTFExporter::setVarToJSonObject(QJsonObject &jsObj, const QString &key, co
jsObj[key] = var.value<float>();
break;
case QMetaType::QSize:
- jsObj[key] = size2jsvec(var.value<QSize>());
+ jsObj[key] = size2jsvec(var.toSize());
break;
case QMetaType::QVector2D:
jsObj[key] = vec2jsvec(var.value<QVector2D>());
diff --git a/src/plugins/sceneparsers/sceneparsers.pro b/src/plugins/sceneparsers/sceneparsers.pro
index befe08e41..cb274b472 100644
--- a/src/plugins/sceneparsers/sceneparsers.pro
+++ b/src/plugins/sceneparsers/sceneparsers.pro
@@ -1,5 +1,11 @@
TEMPLATE = subdirs
# QNX is not supported, and Linux GCC 4.9 on ARM chokes on the assimp
# sources (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66964).
-config_assimp|!cross_compile: SUBDIRS += assimp
-SUBDIRS += gltf gltfexport
+QT_FOR_CONFIG += 3dcore-private
+qtConfig(assimp):if(qtConfig(system-assimp)|!cross_compile): \
+ SUBDIRS += assimp
+SUBDIRS += gltf
+
+qtConfig(temporaryfile):qtConfig(regularexpression) {
+ SUBDIRS += gltfexport
+}
diff --git a/src/quick3d/imports/animation/plugins.qmltypes b/src/quick3d/imports/animation/plugins.qmltypes
new file mode 100644
index 000000000..08879ee52
--- /dev/null
+++ b/src/quick3d/imports/animation/plugins.qmltypes
@@ -0,0 +1,670 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable Qt3D.Animation 2.9'
+
+Module {
+ dependencies: ["QtQuick 2.8"]
+ Component {
+ name: "Qt3DAnimation::Animation::Quick::Quick3DChannelMapper"
+ defaultProperty: "mappings"
+ prototype: "Qt3DAnimation::QChannelMapper"
+ exports: ["Qt3D.Animation/ChannelMapper 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property {
+ name: "mappings"
+ type: "Qt3DAnimation::QChannelMapping"
+ isList: true
+ isReadonly: true
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAbstractAnimation"
+ prototype: "QObject"
+ exports: ["Qt3D.Animation/AbstractAnimation 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "AnimationType"
+ values: {
+ "KeyframeAnimation": 1,
+ "MorphingAnimation": 2,
+ "VertexBlendAnimation": 3
+ }
+ }
+ Property { name: "animationName"; type: "string" }
+ Property { name: "animationType"; type: "QAbstractAnimation::AnimationType"; isReadonly: true }
+ Property { name: "position"; type: "float" }
+ Property { name: "duration"; type: "float"; isReadonly: true }
+ Signal {
+ name: "animationNameChanged"
+ Parameter { name: "name"; type: "string" }
+ }
+ Signal {
+ name: "positionChanged"
+ Parameter { name: "position"; type: "float" }
+ }
+ Signal {
+ name: "durationChanged"
+ Parameter { name: "duration"; type: "float" }
+ }
+ Method {
+ name: "setAnimationName"
+ Parameter { name: "name"; type: "string" }
+ }
+ Method {
+ name: "setPosition"
+ Parameter { name: "position"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAbstractAnimationClip"
+ prototype: "Qt3DCore::QNode"
+ exports: ["Qt3D.Animation/AbstractAnimationClip 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Property { name: "duration"; type: "float"; isReadonly: true }
+ Signal {
+ name: "durationChanged"
+ Parameter { name: "duration"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAbstractClipAnimator"
+ prototype: "Qt3DCore::QComponent"
+ exports: ["Qt3D.Animation/AbstractClipAnimator 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Loops"
+ values: {
+ "Infinite": -1
+ }
+ }
+ Property { name: "running"; type: "bool" }
+ Property { name: "loops"; type: "int" }
+ Property { name: "channelMapper"; type: "Qt3DAnimation::QChannelMapper"; isPointer: true }
+ Signal {
+ name: "runningChanged"
+ Parameter { name: "running"; type: "bool" }
+ }
+ Signal {
+ name: "channelMapperChanged"
+ Parameter { name: "channelMapper"; type: "Qt3DAnimation::QChannelMapper"; isPointer: true }
+ }
+ Signal {
+ name: "loopCountChanged"
+ Parameter { name: "loops"; type: "int" }
+ }
+ Method {
+ name: "setRunning"
+ Parameter { name: "running"; type: "bool" }
+ }
+ Method {
+ name: "setChannelMapper"
+ Parameter { name: "channelMapper"; type: "Qt3DAnimation::QChannelMapper"; isPointer: true }
+ }
+ Method {
+ name: "setLoopCount"
+ Parameter { name: "loops"; type: "int" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAbstractClipBlendNode"
+ prototype: "Qt3DCore::QNode"
+ exports: ["Qt3D.Animation/AbstractClipBlendNode 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "Qt3DAnimation::QAdditiveClipBlend"
+ prototype: "Qt3DAnimation::QAbstractClipBlendNode"
+ exports: ["Qt3D.Animation/AdditiveClipBlend 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "baseClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ Property {
+ name: "additiveClip"
+ type: "Qt3DAnimation::QAbstractClipBlendNode"
+ isPointer: true
+ }
+ Property { name: "additiveFactor"; type: "float" }
+ Signal {
+ name: "additiveFactorChanged"
+ Parameter { name: "additiveFactor"; type: "float" }
+ }
+ Signal {
+ name: "baseClipChanged"
+ Parameter { name: "baseClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ }
+ Signal {
+ name: "additiveClipChanged"
+ Parameter {
+ name: "additiveClip"
+ type: "Qt3DAnimation::QAbstractClipBlendNode"
+ isPointer: true
+ }
+ }
+ Method {
+ name: "setAdditiveFactor"
+ Parameter { name: "additiveFactor"; type: "float" }
+ }
+ Method {
+ name: "setBaseClip"
+ Parameter { name: "baseClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ }
+ Method {
+ name: "setAdditiveClip"
+ Parameter {
+ name: "additiveClip"
+ type: "Qt3DAnimation::QAbstractClipBlendNode"
+ isPointer: true
+ }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAnimationClip"
+ prototype: "Qt3DAnimation::QAbstractAnimationClip"
+ exports: ["Qt3D.Animation/AnimationClip 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "clipData"; type: "Qt3DAnimation::QAnimationClipData" }
+ Signal {
+ name: "clipDataChanged"
+ Parameter { name: "clipData"; type: "Qt3DAnimation::QAnimationClipData" }
+ }
+ Method {
+ name: "setClipData"
+ Parameter { name: "clipData"; type: "Qt3DAnimation::QAnimationClipData" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAnimationClipLoader"
+ prototype: "Qt3DAnimation::QAbstractAnimationClip"
+ exports: ["Qt3D.Animation/AnimationClipLoader 2.9"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Status"
+ values: {
+ "NotReady": 0,
+ "Ready": 1,
+ "Error": 2
+ }
+ }
+ Property { name: "source"; type: "QUrl" }
+ Property { name: "status"; type: "Status"; isReadonly: true }
+ Signal {
+ name: "sourceChanged"
+ Parameter { name: "source"; type: "QUrl" }
+ }
+ Signal {
+ name: "statusChanged"
+ Parameter { name: "status"; type: "Status" }
+ }
+ Method {
+ name: "setSource"
+ Parameter { name: "source"; type: "QUrl" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAnimationController"
+ prototype: "QObject"
+ Property { name: "activeAnimationGroup"; type: "int" }
+ Property { name: "position"; type: "float" }
+ Property { name: "positionScale"; type: "float" }
+ Property { name: "positionOffset"; type: "float" }
+ Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ Property { name: "recursive"; type: "bool" }
+ Signal {
+ name: "activeAnimationGroupChanged"
+ Parameter { name: "index"; type: "int" }
+ }
+ Signal {
+ name: "positionChanged"
+ Parameter { name: "position"; type: "float" }
+ }
+ Signal {
+ name: "positionScaleChanged"
+ Parameter { name: "scale"; type: "float" }
+ }
+ Signal {
+ name: "positionOffsetChanged"
+ Parameter { name: "offset"; type: "float" }
+ }
+ Signal {
+ name: "entityChanged"
+ Parameter { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ }
+ Signal {
+ name: "recursiveChanged"
+ Parameter { name: "recursive"; type: "bool" }
+ }
+ Method {
+ name: "setActiveAnimationGroup"
+ Parameter { name: "index"; type: "int" }
+ }
+ Method {
+ name: "setPosition"
+ Parameter { name: "position"; type: "float" }
+ }
+ Method {
+ name: "setPositionScale"
+ Parameter { name: "scale"; type: "float" }
+ }
+ Method {
+ name: "setPositionOffset"
+ Parameter { name: "offset"; type: "float" }
+ }
+ Method {
+ name: "setEntity"
+ Parameter { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ }
+ Method {
+ name: "setRecursive"
+ Parameter { name: "recursive"; type: "bool" }
+ }
+ Method {
+ name: "getAnimationIndex"
+ type: "int"
+ Parameter { name: "name"; type: "string" }
+ }
+ Method {
+ name: "getGroup"
+ type: "Qt3DAnimation::QAnimationGroup*"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QAnimationGroup"
+ prototype: "QObject"
+ Property { name: "name"; type: "string" }
+ Property { name: "position"; type: "float" }
+ Property { name: "duration"; type: "float"; isReadonly: true }
+ Signal {
+ name: "nameChanged"
+ Parameter { name: "name"; type: "string" }
+ }
+ Signal {
+ name: "positionChanged"
+ Parameter { name: "position"; type: "float" }
+ }
+ Signal {
+ name: "durationChanged"
+ Parameter { name: "duration"; type: "float" }
+ }
+ Method {
+ name: "setName"
+ Parameter { name: "name"; type: "string" }
+ }
+ Method {
+ name: "setPosition"
+ Parameter { name: "position"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QBlendedClipAnimator"
+ prototype: "Qt3DAnimation::QAbstractClipAnimator"
+ exports: ["Qt3D.Animation/BlendedClipAnimator 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "blendTree"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ Signal {
+ name: "blendTreeChanged"
+ Parameter { name: "blendTree"; type: "QAbstractClipBlendNode"; isPointer: true }
+ }
+ Method {
+ name: "setBlendTree"
+ Parameter { name: "blendTree"; type: "QAbstractClipBlendNode"; isPointer: true }
+ }
+ }
+ Component { name: "Qt3DAnimation::QChannelMapper"; prototype: "Qt3DCore::QNode" }
+ Component {
+ name: "Qt3DAnimation::QChannelMapping"
+ prototype: "Qt3DCore::QNode"
+ exports: ["Qt3D.Animation/ChannelMapping 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "channelName"; type: "string" }
+ Property { name: "target"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "property"; type: "string" }
+ Signal {
+ name: "channelNameChanged"
+ Parameter { name: "channelName"; type: "string" }
+ }
+ Signal {
+ name: "targetChanged"
+ Parameter { name: "target"; type: "Qt3DCore::QNode"; isPointer: true }
+ }
+ Signal {
+ name: "propertyChanged"
+ Parameter { name: "property"; type: "string" }
+ }
+ Method {
+ name: "setChannelName"
+ Parameter { name: "channelName"; type: "string" }
+ }
+ Method {
+ name: "setTarget"
+ Parameter { name: "target"; type: "Qt3DCore::QNode"; isPointer: true }
+ }
+ Method {
+ name: "setProperty"
+ Parameter { name: "property"; type: "string" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QClipAnimator"
+ prototype: "Qt3DAnimation::QAbstractClipAnimator"
+ exports: ["Qt3D.Animation/ClipAnimator 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "clip"; type: "Qt3DAnimation::QAbstractAnimationClip"; isPointer: true }
+ Signal {
+ name: "clipChanged"
+ Parameter { name: "clip"; type: "Qt3DAnimation::QAbstractAnimationClip"; isPointer: true }
+ }
+ Method {
+ name: "setClip"
+ Parameter { name: "clip"; type: "Qt3DAnimation::QAbstractAnimationClip"; isPointer: true }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QClipBlendValue"
+ prototype: "Qt3DAnimation::QAbstractClipBlendNode"
+ exports: ["Qt3D.Animation/ClipBlendValue 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "clip"; type: "Qt3DAnimation::QAbstractAnimationClip"; isPointer: true }
+ Signal {
+ name: "clipChanged"
+ Parameter { name: "clip"; type: "Qt3DAnimation::QAbstractAnimationClip"; isPointer: true }
+ }
+ Method {
+ name: "setClip"
+ Parameter { name: "clip"; type: "Qt3DAnimation::QAbstractAnimationClip"; isPointer: true }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QKeyframeAnimation"
+ prototype: "Qt3DAnimation::QAbstractAnimation"
+ Enum {
+ name: "RepeatMode"
+ values: {
+ "None": 0,
+ "Constant": 1,
+ "Repeat": 2
+ }
+ }
+ Property { name: "framePositions"; type: "QVector<float>" }
+ Property { name: "target"; type: "Qt3DCore::QTransform"; isPointer: true }
+ Property { name: "easing"; type: "QEasingCurve" }
+ Property { name: "targetName"; type: "string" }
+ Property { name: "startMode"; type: "QKeyframeAnimation::RepeatMode" }
+ Property { name: "endMode"; type: "QKeyframeAnimation::RepeatMode" }
+ Signal {
+ name: "framePositionsChanged"
+ Parameter { name: "positions"; type: "QVector<float>" }
+ }
+ Signal {
+ name: "targetChanged"
+ Parameter { name: "target"; type: "Qt3DCore::QTransform"; isPointer: true }
+ }
+ Signal {
+ name: "easingChanged"
+ Parameter { name: "easing"; type: "QEasingCurve" }
+ }
+ Signal {
+ name: "targetNameChanged"
+ Parameter { name: "name"; type: "string" }
+ }
+ Signal {
+ name: "startModeChanged"
+ Parameter { name: "startMode"; type: "QKeyframeAnimation::RepeatMode" }
+ }
+ Signal {
+ name: "endModeChanged"
+ Parameter { name: "endMode"; type: "QKeyframeAnimation::RepeatMode" }
+ }
+ Method {
+ name: "setFramePositions"
+ Parameter { name: "positions"; type: "QVector<float>" }
+ }
+ Method {
+ name: "setTarget"
+ Parameter { name: "target"; type: "Qt3DCore::QTransform"; isPointer: true }
+ }
+ Method {
+ name: "setEasing"
+ Parameter { name: "easing"; type: "QEasingCurve" }
+ }
+ Method {
+ name: "setTargetName"
+ Parameter { name: "name"; type: "string" }
+ }
+ Method {
+ name: "setStartMode"
+ Parameter { name: "mode"; type: "RepeatMode" }
+ }
+ Method {
+ name: "setEndMode"
+ Parameter { name: "mode"; type: "RepeatMode" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QLerpClipBlend"
+ prototype: "Qt3DAnimation::QAbstractClipBlendNode"
+ exports: ["Qt3D.Animation/LerpClipBlend 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "startClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ Property { name: "endClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ Property { name: "blendFactor"; type: "float" }
+ Signal {
+ name: "blendFactorChanged"
+ Parameter { name: "blendFactor"; type: "float" }
+ }
+ Signal {
+ name: "startClipChanged"
+ Parameter { name: "startClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ }
+ Signal {
+ name: "endClipChanged"
+ Parameter { name: "endClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ }
+ Method {
+ name: "setBlendFactor"
+ Parameter { name: "blendFactor"; type: "float" }
+ }
+ Method {
+ name: "setStartClip"
+ Parameter { name: "startClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ }
+ Method {
+ name: "setEndClip"
+ Parameter { name: "endClip"; type: "Qt3DAnimation::QAbstractClipBlendNode"; isPointer: true }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QMorphTarget"
+ prototype: "QObject"
+ Property { name: "attributeNames"; type: "QStringList"; isReadonly: true }
+ Signal {
+ name: "attributeNamesChanged"
+ Parameter { name: "attributeNames"; type: "QStringList" }
+ }
+ Method {
+ name: "fromGeometry"
+ type: "QMorphTarget*"
+ Parameter { name: "geometry"; type: "Qt3DRender::QGeometry"; isPointer: true }
+ Parameter { name: "attributes"; type: "QStringList" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::QMorphingAnimation"
+ prototype: "Qt3DAnimation::QAbstractAnimation"
+ Enum {
+ name: "Method"
+ values: {
+ "Normalized": 0,
+ "Relative": 1
+ }
+ }
+ Property { name: "targetPositions"; type: "QVector<float>" }
+ Property { name: "interpolator"; type: "float"; isReadonly: true }
+ Property { name: "target"; type: "Qt3DRender::QGeometryRenderer"; isPointer: true }
+ Property { name: "targetName"; type: "string" }
+ Property { name: "method"; type: "QMorphingAnimation::Method" }
+ Property { name: "easing"; type: "QEasingCurve" }
+ Signal {
+ name: "targetPositionsChanged"
+ Parameter { name: "targetPositions"; type: "QVector<float>" }
+ }
+ Signal {
+ name: "interpolatorChanged"
+ Parameter { name: "interpolator"; type: "float" }
+ }
+ Signal {
+ name: "targetChanged"
+ Parameter { name: "target"; type: "Qt3DRender::QGeometryRenderer"; isPointer: true }
+ }
+ Signal {
+ name: "targetNameChanged"
+ Parameter { name: "name"; type: "string" }
+ }
+ Signal {
+ name: "methodChanged"
+ Parameter { name: "method"; type: "QMorphingAnimation::Method" }
+ }
+ Signal {
+ name: "easingChanged"
+ Parameter { name: "easing"; type: "QEasingCurve" }
+ }
+ Method {
+ name: "setTargetPositions"
+ Parameter { name: "targetPositions"; type: "QVector<float>" }
+ }
+ Method {
+ name: "setTarget"
+ Parameter { name: "target"; type: "Qt3DRender::QGeometryRenderer"; isPointer: true }
+ }
+ Method {
+ name: "setTargetName"
+ Parameter { name: "name"; type: "string" }
+ }
+ Method {
+ name: "setMethod"
+ Parameter { name: "method"; type: "QMorphingAnimation::Method" }
+ }
+ Method {
+ name: "setEasing"
+ Parameter { name: "easing"; type: "QEasingCurve" }
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::Quick::QQuick3DAnimationController"
+ prototype: "Qt3DAnimation::QAnimationController"
+ exports: ["Qt3D.Animation/AnimationController 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property {
+ name: "animationGroups"
+ type: "Qt3DAnimation::QAnimationGroup"
+ isList: true
+ isReadonly: true
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::Quick::QQuick3DAnimationGroup"
+ prototype: "Qt3DAnimation::QAnimationGroup"
+ exports: ["Qt3D.Animation/AnimationGroup 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property {
+ name: "animations"
+ type: "Qt3DAnimation::QAbstractAnimation"
+ isList: true
+ isReadonly: true
+ }
+ }
+ Component {
+ name: "Qt3DAnimation::Quick::QQuick3DKeyframeAnimation"
+ prototype: "Qt3DAnimation::QKeyframeAnimation"
+ exports: ["Qt3D.Animation/KeyframeAnimation 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "keyframes"; type: "Qt3DCore::QTransform"; isList: true; isReadonly: true }
+ }
+ Component {
+ name: "Qt3DAnimation::Quick::QQuick3DMorphTarget"
+ prototype: "Qt3DAnimation::QMorphTarget"
+ exports: ["Qt3D.Animation/MorphTarget 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "attributes"; type: "Qt3DRender::QAttribute"; isList: true; isReadonly: true }
+ }
+ Component {
+ name: "Qt3DAnimation::Quick::QQuick3DMorphingAnimation"
+ prototype: "Qt3DAnimation::QMorphingAnimation"
+ exports: ["Qt3D.Animation/MorphingAnimation 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property {
+ name: "morphTargets"
+ type: "Qt3DAnimation::QMorphTarget"
+ isList: true
+ isReadonly: true
+ }
+ }
+ Component {
+ name: "Qt3DCore::QComponent"
+ prototype: "Qt3DCore::QNode"
+ Property { name: "isShareable"; type: "bool" }
+ Signal {
+ name: "shareableChanged"
+ Parameter { name: "isShareable"; type: "bool" }
+ }
+ Signal {
+ name: "addedToEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
+ Signal {
+ name: "removedFromEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
+ Method {
+ name: "setShareable"
+ Parameter { name: "isShareable"; type: "bool" }
+ }
+ }
+ Component {
+ name: "Qt3DCore::QNode"
+ prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
+ Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
+ Signal {
+ name: "parentChanged"
+ Parameter { name: "parent"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "enabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Signal { name: "nodeDestroyed" }
+ Method {
+ name: "setParent"
+ Parameter { name: "parent"; type: "QNode"; isPointer: true }
+ }
+ Method {
+ name: "setEnabled"
+ Parameter { name: "isEnabled"; type: "bool" }
+ }
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ }
+}
diff --git a/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp b/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp
index e0addd6b0..7feeaf84c 100644
--- a/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp
+++ b/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp
@@ -38,15 +38,33 @@
****************************************************************************/
#include "qt3dquick3danimationplugin.h"
+#include <Qt3DAnimation/qabstractclipanimator.h>
+#include <Qt3DAnimation/qabstractanimationclip.h>
#include <Qt3DAnimation/qanimationclip.h>
+#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/qblendedclipanimator.h>
#include <Qt3DAnimation/qclipanimator.h>
-#include <Qt3DAnimation/qconductedclipanimator.h>
#include <Qt3DAnimation/qchannelmapping.h>
-#include <Qt3DAnimation/qlerpblend.h>
+#include <Qt3DAnimation/qlerpclipblend.h>
+#include <Qt3DAnimation/qadditiveclipblend.h>
+#include <Qt3DAnimation/qclipblendvalue.h>
+
+#include <Qt3DAnimation/qkeyframeanimation.h>
+#include <Qt3DAnimation/qanimationcontroller.h>
+#include <Qt3DAnimation/qabstractanimation.h>
+#include <Qt3DAnimation/qmorphinganimation.h>
+#include <Qt3DAnimation/qanimationgroup.h>
+#include <Qt3DAnimation/qmorphtarget.h>
+#include <Qt3DAnimation/qvertexblendanimation.h>
+
#include <Qt3DQuickAnimation/private/qt3dquickanimation_global_p.h>
#include <Qt3DQuickAnimation/private/quick3dchannelmapper_p.h>
-#include <Qt3DQuickAnimation/private/quick3dabstractclipblendnode_p.h>
+#include <Qt3DQuickAnimation/private/quick3dkeyframeanimation_p.h>
+#include <Qt3DQuickAnimation/private/quick3danimationgroup_p.h>
+#include <Qt3DQuickAnimation/private/quick3danimationcontroller_p.h>
+#include <Qt3DQuickAnimation/private/quick3dmorphtarget_p.h>
+#include <Qt3DQuickAnimation/private/quick3dmorphinganimation_p.h>
+#include <Qt3DQuickAnimation/private/quick3dvertexblendanimation_p.h>
QT_BEGIN_NAMESPACE
@@ -55,16 +73,28 @@ void Qt3DQuick3DAnimationPlugin::registerTypes(const char *uri)
Qt3DAnimation::Quick::Quick3DAnimation_initialize();
// @uri Qt3D.Animation
- qmlRegisterType<Qt3DAnimation::QAnimationClip>(uri, 2, 2, "AnimationClip");
- qmlRegisterType<Qt3DAnimation::QClipAnimator>(uri, 2, 2, "ClipAnimator");
- qmlRegisterType<Qt3DAnimation::QBlendedClipAnimator>(uri, 2, 2, "BlendedClipAnimator");
- qmlRegisterType<Qt3DAnimation::QConductedClipAnimator>(uri, 2, 2, "ConductedClipAnimator");
- qmlRegisterType<Qt3DAnimation::QChannelMapping>(uri, 2, 2, "ChannelMapping");
+ qmlRegisterUncreatableType<Qt3DAnimation::QAbstractClipAnimator>(uri, 2, 9, "AbstractClipAnimator", QStringLiteral("QAbstractClipAnimator is abstract"));
+ qmlRegisterType<Qt3DAnimation::QClipAnimator>(uri, 2, 9, "ClipAnimator");
+ qmlRegisterType<Qt3DAnimation::QBlendedClipAnimator>(uri, 2, 9, "BlendedClipAnimator");
+ qmlRegisterType<Qt3DAnimation::QChannelMapping>(uri, 2, 9, "ChannelMapping");
+ qmlRegisterType<Qt3DAnimation::QChannelMapping>(uri, 2, 9, "ChannelMapping");
+ qmlRegisterUncreatableType<Qt3DAnimation::QAbstractAnimationClip>(uri, 2, 9, "AbstractAnimationClip", QStringLiteral("QAbstractAnimationClip is abstract"));
+ qmlRegisterType<Qt3DAnimation::QAnimationClipLoader>(uri, 2, 9, "AnimationClipLoader");
+ qmlRegisterType<Qt3DAnimation::QAnimationClip>(uri, 2, 9, "AnimationClip");
qmlRegisterExtendedType<Qt3DAnimation::QChannelMapper,
- Qt3DAnimation::Animation::Quick::Quick3DChannelMapper>(uri, 2, 2, "ChannelMapper");
- qmlRegisterExtendedUncreatableType<Qt3DAnimation::QAbstractClipBlendNode,
- Qt3DAnimation::Animation::Quick::Quick3DAbstractClipBlendNode>(uri, 2, 2, "AbstractClipBlendNode", QStringLiteral("QAbstractClipBlendNode is abstract"));
- qmlRegisterType<Qt3DAnimation::QLerpBlend>(uri, 2, 2, "LerpBlend");
+ Qt3DAnimation::Animation::Quick::Quick3DChannelMapper>(uri, 2, 9, "ChannelMapper");
+ qmlRegisterUncreatableType<Qt3DAnimation::QAbstractClipBlendNode>(uri, 2, 9, "AbstractClipBlendNode", QStringLiteral("QAbstractClipBlendNode is abstract"));
+ qmlRegisterType<Qt3DAnimation::QLerpClipBlend>(uri, 2, 9, "LerpClipBlend");
+ qmlRegisterType<Qt3DAnimation::QAdditiveClipBlend>(uri, 2, 9, "AdditiveClipBlend");
+ qmlRegisterType<Qt3DAnimation::QClipBlendValue>(uri, 2, 9, "ClipBlendValue");
+
+ qmlRegisterUncreatableType<Qt3DAnimation::QAbstractAnimation>(uri, 2, 9, "AbstractAnimation", QStringLiteral("AbstractAnimation is abstract"));
+ qmlRegisterExtendedType<Qt3DAnimation::QKeyframeAnimation, Qt3DAnimation::Quick::QQuick3DKeyframeAnimation>(uri, 2, 9, "KeyframeAnimation");
+ qmlRegisterExtendedType<Qt3DAnimation::QAnimationGroup, Qt3DAnimation::Quick::QQuick3DAnimationGroup>(uri, 2, 9, "AnimationGroup");
+ qmlRegisterExtendedType<Qt3DAnimation::QAnimationController, Qt3DAnimation::Quick::QQuick3DAnimationController>(uri, 2, 9, "AnimationController");
+ qmlRegisterExtendedType<Qt3DAnimation::QMorphingAnimation, Qt3DAnimation::Quick::QQuick3DMorphingAnimation>(uri, 2, 9, "MorphingAnimation");
+ qmlRegisterExtendedType<Qt3DAnimation::QMorphTarget, Qt3DAnimation::Quick::QQuick3DMorphTarget>(uri, 2, 9, "MorphTarget");
+ qmlRegisterExtendedType<Qt3DAnimation::QVertexBlendAnimation, Qt3DAnimation::Quick::QQuick3DVertexBlendAnimation>(uri, 2, 9, "VertexBlendAnimation");
}
QT_END_NAMESPACE
diff --git a/src/quick3d/imports/core/plugins.qmltypes b/src/quick3d/imports/core/plugins.qmltypes
index ed06f8e0c..87cdac04c 100644
--- a/src/quick3d/imports/core/plugins.qmltypes
+++ b/src/quick3d/imports/core/plugins.qmltypes
@@ -4,29 +4,41 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt3D.Core 2.0'
+// 'qmlplugindump -nonrelocatable Qt3D.Core 2.9'
Module {
- dependencies: ["QtQuick 2.7"]
+ dependencies: ["QtQuick 2.8"]
Component {
name: "Qt3DCore::QComponent"
- prototype: "Qt3DCore::QNode"
- Property { name: "isShareable"; type: "bool" }
+ defaultProperty: "data"
+ prototype: "Qt3DCore::QComponent"
+ Property { name: "propertyTrackingOverrides"; type: "QJSValue" }
+ Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "childNodes"; type: "Qt3DCore::QNode"; isList: true; isReadonly: true }
Signal {
- name: "shareableChanged"
- Parameter { name: "isShareable"; type: "bool" }
+ name: "propertyTrackingOverridesChanged"
+ Parameter { name: "value"; type: "QJSValue" }
}
- Method {
- name: "setShareable"
- Parameter { name: "isShareable"; type: "bool" }
+ Signal {
+ name: "propertyTrackingOverridesChanged"
+ Parameter { name: "value"; type: "QJSValue" }
}
}
Component { name: "Qt3DCore::QEntity"; prototype: "Qt3DCore::QNode" }
Component {
name: "Qt3DCore::QNode"
prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
Signal {
name: "parentChanged"
Parameter { name: "parent"; type: "QObject"; isPointer: true }
@@ -35,6 +47,10 @@ Module {
name: "enabledChanged"
Parameter { name: "enabled"; type: "bool" }
}
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
Signal { name: "nodeDestroyed" }
Method {
name: "setParent"
@@ -44,11 +60,14 @@ Module {
name: "setEnabled"
Parameter { name: "isEnabled"; type: "bool" }
}
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
}
Component {
name: "Qt3DCore::QTransform"
prototype: "Qt3DCore::QComponent"
- exports: ["Qt3D.Core/Transform 2.0"]
Property { name: "matrix"; type: "QMatrix4x4" }
Property { name: "scale"; type: "float" }
Property { name: "scale3D"; type: "QVector3D" }
@@ -230,10 +249,8 @@ Module {
Component {
name: "Qt3DCore::Quick::Quick3DEntityLoader"
defaultProperty: "data"
- prototype: "Qt3DCore::QEntity"
- exports: ["Qt3D.Core/EntityLoader 2.0"]
- Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true; isReadonly: true }
- Property { name: "source"; type: "QUrl" }
+ prototype: "Qt3DCore::Quick::Quick3DEntityLoader"
+ Property { name: "components"; type: "Qt3DCore::QComponent"; isList: true; isReadonly: true }
}
Component {
name: "Qt3DCore::Quick::Quick3DNode"
@@ -248,13 +265,36 @@ Module {
Component {
name: "Qt3DCore::Quick::Quick3DNodeInstantiator"
defaultProperty: "delegate"
+ prototype: "Qt3DCore::Quick::Quick3DNodeInstantiator"
+ Property { name: "propertyTrackingOverrides"; type: "QJSValue" }
+ Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "childNodes"; type: "Qt3DCore::QNode"; isList: true; isReadonly: true }
+ Signal {
+ name: "propertyTrackingOverridesChanged"
+ Parameter { name: "value"; type: "QJSValue" }
+ }
+ Signal {
+ name: "propertyTrackingOverridesChanged"
+ Parameter { name: "value"; type: "QJSValue" }
+ }
+ }
+ Component {
+ name: "Qt3DCore::Quick::Quick3DNodeV9"
+ defaultProperty: "data"
prototype: "Qt3DCore::QNode"
- exports: ["Qt3D.Core/NodeInstantiator 2.0"]
- Property { name: "active"; type: "bool" }
- Property { name: "asynchronous"; type: "bool" }
- Property { name: "model"; type: "QVariant" }
- Property { name: "count"; type: "int"; isReadonly: true }
- Property { name: "delegate"; type: "QQmlComponent" }
- Property { name: "object"; type: "QObject"; isReadonly: true }
+ exports: ["Qt3D.Core/Node 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [9]
+ Property { name: "propertyTrackingOverrides"; type: "QJSValue" }
+ Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "childNodes"; type: "Qt3DCore::QNode"; isList: true; isReadonly: true }
+ Signal {
+ name: "propertyTrackingOverridesChanged"
+ Parameter { name: "value"; type: "QJSValue" }
+ }
+ Signal {
+ name: "propertyTrackingOverridesChanged"
+ Parameter { name: "value"; type: "QJSValue" }
+ }
}
}
diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
index b72ee9600..3ff63d9d9 100644
--- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
+++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
@@ -38,14 +38,17 @@
****************************************************************************/
#include "qt3dquick3dcoreplugin.h"
+
#include <Qt3DCore/qtransform.h>
-#include <private/quick3dentity_p.h>
-#include <private/quick3dentityloader_p.h>
-#include <private/quick3dnodeinstantiator_p.h>
-#include <private/qquaternionanimation_p.h>
-#include <private/qt3dquick_global_p.h>
#include <QtCore/qvariantanimation.h>
+#include <Qt3DQuick/private/quick3dnodev9_p.h>
+#include <Qt3DQuick/private/quick3dentity_p.h>
+#include <Qt3DQuick/private/quick3dentityloader_p.h>
+#include <Qt3DQuick/private/quick3dnodeinstantiator_p.h>
+#include <Qt3DQuick/private/qquaternionanimation_p.h>
+#include <Qt3DQuick/private/qt3dquick_global_p.h>
+
QT_BEGIN_NAMESPACE
void Qt3DQuick3DCorePlugin::registerTypes(const char *uri)
@@ -65,6 +68,12 @@ void Qt3DQuick3DCorePlugin::registerTypes(const char *uri)
// Ideally we want to make Node an uncreatable type
// We would need qmlRegisterUncreatableExtendedType for that
qmlRegisterExtendedUncreatableType<Qt3DCore::QNode, Qt3DCore::Quick::Quick3DNode>(uri, 2, 0, "Node", QStringLiteral("Node is a base class"));
+ qmlRegisterExtendedUncreatableType<Qt3DCore::QNode, Qt3DCore::Quick::Quick3DNodeV9, 9>(uri, 2, 9, "Node", QStringLiteral("Node is a base class"));
+}
+
+Qt3DQuick3DCorePlugin::~Qt3DQuick3DCorePlugin()
+{
+ Qt3DCore::Quick::Quick3D_uninitialize();
}
QT_END_NAMESPACE
diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.h b/src/quick3d/imports/core/qt3dquick3dcoreplugin.h
index a9b215c4a..b0ef5947c 100644
--- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.h
+++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.h
@@ -57,6 +57,7 @@ class Qt3DQuick3DCorePlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
Qt3DQuick3DCorePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); }
+ ~Qt3DQuick3DCorePlugin();
void registerTypes(const char *uri) Q_DECL_OVERRIDE;
};
diff --git a/src/quick3d/imports/extras/defaults/defaults.pri b/src/quick3d/imports/extras/defaults/defaults.pri
deleted file mode 100644
index 98f542fd6..000000000
--- a/src/quick3d/imports/extras/defaults/defaults.pri
+++ /dev/null
@@ -1,26 +0,0 @@
-
-# When adding new QML files that should be built into the plugin,
-# add them to this variable and they will be listed into a generated
-# resource file.
-#
-# To have the plugin register them as types, add an entries to the
-# qmldir array in qt3dquick3dextrasplugin.cpp
-QML_FILES = \
- $$PWD/qml/DefaultEffect.qml \
- $$PWD/qml/DefaultAlphaEffect.qml \
- $$PWD/qml/PhongMaterial.qml \
- $$PWD/qml/DiffuseMapMaterial.qml \
- $$PWD/qml/DiffuseSpecularMapMaterial.qml \
- $$PWD/qml/NormalDiffuseMapMaterial.qml \
- $$PWD/qml/NormalDiffuseMapAlphaMaterial.qml \
- $$PWD/qml/NormalDiffuseSpecularMapMaterial.qml \
- $$PWD/qml/ForwardRenderer.qml \
- $$PWD/qml/PerVertexColorMaterial.qml \
- $$PWD/qml/SkyboxEntity.qml \
- $$PWD/qml/GoochMaterial.qml \
- $$PWD/qml/PhongAlphaMaterial.qml \
- $$PWD/qml/TextureMaterial.qml \
- $$PWD/qml/OrbitCameraController.qml \
- $$PWD/qml/FirstPersonCameraController.qml \
- $$PWD/qml/NormalDiffuseMapAlphaEffect.qml \
- $$PWD/qml/LevelOfDetailLoader.qml
diff --git a/src/quick3d/imports/extras/defaults/qml/DefaultAlphaEffect.qml b/src/quick3d/imports/extras/defaults/qml/DefaultAlphaEffect.qml
deleted file mode 100644
index c28fda4d1..000000000
--- a/src/quick3d/imports/extras/defaults/qml/DefaultAlphaEffect.qml
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Effect {
- property string vertexES: "qrc:/shaders/es2/phong.vert"
- property string fragmentES: "qrc:/shaders/es2/phongalpha.frag"
- property string vertex: "qrc:/shaders/gl3/phong.vert"
- property string fragment: "qrc:/shaders/gl3/phongalpha.frag"
- property int sourceRgbArg: BlendEquationArguments.SourceAlpha
- property int destinationRgbArg: BlendEquationArguments.OneMinusSourceAlpha
- property int sourceAlphaArg: BlendEquationArguments.One
- property int destinationAlphaArg: BlendEquationArguments.Zero
- property int blendFunctionArg: BlendEquation.Add
-
- FilterKey {
- id: forward
- name: "renderingStyle"
- value: "forward"
- }
-
- ShaderProgram {
- id: gl2Es2Shader
- vertexShaderCode: loadSource(vertexES)
- fragmentShaderCode: loadSource(fragmentES)
- }
-
- ShaderProgram {
- id: gl3Shader
- vertexShaderCode: loadSource(vertex)
- fragmentShaderCode: loadSource(fragment)
- }
-
- techniques: [
- // OpenGL 3.1
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.CoreProfile
- majorVersion: 3
- minorVersion: 1
- }
- renderPasses: RenderPass {
- shaderProgram: gl3Shader
- renderStates: [
- BlendEquationArguments {
- sourceRgb: sourceRgbArg
- destinationRgb: destinationRgbArg
- sourceAlpha: sourceAlphaArg
- destinationAlpha: destinationAlphaArg
- },
- BlendEquation {
- blendFunction: blendFunctionArg
- }
- ]
- }
- },
-
- // OpenGL 2.1
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass {
- shaderProgram: gl2Es2Shader
- renderStates: [
- BlendEquationArguments {
- sourceRgb: sourceRgbArg
- destinationRgb: destinationRgbArg
- sourceAlpha: sourceAlphaArg
- destinationAlpha: destinationAlphaArg
- },
- BlendEquation {
- blendFunction: blendFunctionArg
- }
- ]
- }
- },
-
- // OpenGL ES 2
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGLES
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass {
- shaderProgram: gl2Es2Shader
- renderStates: [
- BlendEquationArguments {
- sourceRgb: sourceRgbArg
- destinationRgb: destinationRgbArg
- sourceAlpha: sourceAlphaArg
- destinationAlpha: destinationAlphaArg
- },
- BlendEquation {
- blendFunction: blendFunctionArg
- }
- ]
- }
- }
- ]
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/DefaultEffect.qml b/src/quick3d/imports/extras/defaults/qml/DefaultEffect.qml
deleted file mode 100644
index fed87c94d..000000000
--- a/src/quick3d/imports/extras/defaults/qml/DefaultEffect.qml
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Effect {
- property string vertexES: "qrc:/shaders/es2/phong.vert"
- property string fragmentES: "qrc:/shaders/es2/phong.frag"
- property string vertex: "qrc:/shaders/gl3/phong.vert"
- property string fragment: "qrc:/shaders/gl3/phong.frag"
-
- FilterKey {
- id: forward
- name: "renderingStyle"
- value: "forward"
- }
-
- ShaderProgram {
- id: gl2Es2Shader
- vertexShaderCode: loadSource(vertexES)
- fragmentShaderCode: loadSource(fragmentES)
- }
-
- ShaderProgram {
- id: gl3Shader
- vertexShaderCode: loadSource(vertex)
- fragmentShaderCode: loadSource(fragment)
- }
-
- techniques: [
- // OpenGL 3.1
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.CoreProfile
- majorVersion: 3
- minorVersion: 1
- }
- renderPasses: RenderPass { shaderProgram: gl3Shader }
- },
-
- // OpenGL 2.1
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass { shaderProgram: gl2Es2Shader }
- },
-
- // OpenGL ES 2
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGLES
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass { shaderProgram: gl2Es2Shader }
- }
- ]
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/DiffuseMapMaterial.qml b/src/quick3d/imports/extras/defaults/qml/DiffuseMapMaterial.qml
deleted file mode 100644
index 4b49d76de..000000000
--- a/src/quick3d/imports/extras/defaults/qml/DiffuseMapMaterial.qml
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property alias diffuse: diffuseTextureImage.source
- property color specular: Qt.rgba( 0.01, 0.01, 0.01, 1.0 )
- property real shininess: 150.0
- property real textureScale: 1.0
-
- parameters: [
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter {
- name: "diffuseTexture"
- value: Texture2D {
- id: diffuseTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: diffuseTextureImage; }
- }
- },
- Parameter { name: "ks"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) },
- Parameter { name: "shininess"; value: root.shininess },
- Parameter { name: "texCoordScale"; value: textureScale }
- ]
-
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/diffusemap.vert"
- fragmentES: "qrc:/shaders/es2/diffusemap.frag"
- vertex: "qrc:/shaders/gl3/diffusemap.vert"
- fragment: "qrc:/shaders/gl3/diffusemap.frag"
- }
-}
-
diff --git a/src/quick3d/imports/extras/defaults/qml/DiffuseSpecularMapMaterial.qml b/src/quick3d/imports/extras/defaults/qml/DiffuseSpecularMapMaterial.qml
deleted file mode 100644
index 629cb6d11..000000000
--- a/src/quick3d/imports/extras/defaults/qml/DiffuseSpecularMapMaterial.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property alias diffuse: diffuseTextureImage.source
- property alias specular: specularTextureImage.source
- property real shininess: 150.0
- property real textureScale: 1.0
-
- parameters: [
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter {
- name: "diffuseTexture"
- value: Texture2D {
- id: diffuseTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: diffuseTextureImage; }
- }
- },
- Parameter { name: "specularTexture";
- value: Texture2D {
- id: specularTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: specularTextureImage; }
- }
- },
- Parameter { name: "shininess"; value: root.shininess },
- Parameter { name: "texCoordScale"; value: textureScale }
- ]
-
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/diffusemap.vert"
- fragmentES: "qrc:/shaders/es2/diffusespecularmap.frag"
- vertex: "qrc:/shaders/gl3/diffusemap.vert"
- fragment: "qrc:/shaders/gl3/diffusespecularmap.frag"
- }
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/FirstPersonCameraController.qml b/src/quick3d/imports/extras/defaults/qml/FirstPersonCameraController.qml
deleted file mode 100644
index 1003c0ea0..000000000
--- a/src/quick3d/imports/extras/defaults/qml/FirstPersonCameraController.qml
+++ /dev/null
@@ -1,191 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Paul Lemire <paul.lemire350@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-import Qt3D.Input 2.0
-import Qt3D.Logic 2.0
-import QtQml 2.2
-
-Entity {
- id: root
- property Camera camera
- property real linearSpeed: 10.0
- property real lookSpeed: 180.0
- property real acceleration: -1.0
- property real deceleration: -1.0
-
- QtObject {
- id: d
- readonly property vector3d firstPersonUp: Qt.vector3d(0, 1, 0)
- readonly property bool leftMouseButtonPressed: leftMouseButtonAction.active
- readonly property real vx: txAxis.value * linearSpeed;
- readonly property real vy: tyAxis.value * linearSpeed;
- readonly property real vz: tzAxis.value * linearSpeed;
- readonly property real dx: rxAxis.value * lookSpeed
- readonly property real dy: ryAxis.value * lookSpeed
- readonly property bool fineMotion: fineMotionAction.active
- }
-
- KeyboardDevice {
- id: keyboardSourceDevice
- }
-
- MouseDevice {
- id: mouseSourceDevice
- sensitivity: d.fineMotion ? 0.01 : 0.1
- }
-
- components: [
-
- LogicalDevice {
- enabled: root.enabled
- actions: [
- Action {
- id: leftMouseButtonAction
- ActionInput {
- sourceDevice: mouseSourceDevice
- buttons: [MouseEvent.LeftButton]
- }
- },
- Action {
- id: fineMotionAction
- ActionInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Shift]
- }
- }
- ] // actions
-
- axes: [
- // Rotation
- Axis {
- id: rxAxis
- AnalogAxisInput {
- sourceDevice: mouseSourceDevice
- axis: MouseDevice.X
- }
- },
- Axis {
- id: ryAxis
- AnalogAxisInput {
- sourceDevice: mouseSourceDevice
- axis: MouseDevice.Y
- }
- },
- // Translation
- Axis {
- id: txAxis
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Left]
- scale: -1.0
- acceleration: root.acceleration
- deceleration: root.deceleration
- }
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Right]
- scale: 1.0
- acceleration: root.acceleration
- deceleration: root.deceleration
- }
- },
- Axis {
- id: tzAxis
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Up]
- scale: 1.0
- acceleration: root.acceleration
- deceleration: root.deceleration
- }
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Down]
- scale: -1.0
- acceleration: root.acceleration
- deceleration: root.deceleration
- }
- },
- Axis {
- id: tyAxis
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_PageUp]
- scale: 1.0
- acceleration: root.acceleration
- deceleration: root.deceleration
- }
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_PageDown]
- scale: -1.0
- acceleration: root.acceleration
- deceleration: root.deceleration
- }
- }
- ] // axes
- },
-
- FrameAction {
- onTriggered: {
- // The time difference since the last frame is passed in as the
- // argument dt. It is a floating point value in units of seconds.
- root.camera.translate(Qt.vector3d(d.vx, d.vy, d.vz).times(dt))
-
- if (d.leftMouseButtonPressed) {
- root.camera.pan(d.dx * dt, d.firstPersonUp)
- root.camera.tilt(d.dy * dt)
- }
- }
- }
- ] // components
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/ForwardRenderer.qml b/src/quick3d/imports/extras/defaults/qml/ForwardRenderer.qml
deleted file mode 100644
index b7ad3188c..000000000
--- a/src/quick3d/imports/extras/defaults/qml/ForwardRenderer.qml
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-TechniqueFilter {
- // Expose camera to allow user to choose which camera to use for rendering
- property alias camera: cameraSelector.camera
- property alias clearColor: clearBuffer.clearColor
- property alias viewportRect: viewport.normalizedRect
- property alias window: surfaceSelector.surface
- property alias externalRenderTargetSize: surfaceSelector.externalRenderTargetSize
- property alias frustumCulling: frustumCulling.enabled
-
- // Select the forward rendering Technique of any used Effect
- matchAll: [ FilterKey { name: "renderingStyle"; value: "forward" } ]
-
- RenderSurfaceSelector {
- id: surfaceSelector
-
- // Use the whole viewport
- Viewport {
- id: viewport
- normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
-
- // Use the specified camera
- CameraSelector {
- id : cameraSelector
- FrustumCulling {
- id: frustumCulling
- ClearBuffers {
- id: clearBuffer
- clearColor: "white"
- buffers : ClearBuffers.ColorDepthBuffer
- }
- }
- }
- }
- }
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/GoochMaterial.qml b/src/quick3d/imports/extras/defaults/qml/GoochMaterial.qml
deleted file mode 100644
index fffa2284d..000000000
--- a/src/quick3d/imports/extras/defaults/qml/GoochMaterial.qml
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color diffuse: Qt.rgba( 0.0, 0.0, 0.0, 1.0 )
- property color specular: Qt.rgba( 0.0, 0.0, 0.0, 1.0 )
- property color coolColor: Qt.rgba( 0.0, 0.0, 0.4, 1.0 )
- property color warmColor: Qt.rgba( 0.4, 0.4, 0.0, 1.0 )
- property real alpha: 0.25
- property real beta: 0.5
- property real shininess: 100.0
-
- parameters: [
- Parameter { name: "kd"; value: root.diffuse },
- Parameter { name: "ks"; value: root.specular },
- Parameter { name: "kblue"; value: root.coolColor },
- Parameter { name: "kyellow"; value: root.warmColor },
- Parameter { name: "alpha"; value: root.alpha },
- Parameter { name: "beta"; value: root.beta },
- Parameter { name: "shininess"; value: root.shininess }
- ]
-
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/gooch.vert"
- fragmentES: "qrc:/shaders/es2/gooch.frag"
- vertex: "qrc:/shaders/gl3/gooch.vert"
- fragment: "qrc:/shaders/gl3/gooch.frag"
- }
-}
-
diff --git a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaEffect.qml b/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaEffect.qml
deleted file mode 100644
index e4f038642..000000000
--- a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaEffect.qml
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Effect {
- property string vertexES: "qrc:/shaders/es2/normaldiffusemap.vert"
- property string fragmentES: "qrc:/shaders/es2/normaldiffusemapalpha.frag"
- property string vertex: "qrc:/shaders/gl3/normaldiffusemap.vert"
- property string fragment: "qrc:/shaders/gl3/normaldiffusemapalpha.frag"
-
- FilterKey {
- id: forward
- name: "renderingStyle"
- value: "forward"
- }
-
- ShaderProgram {
- id: gl2Es2Shader
- vertexShaderCode: loadSource(vertexES)
- fragmentShaderCode: loadSource(fragmentES)
- }
-
- ShaderProgram {
- id: gl3Shader
- vertexShaderCode: loadSource(vertex)
- fragmentShaderCode: loadSource(fragment)
- }
-
- AlphaCoverage { id: alphaCoverage }
-
- techniques: [
- // OpenGL 3.1
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.CoreProfile
- majorVersion: 3
- minorVersion: 1
- }
- renderPasses: RenderPass {
- shaderProgram: gl3Shader
- renderStates: [ alphaCoverage ]
- }
- },
-
- // OpenGL 2.1
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass {
- shaderProgram: gl2Es2Shader
- renderStates: [ alphaCoverage ]
- }
- },
-
- // OpenGL ES 2
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGLES
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass {
- shaderProgram: gl2Es2Shader
- renderStates: [ alphaCoverage ]
- }
- }
- ]
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaMaterial.qml b/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaMaterial.qml
deleted file mode 100644
index 421cc3aa9..000000000
--- a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapAlphaMaterial.qml
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property alias diffuse: diffuseTextureImage.source
- property color specular: Qt.rgba( 0.01, 0.01, 0.01, 1.0 )
- property alias normal: normalTextureImage.source
- property real shininess: 150.0
- property real textureScale: 1.0
-
- parameters: [
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter {
- name: "diffuseTexture"
- value: Texture2D {
- id: diffuseTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: diffuseTextureImage; }
- }
- },
- Parameter {
- name: "normalTexture"
- value: Texture2D {
- id: normalTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: normalTextureImage; }
- }
- },
- Parameter { name: "ks"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) },
- Parameter { name: "shininess"; value: root.shininess },
- Parameter { name: "texCoordScale"; value: textureScale }
- ]
-
- effect: NormalDiffuseMapAlphaEffect { }
-}
-
diff --git a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapMaterial.qml b/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapMaterial.qml
deleted file mode 100644
index 0724cf597..000000000
--- a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseMapMaterial.qml
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property alias diffuse: diffuseTextureImage.source
- property color specular: Qt.rgba( 0.01, 0.01, 0.01, 1.0 )
- property alias normal: normalTextureImage.source
- property real shininess: 150.0
- property real textureScale: 1.0
-
- parameters: [
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter {
- name: "diffuseTexture"
- value: Texture2D {
- id: diffuseTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: diffuseTextureImage; }
- }
- },
- Parameter {
- name: "normalTexture"
- value: Texture2D {
- id: normalTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: normalTextureImage; }
- }
- },
- Parameter { name: "ks"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) },
- Parameter { name: "shininess"; value: root.shininess },
- Parameter { name: "texCoordScale"; value: textureScale }
- ]
-
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/normaldiffusemap.vert"
- fragmentES: "qrc:/shaders/es2/normaldiffusemap.frag"
- vertex: "qrc:/shaders/gl3/normaldiffusemap.vert"
- fragment: "qrc:/shaders/gl3/normaldiffusemap.frag"
- }
-}
-
diff --git a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseSpecularMapMaterial.qml b/src/quick3d/imports/extras/defaults/qml/NormalDiffuseSpecularMapMaterial.qml
deleted file mode 100644
index 497209c32..000000000
--- a/src/quick3d/imports/extras/defaults/qml/NormalDiffuseSpecularMapMaterial.qml
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property alias diffuse: diffuseTextureImage.source
- property alias specular: specularTextureImage.source
- property alias normal: normalTextureImage.source
- property real shininess: 150.0
- property real textureScale: 1.0
-
- parameters: [
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter {
- name: "diffuseTexture"
- value: Texture2D {
- id: diffuseTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: diffuseTextureImage; }
- }
- },
- Parameter { name: "specularTexture";
- value: Texture2D {
- id: specularTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: specularTextureImage; }
- }
- },
- Parameter {
- name: "normalTexture"
- value: Texture2D {
- id: normalTexture
- minificationFilter: Texture.LinearMipMapLinear
- magnificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.Repeat
- y: WrapMode.Repeat
- }
- generateMipMaps: true
- maximumAnisotropy: 16.0
- TextureImage { id: normalTextureImage; }
- }
- },
- Parameter { name: "shininess"; value: root.shininess },
- Parameter { name: "texCoordScale"; value: textureScale }
- ]
-
- effect: DefaultEffect {
- vertexES: "qrc:/shaders/es2/normaldiffusemap.vert"
- fragmentES: "qrc:/shaders/es2/normaldiffusespecularmap.frag"
- vertex: "qrc:/shaders/gl3/normaldiffusemap.vert"
- fragment: "qrc:/shaders/gl3/normaldiffusespecularmap.frag"
- }
-}
-
diff --git a/src/quick3d/imports/extras/defaults/qml/OrbitCameraController.qml b/src/quick3d/imports/extras/defaults/qml/OrbitCameraController.qml
deleted file mode 100644
index ae8869473..000000000
--- a/src/quick3d/imports/extras/defaults/qml/OrbitCameraController.qml
+++ /dev/null
@@ -1,236 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Paul Lemire <paul.lemire350@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-import Qt3D.Input 2.0
-import Qt3D.Logic 2.0
-import QtQml 2.2
-
-Entity {
- id: root
- property Camera camera
- property real linearSpeed: 10.0
- property real lookSpeed: 180.0
- property real zoomLimit: 2.0
-
- QtObject {
- id: d
- readonly property vector3d firstPersonUp: Qt.vector3d(0, 1, 0)
- readonly property bool leftMouseButtonPressed: leftMouseButtonAction.active
- readonly property bool rightMouseButtonPressed: rightMouseButtonAction.active
- readonly property bool shiftPressed: shiftAction.active
- readonly property bool altPressed: altAction.active
- property real translationX: clampInputs(leftMouseButtonPressed ? mouseXAxis.value : 0, keyboardXAxis.value) * linearSpeed;
- property real translationY: clampInputs(leftMouseButtonPressed ? mouseYAxis.value : 0, keyboardYAxis.value) * linearSpeed;
- property real translationZ: keyboardZAxis.value * linearSpeed;
- property real orbitX: clampInputs(rightMouseButtonPressed ? mouseXAxis.value : 0, keyboardXAxis.value) * lookSpeed;
- property real orbitY: clampInputs(rightMouseButtonPressed ? mouseYAxis.value : 0, keyboardYAxis.value) * lookSpeed;
- }
-
- function clampInputs(input1, input2) {
- var axisValue = input1 + input2;
- return (axisValue < -1) ? -1 : (axisValue > 1) ? 1 : axisValue;
- }
-
- function zoomDistance(firstPoint, secondPoint) {
- var u = secondPoint.minus(firstPoint); u = u.times(u);
- return u.x + u.y + u.z;
- }
-
- KeyboardDevice {
- id: keyboardSourceDevice
- }
-
- MouseDevice {
- id: mouseSourceDevice
- sensitivity: 0.1
- }
-
- components: [
-
- LogicalDevice {
- enabled: root.enabled
- actions: [
- Action {
- id: leftMouseButtonAction
- ActionInput {
- sourceDevice: mouseSourceDevice
- buttons: [MouseEvent.LeftButton]
- }
- },
- Action {
- id: rightMouseButtonAction
- ActionInput {
- sourceDevice: mouseSourceDevice
- buttons: [MouseEvent.RightButton]
- }
- },
- Action {
- id: shiftAction
- ActionInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Shift]
- }
- },
- Action {
- id: altAction
- ActionInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Alt]
- }
- }
- ] // actions
-
- axes: [
- // Mouse
- Axis {
- id: mouseXAxis
- AnalogAxisInput {
- sourceDevice: mouseSourceDevice
- axis: MouseDevice.X
- }
- },
- Axis {
- id: mouseYAxis
- AnalogAxisInput {
- sourceDevice: mouseSourceDevice
- axis: MouseDevice.Y
- }
- },
- // Keyboard
- Axis {
- id: keyboardXAxis
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Left]
- scale: -1.0
- }
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Right]
- scale: 1.0
- }
- },
- Axis {
- id: keyboardZAxis
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_PageUp]
- scale: 1.0
- }
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_PageDown]
- scale: -1.0
- }
- },
- Axis {
- id: keyboardYAxis
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Up]
- scale: 1.0
- }
- ButtonAxisInput {
- sourceDevice: keyboardSourceDevice
- buttons: [Qt.Key_Down]
- scale: -1.0
- }
- }
- ] // axes
- },
-
- FrameAction {
- onTriggered: {
- // The time difference since the last frame is passed in as the
- // argument dt. It is a floating point value in units of seconds.
-
- // Mouse input
- if (d.leftMouseButtonPressed) {
- if (d.rightMouseButtonPressed) {
- if (zoomDistance(root.camera.position, root.camera.viewCenter) > root.zoomLimit * root.zoomLimit) {
- // Dolly up to limit
- root.camera.translate(Qt.vector3d(0, 0, d.translationY).times(dt), Camera.DontTranslateViewCenter);
- } else {
- // Too close, Dolly backwards
- root.camera.translate(Qt.vector3d(0, 0, -1).times(dt), Camera.DontTranslateViewCenter);
- }
- } else {
- // Translate
- root.camera.translate(Qt.vector3d(d.translationX, d.translationY, 0).times(dt));
- }
- return
- } else if (d.rightMouseButtonPressed) {
- // Orbit
- root.camera.panAboutViewCenter(d.orbitX * dt, d.firstPersonUp);
- root.camera.tiltAboutViewCenter(d.orbitY * dt);
- }
- // Keyboard input
- if (d.altPressed) {
- // Orbit
- root.camera.panAboutViewCenter(d.orbitX * dt, d.firstPersonUp);
- root.camera.tiltAboutViewCenter(d.orbitY * dt);
- } else if (d.shiftPressed) {
- if (zoomDistance(root.camera.position, root.camera.viewCenter) > root.zoomLimit * root.zoomLimit) {
- // Dolly up to limit
- root.camera.translate(Qt.vector3d(0, 0, d.translationY).times(dt), Camera.DontTranslateViewCenter);
- } else {
- // Too close, Dolly backwards
- root.camera.translate(Qt.vector3d(0, 0, -1).times(dt), Camera.DontTranslateViewCenter);
- }
- } else {
- // Translate
- root.camera.translate(Qt.vector3d(d.translationX, d.translationY, d.translationZ).times(dt));
- }
- }
- }
- ] // components
-}
diff --git a/src/quick3d/imports/extras/defaults/qml/PhongAlphaMaterial.qml b/src/quick3d/imports/extras/defaults/qml/PhongAlphaMaterial.qml
deleted file mode 100644
index 87373242d..000000000
--- a/src/quick3d/imports/extras/defaults/qml/PhongAlphaMaterial.qml
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Paul Lemire
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-
-Material {
- id: root
-
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property color diffuse: Qt.rgba( 0.7, 0.7, 0.7, 1.0 )
- property color specular: Qt.rgba( 0.01, 0.01, 0.01, 1.0 )
- property real shininess: 150.0
- property real alpha: 0.5
-
- property alias sourceRgbArg: alphaEffect.sourceRgbArg
- property alias destinationRgbArg: alphaEffect.destinationRgbArg
- property alias sourceAlphaArg: alphaEffect.sourceAlphaArg
- property alias destinationAlphaArg: alphaEffect.destinationAlphaArg
- property alias blendFunctionArg: alphaEffect.blendFunctionArg
-
- parameters: [
- Parameter { name: "alpha"; value: root.alpha },
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter { name: "kd"; value: Qt.vector3d(root.diffuse.r, root.diffuse.g, root.diffuse.b) },
- Parameter { name: "ks"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) },
- Parameter { name: "shininess"; value: root.shininess }
- ]
-
- effect: DefaultAlphaEffect { id: alphaEffect }
-}
-
diff --git a/src/quick3d/imports/extras/defaults/qml/SkyboxEntity.qml b/src/quick3d/imports/extras/defaults/qml/SkyboxEntity.qml
deleted file mode 100644
index 00bff6f10..000000000
--- a/src/quick3d/imports/extras/defaults/qml/SkyboxEntity.qml
+++ /dev/null
@@ -1,151 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-import Qt3D.Extras 2.0
-
-Entity {
- property string baseName: "";
- property string extension: ".png"
-
- property TextureCubeMap skyboxTexture: TextureCubeMap {
- generateMipMaps: false
- magnificationFilter: Texture.Linear
- minificationFilter: Texture.Linear
- wrapMode {
- x: WrapMode.ClampToEdge
- y: WrapMode.ClampToEdge
- }
- TextureImage { mirrored: false; face: Texture.CubeMapPositiveX; source: baseName + "_posx" + extension }
- TextureImage { mirrored: false; face: Texture.CubeMapPositiveY; source: baseName + "_posy" + extension }
- TextureImage { mirrored: false; face: Texture.CubeMapPositiveZ; source: baseName + "_posz" + extension }
- TextureImage { mirrored: false; face: Texture.CubeMapNegativeX; source: baseName + "_negx" + extension }
- TextureImage { mirrored: false; face: Texture.CubeMapNegativeY; source: baseName + "_negy" + extension }
- TextureImage { mirrored: false; face: Texture.CubeMapNegativeZ; source: baseName + "_negz" + extension }
- }
-
- ShaderProgram {
- id: gl3SkyboxShader
- vertexShaderCode: loadSource("qrc:/shaders/gl3/skybox.vert")
- fragmentShaderCode: loadSource("qrc:/shaders/gl3/skybox.frag")
- }
-
- ShaderProgram {
- id: gl2es2SkyboxShader
- vertexShaderCode: loadSource("qrc:/shaders/es2/skybox.vert")
- fragmentShaderCode: loadSource("qrc:/shaders/es2/skybox.frag")
- }
-
- CuboidMesh {
- id: cuboidMesh
- yzMeshResolution: Qt.size(2, 2)
- xzMeshResolution: Qt.size(2, 2)
- xyMeshResolution: Qt.size(2, 2)
- }
-
- Material {
- id: skyboxMaterial
- parameters: Parameter { name: "skyboxTexture"; value: skyboxTexture}
-
- effect: Effect {
- FilterKey {
- id: forward
- name: "renderingStyle"
- value: "forward"
- }
-
- techniques: [
- // GL3 Technique
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.CoreProfile
- majorVersion: 3
- minorVersion: 1
- }
- renderPasses: RenderPass {
- shaderProgram: gl3SkyboxShader
- renderStates: [
- // cull front faces
- CullFace { mode: CullFace.Front },
- DepthTest { depthFunction: DepthTest.LessOrEqual }
- ]
- }
- },
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGL
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass {
- shaderProgram: gl2es2SkyboxShader
- renderStates: [
- CullFace { mode: CullFace.Front },
- DepthTest { depthFunction: DepthTest.LessOrEqual }
- ]
- }
- },
- Technique {
- filterKeys: [ forward ]
- graphicsApiFilter {
- api: GraphicsApiFilter.OpenGLES
- profile: GraphicsApiFilter.NoProfile
- majorVersion: 2
- minorVersion: 0
- }
- renderPasses: RenderPass {
- shaderProgram: gl2es2SkyboxShader
- renderStates: [
- CullFace { mode: CullFace.Front },
- DepthTest { depthFunction: DepthTest.LessOrEqual }
- ]
- }
- }
- ]
- }
- }
-
- components: [cuboidMesh, skyboxMaterial]
-}
-
diff --git a/src/quick3d/imports/extras/importsextras.pro b/src/quick3d/imports/extras/importsextras.pro
index 6a70238f4..22f753ee0 100644
--- a/src/quick3d/imports/extras/importsextras.pro
+++ b/src/quick3d/imports/extras/importsextras.pro
@@ -14,32 +14,6 @@ HEADERS += \
SOURCES += \
qt3dquick3dextrasplugin.cpp
-load(qml_plugin)
-
-include(./defaults/defaults.pri)
-
-OTHER_FILES += \
- qmldir \
- $$QML_FILES
-
-# Create a resource file for qml files that need to be registered by the plugin
-GENERATED_RESOURCE_FILE = $$OUT_PWD/defaults.qrc
-INCLUDED_RESOURCE_FILES = $$QML_FILES
-RESOURCE_CONTENT = \
- "<RCC>" \
- "<qresource prefix=\"/qt-project.org/imports/Qt3D/Extras/\">"
+OTHER_FILES += qmldir
-for(resourcefile, INCLUDED_RESOURCE_FILES) {
- resourcefileabsolutepath = $$absolute_path($$resourcefile)
- relativepath_in = $$relative_path($$resourcefileabsolutepath, $$_PRO_FILE_PWD_)
- relativepath_out = $$relative_path($$resourcefileabsolutepath, $$OUT_PWD)
- RESOURCE_CONTENT += "<file alias=\"$$relativepath_in\">$$relativepath_out</file>"
-}
-
-RESOURCE_CONTENT += \
- "</qresource>" \
- "</RCC>"
-
-write_file($$GENERATED_RESOURCE_FILE, RESOURCE_CONTENT)|error("Aborting.")
-
-RESOURCES += $$GENERATED_RESOURCE_FILE
+load(qml_plugin)
diff --git a/src/quick3d/imports/extras/plugins.qmltypes b/src/quick3d/imports/extras/plugins.qmltypes
index 6a7e1203d..a623f385c 100644
--- a/src/quick3d/imports/extras/plugins.qmltypes
+++ b/src/quick3d/imports/extras/plugins.qmltypes
@@ -4,10 +4,31 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt3D.Extras 2.0'
+// 'qmlplugindump -nonrelocatable Qt3D.Extras 2.9'
Module {
dependencies: ["Qt3D.Logic 2.0"]
+ Component { name: "Qt3DCore::QEntity"; prototype: "Qt3DCore::QNode" }
+ Component {
+ name: "Qt3DExtras::Extras::Quick::Quick3DLevelOfDetailLoader"
+ prototype: "Qt3DCore::QEntity"
+ exports: ["Qt3D.Extras/LevelOfDetailLoader 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "sources"; type: "QVariantList" }
+ Property { name: "camera"; type: "Qt3DRender::QCamera"; isPointer: true }
+ Property { name: "currentIndex"; type: "int" }
+ Property { name: "thresholdType"; type: "Qt3DRender::QLevelOfDetail::ThresholdType" }
+ Property { name: "thresholds"; type: "QVector<qreal>" }
+ Property { name: "volumeOverride"; type: "Qt3DRender::QLevelOfDetailBoundingSphere" }
+ Property { name: "entity"; type: "QObject"; isReadonly: true; isPointer: true }
+ Property { name: "source"; type: "QUrl"; isReadonly: true }
+ Method {
+ name: "createBoundingSphere"
+ type: "Qt3DRender::QLevelOfDetailBoundingSphere"
+ Parameter { name: "center"; type: "QVector3D" }
+ Parameter { name: "radius"; type: "float" }
+ }
+ }
Component {
name: "Qt3DExtras::QConeGeometry"
prototype: "Qt3DRender::QGeometry"
@@ -429,6 +450,723 @@ Module {
}
}
Component {
+ name: "Qt3DExtras::QDiffuseMapMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/DiffuseMapMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "specular"; type: "QColor" }
+ Property { name: "shininess"; type: "float" }
+ Property { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "textureScale"; type: "float" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Signal {
+ name: "textureScaleChanged"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "color"; type: "QColor" }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setTextureScale"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QDiffuseSpecularMapMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/DiffuseSpecularMapMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "shininess"; type: "float" }
+ Property { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "textureScale"; type: "float" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Signal {
+ name: "textureScaleChanged"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setTextureScale"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QExtrudedTextGeometry"
+ prototype: "Qt3DRender::QGeometry"
+ exports: ["Qt3D.Extras/ExtrudedTextGeometry 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "text"; type: "string" }
+ Property { name: "font"; type: "QFont" }
+ Property { name: "extrusionLength"; type: "float" }
+ Property {
+ name: "positionAttribute"
+ type: "Qt3DRender::QAttribute"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "normalAttribute"
+ type: "Qt3DRender::QAttribute"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "indexAttribute"
+ type: "Qt3DRender::QAttribute"
+ isReadonly: true
+ isPointer: true
+ }
+ Signal {
+ name: "textChanged"
+ Parameter { name: "text"; type: "string" }
+ }
+ Signal {
+ name: "fontChanged"
+ Parameter { name: "font"; type: "QFont" }
+ }
+ Signal {
+ name: "depthChanged"
+ Parameter { name: "extrusionLength"; type: "float" }
+ }
+ Method {
+ name: "setText"
+ Parameter { name: "text"; type: "string" }
+ }
+ Method {
+ name: "setFont"
+ Parameter { name: "font"; type: "QFont" }
+ }
+ Method {
+ name: "setDepth"
+ Parameter { name: "extrusionLength"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QExtrudedTextMesh"
+ prototype: "Qt3DRender::QGeometryRenderer"
+ exports: ["Qt3D.Extras/ExtrudedTextMesh 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "text"; type: "string" }
+ Property { name: "font"; type: "QFont" }
+ Property { name: "depth"; type: "float" }
+ Signal {
+ name: "textChanged"
+ Parameter { name: "text"; type: "string" }
+ }
+ Signal {
+ name: "fontChanged"
+ Parameter { name: "font"; type: "QFont" }
+ }
+ Signal {
+ name: "depthChanged"
+ Parameter { name: "depth"; type: "float" }
+ }
+ Method {
+ name: "setText"
+ Parameter { name: "text"; type: "string" }
+ }
+ Method {
+ name: "setFont"
+ Parameter { name: "font"; type: "QFont" }
+ }
+ Method {
+ name: "setDepth"
+ Parameter { name: "depth"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QFirstPersonCameraController"
+ prototype: "Qt3DCore::QEntity"
+ exports: ["Qt3D.Extras/FirstPersonCameraController 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "camera"; type: "Qt3DRender::QCamera"; isPointer: true }
+ Property { name: "linearSpeed"; type: "float" }
+ Property { name: "lookSpeed"; type: "float" }
+ Property { name: "acceleration"; type: "float" }
+ Property { name: "deceleration"; type: "float" }
+ Signal {
+ name: "accelerationChanged"
+ Parameter { name: "acceleration"; type: "float" }
+ }
+ Signal {
+ name: "decelerationChanged"
+ Parameter { name: "deceleration"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QForwardRenderer"
+ prototype: "Qt3DRender::QTechniqueFilter"
+ exports: ["Qt3D.Extras/ForwardRenderer 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "surface"; type: "QObject"; isPointer: true }
+ Property { name: "window"; type: "QObject"; isPointer: true }
+ Property { name: "viewportRect"; type: "QRectF" }
+ Property { name: "clearColor"; type: "QColor" }
+ Property { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
+ Property { name: "externalRenderTargetSize"; type: "QSize" }
+ Property { name: "frustumCulling"; type: "bool" }
+ Property { name: "gamma"; revision: 9; type: "float" }
+ Signal {
+ name: "viewportRectChanged"
+ Parameter { name: "viewportRect"; type: "QRectF" }
+ }
+ Signal {
+ name: "clearColorChanged"
+ Parameter { name: "clearColor"; type: "QColor" }
+ }
+ Signal {
+ name: "cameraChanged"
+ Parameter { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
+ }
+ Signal {
+ name: "surfaceChanged"
+ Parameter { name: "surface"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "externalRenderTargetSizeChanged"
+ Parameter { name: "size"; type: "QSize" }
+ }
+ Signal {
+ name: "frustumCullingEnabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "gammaChanged"
+ Parameter { name: "gamma"; type: "float" }
+ }
+ Method {
+ name: "setViewportRect"
+ Parameter { name: "viewportRect"; type: "QRectF" }
+ }
+ Method {
+ name: "setClearColor"
+ Parameter { name: "clearColor"; type: "QColor" }
+ }
+ Method {
+ name: "setCamera"
+ Parameter { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
+ }
+ Method {
+ name: "setSurface"
+ Parameter { name: "surface"; type: "QObject"; isPointer: true }
+ }
+ Method {
+ name: "setExternalRenderTargetSize"
+ Parameter { name: "size"; type: "QSize" }
+ }
+ Method {
+ name: "setFrustumCullingEnabled"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Method {
+ name: "setGamma"
+ Parameter { name: "gamma"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QGoochMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/GoochMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "diffuse"; type: "QColor" }
+ Property { name: "specular"; type: "QColor" }
+ Property { name: "cool"; type: "QColor" }
+ Property { name: "warm"; type: "QColor" }
+ Property { name: "alpha"; type: "float" }
+ Property { name: "beta"; type: "float" }
+ Property { name: "shininess"; type: "float" }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Signal {
+ name: "coolChanged"
+ Parameter { name: "cool"; type: "QColor" }
+ }
+ Signal {
+ name: "warmChanged"
+ Parameter { name: "warm"; type: "QColor" }
+ }
+ Signal {
+ name: "alphaChanged"
+ Parameter { name: "alpha"; type: "float" }
+ }
+ Signal {
+ name: "betaChanged"
+ Parameter { name: "beta"; type: "float" }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Method {
+ name: "setCool"
+ Parameter { name: "cool"; type: "QColor" }
+ }
+ Method {
+ name: "setWarm"
+ Parameter { name: "warm"; type: "QColor" }
+ }
+ Method {
+ name: "setAlpha"
+ Parameter { name: "alpha"; type: "float" }
+ }
+ Method {
+ name: "setBeta"
+ Parameter { name: "beta"; type: "float" }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QMetalRoughMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/MetalRoughMaterial 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "baseColor"; type: "QColor" }
+ Property { name: "metalness"; type: "float" }
+ Property { name: "roughness"; type: "float" }
+ Signal {
+ name: "baseColorChanged"
+ Parameter { name: "baseColor"; type: "QColor" }
+ }
+ Signal {
+ name: "metalnessChanged"
+ Parameter { name: "metalness"; type: "float" }
+ }
+ Signal {
+ name: "roughnessChanged"
+ Parameter { name: "roughness"; type: "float" }
+ }
+ Method {
+ name: "setBaseColor"
+ Parameter { name: "baseColor"; type: "QColor" }
+ }
+ Method {
+ name: "setMetalness"
+ Parameter { name: "metalness"; type: "float" }
+ }
+ Method {
+ name: "setRoughness"
+ Parameter { name: "roughness"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QMorphPhongMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/MorphPhongMaterial 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "diffuse"; type: "QColor" }
+ Property { name: "specular"; type: "QColor" }
+ Property { name: "shininess"; type: "float" }
+ Property { name: "interpolator"; type: "float" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Signal {
+ name: "interpolatorChanged"
+ Parameter { name: "interpolator"; type: "float" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setInterpolator"
+ Parameter { name: "interpolator"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QNormalDiffuseMapAlphaMaterial"
+ prototype: "Qt3DExtras::QNormalDiffuseMapMaterial"
+ exports: ["Qt3D.Extras/NormalDiffuseMapAlphaMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "Qt3DExtras::QNormalDiffuseMapMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/NormalDiffuseMapMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "specular"; type: "QColor" }
+ Property { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "shininess"; type: "float" }
+ Property { name: "textureScale"; type: "float" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "normalChanged"
+ Parameter { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Signal {
+ name: "textureScaleChanged"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setNormal"
+ Parameter { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setTextureScale"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QNormalDiffuseSpecularMapMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/NormalDiffuseSpecularMapMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "shininess"; type: "float" }
+ Property { name: "textureScale"; type: "float" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "normalChanged"
+ Parameter { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Signal {
+ name: "textureScaleChanged"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setNormal"
+ Parameter { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setTextureScale"
+ Parameter { name: "textureScale"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QOrbitCameraController"
+ prototype: "Qt3DCore::QEntity"
+ exports: ["Qt3D.Extras/OrbitCameraController 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "camera"; type: "Qt3DRender::QCamera"; isPointer: true }
+ Property { name: "linearSpeed"; type: "float" }
+ Property { name: "lookSpeed"; type: "float" }
+ Property { name: "zoomInLimit"; type: "float" }
+ }
+ Component {
+ name: "Qt3DExtras::QPerVertexColorMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/PerVertexColorMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "Qt3DExtras::QPhongAlphaMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/PhongAlphaMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "diffuse"; type: "QColor" }
+ Property { name: "specular"; type: "QColor" }
+ Property { name: "shininess"; type: "float" }
+ Property { name: "alpha"; type: "float" }
+ Property { name: "sourceRgbArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ Property { name: "destinationRgbArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ Property { name: "sourceAlphaArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ Property {
+ name: "destinationAlphaArg"
+ type: "Qt3DRender::QBlendEquationArguments::Blending"
+ }
+ Property { name: "blendFunctionArg"; type: "Qt3DRender::QBlendEquation::BlendFunction" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Signal {
+ name: "alphaChanged"
+ Parameter { name: "alpha"; type: "float" }
+ }
+ Signal {
+ name: "sourceRgbArgChanged"
+ Parameter { name: "sourceRgbArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ }
+ Signal {
+ name: "destinationRgbArgChanged"
+ Parameter { name: "destinationRgbArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ }
+ Signal {
+ name: "sourceAlphaArgChanged"
+ Parameter { name: "sourceAlphaArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ }
+ Signal {
+ name: "destinationAlphaArgChanged"
+ Parameter {
+ name: "destinationAlphaArg"
+ type: "Qt3DRender::QBlendEquationArguments::Blending"
+ }
+ }
+ Signal {
+ name: "blendFunctionArgChanged"
+ Parameter { name: "blendFunctionArg"; type: "Qt3DRender::QBlendEquation::BlendFunction" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setAlpha"
+ Parameter { name: "alpha"; type: "float" }
+ }
+ Method {
+ name: "setSourceRgbArg"
+ Parameter { name: "sourceRgbArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ }
+ Method {
+ name: "setDestinationRgbArg"
+ Parameter { name: "destinationRgbArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ }
+ Method {
+ name: "setSourceAlphaArg"
+ Parameter { name: "sourceAlphaArg"; type: "Qt3DRender::QBlendEquationArguments::Blending" }
+ }
+ Method {
+ name: "setDestinationAlphaArg"
+ Parameter {
+ name: "destinationAlphaArg"
+ type: "Qt3DRender::QBlendEquationArguments::Blending"
+ }
+ }
+ Method {
+ name: "setBlendFunctionArg"
+ Parameter { name: "blendFunctionArg"; type: "Qt3DRender::QBlendEquation::BlendFunction" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QPhongMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/PhongMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "ambient"; type: "QColor" }
+ Property { name: "diffuse"; type: "QColor" }
+ Property { name: "specular"; type: "QColor" }
+ Property { name: "shininess"; type: "float" }
+ Signal {
+ name: "ambientChanged"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Signal {
+ name: "diffuseChanged"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Signal {
+ name: "shininessChanged"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ Method {
+ name: "setAmbient"
+ Parameter { name: "ambient"; type: "QColor" }
+ }
+ Method {
+ name: "setDiffuse"
+ Parameter { name: "diffuse"; type: "QColor" }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "QColor" }
+ }
+ Method {
+ name: "setShininess"
+ Parameter { name: "shininess"; type: "float" }
+ }
+ }
+ Component {
name: "Qt3DExtras::QPlaneGeometry"
prototype: "Qt3DRender::QGeometry"
exports: ["Qt3D.Extras/PlaneGeometry 2.0"]
@@ -525,6 +1263,39 @@ Module {
}
}
Component {
+ name: "Qt3DExtras::QSkyboxEntity"
+ prototype: "Qt3DCore::QEntity"
+ exports: ["Qt3D.Extras/SkyboxEntity 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "baseName"; type: "string" }
+ Property { name: "extension"; type: "string" }
+ Property { name: "gammaCorrect"; revision: 9; type: "bool" }
+ Signal {
+ name: "baseNameChanged"
+ Parameter { name: "path"; type: "string" }
+ }
+ Signal {
+ name: "extensionChanged"
+ Parameter { name: "extension"; type: "string" }
+ }
+ Signal {
+ name: "gammaCorrectEnabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Method {
+ name: "setBaseName"
+ Parameter { name: "path"; type: "string" }
+ }
+ Method {
+ name: "setExtension"
+ Parameter { name: "extension"; type: "string" }
+ }
+ Method {
+ name: "setGammaCorrectEnabled"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ }
+ Component {
name: "Qt3DExtras::QSphereGeometry"
prototype: "Qt3DRender::QGeometry"
exports: ["Qt3D.Extras/SphereGeometry 2.0"]
@@ -639,6 +1410,112 @@ Module {
}
}
Component {
+ name: "Qt3DExtras::QText2DEntity"
+ prototype: "Qt3DCore::QEntity"
+ exports: ["Qt3D.Extras/Text2DEntity 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "font"; type: "QFont" }
+ Property { name: "text"; type: "string" }
+ Property { name: "color"; type: "QColor" }
+ Property { name: "width"; type: "float" }
+ Property { name: "height"; type: "float" }
+ Signal {
+ name: "fontChanged"
+ Parameter { name: "font"; type: "QFont" }
+ }
+ Signal {
+ name: "colorChanged"
+ Parameter { name: "color"; type: "QColor" }
+ }
+ Signal {
+ name: "textChanged"
+ Parameter { name: "text"; type: "string" }
+ }
+ Signal {
+ name: "widthChanged"
+ Parameter { name: "width"; type: "float" }
+ }
+ Signal {
+ name: "heightChanged"
+ Parameter { name: "height"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QTextureMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/TextureMaterial 2.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "textureOffset"; type: "QVector2D" }
+ Signal {
+ name: "textureChanged"
+ Parameter { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "textureOffsetChanged"
+ Parameter { name: "textureOffset"; type: "QVector2D" }
+ }
+ Method {
+ name: "setTexture"
+ Parameter { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setTextureOffset"
+ Parameter { name: "textureOffset"; type: "QVector2D" }
+ }
+ }
+ Component {
+ name: "Qt3DExtras::QTexturedMetalRoughMaterial"
+ prototype: "Qt3DRender::QMaterial"
+ exports: ["Qt3D.Extras/TexturedMetalRoughMaterial 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "baseColor"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "metalness"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "roughness"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "ambientOcclusion"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Signal {
+ name: "baseColorChanged"
+ Parameter { name: "baseColor"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "metalnessChanged"
+ Parameter { name: "metalness"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "roughnessChanged"
+ Parameter { name: "roughness"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "ambientOcclusionChanged"
+ Parameter { name: "ambientOcclusion"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "normalChanged"
+ Parameter { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setBaseColor"
+ Parameter { name: "baseColor"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setMetalness"
+ Parameter { name: "metalness"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setRoughness"
+ Parameter { name: "roughness"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setAmbientOcclusion"
+ Parameter { name: "ambientOcclusion"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setNormal"
+ Parameter { name: "normal"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ }
+ Component {
name: "Qt3DExtras::QTorusGeometry"
prototype: "Qt3DRender::QGeometry"
exports: ["Qt3D.Extras/TorusGeometry 2.0"]
@@ -746,6 +1623,7 @@ Module {
Parameter { name: "minorRadius"; type: "float" }
}
}
+ Component { name: "Qt3DRender::QFrameGraphNode"; prototype: "Qt3DCore::QNode" }
Component {
name: "Qt3DRender::QGeometry"
prototype: "Qt3DCore::QNode"
@@ -883,306 +1761,8 @@ Module {
}
}
Component {
- prototype: "Qt3DCore::QNode"
- name: "Qt3D.Extras/DefaultAlphaEffect 2.0"
- exports: ["Qt3D.Extras/DefaultAlphaEffect 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "vertexES"; type: "string" }
- Property { name: "fragmentES"; type: "string" }
- Property { name: "vertex"; type: "string" }
- Property { name: "fragment"; type: "string" }
- Property { name: "sourceRgbArg"; type: "int" }
- Property { name: "destinationRgbArg"; type: "int" }
- Property { name: "sourceAlphaArg"; type: "int" }
- Property { name: "destinationAlphaArg"; type: "int" }
- Property { name: "blendFunctionArg"; type: "int" }
- }
- Component {
- prototype: "Qt3DCore::QNode"
- name: "Qt3D.Extras/DefaultEffect 2.0"
- exports: ["Qt3D.Extras/DefaultEffect 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "vertexES"; type: "string" }
- Property { name: "fragmentES"; type: "string" }
- Property { name: "vertex"; type: "string" }
- Property { name: "fragment"; type: "string" }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/DiffuseMapMaterial 2.0"
- exports: ["Qt3D.Extras/DiffuseMapMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "specular"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "textureScale"; type: "double" }
- Property { name: "diffuse"; type: "QUrl" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/DiffuseSpecularMapMaterial 2.0"
- exports: ["Qt3D.Extras/DiffuseSpecularMapMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "textureScale"; type: "double" }
- Property { name: "diffuse"; type: "QUrl" }
- Property { name: "specular"; type: "QUrl" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QNode"
- name: "Qt3D.Extras/FirstPersonCameraController 2.0"
- exports: ["Qt3D.Extras/FirstPersonCameraController 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "camera"; type: "Qt3DRender::QCamera"; isPointer: true }
- Property { name: "linearSpeed"; type: "double" }
- Property { name: "lookSpeed"; type: "double" }
- Property { name: "acceleration"; type: "double" }
- Property { name: "deceleration"; type: "double" }
- }
- Component {
- prototype: "Qt3DCore::QNode"
- name: "Qt3D.Extras/ForwardRenderer 2.0"
- exports: ["Qt3D.Extras/ForwardRenderer 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
- Property { name: "clearColor"; type: "QColor" }
- Property { name: "viewportRect"; type: "QRectF" }
- Property { name: "window"; type: "QObject"; isPointer: true }
- }
- Component {
+ name: "Qt3DRender::QMaterial"
prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/GoochMaterial 2.0"
- exports: ["Qt3D.Extras/GoochMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "diffuse"; type: "QColor" }
- Property { name: "specular"; type: "QColor" }
- Property { name: "coolColor"; type: "QColor" }
- Property { name: "warmColor"; type: "QColor" }
- Property { name: "alpha"; type: "double" }
- Property { name: "beta"; type: "double" }
- Property { name: "shininess"; type: "double" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QNode"
- name: "Qt3D.Extras/NormalDiffuseMapAlphaEffect 2.0"
- exports: ["Qt3D.Extras/NormalDiffuseMapAlphaEffect 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "vertexES"; type: "string" }
- Property { name: "fragmentES"; type: "string" }
- Property { name: "vertex"; type: "string" }
- Property { name: "fragment"; type: "string" }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/NormalDiffuseMapAlphaMaterial 2.0"
- exports: ["Qt3D.Extras/NormalDiffuseMapAlphaMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "specular"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "textureScale"; type: "double" }
- Property { name: "diffuse"; type: "QUrl" }
- Property { name: "normal"; type: "QUrl" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/NormalDiffuseMapMaterial 2.0"
- exports: ["Qt3D.Extras/NormalDiffuseMapMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "specular"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "textureScale"; type: "double" }
- Property { name: "diffuse"; type: "QUrl" }
- Property { name: "normal"; type: "QUrl" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/NormalDiffuseSpecularMapMaterial 2.0"
- exports: ["Qt3D.Extras/NormalDiffuseSpecularMapMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "textureScale"; type: "double" }
- Property { name: "diffuse"; type: "QUrl" }
- Property { name: "specular"; type: "QUrl" }
- Property { name: "normal"; type: "QUrl" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QNode"
- name: "Qt3D.Extras/OrbitCameraController 2.0"
- exports: ["Qt3D.Extras/OrbitCameraController 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "camera"; type: "Qt3DRender::QCamera"; isPointer: true }
- Property { name: "linearSpeed"; type: "double" }
- Property { name: "lookSpeed"; type: "double" }
- Property { name: "zoomLimit"; type: "double" }
- Method {
- name: "clampInputs"
- type: "QVariant"
- Parameter { name: "input1"; type: "QVariant" }
- Parameter { name: "input2"; type: "QVariant" }
- }
- Method {
- name: "zoomDistance"
- type: "QVariant"
- Parameter { name: "firstPoint"; type: "QVariant" }
- Parameter { name: "secondPoint"; type: "QVariant" }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/PerVertexColorMaterial 2.0"
- exports: ["Qt3D.Extras/PerVertexColorMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/PhongAlphaMaterial 2.0"
- exports: ["Qt3D.Extras/PhongAlphaMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "diffuse"; type: "QColor" }
- Property { name: "specular"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "alpha"; type: "double" }
- Property { name: "sourceRgbArg"; type: "int" }
- Property { name: "destinationRgbArg"; type: "int" }
- Property { name: "sourceAlphaArg"; type: "int" }
- Property { name: "destinationAlphaArg"; type: "int" }
- Property { name: "blendFunctionArg"; type: "int" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/PhongMaterial 2.0"
- exports: ["Qt3D.Extras/PhongMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "ambient"; type: "QColor" }
- Property { name: "diffuse"; type: "QColor" }
- Property { name: "specular"; type: "QColor" }
- Property { name: "shininess"; type: "double" }
- Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
- Signal {
- name: "effectChanged"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- Method {
- name: "setEffect"
- Parameter { name: "effect"; type: "QEffect"; isPointer: true }
- }
- }
- Component {
- prototype: "Qt3DCore::QComponent"
- name: "Qt3D.Extras/TextureMaterial 2.0"
- exports: ["Qt3D.Extras/TextureMaterial 2.0"]
- exportMetaObjectRevisions: [0]
- isComposite: true
- defaultProperty: "data"
- Property { name: "texture"; type: "Qt3DRender::QTexture2D"; isPointer: true }
- Property { name: "textureOffset"; type: "QVector2D" }
Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
Signal {
name: "effectChanged"
@@ -1193,4 +1773,5 @@ Module {
Parameter { name: "effect"; type: "QEffect"; isPointer: true }
}
}
+ Component { name: "Qt3DRender::QTechniqueFilter"; prototype: "Qt3DRender::QFrameGraphNode" }
}
diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
index 55af6432b..879b79294 100644
--- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
+++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
@@ -38,69 +38,76 @@
****************************************************************************/
#include "qt3dquick3dextrasplugin.h"
-#include <Qt3DExtras/qcuboidmesh.h>
+
+#include <Qt3DExtras/qconegeometry.h>
#include <Qt3DExtras/qconemesh.h>
+#include <Qt3DExtras/qcuboidgeometry.h>
+#include <Qt3DExtras/qcuboidmesh.h>
+#include <Qt3DExtras/qcylindergeometry.h>
#include <Qt3DExtras/qcylindermesh.h>
+#include <Qt3DExtras/qdiffusemapmaterial.h>
+#include <Qt3DExtras/qdiffusespecularmapmaterial.h>
+#include <Qt3DExtras/qextrudedtextgeometry.h>
+#include <Qt3DExtras/qextrudedtextmesh.h>
+#include <Qt3DExtras/qfirstpersoncameracontroller.h>
+#include <Qt3DExtras/qforwardrenderer.h>
+#include <Qt3DExtras/qgoochmaterial.h>
+#include <Qt3DExtras/qmetalroughmaterial.h>
+#include <Qt3DExtras/qmorphphongmaterial.h>
+#include <Qt3DExtras/qnormaldiffusemapalphamaterial.h>
+#include <Qt3DExtras/qnormaldiffusemapmaterial.h>
+#include <Qt3DExtras/qnormaldiffusespecularmapmaterial.h>
+#include <Qt3DExtras/qorbitcameracontroller.h>
+#include <Qt3DExtras/qpervertexcolormaterial.h>
+#include <Qt3DExtras/qphongalphamaterial.h>
+#include <Qt3DExtras/qphongmaterial.h>
+#include <Qt3DExtras/qplanegeometry.h>
#include <Qt3DExtras/qplanemesh.h>
+#include <Qt3DExtras/qskyboxentity.h>
+#include <Qt3DExtras/qspheregeometry.h>
#include <Qt3DExtras/qspheremesh.h>
-#include <Qt3DExtras/qtorusmesh.h>
+#include <Qt3DExtras/qtext2dentity.h>
+#include <Qt3DExtras/qtexturedmetalroughmaterial.h>
+#include <Qt3DExtras/qtexturematerial.h>
#include <Qt3DExtras/qtorusgeometry.h>
-#include <Qt3DExtras/qspheregeometry.h>
-#include <Qt3DExtras/qcuboidgeometry.h>
-#include <Qt3DExtras/qplanegeometry.h>
-#include <Qt3DExtras/qconegeometry.h>
-#include <Qt3DExtras/qcylindergeometry.h>
-#include <Qt3DExtras/qtext3dgeometry.h>
-#include <Qt3DExtras/qtext3dmesh.h>
-#include <Qt3DExtras/qkeyframeanimation.h>
-#include <Qt3DExtras/qanimationcontroller.h>
-#include <Qt3DExtras/qabstractanimation.h>
-#include <Qt3DExtras/qmorphinganimation.h>
-#include <Qt3DExtras/qanimationgroup.h>
-#include <Qt3DExtras/qmorphtarget.h>
+#include <Qt3DExtras/qtorusmesh.h>
-#include <Qt3DQuickExtras/private/quick3dkeyframeanimation_p.h>
-#include <Qt3DQuickExtras/private/quick3danimationgroup_p.h>
-#include <Qt3DQuickExtras/private/quick3danimationcontroller_p.h>
-#include <Qt3DQuickExtras/private/quick3dmorphtarget_p.h>
-#include <Qt3DQuickExtras/private/quick3dmorphinganimation_p.h>
+#include <Qt3DQuickExtras/private/quick3dlevelofdetailloader_p.h>
#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
-static const struct {
- const char *type;
- int major, minor;
-} qmldir [] = {
- // Materials
- { "PhongMaterial", 2, 0 },
- { "PhongAlphaMaterial", 2, 0 },
- { "DiffuseMapMaterial", 2, 0 },
- { "DiffuseSpecularMapMaterial", 2, 0 },
- { "NormalDiffuseMapAlphaMaterial", 2, 0 },
- { "NormalDiffuseMapMaterial", 2, 0 },
- { "NormalDiffuseSpecularMapMaterial", 2, 0 },
- { "PerVertexColorMaterial", 2, 0 },
- { "GoochMaterial", 2, 0 },
- { "TextureMaterial", 2, 0 },
- // Effects
- { "DefaultEffect", 2, 0 },
- { "DefaultAlphaEffect", 2, 0 },
- { "NormalDiffuseMapAlphaEffect", 2, 0 },
- // Scene Graph
- { "LevelOfDetailLoader", 2, 2 },
- // FrameGraphs
- { "ForwardRenderer", 2, 0 },
+void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
+{
+ // Framegraphs
+ qmlRegisterType<Qt3DExtras::QForwardRenderer>(uri, 2, 0, "ForwardRenderer");
+ qmlRegisterRevision<Qt3DExtras::QForwardRenderer, 9>(uri, 2, 9);
+
// Entities
- { "SkyboxEntity", 2, 0 },
+ qmlRegisterType<Qt3DExtras::QSkyboxEntity>(uri, 2, 0, "SkyboxEntity");
+ qmlRegisterRevision<Qt3DExtras::QSkyboxEntity, 9>(uri, 2, 9);
+ qmlRegisterType<Qt3DExtras::Extras::Quick::Quick3DLevelOfDetailLoader>(uri, 2, 9, "LevelOfDetailLoader");
+
// Camera Controllers
- { "OrbitCameraController", 2, 0 },
- { "FirstPersonCameraController", 2, 0 },
-};
+ qmlRegisterType<Qt3DExtras::QFirstPersonCameraController>(uri, 2, 0, "FirstPersonCameraController");
+ qmlRegisterType<Qt3DExtras::QOrbitCameraController>(uri, 2, 0, "OrbitCameraController");
+
+ // Materials
+ qmlRegisterType<Qt3DExtras::QPhongMaterial>(uri, 2, 0, "PhongMaterial");
+ qmlRegisterType<Qt3DExtras::QPhongAlphaMaterial>(uri, 2, 0, "PhongAlphaMaterial");
+ qmlRegisterType<Qt3DExtras::QDiffuseMapMaterial>(uri, 2, 0, "DiffuseMapMaterial");
+ qmlRegisterType<Qt3DExtras::QDiffuseSpecularMapMaterial>(uri, 2, 0, "DiffuseSpecularMapMaterial");
+ qmlRegisterType<Qt3DExtras::QNormalDiffuseMapAlphaMaterial>(uri, 2, 0, "NormalDiffuseMapAlphaMaterial");
+ qmlRegisterType<Qt3DExtras::QNormalDiffuseMapMaterial>(uri, 2, 0, "NormalDiffuseMapMaterial");
+ qmlRegisterType<Qt3DExtras::QNormalDiffuseSpecularMapMaterial>(uri, 2, 0, "NormalDiffuseSpecularMapMaterial");
+ qmlRegisterType<Qt3DExtras::QPerVertexColorMaterial>(uri, 2, 0, "PerVertexColorMaterial");
+ qmlRegisterType<Qt3DExtras::QGoochMaterial>(uri, 2, 0, "GoochMaterial");
+ qmlRegisterType<Qt3DExtras::QTextureMaterial>(uri, 2, 0, "TextureMaterial");
+ qmlRegisterType<Qt3DExtras::QMetalRoughMaterial>(uri, 2, 9, "MetalRoughMaterial");
+ qmlRegisterType<Qt3DExtras::QTexturedMetalRoughMaterial>(uri, 2, 9, "TexturedMetalRoughMaterial");
+ qmlRegisterType<Qt3DExtras::QMorphPhongMaterial>(uri, 2, 9, "MorphPhongMaterial");
-void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
-{
// Meshes
qmlRegisterType<Qt3DExtras::QConeMesh>(uri, 2, 0, "ConeMesh");
qmlRegisterType<Qt3DExtras::QConeGeometry>(uri, 2, 0, "ConeGeometry");
@@ -109,31 +116,19 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DExtras::QCylinderMesh>(uri, 2, 0, "CylinderMesh");
qmlRegisterType<Qt3DExtras::QCylinderGeometry>(uri, 2, 0, "CylinderGeometry");
qmlRegisterType<Qt3DExtras::QPlaneMesh>(uri, 2, 0, "PlaneMesh");
+ qmlRegisterRevision<Qt3DExtras::QPlaneMesh, 9>(uri, 2, 9);
qmlRegisterType<Qt3DExtras::QPlaneGeometry>(uri, 2, 0, "PlaneGeometry");
+ qmlRegisterRevision<Qt3DExtras::QPlaneGeometry, 9>(uri, 2, 9);
qmlRegisterType<Qt3DExtras::QTorusMesh>(uri, 2, 0, "TorusMesh");
qmlRegisterType<Qt3DExtras::QTorusGeometry>(uri, 2, 0, "TorusGeometry");
qmlRegisterType<Qt3DExtras::QSphereMesh>(uri, 2, 0, "SphereMesh");
qmlRegisterType<Qt3DExtras::QSphereGeometry>(uri, 2, 0, "SphereGeometry");
// 3D Text
- qmlRegisterType<Qt3DExtras::QText3DGeometry>(uri, 2, 2, "Text3DGeometry");
- qmlRegisterType<Qt3DExtras::QText3DMesh>(uri, 2, 2, "Text3DMesh");
-
- qmlRegisterUncreatableType<Qt3DExtras::QAbstractAnimation>(uri, 2, 0, "AbstractAnimation", QStringLiteral("AbstractAnimation is abstract"));
- qmlRegisterExtendedType<Qt3DExtras::QKeyframeAnimation, Qt3DExtras::Quick::QQuick3DKeyframeAnimation>(uri, 2, 2, "KeyframeAnimation");
- qmlRegisterExtendedType<Qt3DExtras::QAnimationGroup, Qt3DExtras::Quick::QQuick3DAnimationGroup>(uri, 2, 2, "AnimationGroup");
- qmlRegisterExtendedType<Qt3DExtras::QAnimationController, Qt3DExtras::Quick::QQuick3DAnimationController>(uri, 2, 2, "AnimationController");
- qmlRegisterExtendedType<Qt3DExtras::QMorphingAnimation, Qt3DExtras::Quick::QQuick3DMorphingAnimation>(uri, 2, 2, "MorphingAnimation");
- qmlRegisterExtendedType<Qt3DExtras::QMorphTarget, Qt3DExtras::Quick::QQuick3DMorphTarget>(uri, 2, 2, "MorphTarget");
+ qmlRegisterType<Qt3DExtras::QExtrudedTextGeometry>(uri, 2, 9, "ExtrudedTextGeometry");
+ qmlRegisterType<Qt3DExtras::QExtrudedTextMesh>(uri, 2, 9, "ExtrudedTextMesh");
- // Register types provided as QML files compiled into the plugin
- for (int i = 0; i < int(sizeof(qmldir) / sizeof(qmldir[0])); i++) {
- auto path = QLatin1String("qrc:/qt-project.org/imports/Qt3D/Extras/defaults/qml/");
- qmlRegisterType(QUrl(path + qmldir[i].type + QLatin1String(".qml")),
- uri,
- qmldir[i].major, qmldir[i].minor,
- qmldir[i].type);
- }
+ qmlRegisterType<Qt3DExtras::QText2DEntity>(uri, 2, 9, "Text2DEntity");
}
diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h
index f5ea6a7f1..f24a93b3f 100644
--- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h
+++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h
@@ -46,7 +46,6 @@ static void initResources()
{
#ifdef QT_STATIC
Q_INIT_RESOURCE(qmake_Qt3D_Extras);
- Q_INIT_RESOURCE(defaults);
Q_INIT_RESOURCE(extras);
#endif
}
diff --git a/src/quick3d/imports/input/plugins.qmltypes b/src/quick3d/imports/input/plugins.qmltypes
index 860ab4d68..24655977e 100644
--- a/src/quick3d/imports/input/plugins.qmltypes
+++ b/src/quick3d/imports/input/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt3D.Input 2.0'
+// 'qmlplugindump -nonrelocatable Qt3D.Input 2.1'
Module {
- dependencies: ["QtQuick 2.7"]
+ dependencies: ["QtQuick 2.8"]
Component {
name: "Qt3DCore::QComponent"
prototype: "Qt3DCore::QNode"
@@ -16,6 +16,14 @@ Module {
name: "shareableChanged"
Parameter { name: "isShareable"; type: "bool" }
}
+ Signal {
+ name: "addedToEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
+ Signal {
+ name: "removedFromEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
Method {
name: "setShareable"
Parameter { name: "isShareable"; type: "bool" }
@@ -24,8 +32,17 @@ Module {
Component {
name: "Qt3DCore::QNode"
prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
Signal {
name: "parentChanged"
Parameter { name: "parent"; type: "QObject"; isPointer: true }
@@ -34,6 +51,10 @@ Module {
name: "enabledChanged"
Parameter { name: "enabled"; type: "bool" }
}
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
Signal { name: "nodeDestroyed" }
Method {
name: "setParent"
@@ -43,6 +64,10 @@ Module {
name: "setEnabled"
Parameter { name: "isEnabled"; type: "bool" }
}
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
}
Component {
name: "Qt3DInput::Input::Quick::Quick3DAction"
@@ -101,6 +126,7 @@ Module {
name: "Qt3DInput::Input::Quick::Quick3DPhysicalDevice"
prototype: "Qt3DInput::QAbstractPhysicalDevice"
exports: ["Qt3D.Input/QAbstractPhysicalDevice 2.0"]
+ isCreatable: false
exportMetaObjectRevisions: [0]
Property { name: "axisSettings"; type: "Qt3DInput::QAxisSetting"; isList: true; isReadonly: true }
}
@@ -186,6 +212,56 @@ Module {
}
}
Component {
+ name: "Qt3DInput::QAxisAccumulator"
+ prototype: "Qt3DCore::QComponent"
+ exports: ["Qt3D.Input/AxisAccumulator 2.1"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "SourceAxisType"
+ values: {
+ "Velocity": 0,
+ "Acceleration": 1
+ }
+ }
+ Property { name: "sourceAxis"; type: "Qt3DInput::QAxis"; isPointer: true }
+ Property { name: "sourceAxisType"; type: "SourceAxisType" }
+ Property { name: "scale"; type: "float" }
+ Property { name: "value"; type: "float"; isReadonly: true }
+ Property { name: "velocity"; type: "float"; isReadonly: true }
+ Signal {
+ name: "sourceAxisChanged"
+ Parameter { name: "sourceAxis"; type: "Qt3DInput::QAxis"; isPointer: true }
+ }
+ Signal {
+ name: "sourceAxisTypeChanged"
+ Parameter { name: "sourceAxisType"; type: "QAxisAccumulator::SourceAxisType" }
+ }
+ Signal {
+ name: "valueChanged"
+ Parameter { name: "value"; type: "float" }
+ }
+ Signal {
+ name: "velocityChanged"
+ Parameter { name: "value"; type: "float" }
+ }
+ Signal {
+ name: "scaleChanged"
+ Parameter { name: "scale"; type: "float" }
+ }
+ Method {
+ name: "setSourceAxis"
+ Parameter { name: "sourceAxis"; type: "Qt3DInput::QAxis"; isPointer: true }
+ }
+ Method {
+ name: "setSourceAxisType"
+ Parameter { name: "sourceAxisType"; type: "QAxisAccumulator::SourceAxisType" }
+ }
+ Method {
+ name: "setScale"
+ Parameter { name: "scale"; type: "float" }
+ }
+ }
+ Component {
name: "Qt3DInput::QAxisSetting"
prototype: "Qt3DCore::QNode"
exports: ["Qt3D.Input/AxisSetting 2.0"]
@@ -337,7 +413,6 @@ Module {
Component {
name: "Qt3DInput::QKeyboardDevice"
prototype: "Qt3DInput::QAbstractPhysicalDevice"
- exports: ["Qt3D.Input/KeyboardDevice 2.0"]
Property {
name: "activeInput"
type: "Qt3DInput::QKeyboardHandler"
@@ -537,12 +612,13 @@ Module {
Component {
name: "Qt3DInput::QMouseDevice"
prototype: "Qt3DInput::QAbstractPhysicalDevice"
- exports: ["Qt3D.Input/MouseDevice 2.0"]
Enum {
name: "Axis"
values: {
"X": 0,
- "Y": 1
+ "Y": 1,
+ "WheelX": 2,
+ "WheelY": 3
}
}
Property { name: "sensitivity"; type: "float" }
diff --git a/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp b/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp
index d31680b4d..5719a2b98 100644
--- a/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp
+++ b/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp
@@ -37,29 +37,31 @@
**
****************************************************************************/
-#include <QtQml>
-#include <Qt3DInput/qkeyboarddevice.h>
-#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DInput/qkeyevent.h>
-#include <Qt3DInput/qmousedevice.h>
-#include <Qt3DInput/qmousehandler.h>
-#include <Qt3DInput/qmouseevent.h>
+#include "qt3dquick3dinputplugin.h"
-#include <Qt3DInput/qaxis.h>
-#include <Qt3DInput/qaxisaccumulator.h>
-#include <Qt3DInput/qaxissetting.h>
+#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/qaction.h>
#include <Qt3DInput/qactioninput.h>
#include <Qt3DInput/qanalogaxisinput.h>
+#include <Qt3DInput/qaxis.h>
+#include <Qt3DInput/qaxisaccumulator.h>
+#include <Qt3DInput/qaxissetting.h>
#include <Qt3DInput/qbuttonaxisinput.h>
-#include <Qt3DInput/qinputsequence.h>
#include <Qt3DInput/qinputchord.h>
-#include <Qt3DInput/qlogicaldevice.h>
-#include <Qt3DInput/qabstractphysicaldevice.h>
+#include <Qt3DInput/qinputsequence.h>
#include <Qt3DInput/qinputsettings.h>
+#include <Qt3DInput/qkeyboarddevice.h>
+#include <Qt3DInput/qkeyboardhandler.h>
+#include <Qt3DInput/qkeyevent.h>
+#include <Qt3DInput/qlogicaldevice.h>
+#include <Qt3DInput/qmousedevice.h>
+#include <Qt3DInput/qmouseevent.h>
+#include <Qt3DInput/qmousehandler.h>
+#include <QtQml>
+
#include <Qt3DInput/private/qgenericinputdevice_p.h>
-#include <Qt3DQuickInput/private/quick3daxis_p.h>
#include <Qt3DQuickInput/private/quick3daction_p.h>
+#include <Qt3DQuickInput/private/quick3daxis_p.h>
#include <Qt3DQuickInput/private/quick3dinputchord_p.h>
#include <Qt3DQuickInput/private/quick3dinputsequence_p.h>
#include <Qt3DQuickInput/private/quick3dlogicaldevice_p.h>
@@ -69,8 +71,6 @@
# include <Qt3DInput/private/qgamepadinput_p.h>
#endif
-#include "qt3dquick3dinputplugin.h"
-
QT_BEGIN_NAMESPACE
void Qt3DQuick3DInputPlugin::registerTypes(const char *uri)
@@ -81,7 +81,9 @@ void Qt3DQuick3DInputPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DInput::QInputSettings>(uri, 2, 0, "InputSettings");
qmlRegisterUncreatableType<Qt3DInput::QMouseEvent>(uri, 2, 0, "MouseEvent", QStringLiteral("Events cannot be created"));
+#if QT_CONFIG(wheelevent)
qmlRegisterUncreatableType<Qt3DInput::QWheelEvent>(uri, 2, 0, "WheelEvent", QStringLiteral("Events cannot be created"));
+#endif
qmlRegisterType<Qt3DInput::QMouseHandler>(uri, 2, 0, "MouseHandler");
qmlRegisterType<Qt3DInput::QMouseDevice>(uri, 2, 0, "MouseDevice");
diff --git a/src/quick3d/imports/logic/plugins.qmltypes b/src/quick3d/imports/logic/plugins.qmltypes
index 0c0ccc847..61b67ca73 100644
--- a/src/quick3d/imports/logic/plugins.qmltypes
+++ b/src/quick3d/imports/logic/plugins.qmltypes
@@ -7,7 +7,7 @@ import QtQuick.tooling 1.2
// 'qmlplugindump -nonrelocatable Qt3D.Logic 2.0'
Module {
- dependencies: ["QtQuick 2.7"]
+ dependencies: ["QtQuick 2.8"]
Component {
name: "Qt3DCore::QComponent"
prototype: "Qt3DCore::QNode"
@@ -16,6 +16,14 @@ Module {
name: "shareableChanged"
Parameter { name: "isShareable"; type: "bool" }
}
+ Signal {
+ name: "addedToEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
+ Signal {
+ name: "removedFromEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
Method {
name: "setShareable"
Parameter { name: "isShareable"; type: "bool" }
@@ -24,8 +32,17 @@ Module {
Component {
name: "Qt3DCore::QNode"
prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
Signal {
name: "parentChanged"
Parameter { name: "parent"; type: "QObject"; isPointer: true }
@@ -34,6 +51,10 @@ Module {
name: "enabledChanged"
Parameter { name: "enabled"; type: "bool" }
}
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
Signal { name: "nodeDestroyed" }
Method {
name: "setParent"
@@ -43,6 +64,10 @@ Module {
name: "setEnabled"
Parameter { name: "isEnabled"; type: "bool" }
}
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
}
Component {
name: "Qt3DLogic::QFrameAction"
diff --git a/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp b/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp
index 3f96928b7..f97bc8fc6 100644
--- a/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp
+++ b/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp
@@ -37,10 +37,11 @@
**
****************************************************************************/
-#include <QtQml>
-#include <Qt3DLogic/qframeaction.h>
#include "qt3dquick3dlogicplugin.h"
+#include <Qt3DLogic/qframeaction.h>
+#include <QtQml>
+
QT_BEGIN_NAMESPACE
void Qt3DQuick3DLogicPlugin::registerTypes(const char *uri)
diff --git a/src/quick3d/imports/render/importsrender.pro b/src/quick3d/imports/render/importsrender.pro
index 442068fe7..cc34ff3df 100644
--- a/src/quick3d/imports/render/importsrender.pro
+++ b/src/quick3d/imports/render/importsrender.pro
@@ -3,7 +3,7 @@ TARGET = quick3drenderplugin
TARGETPATH = Qt3D/Render
IMPORT_VERSION = 2.0
-QT += core-private qml qml-private 3dcore 3drender 3dquick 3dquick-private 3dquickrender-private
+QT += core-private qml qml-private 3dcore 3drender 3drender-private 3dquick 3dquick-private 3dquickrender-private
# Qt3D is free of Q_FOREACH - make sure it stays that way:
DEFINES += QT_NO_FOREACH
diff --git a/src/quick3d/imports/render/plugins.qmltypes b/src/quick3d/imports/render/plugins.qmltypes
index 9e6e5fe38..aa0272430 100644
--- a/src/quick3d/imports/render/plugins.qmltypes
+++ b/src/quick3d/imports/render/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt3D.Render 2.0'
+// 'qmlplugindump -nonrelocatable Qt3D.Render 2.9'
Module {
- dependencies: ["QtQuick 2.7"]
+ dependencies: ["QtQuick 2.8"]
Component {
name: "QWindow"
prototype: "QObject"
@@ -25,6 +25,13 @@ Module {
"FullScreen": 5
}
}
+ Enum {
+ name: "AncestorMode"
+ values: {
+ "ExcludeTransients": 0,
+ "IncludeTransients": 1
+ }
+ }
Property { name: "title"; type: "string" }
Property { name: "modality"; type: "Qt::WindowModality" }
Property { name: "flags"; type: "Qt::WindowFlags" }
@@ -178,6 +185,14 @@ Module {
name: "shareableChanged"
Parameter { name: "isShareable"; type: "bool" }
}
+ Signal {
+ name: "addedToEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
+ Signal {
+ name: "removedFromEntity"
+ Parameter { name: "entity"; type: "QEntity"; isPointer: true }
+ }
Method {
name: "setShareable"
Parameter { name: "isShareable"; type: "bool" }
@@ -187,8 +202,17 @@ Module {
Component {
name: "Qt3DCore::QNode"
prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
Signal {
name: "parentChanged"
Parameter { name: "parent"; type: "QObject"; isPointer: true }
@@ -197,6 +221,10 @@ Module {
name: "enabledChanged"
Parameter { name: "enabled"; type: "bool" }
}
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
Signal { name: "nodeDestroyed" }
Method {
name: "setParent"
@@ -206,6 +234,10 @@ Module {
name: "setEnabled"
Parameter { name: "isEnabled"; type: "bool" }
}
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
}
Component {
name: "Qt3DCore::Quick::Quick3DNode"
@@ -404,7 +436,8 @@ Module {
"CubeMapPositiveY": 34071,
"CubeMapNegativeY": 34072,
"CubeMapPositiveZ": 34073,
- "CubeMapNegativeZ": 34074
+ "CubeMapNegativeZ": 34074,
+ "AllFaces": 34075
}
}
Enum {
@@ -446,6 +479,7 @@ Module {
Property { name: "comparisonFunction"; type: "ComparisonFunction" }
Property { name: "comparisonMode"; type: "ComparisonMode" }
Property { name: "layers"; type: "int" }
+ Property { name: "samples"; type: "int" }
Signal {
name: "formatChanged"
Parameter { name: "format"; type: "TextureFormat" }
@@ -494,6 +528,10 @@ Module {
name: "layersChanged"
Parameter { name: "layers"; type: "int" }
}
+ Signal {
+ name: "samplesChanged"
+ Parameter { name: "samples"; type: "int" }
+ }
Method {
name: "setFormat"
Parameter { name: "format"; type: "TextureFormat" }
@@ -538,6 +576,10 @@ Module {
name: "setLayers"
Parameter { name: "layers"; type: "int" }
}
+ Method {
+ name: "setSamples"
+ Parameter { name: "samples"; type: "int" }
+ }
}
Component {
name: "Qt3DRender::QAbstractTextureImage"
@@ -625,7 +667,8 @@ Module {
name: "AttributeType"
values: {
"VertexAttribute": 0,
- "IndexAttribute": 1
+ "IndexAttribute": 1,
+ "DrawIndirectAttribute": 2
}
}
Enum {
@@ -651,6 +694,11 @@ Module {
Property { name: "byteOffset"; type: "uint" }
Property { name: "divisor"; type: "uint" }
Property { name: "attributeType"; type: "AttributeType" }
+ Property { name: "defaultPositionAttributeName"; type: "string"; isReadonly: true }
+ Property { name: "defaultNormalAttributeName"; type: "string"; isReadonly: true }
+ Property { name: "defaultColorAttributeName"; type: "string"; isReadonly: true }
+ Property { name: "defaultTextureCoordinateAttributeName"; type: "string"; isReadonly: true }
+ Property { name: "defaultTangentAttributeName"; type: "string"; isReadonly: true }
Signal {
name: "bufferChanged"
Parameter { name: "buffer"; type: "QBuffer"; isPointer: true }
@@ -660,6 +708,14 @@ Module {
Parameter { name: "name"; type: "string" }
}
Signal {
+ name: "vertexBaseTypeChanged"
+ Parameter { name: "vertexBaseType"; type: "VertexBaseType" }
+ }
+ Signal {
+ name: "vertexSizeChanged"
+ Parameter { name: "vertexSize"; type: "uint" }
+ }
+ Signal {
name: "dataTypeChanged"
Parameter { name: "vertexBaseType"; type: "VertexBaseType" }
}
@@ -696,6 +752,14 @@ Module {
Parameter { name: "name"; type: "string" }
}
Method {
+ name: "setVertexBaseType"
+ Parameter { name: "type"; type: "VertexBaseType" }
+ }
+ Method {
+ name: "setVertexSize"
+ Parameter { name: "size"; type: "uint" }
+ }
+ Method {
name: "setDataType"
Parameter { name: "type"; type: "VertexBaseType" }
}
@@ -780,7 +844,8 @@ Module {
"OneMinusConstantColor": 32770,
"OneMinusConstantAlpha": 32772,
"OneMinusSource1Alpha": 32773,
- "OneMinusSource1Color": 32774
+ "OneMinusSource1Color": 32774,
+ "OneMinusSource1Color0": 32774
}
}
Property { name: "sourceRgb"; type: "Blending" }
@@ -848,6 +913,9 @@ Module {
Component {
name: "Qt3DRender::QBuffer"
prototype: "Qt3DCore::QNode"
+ exports: ["Qt3D.Render/BufferBase 2.0", "Qt3D.Render/BufferBase 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0, 9]
Enum {
name: "BufferType"
values: {
@@ -856,7 +924,8 @@ Module {
"PixelPackBuffer": 35051,
"PixelUnpackBuffer": 35052,
"UniformBuffer": 35345,
- "ShaderStorageBuffer": 37074
+ "ShaderStorageBuffer": 37074,
+ "DrawIndirectBuffer": 36671
}
}
Enum {
@@ -873,9 +942,18 @@ Module {
"DynamicCopy": 35050
}
}
+ Enum {
+ name: "AccessType"
+ values: {
+ "Write": 1,
+ "Read": 2,
+ "ReadWrite": 3
+ }
+ }
Property { name: "type"; type: "BufferType" }
Property { name: "usage"; type: "UsageType" }
Property { name: "syncData"; type: "bool" }
+ Property { name: "accessType"; revision: 9; type: "AccessType" }
Signal {
name: "dataChanged"
Parameter { name: "bytes"; type: "QByteArray" }
@@ -892,6 +970,11 @@ Module {
name: "syncDataChanged"
Parameter { name: "syncData"; type: "bool" }
}
+ Signal {
+ name: "accessTypeChanged"
+ Parameter { name: "access"; type: "AccessType" }
+ }
+ Signal { name: "dataAvailable" }
Method {
name: "setType"
Parameter { name: "type"; type: "BufferType" }
@@ -904,6 +987,21 @@ Module {
name: "setSyncData"
Parameter { name: "syncData"; type: "bool" }
}
+ Method {
+ name: "setAccessType"
+ Parameter { name: "access"; type: "AccessType" }
+ }
+ Method {
+ name: "updateData"
+ Parameter { name: "offset"; type: "int" }
+ Parameter { name: "bytes"; type: "QByteArray" }
+ }
+ }
+ Component {
+ name: "Qt3DRender::QBufferCapture"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ exports: ["Qt3D.Render/BufferCapture 2.9"]
+ exportMetaObjectRevisions: [0]
}
Component {
name: "Qt3DRender::QCamera"
@@ -927,6 +1025,7 @@ Module {
Property { name: "bottom"; type: "float" }
Property { name: "top"; type: "float" }
Property { name: "projectionMatrix"; type: "QMatrix4x4" }
+ Property { name: "exposure"; revision: 9; type: "float" }
Property { name: "position"; type: "QVector3D" }
Property { name: "upVector"; type: "QVector3D" }
Property { name: "viewCenter"; type: "QVector3D" }
@@ -973,6 +1072,10 @@ Module {
Parameter { name: "projectionMatrix"; type: "QMatrix4x4" }
}
Signal {
+ name: "exposureChanged"
+ Parameter { name: "exposure"; type: "float" }
+ }
+ Signal {
name: "positionChanged"
Parameter { name: "position"; type: "QVector3D" }
}
@@ -1029,6 +1132,10 @@ Module {
Parameter { name: "projectionMatrix"; type: "QMatrix4x4" }
}
Method {
+ name: "setExposure"
+ Parameter { name: "exposure"; type: "float" }
+ }
+ Method {
name: "setPosition"
Parameter { name: "position"; type: "QVector3D" }
}
@@ -1146,6 +1253,7 @@ Module {
Property { name: "bottom"; type: "float" }
Property { name: "top"; type: "float" }
Property { name: "projectionMatrix"; type: "QMatrix4x4" }
+ Property { name: "exposure"; revision: 9; type: "float" }
Signal {
name: "projectionTypeChanged"
Parameter { name: "projectionType"; type: "QCameraLens::ProjectionType" }
@@ -1186,6 +1294,10 @@ Module {
name: "projectionMatrixChanged"
Parameter { name: "projectionMatrix"; type: "QMatrix4x4" }
}
+ Signal {
+ name: "exposureChanged"
+ Parameter { name: "exposure"; type: "float" }
+ }
Method {
name: "setProjectionType"
Parameter { name: "projectionType"; type: "ProjectionType" }
@@ -1226,6 +1338,10 @@ Module {
name: "setProjectionMatrix"
Parameter { name: "projectionMatrix"; type: "QMatrix4x4" }
}
+ Method {
+ name: "setExposure"
+ Parameter { name: "exposure"; type: "float" }
+ }
}
Component {
name: "Qt3DRender::QCameraSelector"
@@ -1496,6 +1612,34 @@ Module {
}
Component { name: "Qt3DRender::QEffect"; prototype: "Qt3DCore::QNode" }
Component {
+ name: "Qt3DRender::QEnvironmentLight"
+ prototype: "Qt3DCore::QComponent"
+ exports: ["Qt3D.Render/EnvironmentLight 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "irradiance"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Signal {
+ name: "irradianceChanged"
+ Parameter {
+ name: "environmentIrradiance"
+ type: "Qt3DRender::QAbstractTexture"
+ isPointer: true
+ }
+ }
+ Signal {
+ name: "specularChanged"
+ Parameter { name: "environmentSpecular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setIrradiance"
+ Parameter { name: "irradiance"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setSpecular"
+ Parameter { name: "specular"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ }
+ Component {
name: "Qt3DRender::QFilterKey"
prototype: "Qt3DCore::QNode"
exports: ["Qt3D.Render/FilterKey 2.0"]
@@ -1523,7 +1667,6 @@ Module {
name: "Qt3DRender::QFrameGraphNode"
prototype: "Qt3DCore::QNode"
exports: ["Qt3D.Render/FrameGraphNode 2.0"]
- isCreatable: false
exportMetaObjectRevisions: [0]
}
Component {
@@ -1776,6 +1919,76 @@ Module {
}
Component { name: "Qt3DRender::QLayerFilter"; prototype: "Qt3DRender::QFrameGraphNode" }
Component {
+ name: "Qt3DRender::QLevelOfDetail"
+ prototype: "Qt3DCore::QComponent"
+ exports: ["Qt3D.Render/LevelOfDetail 2.9"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "ThresholdType"
+ values: {
+ "DistanceToCameraThreshold": 0,
+ "ProjectedScreenPixelSizeThreshold": 1
+ }
+ }
+ Property { name: "camera"; type: "Qt3DRender::QCamera"; isPointer: true }
+ Property { name: "currentIndex"; type: "int" }
+ Property { name: "thresholdType"; type: "ThresholdType" }
+ Property { name: "thresholds"; type: "QVector<qreal>" }
+ Property { name: "volumeOverride"; type: "Qt3DRender::QLevelOfDetailBoundingSphere" }
+ Signal {
+ name: "cameraChanged"
+ Parameter { name: "camera"; type: "QCamera"; isPointer: true }
+ }
+ Signal {
+ name: "currentIndexChanged"
+ Parameter { name: "currentIndex"; type: "int" }
+ }
+ Signal {
+ name: "thresholdTypeChanged"
+ Parameter { name: "thresholdType"; type: "ThresholdType" }
+ }
+ Signal {
+ name: "thresholdsChanged"
+ Parameter { name: "thresholds"; type: "QVector<qreal>" }
+ }
+ Signal {
+ name: "volumeOverrideChanged"
+ Parameter { name: "volumeOverride"; type: "QLevelOfDetailBoundingSphere" }
+ }
+ Method {
+ name: "setCamera"
+ Parameter { name: "camera"; type: "QCamera"; isPointer: true }
+ }
+ Method {
+ name: "setCurrentIndex"
+ Parameter { name: "currentIndex"; type: "int" }
+ }
+ Method {
+ name: "setThresholdType"
+ Parameter { name: "thresholdType"; type: "ThresholdType" }
+ }
+ Method {
+ name: "setThresholds"
+ Parameter { name: "thresholds"; type: "QVector<qreal>" }
+ }
+ Method {
+ name: "setVolumeOverride"
+ Parameter { name: "volumeOverride"; type: "QLevelOfDetailBoundingSphere" }
+ }
+ Method {
+ name: "createBoundingSphere"
+ type: "QLevelOfDetailBoundingSphere"
+ Parameter { name: "center"; type: "QVector3D" }
+ Parameter { name: "radius"; type: "float" }
+ }
+ }
+ Component {
+ name: "Qt3DRender::QLevelOfDetailSwitch"
+ prototype: "Qt3DRender::QLevelOfDetail"
+ exports: ["Qt3D.Render/LevelOfDetailSwitch 2.9"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "Qt3DRender::QMaterial"
prototype: "Qt3DCore::QComponent"
Property { name: "effect"; type: "Qt3DRender::QEffect"; isPointer: true }
@@ -1789,6 +2002,39 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QMemoryBarrier"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ Enum {
+ name: "Operation"
+ values: {
+ "None": 0,
+ "VertexAttributeArray": 1,
+ "ElementArray": 2,
+ "Uniform": 4,
+ "TextureFetch": 8,
+ "ShaderImageAccess": 16,
+ "Command": 32,
+ "PixelBuffer": 64,
+ "TextureUpdate": 128,
+ "BufferUpdate": 256,
+ "FrameBuffer": 512,
+ "TransformFeedback": 1024,
+ "AtomicCounter": 2048,
+ "ShaderStorage": 4096,
+ "QueryBuffer": 8192,
+ "All": -1
+ }
+ }
+ Signal {
+ name: "waitOperationsChanged"
+ Parameter { name: "barrierTypes"; type: "QMemoryBarrier::Operations" }
+ }
+ Method {
+ name: "setWaitOperations"
+ Parameter { name: "operations"; type: "QMemoryBarrier::Operations" }
+ }
+ }
+ Component {
name: "Qt3DRender::QMesh"
prototype: "Qt3DRender::QGeometryRenderer"
exports: ["Qt3D.Render/Mesh 2.0"]
@@ -1913,11 +2159,35 @@ Module {
exports: ["Qt3D.Render/PickEvent 2.0"]
isCreatable: false
exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Buttons"
+ values: {
+ "LeftButton": 1,
+ "RightButton": 2,
+ "MiddleButton": 4,
+ "BackButton": 8,
+ "NoButton": 0
+ }
+ }
+ Enum {
+ name: "Modifiers"
+ values: {
+ "NoModifier": 0,
+ "ShiftModifier": 33554432,
+ "ControlModifier": 67108864,
+ "AltModifier": 134217728,
+ "MetaModifier": 268435456,
+ "KeypadModifier": 536870912
+ }
+ }
Property { name: "accepted"; type: "bool" }
Property { name: "position"; type: "QPointF"; isReadonly: true }
Property { name: "distance"; type: "float"; isReadonly: true }
Property { name: "localIntersection"; type: "QVector3D"; isReadonly: true }
Property { name: "worldIntersection"; type: "QVector3D"; isReadonly: true }
+ Property { name: "button"; type: "Qt3DRender::QPickEvent::Buttons"; isReadonly: true }
+ Property { name: "buttons"; type: "int"; isReadonly: true }
+ Property { name: "modifiers"; type: "int"; isReadonly: true }
Signal {
name: "acceptedChanged"
Parameter { name: "accepted"; type: "bool" }
@@ -1946,8 +2216,17 @@ Module {
"AllPicks": 1
}
}
+ Enum {
+ name: "FaceOrientationPickingMode"
+ values: {
+ "FrontFace": 1,
+ "BackFace": 2,
+ "FrontAndBackFace": 3
+ }
+ }
Property { name: "pickMethod"; type: "PickMethod" }
Property { name: "pickResultMode"; type: "PickResultMode" }
+ Property { name: "faceOrientationPickingMode"; type: "FaceOrientationPickingMode" }
Signal {
name: "pickMethodChanged"
Parameter { name: "pickMethod"; type: "QPickingSettings::PickMethod" }
@@ -1956,6 +2235,13 @@ Module {
name: "pickResultModeChanged"
Parameter { name: "pickResult"; type: "QPickingSettings::PickResultMode" }
}
+ Signal {
+ name: "faceOrientationPickingModeChanged"
+ Parameter {
+ name: "faceOrientationPickingMode"
+ type: "QPickingSettings::FaceOrientationPickingMode"
+ }
+ }
Method {
name: "setPickMethod"
Parameter { name: "pickMethod"; type: "PickMethod" }
@@ -1964,6 +2250,10 @@ Module {
name: "setPickResultMode"
Parameter { name: "pickResultMode"; type: "PickResultMode" }
}
+ Method {
+ name: "setFaceOrientationPickingMode"
+ Parameter { name: "faceOrientationPickingMode"; type: "FaceOrientationPickingMode" }
+ }
}
Component {
name: "Qt3DRender::QPointLight"
@@ -2054,6 +2344,42 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QRenderCapture"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ exports: ["Qt3D.Render/RenderCapture 2.1"]
+ exportMetaObjectRevisions: [0]
+ Method {
+ name: "requestCapture"
+ type: "Qt3DRender::QRenderCaptureReply*"
+ Parameter { name: "captureId"; type: "int" }
+ }
+ Method { name: "requestCapture"; revision: 9; type: "Qt3DRender::QRenderCaptureReply*" }
+ }
+ Component {
+ name: "Qt3DRender::QRenderCaptureReply"
+ prototype: "QObject"
+ exports: ["Qt3D.Render/RenderCaptureReply 2.1"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Property { name: "image"; type: "QImage"; isReadonly: true }
+ Property { name: "captureId"; type: "int"; isReadonly: true }
+ Property { name: "complete"; type: "bool"; isReadonly: true }
+ Signal {
+ name: "completeChanged"
+ Parameter { name: "isComplete"; type: "bool" }
+ }
+ Signal { name: "completed" }
+ Method {
+ name: "saveImage"
+ type: "bool"
+ Parameter { name: "fileName"; type: "string" }
+ }
+ Method {
+ name: "saveToFile"
+ Parameter { name: "fileName"; type: "string" }
+ }
+ }
+ Component {
name: "Qt3DRender::QRenderPass"
prototype: "Qt3DCore::QNode"
Property { name: "shaderProgram"; type: "Qt3DRender::QShaderProgram"; isPointer: true }
@@ -2119,7 +2445,7 @@ Module {
exports: ["Qt3D.Render/RenderSurfaceSelector 2.0"]
exportMetaObjectRevisions: [0]
Property { name: "surface"; type: "QObject"; isPointer: true }
- Property { name: "externalRenderTargetSize"; type: "QSize"; isReadonly: true }
+ Property { name: "externalRenderTargetSize"; type: "QSize" }
Property { name: "surfacePixelRatio"; type: "float" }
Signal {
name: "surfaceChanged"
@@ -2141,6 +2467,10 @@ Module {
name: "setSurfacePixelRatio"
Parameter { name: "ratio"; type: "float" }
}
+ Method {
+ name: "setExternalRenderTargetSize"
+ Parameter { name: "size"; type: "QSize" }
+ }
}
Component { name: "Qt3DRender::QRenderTarget"; prototype: "Qt3DCore::QComponent" }
Component {
@@ -2176,7 +2506,7 @@ Module {
Property { name: "texture"; type: "QAbstractTexture"; isPointer: true }
Property { name: "mipLevel"; type: "int" }
Property { name: "layer"; type: "int" }
- Property { name: "face"; type: "QAbstractTexture::CubeMapFace" }
+ Property { name: "face"; type: "Qt3DRender::QAbstractTexture::CubeMapFace" }
Signal {
name: "attachmentPointChanged"
Parameter { name: "attachmentPoint"; type: "AttachmentPoint" }
@@ -2243,6 +2573,17 @@ Module {
"Error": 3
}
}
+ Enum {
+ name: "ComponentType"
+ values: {
+ "UnknownComponent": 0,
+ "GeometryRendererComponent": 1,
+ "TransformComponent": 2,
+ "MaterialComponent": 3,
+ "LightComponent": 4,
+ "CameraLensComponent": 5
+ }
+ }
Property { name: "source"; type: "QUrl" }
Property { name: "status"; type: "Status"; isReadonly: true }
Signal {
@@ -2261,6 +2602,20 @@ Module {
name: "setStatus"
Parameter { name: "status"; type: "Status" }
}
+ Method {
+ name: "entity"
+ revision: 9
+ type: "Qt3DCore::QEntity*"
+ Parameter { name: "entityName"; type: "string" }
+ }
+ Method { name: "entityNames"; revision: 9; type: "QStringList" }
+ Method {
+ name: "component"
+ revision: 9
+ type: "Qt3DCore::QComponent*"
+ Parameter { name: "entityName"; type: "string" }
+ Parameter { name: "componentType"; type: "ComponentType" }
+ }
}
Component {
name: "Qt3DRender::QScissorTest"
@@ -2333,12 +2688,22 @@ Module {
"Compute": 5
}
}
+ Enum {
+ name: "Status"
+ values: {
+ "NotReady": 0,
+ "Ready": 1,
+ "Error": 2
+ }
+ }
Property { name: "vertexShaderCode"; type: "QByteArray" }
Property { name: "tessellationControlShaderCode"; type: "QByteArray" }
Property { name: "tessellationEvaluationShaderCode"; type: "QByteArray" }
Property { name: "geometryShaderCode"; type: "QByteArray" }
Property { name: "fragmentShaderCode"; type: "QByteArray" }
Property { name: "computeShaderCode"; type: "QByteArray" }
+ Property { name: "log"; revision: 9; type: "string"; isReadonly: true }
+ Property { name: "status"; revision: 9; type: "Status"; isReadonly: true }
Signal {
name: "vertexShaderCodeChanged"
Parameter { name: "vertexShaderCode"; type: "QByteArray" }
@@ -2363,6 +2728,14 @@ Module {
name: "computeShaderCodeChanged"
Parameter { name: "computeShaderCode"; type: "QByteArray" }
}
+ Signal {
+ name: "logChanged"
+ Parameter { name: "log"; type: "string" }
+ }
+ Signal {
+ name: "statusChanged"
+ Parameter { name: "status"; type: "Status" }
+ }
Method {
name: "setVertexShaderCode"
Parameter { name: "vertexShaderCode"; type: "QByteArray" }
@@ -2701,6 +3074,7 @@ Module {
}
Property { name: "source"; type: "QUrl" }
Property { name: "status"; type: "Status"; isReadonly: true }
+ Property { name: "mirrored"; type: "bool" }
Signal {
name: "sourceChanged"
Parameter { name: "source"; type: "QUrl" }
@@ -2709,23 +3083,40 @@ Module {
name: "statusChanged"
Parameter { name: "status"; type: "Status" }
}
+ Signal {
+ name: "mirroredChanged"
+ Parameter { name: "mirrored"; type: "bool" }
+ }
Method {
name: "setSource"
Parameter { name: "source"; type: "QUrl" }
}
+ Method {
+ name: "setMirrored"
+ Parameter { name: "mirrored"; type: "bool" }
+ }
}
Component {
name: "Qt3DRender::QTextureLoader"
prototype: "Qt3DRender::QAbstractTexture"
Property { name: "source"; type: "QUrl" }
+ Property { name: "mirrored"; type: "bool" }
Signal {
name: "sourceChanged"
Parameter { name: "source"; type: "QUrl" }
}
+ Signal {
+ name: "mirroredChanged"
+ Parameter { name: "mirrored"; type: "bool" }
+ }
Method {
name: "setSource"
Parameter { name: "source"; type: "QUrl" }
}
+ Method {
+ name: "setMirrored"
+ Parameter { name: "mirrored"; type: "bool" }
+ }
}
Component { name: "Qt3DRender::QTextureRectangle"; prototype: "Qt3DRender::QAbstractTexture" }
Component {
@@ -2774,14 +3165,23 @@ Module {
name: "Qt3DRender::QViewport"
prototype: "Qt3DRender::QFrameGraphNode"
Property { name: "normalizedRect"; type: "QRectF" }
+ Property { name: "gamma"; revision: 9; type: "float" }
Signal {
name: "normalizedRectChanged"
Parameter { name: "normalizedRect"; type: "QRectF" }
}
+ Signal {
+ name: "gammaChanged"
+ Parameter { name: "gamma"; type: "float" }
+ }
Method {
name: "setNormalizedRect"
Parameter { name: "normalizedRect"; type: "QRectF" }
}
+ Method {
+ name: "setGamma"
+ Parameter { name: "gamma"; type: "float" }
+ }
}
Component {
name: "Qt3DRender::Render::Quick::Quick3DBuffer"
@@ -2790,7 +3190,16 @@ Module {
exportMetaObjectRevisions: [0]
Property { name: "data"; type: "QVariant" }
Signal { name: "bufferDataChanged" }
- Signal { name: "bufferDataChanged" }
+ Method {
+ name: "updateData"
+ Parameter { name: "offset"; type: "int" }
+ Parameter { name: "bytes"; type: "QVariant" }
+ }
+ Method {
+ name: "readBinaryFile"
+ type: "QVariant"
+ Parameter { name: "fileUrl"; type: "QUrl" }
+ }
}
Component {
name: "Qt3DRender::Render::Quick::Quick3DEffect"
@@ -2823,6 +3232,13 @@ Module {
Property { name: "parameters"; type: "Qt3DRender::QParameter"; isList: true; isReadonly: true }
}
Component {
+ name: "Qt3DRender::Render::Quick::Quick3DMemoryBarrier"
+ prototype: "Qt3DRender::QMemoryBarrier"
+ exports: ["Qt3D.Render/MemoryBarrier 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "waitFor"; type: "int" }
+ }
+ Component {
name: "Qt3DRender::Render::Quick::Quick3DParameter"
prototype: "Qt3DRender::QParameter"
exports: ["Qt3D.Render/Parameter 2.0"]
@@ -2921,7 +3337,7 @@ Module {
Component {
name: "Qt3DRender::Render::Quick::Quick3DTextureExtension"
defaultProperty: "textureImages"
- prototype: "Qt3DRender::QTextureLoader"
+ prototype: "Qt3DRender::QTextureRectangle"
exports: [
"Qt3D.Render/Texture1D 2.0",
"Qt3D.Render/Texture1DArray 2.0",
diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
index c6831dbce..f81b1fa53 100644
--- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
+++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
@@ -39,94 +39,99 @@
****************************************************************************/
#include "qt3dquick3drenderplugin.h"
-#include <Qt3DRender/qsceneloader.h>
-#include <Qt3DRender/qmesh.h>
-#include <Qt3DRender/qrenderpass.h>
-#include <Qt3DRender/qshaderprogram.h>
-#include <Qt3DRender/qviewport.h>
-#include <Qt3DRender/qrenderpassfilter.h>
-#include <Qt3DRender/qtechniquefilter.h>
-#include <Qt3DRender/qrendertargetselector.h>
-#include <Qt3DRender/qrendersurfaceselector.h>
-#include <Qt3DRender/qtexture.h>
-#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qabstractlight.h>
+#include <Qt3DRender/qalphacoverage.h>
+#include <Qt3DRender/qalphatest.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qblendequation.h>
+#include <Qt3DRender/qblendequationarguments.h>
+#include <Qt3DRender/qbuffer.h>
+#include <Qt3DRender/qbuffercapture.h>
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DRender/qcameralens.h>
#include <Qt3DRender/qcameraselector.h>
+#include <Qt3DRender/qclearbuffers.h>
+#include <Qt3DRender/qclipplane.h>
+#include <Qt3DRender/qcolormask.h>
+#include <Qt3DRender/qcomputecommand.h>
+#include <Qt3DRender/qcullface.h>
+#include <Qt3DRender/qdepthtest.h>
+#include <Qt3DRender/qdirectionallight.h>
+#include <Qt3DRender/qdispatchcompute.h>
+#include <Qt3DRender/qdithering.h>
#include <Qt3DRender/qeffect.h>
-#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qenvironmentlight.h>
#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qfrontface.h>
+#include <Qt3DRender/qfrustumculling.h>
+#include <Qt3DRender/qgeometry.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/qlevelofdetail.h>
+#include <Qt3DRender/qlevelofdetailboundingsphere.h>
#include <Qt3DRender/qlevelofdetailswitch.h>
-#include <Qt3DRender/qboundingsphere.h>
-#include <Qt3DRender/qabstractlight.h>
-#include <Qt3DRender/qspotlight.h>
-#include <Qt3DRender/qdirectionallight.h>
-#include <Qt3DRender/qpointlight.h>
-#include <Qt3DRender/qgraphicsapifilter.h>
-#include <Qt3DRender/qrenderstate.h>
-#include <Qt3DRender/qblendequationarguments.h>
-#include <Qt3DRender/qblendequation.h>
-#include <Qt3DRender/qalphatest.h>
-#include <Qt3DRender/qdepthtest.h>
-#include <Qt3DRender/qnodepthmask.h>
-#include <Qt3DRender/qcullface.h>
-#include <Qt3DRender/qfrontface.h>
-#include <Qt3DRender/qstenciltest.h>
-#include <Qt3DRender/qstenciltestarguments.h>
-#include <Qt3DRender/qscissortest.h>
-#include <Qt3DRender/qdithering.h>
-#include <Qt3DRender/qrendertargetoutput.h>
-#include <Qt3DRender/qclearbuffers.h>
-#include <Qt3DRender/qalphacoverage.h>
+#include <Qt3DRender/qmemorybarrier.h>
+#include <Qt3DRender/qmesh.h>
#include <Qt3DRender/qmultisampleantialiasing.h>
+#include <Qt3DRender/qnodepthmask.h>
+#include <Qt3DRender/qnodraw.h>
+#include <Qt3DRender/qobjectpicker.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qpickevent.h>
+#include <Qt3DRender/qpickingsettings.h>
+#include <Qt3DRender/qpointlight.h>
#include <Qt3DRender/qpointsize.h>
#include <Qt3DRender/qpolygonoffset.h>
-#include <Qt3DRender/qcolormask.h>
-#include <Qt3DRender/qshaderdata.h>
-#include <Qt3DRender/qnodraw.h>
-#include <Qt3DRender/qclipplane.h>
+#include <Qt3DRender/qrendercapture.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qrenderpassfilter.h>
+#include <Qt3DRender/qrendersettings.h>
+#include <Qt3DRender/qrenderstate.h>
+#include <Qt3DRender/qrendersurfaceselector.h>
+#include <Qt3DRender/qrendertargetoutput.h>
+#include <Qt3DRender/qrendertargetselector.h>
+#include <Qt3DRender/qsceneloader.h>
+#include <Qt3DRender/qscissortest.h>
#include <Qt3DRender/qseamlesscubemap.h>
+#include <Qt3DRender/qshaderdata.h>
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qsortpolicy.h>
+#include <Qt3DRender/qspotlight.h>
+#include <Qt3DRender/qstencilmask.h>
#include <Qt3DRender/qstenciloperation.h>
#include <Qt3DRender/qstenciloperationarguments.h>
-#include <Qt3DRender/qstencilmask.h>
-#include <Qt3DRender/qattribute.h>
-#include <Qt3DRender/qbuffer.h>
-#include <Qt3DRender/qgeometry.h>
-#include <Qt3DRender/qgeometryrenderer.h>
-#include <Qt3DRender/qobjectpicker.h>
-#include <Qt3DRender/qpickevent.h>
-#include <Qt3DRender/qfrustumculling.h>
-#include <Qt3DRender/qdispatchcompute.h>
-#include <Qt3DRender/qcomputecommand.h>
-#include <Qt3DRender/qcameralens.h>
-#include <Qt3DRender/qcamera.h>
-#include <Qt3DRender/qrendersettings.h>
-#include <Qt3DRender/qpickingsettings.h>
-#include <Qt3DRender/qrendercapture.h>
-#include <Qt3DRender/qmemorybarrier.h>
+#include <Qt3DRender/qstenciltest.h>
+#include <Qt3DRender/qstenciltestarguments.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qtechniquefilter.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qviewport.h>
+
+#include <QtGui/qwindow.h>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+#include <Qt3DQuickRender/private/quick3dbuffer_p.h>
+#include <Qt3DQuickRender/private/quick3deffect_p.h>
+#include <Qt3DQuickRender/private/quick3dgeometry_p.h>
#include <Qt3DQuickRender/private/quick3dlayerfilter_p.h>
-#include <Qt3DQuickRender/private/quick3dtechnique_p.h>
#include <Qt3DQuickRender/private/quick3dmaterial_p.h>
-#include <Qt3DQuickRender/private/quick3dtechniquefilter_p.h>
-#include <Qt3DQuickRender/private/quick3dviewport_p.h>
+#include <Qt3DQuickRender/private/quick3dmemorybarrier_p.h>
+#include <Qt3DQuickRender/private/quick3dparameter_p.h>
+#include <Qt3DQuickRender/private/quick3drenderpass_p.h>
#include <Qt3DQuickRender/private/quick3drenderpassfilter_p.h>
#include <Qt3DQuickRender/private/quick3drendertargetoutput_p.h>
-#include <Qt3DQuickRender/private/quick3deffect_p.h>
+#include <Qt3DQuickRender/private/quick3drendertargetselector_p.h>
#include <Qt3DQuickRender/private/quick3dscene_p.h>
-#include <Qt3DQuickRender/private/quick3dtexture_p.h>
-#include <Qt3DQuickRender/private/quick3drenderpass_p.h>
-#include <Qt3DQuickRender/private/quick3dparameter_p.h>
#include <Qt3DQuickRender/private/quick3dshaderdata_p.h>
#include <Qt3DQuickRender/private/quick3dshaderdataarray_p.h>
#include <Qt3DQuickRender/private/quick3dstateset_p.h>
-#include <Qt3DQuickRender/private/quick3drendertargetselector_p.h>
-#include <Qt3DQuickRender/private/quick3dgeometry_p.h>
-#include <Qt3DQuickRender/private/quick3dbuffer_p.h>
-#include <Qt3DQuickRender/private/quick3dmemorybarrier_p.h>
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+#include <Qt3DQuickRender/private/quick3dtechnique_p.h>
+#include <Qt3DQuickRender/private/quick3dtechniquefilter_p.h>
+#include <Qt3DQuickRender/private/quick3dtexture_p.h>
+#include <Qt3DQuickRender/private/quick3dviewport_p.h>
-#include <QtGui/qwindow.h>
QT_BEGIN_NAMESPACE
@@ -155,6 +160,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
// @uri Qt3D.Render
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QSceneLoader, Qt3DRender::Render::Quick::Quick3DScene>("QSceneLoader", "Qt3D.Render/SceneLoader", uri, 2, 0, "SceneLoader");
+ qmlRegisterRevision<Qt3DRender::QSceneLoader, 9>(uri, 2, 9);
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QEffect, Qt3DRender::Render::Quick::Quick3DEffect>("QEffect", "Qt3D.Render/Effect", uri, 2, 0, "Effect");
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QTechnique, Qt3DRender::Render::Quick::Quick3DTechnique>("QTechnique", "Qt3D.Render/Technique", uri, 2, 0, "Technique");
qmlRegisterType<Qt3DRender::QFilterKey>(uri, 2, 0, "FilterKey");
@@ -164,13 +170,16 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QMaterial, Qt3DRender::Render::Quick::Quick3DMaterial>("QMaterial", "Qt3D.Render/Material", uri, 2, 0, "Material");
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QRenderPass, Qt3DRender::Render::Quick::Quick3DRenderPass>("QRenderPass", "Qt3D.Render/RenderPass", uri, 2, 0, "RenderPass");
qmlRegisterType<Qt3DRender::QShaderProgram>(uri, 2, 0, "ShaderProgram");
+ qmlRegisterRevision<Qt3DRender::QShaderProgram, 9>(uri, 2, 9);
qmlRegisterUncreatableType<Qt3DRender::QShaderData>(uri, 2, 0, "QShaderData", "Quick3D should instantiate Quick3DShaderData only");
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DShaderDataArray>(uri, 2, 0, "ShaderDataArray");
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DShaderData>(uri, 2, 0, "ShaderData");
// Camera
qmlRegisterType<Qt3DRender::QCamera>(uri, 2, 0, "Camera");
+ qmlRegisterRevision<Qt3DRender::QCamera, 9>(uri, 2, 9);
qmlRegisterType<Qt3DRender::QCameraLens>(uri, 2, 0, "CameraLens");
+ qmlRegisterRevision<Qt3DRender::QCameraLens, 9>(uri, 2, 9);
// Textures
qmlRegisterType<Qt3DRender::QTextureWrapMode>(uri, 2, 0, "WrapMode");//, QStringLiteral("QTextureWrapMode cannot be created from QML"));
@@ -193,18 +202,20 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
// Geometry
qmlRegisterType<Qt3DRender::QAttribute>(uri, 2, 0, "Attribute");
qmlRegisterUncreatableType<Qt3DRender::QBuffer>(uri, 2, 0, "BufferBase", QStringLiteral("Use Quick3DBuffer in QML"));
+ qmlRegisterUncreatableType<Qt3DRender::QBuffer, 9>(uri, 2, 9, "BufferBase", QStringLiteral("Use Quick3DBuffer in QML"));
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DBuffer>(uri, 2, 0, "Buffer");
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QGeometry, Qt3DRender::Render::Quick::Quick3DGeometry>("QGeometry", "Qt3D.Render/Geometry", uri, 2, 0, "Geometry");
qmlRegisterType<Qt3DRender::QGeometryRenderer>(uri, 2, 0, "GeometryRenderer");
- qmlRegisterType<Qt3DRender::QLevelOfDetail>(uri, 2, 2, "LevelOfDetail");
- qmlRegisterType<Qt3DRender::QLevelOfDetailSwitch>(uri, 2, 2, "LevelOfDetailSwitch");
- qmlRegisterType<Qt3DRender::QBoundingSphere>(uri, 2, 2, "BoundingSphere");
+ qmlRegisterType<Qt3DRender::QLevelOfDetail>(uri, 2, 9, "LevelOfDetail");
+ qmlRegisterType<Qt3DRender::QLevelOfDetailSwitch>(uri, 2, 9, "LevelOfDetailSwitch");
+ qRegisterMetaType<Qt3DRender::QLevelOfDetailBoundingSphere>("LevelOfDetailBoundingSphere");
// Mesh
qmlRegisterType<Qt3DRender::QMesh>(uri, 2, 0, "Mesh");
// Picking
qmlRegisterType<Qt3DRender::QObjectPicker>(uri, 2, 0, "ObjectPicker");
+ qmlRegisterRevision<Qt3DRender::QObjectPicker, 9>(uri, 2, 9);
qmlRegisterUncreatableType<Qt3DRender::QPickEvent>(uri, 2, 0, "PickEvent", QStringLiteral("Events cannot be created"));
// Compute Job
@@ -218,6 +229,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<Qt3DRender::QAbstractLight>(uri, 2, 0, "Light", QStringLiteral("Light is an abstract base class"));
qmlRegisterType<Qt3DRender::QPointLight>(uri, 2, 0, "PointLight");
qmlRegisterType<Qt3DRender::QDirectionalLight>(uri, 2, 0, "DirectionalLight");
+ qmlRegisterType<Qt3DRender::QEnvironmentLight>(uri, 2, 9, "EnvironmentLight");
qmlRegisterType<Qt3DRender::QSpotLight>(uri, 2, 0, "SpotLight");
// FrameGraph
@@ -225,6 +237,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QRenderPassFilter, Qt3DRender::Render::Quick::Quick3DRenderPassFilter>("QRenderPassFilter", "Qt3D.Render/RenderPassFilter", uri, 2, 0, "RenderPassFilter");
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QTechniqueFilter, Qt3DRender::Render::Quick::Quick3DTechniqueFilter>("QTechniqueFilter", "Qt3D.Render/TechniqueFilter", uri, 2, 0, "TechniqueFilter");
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QViewport, Qt3DRender::Render::Quick::Quick3DViewport>("QViewport", "Qt3D.Render/Viewport", uri, 2, 0, "Viewport");
+ qmlRegisterRevision<Qt3DRender::QViewport, 9>(uri, 2, 9);
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QRenderTargetSelector, Qt3DRender::Render::Quick::Quick3DRenderTargetSelector>("QRenderTargetSelector", "Qt3D.Render/RenderTargetSelector", uri, 2, 0, "RenderTargetSelector");
qmlRegisterType<Qt3DRender::QClearBuffers>(uri, 2, 0, "ClearBuffers");
qmlRegisterType<Qt3DRender::QFrameGraphNode>(uri, 2, 0, "FrameGraphNode");
@@ -233,8 +246,10 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DRender::QFrustumCulling>(uri, 2, 0, "FrustumCulling");
qmlRegisterType<Qt3DRender::QDispatchCompute>(uri, 2, 0, "DispatchCompute");
qmlRegisterType<Qt3DRender::QRenderCapture>(uri, 2, 1, "RenderCapture");
+ qmlRegisterRevision<Qt3DRender::QRenderCapture, 9>(uri, 2, 9);
qmlRegisterUncreatableType<Qt3DRender::QRenderCaptureReply>(uri, 2, 1, "RenderCaptureReply", QStringLiteral("RenderCaptureReply is only instantiated by RenderCapture"));
- Qt3DRender::Quick::registerExtendedType<Qt3DRender::QMemoryBarrier, Qt3DRender::Render::Quick::Quick3DMemoryBarrier>("QMemoryBarrier", "Qt3D.Render/MemoryBarrier", uri, 2, 0, "MemoryBarrier");
+ qmlRegisterType<Qt3DRender::QBufferCapture>(uri, 2, 9, "BufferCapture");
+ Qt3DRender::Quick::registerExtendedType<Qt3DRender::QMemoryBarrier, Qt3DRender::Render::Quick::Quick3DMemoryBarrier>("QMemoryBarrier", "Qt3D.Render/MemoryBarrier", uri, 2, 9, "MemoryBarrier");
// RenderTarget
qmlRegisterType<Qt3DRender::QRenderTargetOutput>(uri, 2, 0, "RenderTargetOutput");
diff --git a/src/quick3d/imports/scene2d/importsscene2d.pro b/src/quick3d/imports/scene2d/importsscene2d.pro
new file mode 100644
index 000000000..32fbc5b1b
--- /dev/null
+++ b/src/quick3d/imports/scene2d/importsscene2d.pro
@@ -0,0 +1,19 @@
+CXX_MODULE = qml
+TARGET = qtquickscene2dplugin
+TARGETPATH = QtQuick/Scene2D
+IMPORT_VERSION = 2.0
+
+QT += qml quick 3dcore 3drender 3drender-private 3dinput 3dlogic 3dquickscene2d 3dquickscene2d-private
+
+# Qt3D is free of Q_FOREACH - make sure it stays that way:
+DEFINES += QT_NO_FOREACH
+
+HEADERS += \
+ qtquickscene2dplugin.h \
+
+SOURCES += \
+ qtquickscene2dplugin.cpp \
+
+OTHER_FILES += qmldir
+
+load(qml_plugin)
diff --git a/src/quick3d/imports/scene2d/plugins.qmltypes b/src/quick3d/imports/scene2d/plugins.qmltypes
new file mode 100644
index 000000000..a26dcbec0
--- /dev/null
+++ b/src/quick3d/imports/scene2d/plugins.qmltypes
@@ -0,0 +1,121 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable -output plugins.qmltypes QtQuick.Scene2D 2.9'
+
+Module {
+ dependencies: []
+ Component {
+ name: "Qt3DCore::QNode"
+ prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
+ Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
+ Signal {
+ name: "parentChanged"
+ Parameter { name: "parent"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "enabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Signal { name: "nodeDestroyed" }
+ Method {
+ name: "setParent"
+ Parameter { name: "parent"; type: "QNode"; isPointer: true }
+ }
+ Method {
+ name: "setEnabled"
+ Parameter { name: "isEnabled"; type: "bool" }
+ }
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ }
+ Component {
+ name: "Qt3DRender::Quick::QScene2D"
+ defaultProperty: "item"
+ prototype: "Qt3DCore::QNode"
+ Enum {
+ name: "RenderPolicy"
+ values: {
+ "Continuous": 0,
+ "SingleShot": 1
+ }
+ }
+ Property { name: "output"; type: "Qt3DRender::QRenderTargetOutput"; isPointer: true }
+ Property { name: "source"; type: "QUrl" }
+ Property { name: "renderPolicy"; type: "QScene2D::RenderPolicy" }
+ Property { name: "loaded"; type: "bool"; isReadonly: true }
+ Property { name: "item"; type: "QQuickItem"; isPointer: true }
+ Property { name: "grabMouse"; type: "bool" }
+ Signal {
+ name: "outputChanged"
+ Parameter { name: "output"; type: "Qt3DRender::QRenderTargetOutput"; isPointer: true }
+ }
+ Signal {
+ name: "sourceChanged"
+ Parameter { name: "url"; type: "QUrl" }
+ }
+ Signal {
+ name: "loadedChanged"
+ Parameter { name: "loaded"; type: "bool" }
+ }
+ Signal {
+ name: "renderPolicyChanged"
+ Parameter { name: "policy"; type: "QScene2D::RenderPolicy" }
+ }
+ Signal {
+ name: "itemChanged"
+ Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
+ }
+ Signal {
+ name: "grabMouseChanged"
+ Parameter { name: "grab"; type: "bool" }
+ }
+ Method {
+ name: "setOutput"
+ Parameter { name: "output"; type: "Qt3DRender::QRenderTargetOutput"; isPointer: true }
+ }
+ Method {
+ name: "setSource"
+ Parameter { name: "url"; type: "QUrl" }
+ }
+ Method {
+ name: "setRenderPolicy"
+ Parameter { name: "policy"; type: "QScene2D::RenderPolicy" }
+ }
+ Method {
+ name: "setItem"
+ Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
+ }
+ Method {
+ name: "setGrabMouseEnabled"
+ Parameter { name: "grab"; type: "bool" }
+ }
+ }
+ Component {
+ name: "Qt3DRender::Render::Quick::QQuick3DScene2D"
+ defaultProperty: "item"
+ prototype: "Qt3DRender::Quick::QScene2D"
+ exports: ["QtQuick.Scene2D/Scene2D 2.9"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "entities"; type: "Qt3DCore::QEntity"; isList: true; isReadonly: true }
+ }
+}
diff --git a/src/quick3d/imports/scene2d/qmldir b/src/quick3d/imports/scene2d/qmldir
new file mode 100644
index 000000000..2e807f1e6
--- /dev/null
+++ b/src/quick3d/imports/scene2d/qmldir
@@ -0,0 +1,3 @@
+module QtQuick.Scene2D
+plugin qtquickscene2dplugin
+classname QtQuickScene2DPlugin
diff --git a/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp b/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp
new file mode 100644
index 000000000..4e6245d2d
--- /dev/null
+++ b/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtquickscene2dplugin.h"
+
+#include <Qt3DQuickScene2D/qscene2d.h>
+#include <private/qrenderaspect_p.h>
+#include <Qt3DQuickScene2D/private/qt3dquick3dscene2d_p.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+static void initScene2dPlugin()
+{
+ Qt3DRender::QRenderAspectPrivate::configurePlugin("scene2d");
+}
+
+Q_COREAPP_STARTUP_FUNCTION(initScene2dPlugin)
+
+void QtQuickScene2DPlugin::registerTypes(const char *uri)
+{
+ qmlRegisterExtendedType<Qt3DRender::Quick::QScene2D, Qt3DRender::Render::Quick::QQuick3DScene2D>(uri, 2, 9, "Scene2D");
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene2d/qtquickscene2dplugin.h b/src/quick3d/imports/scene2d/qtquickscene2dplugin.h
new file mode 100644
index 000000000..c9318673f
--- /dev/null
+++ b/src/quick3d/imports/scene2d/qtquickscene2dplugin.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTQUICKSCENE2DPLUGIN_H
+#define QTQUICKSCENE2DPLUGIN_H
+
+#include <QtQml/qqmlextensionplugin.h>
+
+static void initResources()
+{
+#ifdef QT_STATIC
+ Q_INIT_RESOURCE(qmake_QtQuick_Scene2D);
+#endif
+}
+
+QT_BEGIN_NAMESPACE
+
+class QtQuickScene2DPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+public:
+ QtQuickScene2DPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ void registerTypes(const char *uri) Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTQUICKSCENE2DPLUGIN_H
diff --git a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp
index 7103a1bb8..6b9ec96f8 100644
--- a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp
+++ b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp
@@ -37,9 +37,11 @@
**
****************************************************************************/
-#include <QtQml>
#include "qtquickscene3dplugin.h"
-#include "scene3ditem_p.h"
+
+#include <QtQml>
+
+#include <scene3ditem_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dcleaner.cpp b/src/quick3d/imports/scene3d/scene3dcleaner.cpp
index 06b795c8a..ec371410d 100644
--- a/src/quick3d/imports/scene3d/scene3dcleaner.cpp
+++ b/src/quick3d/imports/scene3d/scene3dcleaner.cpp
@@ -38,13 +38,13 @@
****************************************************************************/
#include "scene3dcleaner_p.h"
-#include "scene3dlogging_p.h"
-#include "scene3drenderer_p.h"
#include <Qt3DCore/qaspectengine.h>
-
#include <QtCore/qthread.h>
+#include <scene3dlogging_p.h>
+#include <scene3drenderer_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/imports/scene3d/scene3dcleaner_p.h b/src/quick3d/imports/scene3d/scene3dcleaner_p.h
index 6ec2c7e6b..a246cbde7 100644
--- a/src/quick3d/imports/scene3d/scene3dcleaner_p.h
+++ b/src/quick3d/imports/scene3d/scene3dcleaner_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QObject>
+#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index 4a5c959c4..c31f4aa97 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -38,23 +38,26 @@
****************************************************************************/
#include "scene3ditem_p.h"
-#include "scene3dcleaner_p.h"
-#include "scene3dlogging_p.h"
-#include "scene3drenderer_p.h"
-#include "scene3dsgnode_p.h"
#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/qentity.h>
-#include <Qt3DRender/qcamera.h>
-#include <Qt3DRender/QRenderAspect>
-#include <Qt3DRender/qrendersurfaceselector.h>
-#include <Qt3DRender/private/qrendersurfaceselector_p.h>
#include <Qt3DInput/QInputAspect>
#include <Qt3DInput/qinputsettings.h>
#include <Qt3DLogic/qlogicaspect.h>
+#include <Qt3DRender/QRenderAspect>
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DRender/qrendersurfaceselector.h>
-
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qoffscreensurface.h>
#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qquickrendercontrol.h>
+
+#include <Qt3DRender/private/qrendersurfaceselector_p.h>
+#include <scene3dcleaner_p.h>
+#include <scene3dlogging_p.h>
+#include <scene3drenderer_p.h>
+#include <scene3dsgnode_p.h>
QT_BEGIN_NAMESPACE
@@ -179,7 +182,7 @@ void Scene3DItem::applyRootEntityChange()
QList<Qt3DRender::QCamera *> cameras
= m_entity->findChildren<Qt3DRender::QCamera *>();
if (cameras.isEmpty()) {
- qWarning() << "No camera found and automatic aspect ratio requested";
+ qCDebug(Scene3D) << "No camera found and automatic aspect ratio requested";
} else {
m_camera = cameras.first();
setCameraAspectModeHelper();
@@ -191,7 +194,7 @@ void Scene3DItem::applyRootEntityChange()
if (inputSettings) {
inputSettings->setEventSource(this);
} else {
- qWarning() << "No Input Settings found, keyboard and mouse events won't be handled";
+ qCDebug(Scene3D) << "No Input Settings found, keyboard and mouse events won't be handled";
}
}
}
@@ -202,11 +205,25 @@ void Scene3DItem::setWindowSurface(QObject *rootObject)
// Set the item's window surface if it appears
// the surface wasn't set on the surfaceSelector
- if (surfaceSelector && !surfaceSelector->surface())
- surfaceSelector->setSurface(this->window());
+ if (surfaceSelector && !surfaceSelector->surface()) {
+ // We may not have a real, exposed QQuickWindow when the Quick rendering
+ // is redirected via QQuickRenderControl (f.ex. QQuickWidget).
+ if (QWindow *rw = QQuickRenderControl::renderWindowFor(this->window())) {
+ // rw is the top-level window that is backed by a native window. Do
+ // not use that though since we must not clash with e.g. the widget
+ // backingstore compositor in the gui thread.
+ m_dummySurface = new QOffscreenSurface;
+ m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living
+ m_dummySurface->setFormat(rw->format());
+ m_dummySurface->create();
+ surfaceSelector->setSurface(m_dummySurface);
+ } else {
+ surfaceSelector->setSurface(this->window());
+ }
+ }
}
-void Scene3DItem::setItemArea(const QSize &area)
+void Scene3DItem::setItemArea(QSize area)
{
Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(m_entity);
if (surfaceSelector)
diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h
index 09859a763..e0ce3addc 100644
--- a/src/quick3d/imports/scene3d/scene3ditem_p.h
+++ b/src/quick3d/imports/scene3d/scene3ditem_p.h
@@ -51,11 +51,13 @@
// We mean it.
//
-#include <QQuickItem>
#include <QtCore/qpointer.h>
+#include <QtQuick/QQuickItem>
QT_BEGIN_NAMESPACE
+class QOffscreenSurface;
+
namespace Qt3DCore {
class QAspectEngine;
class QEntity;
@@ -86,7 +88,7 @@ public:
bool multisample() const;
void setMultisample(bool enable);
- void setItemArea(const QSize &area);
+ Q_INVOKABLE void setItemArea(QSize area);
bool isHoverEnabled() const;
enum CameraAspectRatioMode {
@@ -131,6 +133,7 @@ private:
QPointer<Qt3DRender::QCamera> m_camera;
CameraAspectRatioMode m_cameraAspectRatioMode;
+ QOffscreenSurface *m_dummySurface;
};
} // Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3dlogging.cpp b/src/quick3d/imports/scene3d/scene3dlogging.cpp
index b9582799b..b6656541b 100644
--- a/src/quick3d/imports/scene3d/scene3dlogging.cpp
+++ b/src/quick3d/imports/scene3d/scene3dlogging.cpp
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-Q_LOGGING_CATEGORY(Scene3D, "Qt3D.Scene3D")
+Q_LOGGING_CATEGORY(Scene3D, "Qt3D.Scene3D", QtWarningMsg)
} // Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3dlogging_p.h b/src/quick3d/imports/scene3d/scene3dlogging_p.h
index 0f9448d42..91430939f 100644
--- a/src/quick3d/imports/scene3d/scene3dlogging_p.h
+++ b/src/quick3d/imports/scene3d/scene3dlogging_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QLoggingCategory>
+#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
index 3065b19ac..b32191391 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer.cpp
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -38,27 +38,36 @@
****************************************************************************/
#include "scene3drenderer_p.h"
-#include "scene3dcleaner_p.h"
-#include "scene3ditem_p.h"
-#include "scene3dlogging_p.h"
-#include "scene3dsgnode_p.h"
-#include <Qt3DRender/qrenderaspect.h>
-#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DCore/qaspectengine.h>
-#include <Qt3DCore/private/qaspectengine_p.h>
-
-#include <QtQuick/qquickwindow.h>
-
+#include <Qt3DRender/qrenderaspect.h>
+#include <QtCore/qthread.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglframebufferobject.h>
+#include <QtQuick/qquickwindow.h>
-#include <QtCore/qthread.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <scene3dcleaner_p.h>
+#include <scene3ditem_p.h>
+#include <scene3dlogging_p.h>
+#include <scene3dsgnode_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+namespace {
+
+inline QMetaMethod setItemAreaMethod()
+{
+ const int idx = Scene3DItem::staticMetaObject.indexOfMethod("setItemArea(QSize)");
+ Q_ASSERT(idx != -1);
+ return Scene3DItem::staticMetaObject.method(idx);
+}
+
+} // anonymous
+
class ContextSaver
{
public:
@@ -120,14 +129,18 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp
, m_multisampledFBO(nullptr)
, m_finalFBO(nullptr)
, m_texture(nullptr)
+ , m_node(nullptr)
+ , m_cleaner(nullptr)
, m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead
, m_lastMultisample(false)
+ , m_needsShutdown(true)
{
Q_CHECK_PTR(m_item);
Q_CHECK_PTR(m_item->window());
QObject::connect(m_item->window(), &QQuickWindow::beforeRendering, this, &Scene3DRenderer::render, Qt::DirectConnection);
- QObject::connect(m_item, &QQuickItem::windowChanged, this, &Scene3DRenderer::onWindowChangedQueued, Qt::QueuedConnection);
+ QObject::connect(m_item->window(), &QQuickWindow::sceneGraphInvalidated, this, &Scene3DRenderer::onSceneGraphInvalidated, Qt::DirectConnection);
+ QObject::connect(m_item, &QQuickItem::windowChanged, this, &Scene3DRenderer::onWindowChanged, Qt::QueuedConnection);
Q_ASSERT(QOpenGLContext::currentContext());
ContextSaver saver;
@@ -173,7 +186,7 @@ void Scene3DRenderer::setCleanerHelper(Scene3DCleaner *cleaner)
}
}
-// Executed in the QtQuick render thread.
+// Executed in the QtQuick render thread (which may even be the gui/main with QQuickWidget / RenderControl).
void Scene3DRenderer::shutdown()
{
qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
@@ -195,19 +208,29 @@ void Scene3DRenderer::shutdown()
static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderShutdown();
}
-// SGThread
-void Scene3DRenderer::onWindowChangedQueued(QQuickWindow *w)
+// QtQuick render thread (which may also be the gui/main thread with QQuickWidget / RenderControl)
+void Scene3DRenderer::onSceneGraphInvalidated()
{
- if (w == nullptr) {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+ if (m_needsShutdown) {
+ m_needsShutdown = false;
shutdown();
- // Will only trigger something with the Loader case
- // The window closed cases is handled by the window's destroyed
- // signal
QMetaObject::invokeMethod(m_cleaner, "cleanup");
}
}
+void Scene3DRenderer::onWindowChanged(QQuickWindow *w)
+{
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread() << w;
+ if (!w) {
+ if (m_needsShutdown) {
+ m_needsShutdown = false;
+ shutdown();
+ QMetaObject::invokeMethod(m_cleaner, "cleanup");
+ }
+ }
+}
+
void Scene3DRenderer::synchronize()
{
m_multisample = m_item->multisample();
@@ -238,8 +261,11 @@ void Scene3DRenderer::render()
const bool multisampleHasChanged = m_multisample != m_lastMultisample;
const bool forceRecreate = sizeHasChanged || multisampleHasChanged;
- if (sizeHasChanged)
- m_item->setItemArea(boundingRectSize);
+ if (sizeHasChanged) {
+ // We are in the QSGRenderThread (doing a direct call would result in a race)
+ static const QMetaMethod setItemArea = setItemAreaMethod();
+ setItemArea.invoke(m_item, Qt::QueuedConnection, Q_ARG(QSize, boundingRectSize));
+ }
// Rebuild FBO and textures if never created or a resize has occurred
if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) {
diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h
index 9ff5e7f36..ab1db1010 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer_p.h
+++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h
@@ -51,8 +51,7 @@
// We mean it.
//
-#include <QObject>
-
+#include <QtCore/QObject>
#include <QtCore/qsize.h>
QT_BEGIN_NAMESPACE
@@ -91,7 +90,8 @@ public:
public Q_SLOTS:
void render();
void shutdown();
- void onWindowChangedQueued(QQuickWindow *w);
+ void onSceneGraphInvalidated();
+ void onWindowChanged(QQuickWindow *w);
private:
Scene3DItem *m_item; // Will be released by the QQuickWindow/QML Engine
@@ -105,6 +105,7 @@ private:
QSize m_lastSize;
bool m_multisample;
bool m_lastMultisample;
+ bool m_needsShutdown;
friend class Scene3DCleaner;
};
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
index f3817dc05..df431e452 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
@@ -52,10 +52,10 @@
//
#include <QtQuick/QSGMaterial>
-#include "scene3dsgmaterialshader_p.h"
-
#include <QtQuick/qsgtexture.h>
+#include <scene3dsgmaterialshader_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
index 5ce0f4d60..8a4585558 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
@@ -38,12 +38,13 @@
****************************************************************************/
#include "scene3dsgmaterialshader_p.h"
-#include "scene3dsgmaterial_p.h"
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>
#include <QtGui/qsurfaceformat.h>
+#include <scene3dsgmaterial_p.h>
+
QT_BEGIN_NAMESPACE
namespace {
@@ -71,6 +72,13 @@ namespace Qt3DRender {
QSGMaterialType Scene3DSGMaterialShader::type;
+Scene3DSGMaterialShader::Scene3DSGMaterialShader()
+ : QSGMaterialShader()
+ , m_matrixId(-1)
+ , m_opacityId(-1)
+{
+}
+
const char * const *Scene3DSGMaterialShader::attributeNames() const
{
static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 };
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
index 64d281ec4..a1222b07d 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
@@ -60,6 +60,7 @@ namespace Qt3DRender {
class Scene3DSGMaterialShader : public QSGMaterialShader
{
public:
+ Scene3DSGMaterialShader();
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) Q_DECL_FINAL;
const char * const *attributeNames() const Q_DECL_FINAL;
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode.cpp b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
index ae0a07350..8806b59a9 100644
--- a/src/quick3d/imports/scene3d/scene3dsgnode.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
@@ -38,10 +38,11 @@
****************************************************************************/
#include "scene3dsgnode_p.h"
-#include "scene3dlogging_p.h"
#include <QtCore/qthread.h>
+#include <scene3dlogging_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode_p.h b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
index f7b21e2b9..68b68eea5 100644
--- a/src/quick3d/imports/scene3d/scene3dsgnode_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
@@ -53,7 +53,7 @@
#include <QtQuick/QSGGeometryNode>
-#include "scene3dsgmaterial_p.h"
+#include <scene3dsgmaterial_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/items/items.pri b/src/quick3d/quick3d/items/items.pri
index 4c5e93fb2..4749c83cf 100644
--- a/src/quick3d/quick3d/items/items.pri
+++ b/src/quick3d/quick3d/items/items.pri
@@ -3,12 +3,14 @@ HEADERS += \
$$PWD/quick3dentity_p.h \
$$PWD/quick3dentityloader_p_p.h \
$$PWD/quick3dentityloader_p.h \
- $$PWD/quick3dnode_p.h
+ $$PWD/quick3dnode_p.h \
+ $$PWD/quick3dnodev9_p.h
SOURCES += \
$$PWD/quick3dnode.cpp \
$$PWD/quick3dentity.cpp \
$$PWD/quick3dentityloader.cpp \
- $$PWD/quick3dnodeinstantiator.cpp
+ $$PWD/quick3dnodeinstantiator.cpp \
+ $$PWD/quick3dnodev9.cpp
INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3d/items/quick3dentity.cpp b/src/quick3d/quick3d/items/quick3dentity.cpp
index ebc92e843..c2814a79e 100644
--- a/src/quick3d/quick3d/items/quick3dentity.cpp
+++ b/src/quick3d/quick3d/items/quick3dentity.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "quick3dentity_p.h"
+
#include <Qt3DCore/qcomponent.h>
QT_BEGIN_NAMESPACE
@@ -92,6 +93,7 @@ void Quick3DEntity::qmlAppendComponent(QQmlListProperty<QComponent> *list, QComp
if (comp == nullptr)
return;
Quick3DEntity *self = static_cast<Quick3DEntity *>(list->object);
+ self->m_managedComponents.push_back(comp);
self->parentEntity()->addComponent(comp);
}
@@ -110,10 +112,9 @@ int Quick3DEntity::qmlComponentsCount(QQmlListProperty<QComponent> *list)
void Quick3DEntity::qmlClearComponents(QQmlListProperty<QComponent> *list)
{
Quick3DEntity *self = static_cast<Quick3DEntity *>(list->object);
- const QComponentVector components = self->parentEntity()->components();
- for (QComponent *comp : components) {
+ for (QComponent *comp : qAsConst(self->m_managedComponents))
self->parentEntity()->removeComponent(comp);
- }
+ self->m_managedComponents.clear();
}
} // namespace Quick
diff --git a/src/quick3d/quick3d/items/quick3dentity_p.h b/src/quick3d/quick3d/items/quick3dentity_p.h
index eb716a0c3..7ba5c62c2 100644
--- a/src/quick3d/quick3d/items/quick3dentity_p.h
+++ b/src/quick3d/quick3d/items/quick3dentity_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
-#include <QQmlListProperty>
#include <Qt3DCore/qentity.h>
+#include <QtQml/QQmlListProperty>
+
#include <Qt3DQuick/private/quick3dnode_p.h>
#include <Qt3DQuick/private/qt3dquick_global_p.h>
@@ -82,6 +83,8 @@ private:
static QComponent *qmlComponentAt(QQmlListProperty<Qt3DCore::QComponent> *list, int index);
static int qmlComponentsCount(QQmlListProperty<Qt3DCore::QComponent> *list);
static void qmlClearComponents(QQmlListProperty<Qt3DCore::QComponent> *list);
+
+ QVector<Qt3DCore::QComponent *> m_managedComponents;
};
} // namespace Quick
diff --git a/src/quick3d/quick3d/items/quick3dentityloader.cpp b/src/quick3d/quick3d/items/quick3dentityloader.cpp
index 9c82db7ad..8a9b19024 100644
--- a/src/quick3d/quick3d/items/quick3dentityloader.cpp
+++ b/src/quick3d/quick3d/items/quick3dentityloader.cpp
@@ -39,9 +39,9 @@
#include "quick3dentityloader_p_p.h"
-#include <QQmlContext>
-#include <QQmlEngine>
-#include <QQmlIncubator>
+#include <QtQml/QQmlContext>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlIncubator>
#include <QtQml/private/qqmlengine_p.h>
@@ -50,6 +50,32 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
namespace Quick {
+namespace {
+struct Quick3DQmlOwner
+{
+ Quick3DQmlOwner(QQmlEngine *e, QObject *o)
+ : engine(e)
+ , object(o)
+ {}
+
+ QQmlEngine *engine;
+ QObject *object;
+
+ QQmlContext *context() const
+ {
+ return engine->contextForObject(object);
+ }
+};
+
+Quick3DQmlOwner _q_findQmlOwner(QObject *object)
+{
+ auto o = object;
+ while (!qmlEngine(o) && o->parent())
+ o = o->parent();
+ return Quick3DQmlOwner(qmlEngine(o), o);
+}
+}
+
class Quick3DEntityLoaderIncubator : public QQmlIncubator
{
public:
@@ -71,13 +97,20 @@ protected:
Q_ASSERT(priv->m_entity != nullptr);
priv->m_entity->setParent(m_loader);
emit m_loader->entityChanged();
+ priv->setStatus(Quick3DEntityLoader::Ready);
+ break;
+ }
+
+ case Loading: {
+ priv->setStatus(Quick3DEntityLoader::Loading);
break;
}
case Error: {
- QQmlEnginePrivate::warning(qmlEngine(m_loader), errors());
+ QQmlEnginePrivate::warning(_q_findQmlOwner(m_loader).engine, errors());
priv->clear();
emit m_loader->entityChanged();
+ priv->setStatus(Quick3DEntityLoader::Error);
break;
}
@@ -95,13 +128,21 @@ private:
\inqmlmodule Qt3D.Core
\inherits Entity
\since 5.5
- \brief Provides the facility to load entities from qml source
+ \brief Provides a way to dynamically load an Entity subtree
An EntityLoader provides the facitily to load predefined set of entities
from qml source file. EntityLoader itself is an entity and the loaded entity
tree is set as a child of the loader. The loaded entity tree root can be
accessed with EntityLoader::entity property.
+
+ \badcode
+ EntityLoader {
+ id: loader
+ source: "./SphereEntity.qml"
+ }
+ \endcode
*/
+
Quick3DEntityLoader::Quick3DEntityLoader(QNode *parent)
: QEntity(*new Quick3DEntityLoaderPrivate, parent)
{
@@ -117,6 +158,10 @@ Quick3DEntityLoader::~Quick3DEntityLoader()
\qmlproperty QtQml::QtObject EntityLoader::entity
Holds the loaded entity tree root.
\readonly
+
+ This property allows access to the content of the loader. It references
+ either a valid Entity object if the status property equals
+ EntityLoader.Ready, it is equal to null otherwise.
*/
QObject *Quick3DEntityLoader::entity() const
{
@@ -147,12 +192,30 @@ void Quick3DEntityLoader::setSource(const QUrl &url)
d->loadFromSource();
}
+/*!
+ \qmlproperty Status Qt3DCore::EntityLoader::status
+
+ Holds the status of the entity loader.
+ \list
+ \li EntityLoader.Null
+ \li EntityLoader.Loading
+ \li EntityLoader.Ready
+ \li EntityLoader.Error
+ \endlist
+ */
+Quick3DEntityLoader::Status Quick3DEntityLoader::status() const
+{
+ Q_D(const Quick3DEntityLoader);
+ return d->m_status;
+}
+
Quick3DEntityLoaderPrivate::Quick3DEntityLoaderPrivate()
: QEntityPrivate(),
m_incubator(nullptr),
m_context(nullptr),
m_component(nullptr),
- m_entity(nullptr)
+ m_entity(nullptr),
+ m_status(Quick3DEntityLoader::Null)
{
}
@@ -201,7 +264,8 @@ void Quick3DEntityLoaderPrivate::loadComponent(const QUrl &source)
Q_ASSERT(m_component == nullptr);
Q_ASSERT(m_context == nullptr);
- m_component = new QQmlComponent(qmlEngine(q), q);
+ auto owner = _q_findQmlOwner(q);
+ m_component = new QQmlComponent(owner.engine, owner.object);
QObject::connect(m_component, SIGNAL(statusChanged(QQmlComponent::Status)),
q, SLOT(_q_componentStatusChanged(QQmlComponent::Status)));
m_component->loadUrl(source, QQmlComponent::Asynchronous);
@@ -216,8 +280,10 @@ void Quick3DEntityLoaderPrivate::_q_componentStatusChanged(QQmlComponent::Status
Q_ASSERT(m_context == nullptr);
Q_ASSERT(m_incubator == nullptr);
+ auto owner = _q_findQmlOwner(q);
+
if (!m_component->errors().isEmpty()) {
- QQmlEnginePrivate::warning(qmlEngine(q), m_component->errors());
+ QQmlEnginePrivate::warning(owner.engine, m_component->errors());
clear();
emit q->entityChanged();
return;
@@ -227,13 +293,24 @@ void Quick3DEntityLoaderPrivate::_q_componentStatusChanged(QQmlComponent::Status
if (status != QQmlComponent::Ready)
return;
- m_context = new QQmlContext(qmlContext(q));
- m_context->setContextObject(q);
+ m_context = new QQmlContext(owner.context());
+ m_context->setContextObject(owner.object);
m_incubator = new Quick3DEntityLoaderIncubator(q);
m_component->create(*m_incubator, m_context);
}
+void Quick3DEntityLoaderPrivate::setStatus(Quick3DEntityLoader::Status status)
+{
+ Q_Q(Quick3DEntityLoader);
+ if (status != m_status) {
+ m_status = status;
+ const bool blocked = q->blockNotifications(true);
+ emit q->statusChanged(m_status);
+ q->blockNotifications(blocked);
+ }
+}
+
} // namespace Quick
} // namespace Qt3DCore
diff --git a/src/quick3d/quick3d/items/quick3dentityloader_p.h b/src/quick3d/quick3d/items/quick3dentityloader_p.h
index 5721af115..6a2fe5473 100644
--- a/src/quick3d/quick3d/items/quick3dentityloader_p.h
+++ b/src/quick3d/quick3d/items/quick3dentityloader_p.h
@@ -51,10 +51,9 @@
// We mean it.
//
-#include <QObject>
-#include <QUrl>
-
#include <Qt3DCore/QEntity>
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
#include <Qt3DQuick/private/qt3dquick_global_p.h>
@@ -74,7 +73,16 @@ class QT3DQUICKSHARED_PRIVATE_EXPORT Quick3DEntityLoader : public QEntity
Q_OBJECT
Q_PROPERTY(QObject *entity READ entity NOTIFY entityChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
public:
+ enum Status {
+ Null = 0,
+ Loading,
+ Ready,
+ Error
+ };
+ Q_ENUM(Status)
+
explicit Quick3DEntityLoader(QNode *parent = 0);
~Quick3DEntityLoader();
@@ -83,9 +91,12 @@ public:
QUrl source() const;
void setSource(const QUrl &url);
+ Status status() const;
+
Q_SIGNALS:
void entityChanged();
void sourceChanged();
+ void statusChanged(Status status);
private:
Q_DECLARE_PRIVATE(Quick3DEntityLoader)
diff --git a/src/quick3d/quick3d/items/quick3dentityloader_p_p.h b/src/quick3d/quick3d/items/quick3dentityloader_p_p.h
index 235870933..4d067f0e6 100644
--- a/src/quick3d/quick3d/items/quick3dentityloader_p_p.h
+++ b/src/quick3d/quick3d/items/quick3dentityloader_p_p.h
@@ -51,11 +51,10 @@
// We mean it.
//
-#include "quick3dentityloader_p.h"
-
-#include <QQmlComponent>
+#include <QtQml/QQmlComponent>
#include <Qt3DCore/private/qentity_p.h>
+#include <Qt3DQuick/private/quick3dentityloader_p.h>
QT_BEGIN_NAMESPACE
@@ -82,6 +81,7 @@ public:
void loadComponent(const QUrl &source);
void _q_componentStatusChanged(QQmlComponent::Status status);
+ void setStatus(Quick3DEntityLoader::Status status);
static inline Quick3DEntityLoaderPrivate *get(Quick3DEntityLoader *q) { return q->d_func(); }
@@ -90,6 +90,7 @@ public:
QQmlContext *m_context;
QQmlComponent *m_component;
QEntity *m_entity;
+ Quick3DEntityLoader::Status m_status;
};
} // namespace Quick
diff --git a/src/quick3d/quick3d/items/quick3dnode.cpp b/src/quick3d/quick3d/items/quick3dnode.cpp
index 3761f8d64..fb91f4ae0 100644
--- a/src/quick3d/quick3d/items/quick3dnode.cpp
+++ b/src/quick3d/quick3d/items/quick3dnode.cpp
@@ -38,7 +38,8 @@
****************************************************************************/
#include "quick3dnode_p.h"
-#include <QDebug>
+
+#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/items/quick3dnode_p.h b/src/quick3d/quick3d/items/quick3dnode_p.h
index 9798d0d4c..640a58149 100644
--- a/src/quick3d/quick3d/items/quick3dnode_p.h
+++ b/src/quick3d/quick3d/items/quick3dnode_p.h
@@ -51,8 +51,9 @@
// We mean it.
//
-#include <QQmlListProperty>
#include <Qt3DCore/qnode.h>
+#include <QtQml/QQmlListProperty>
+
#include <Qt3DQuick/private/qt3dquick_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
index eb6df2756..1626554ea 100644
--- a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
@@ -42,13 +42,13 @@
#include <QtQml/QQmlContext>
#include <QtQml/QQmlComponent>
-#include <QtQml/QQmlInfo>
#include <QtQml/QQmlError>
-#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtQml/QQmlInfo>
+
+#include <Qt3DCore/private/qnode_p.h>
+#include <QtQml/private/qqmlchangeset_p.h>
#include <QtQml/private/qqmldelegatemodel_p.h>
-#include <private/qnode_p.h>
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlobjectmodel_p.h>
+#include <QtQml/private/qqmlobjectmodel_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h b/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h
index d861fc2fe..fd7a1d83d 100644
--- a/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator_p.h
@@ -52,11 +52,12 @@
// We mean it.
//
-#include <Qt3DQuick/private/qt3dquick_global_p.h>
#include <Qt3DCore/qnode.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlparserstatus.h>
+#include <Qt3DQuick/private/qt3dquick_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
diff --git a/src/quick3d/quick3d/items/quick3dnodev9.cpp b/src/quick3d/quick3d/items/quick3dnodev9.cpp
new file mode 100644
index 000000000..d1a9011b5
--- /dev/null
+++ b/src/quick3d/quick3d/items/quick3dnodev9.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dnodev9_p.h"
+#include <QtQml/QJSValueIterator>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+namespace Quick {
+
+Quick3DNodeV9::Quick3DNodeV9(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ \qmlproperty QJSValue Qt3DCore::Node::propertyTrackingOverrides
+ \default {}
+
+ Assuming a Qt3DCore::Node needs to override the PropertyTrackingMode on two
+ properties (enabled and displacement), the value should be set as shown
+ below.
+
+ \badcode
+ propertyTrackingOverrides: {
+ "enabled": Entity.DontTrackValues,
+ "displacement": Entity.TrackFinalValues
+ }
+ \endcode
+
+ \since 2.9
+*/
+
+QJSValue Quick3DNodeV9::propertyTrackingOverrides() const
+{
+ return m_propertyTrackingOverrides;
+}
+
+void Quick3DNodeV9::setPropertyTrackingOverrides(const QJSValue &value)
+{
+ m_propertyTrackingOverrides = value;
+
+ QNode *parentNode = this->parentNode();
+ parentNode->clearPropertyTrackings();
+
+ if (value.isObject()) {
+ QJSValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ parentNode->setPropertyTracking(it.name(), static_cast<QNode::PropertyTrackingMode>(it.value().toInt()));
+ }
+ }
+ emit propertyTrackingOverridesChanged(value);
+}
+
+/*!
+ \qmlproperty list<QtQml::QtObject> Qt3DCore::Node::data
+ \default
+*/
+
+QQmlListProperty<QObject> Quick3DNodeV9::data()
+{
+ return QQmlListProperty<QObject>(this, 0,
+ Quick3DNodeV9::appendData,
+ Quick3DNodeV9::dataCount,
+ Quick3DNodeV9::dataAt,
+ Quick3DNodeV9::clearData);
+}
+
+/*!
+ \qmlproperty list<Node> Qt3DCore::Node::childNodes
+ \readonly
+*/
+
+QQmlListProperty<QNode> Quick3DNodeV9::childNodes()
+{
+ return QQmlListProperty<QNode>(this, 0,
+ Quick3DNodeV9::appendChild,
+ Quick3DNodeV9::childCount,
+ Quick3DNodeV9::childAt,
+ Quick3DNodeV9::clearChildren);
+}
+
+void Quick3DNodeV9::appendData(QQmlListProperty<QObject> *list, QObject *obj)
+{
+ if (!obj)
+ return;
+
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ self->childAppended(0, obj);
+}
+
+QObject *Quick3DNodeV9::dataAt(QQmlListProperty<QObject> *list, int index)
+{
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ return self->parentNode()->children().at(index);
+}
+
+int Quick3DNodeV9::dataCount(QQmlListProperty<QObject> *list)
+{
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ return self->parentNode()->children().count();
+}
+
+void Quick3DNodeV9::clearData(QQmlListProperty<QObject> *list)
+{
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ for (QObject *const child : self->parentNode()->children())
+ self->childRemoved(0, child);
+}
+
+void Quick3DNodeV9::appendChild(QQmlListProperty<Qt3DCore::QNode> *list, Qt3DCore::QNode *obj)
+{
+ if (!obj)
+ return;
+
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ Q_ASSERT(!self->parentNode()->children().contains(obj));
+
+ self->childAppended(0, obj);
+}
+
+Qt3DCore::QNode *Quick3DNodeV9::childAt(QQmlListProperty<Qt3DCore::QNode> *list, int index)
+{
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ return qobject_cast<QNode *>(self->parentNode()->children().at(index));
+}
+
+int Quick3DNodeV9::childCount(QQmlListProperty<Qt3DCore::QNode> *list)
+{
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ return self->parentNode()->children().count();
+}
+
+void Quick3DNodeV9::clearChildren(QQmlListProperty<Qt3DCore::QNode> *list)
+{
+ Quick3DNodeV9 *self = static_cast<Quick3DNodeV9 *>(list->object);
+ for (QObject *const child : self->parentNode()->children())
+ self->childRemoved(0, child);
+}
+
+void Quick3DNodeV9::childAppended(int, QObject *obj)
+{
+ QNode *parentNode = this->parentNode();
+ if (obj->parent() == parentNode)
+ obj->setParent(0);
+ // Set after otherwise addChild might not work
+ if (QNode *n = qobject_cast<QNode *>(obj))
+ n->setParent(parentNode);
+ else
+ obj->setParent(parentNode);
+}
+
+void Quick3DNodeV9::childRemoved(int, QObject *obj)
+{
+ if (QNode *n = qobject_cast<QNode *>(obj))
+ n->setParent(Q_NODE_NULLPTR);
+ else
+ obj->setParent(nullptr);
+}
+
+
+} // namespace Quick
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3d/items/quick3dnodev9_p.h b/src/quick3d/quick3d/items/quick3dnodev9_p.h
new file mode 100644
index 000000000..d969c4b64
--- /dev/null
+++ b/src/quick3d/quick3d/items/quick3dnodev9_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QUICK_QUICK3DNODEV9_P_H
+#define QT3D_QUICK_QUICK3DNODEV9_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/QJSValue>
+#include <QQmlListProperty>
+#include <Qt3DCore/qnode.h>
+#include <Qt3DQuick/private/qt3dquick_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+namespace Quick {
+
+class QT3DQUICKSHARED_PRIVATE_EXPORT Quick3DNodeV9 : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QJSValue propertyTrackingOverrides READ propertyTrackingOverrides WRITE setPropertyTrackingOverrides NOTIFY propertyTrackingOverridesChanged)
+ Q_PROPERTY(QQmlListProperty<QObject> data READ data)
+ Q_PROPERTY(QQmlListProperty<Qt3DCore::QNode> childNodes READ childNodes)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ explicit Quick3DNodeV9(QObject *parent = nullptr);
+
+ QJSValue propertyTrackingOverrides() const;
+ QQmlListProperty<QObject> data();
+ QQmlListProperty<Qt3DCore::QNode> childNodes();
+
+ inline QNode *parentNode() const { return qobject_cast<QNode*>(parent()); }
+
+Q_SIGNALS:
+ void propertyTrackingOverridesChanged(const QJSValue &value);
+
+private Q_SLOTS:
+ void setPropertyTrackingOverrides(const QJSValue &value);
+ void childAppended(int idx, QObject *child);
+ void childRemoved(int idx, QObject *child);
+
+private:
+ static void appendData(QQmlListProperty<QObject> *list, QObject *obj);
+ static QObject *dataAt(QQmlListProperty<QObject> *list, int index);
+ static int dataCount(QQmlListProperty<QObject> *list);
+ static void clearData(QQmlListProperty<QObject> *list);
+
+ static void appendChild(QQmlListProperty<Qt3DCore::QNode> *list, Qt3DCore::QNode *obj);
+ static QNode *childAt(QQmlListProperty<Qt3DCore::QNode> *list, int index);
+ static int childCount(QQmlListProperty<Qt3DCore::QNode> *list);
+ static void clearChildren(QQmlListProperty<Qt3DCore::QNode> *list);
+
+ QJSValue m_propertyTrackingOverrides;
+};
+
+} // namespace Quick
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+
+#endif // QT3D_QUICK_QUICK3DNODEV9_P_H
diff --git a/src/quick3d/quick3d/qqmlaspectengine.cpp b/src/quick3d/quick3d/qqmlaspectengine.cpp
index 4b694d26e..912c71fb3 100644
--- a/src/quick3d/quick3d/qqmlaspectengine.cpp
+++ b/src/quick3d/quick3d/qqmlaspectengine.cpp
@@ -38,10 +38,11 @@
****************************************************************************/
#include "qqmlaspectengine_p.h"
-#include <QQmlComponent>
-#include <QQmlContext>
-#include <QDebug>
+
#include <Qt3DCore/qentity.h>
+#include <QtCore/QDebug>
+#include <QtQml/QQmlComponent>
+#include <QtQml/QQmlContext>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qqmlaspectengine.h b/src/quick3d/quick3d/qqmlaspectengine.h
index c85cbb8ea..a7b09ec8a 100644
--- a/src/quick3d/quick3d/qqmlaspectengine.h
+++ b/src/quick3d/quick3d/qqmlaspectengine.h
@@ -40,9 +40,9 @@
#ifndef QT3D_QUICK_QQMLASPECTENGINE_H
#define QT3D_QUICK_QQMLASPECTENGINE_H
-#include <QQmlEngine>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DQuick/qt3dquick_global.h>
+#include <QtQml/QQmlEngine>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qqmlaspectengine_p.h b/src/quick3d/quick3d/qqmlaspectengine_p.h
index f9343ae68..960ecb344 100644
--- a/src/quick3d/quick3d/qqmlaspectengine_p.h
+++ b/src/quick3d/quick3d/qqmlaspectengine_p.h
@@ -53,8 +53,9 @@
#include <Qt3DQuick/qt3dquick_global.h>
#include <Qt3DQuick/qqmlaspectengine.h>
-#include <private/qobject_p.h>
-#include <QScopedPointer>
+#include <QtCore/QScopedPointer>
+
+#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qquaternionanimation.cpp b/src/quick3d/quick3d/qquaternionanimation.cpp
index 25cad523b..adccf4d97 100644
--- a/src/quick3d/quick3d/qquaternionanimation.cpp
+++ b/src/quick3d/quick3d/qquaternionanimation.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qquaternionanimation_p.h"
+
#include <QtQuick/private/qquickanimation_p_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qquaternionanimation_p.h b/src/quick3d/quick3d/qquaternionanimation_p.h
index 3c5f092c4..172d3bc85 100644
--- a/src/quick3d/quick3d/qquaternionanimation_p.h
+++ b/src/quick3d/quick3d/qquaternionanimation_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
+#include <QtGui/qquaternion.h>
+
#include <Qt3DQuick/private/qt3dquick_global_p.h>
#include <QtQuick/private/qquickanimation_p.h>
-#include <QtGui/qquaternion.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qt3dquick_global.cpp b/src/quick3d/quick3d/qt3dquick_global.cpp
index f25aae268..a98211991 100644
--- a/src/quick3d/quick3d/qt3dquick_global.cpp
+++ b/src/quick3d/quick3d/qt3dquick_global.cpp
@@ -38,12 +38,13 @@
****************************************************************************/
#include "qt3dquick_global_p.h"
-#include "qt3dquicknodefactory_p.h"
-#include <private/qqmlglobal_p.h>
-#include <private/qt3dquickvaluetypes_p.h>
-#include <private/qv8engine_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4object_p.h>
+
+#include <Qt3DQuick/private/qt3dquicknodefactory_p.h>
+#include <Qt3DQuick/private/qt3dquickvaluetypes_p.h>
+#include <QtQml/private/qqmlglobal_p.h>
+#include <QtQml/private/qv4engine_p.h>
+#include <QtQml/private/qv4object_p.h>
+#include <QtQml/private/qv8engine_p.h>
QT_BEGIN_NAMESPACE
@@ -579,6 +580,7 @@ public:
case QMetaType::QColor:
{
Q_ASSERT(dstSize >= sizeof(QColor));
+ Q_UNUSED(dstSize);
const QRgb *rgb = reinterpret_cast<const QRgb *>(src);
QColor *color = reinterpret_cast<QColor *>(dst);
new (color) QColor(QColor::fromRgba(*rgb));
@@ -657,9 +659,9 @@ public:
#undef ASSERT_VALID_SIZE
};
+static Quick3DValueTypeProvider valueTypeProvider;
static Quick3DValueTypeProvider *getValueTypeProvider()
{
- static Quick3DValueTypeProvider valueTypeProvider;
return &valueTypeProvider;
}
@@ -704,6 +706,11 @@ void Quick3D_initialize()
QQmlPrivate::qmlregister(QQmlPrivate::AutoParentRegistration, &autoparent);
}
+void Quick3D_uninitialize()
+{
+ QQml_removeValueTypeProvider(&valueTypeProvider);
+}
+
void Quick3D_registerType(const char *className, const char *quickName, int major, int minor)
{
QuickNodeFactory::instance()->registerType(className, quickName, major, minor);
diff --git a/src/quick3d/quick3d/qt3dquick_global_p.h b/src/quick3d/quick3d/qt3dquick_global_p.h
index d67209404..ffc603f91 100644
--- a/src/quick3d/quick3d/qt3dquick_global_p.h
+++ b/src/quick3d/quick3d/qt3dquick_global_p.h
@@ -62,6 +62,7 @@ namespace Qt3DCore {
namespace Quick {
QT3DQUICKSHARED_PRIVATE_EXPORT void Quick3D_initialize();
+QT3DQUICKSHARED_PRIVATE_EXPORT void Quick3D_uninitialize();
QT3DQUICKSHARED_PRIVATE_EXPORT void Quick3D_registerType(const char *className, const char *quickName, int major, int minor);
template<class T, class E> void registerExtendedType(const char *className, const char *quickName,
diff --git a/src/quick3d/quick3d/qt3dquicknodefactory.cpp b/src/quick3d/quick3d/qt3dquicknodefactory.cpp
index 923793506..a8c021754 100644
--- a/src/quick3d/quick3d/qt3dquicknodefactory.cpp
+++ b/src/quick3d/quick3d/qt3dquicknodefactory.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qt3dquicknodefactory_p.h"
+
#include <QtQml/private/qqmlmetatype_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qt3dquicknodefactory_p.h b/src/quick3d/quick3d/qt3dquicknodefactory_p.h
index 4dd455461..6c074da04 100644
--- a/src/quick3d/quick3d/qt3dquicknodefactory_p.h
+++ b/src/quick3d/quick3d/qt3dquicknodefactory_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qabstractnodefactory_p.h>
#include <QtCore/qhash.h>
+#include <Qt3DCore/private/qabstractnodefactory_p.h>
+
QT_BEGIN_NAMESPACE
class QQmlType;
diff --git a/src/quick3d/quick3d/qt3dquickvaluetypes_p.h b/src/quick3d/quick3d/qt3dquickvaluetypes_p.h
index ed80d0426..46500b935 100644
--- a/src/quick3d/quick3d/qt3dquickvaluetypes_p.h
+++ b/src/quick3d/quick3d/qt3dquickvaluetypes_p.h
@@ -52,15 +52,15 @@
// We mean it.
//
-#include <private/qt3dquick_global_p.h>
-#include <private/qqmlvaluetype_p.h>
-
#include <QtGui/QColor>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/QQuaternion>
#include <QtGui/QVector2D>
#include <QtGui/QVector3D>
#include <QtGui/QVector4D>
-#include <QtGui/QQuaternion>
-#include <QtGui/QMatrix4x4>
+
+#include <Qt3DQuick/private/qt3dquick_global_p.h>
+#include <QtQml/private/qqmlvaluetype_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3danimation/items/items.pri b/src/quick3d/quick3danimation/items/items.pri
index 0c3511902..27adabbe4 100644
--- a/src/quick3d/quick3danimation/items/items.pri
+++ b/src/quick3d/quick3danimation/items/items.pri
@@ -1,9 +1,19 @@
SOURCES += \
$$PWD/quick3dchannelmapper.cpp \
- $$PWD/quick3dabstractclipblendnode.cpp
+ $$PWD/quick3danimationcontroller.cpp \
+ $$PWD/quick3danimationgroup.cpp \
+ $$PWD/quick3dkeyframeanimation.cpp \
+ $$PWD/quick3dmorphinganimation.cpp \
+ $$PWD/quick3dmorphtarget.cpp \
+ $$PWD/quick3dvertexblendanimation.cpp
HEADERS += \
$$PWD/quick3dchannelmapper_p.h \
- $$PWD/quick3dabstractclipblendnode_p.h
+ $$PWD/quick3danimationcontroller_p.h \
+ $$PWD/quick3danimationgroup_p.h \
+ $$PWD/quick3dkeyframeanimation_p.h \
+ $$PWD/quick3dmorphinganimation_p.h \
+ $$PWD/quick3dmorphtarget_p.h \
+ $$PWD/quick3dvertexblendanimation_p.h
INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp b/src/quick3d/quick3danimation/items/quick3danimationcontroller.cpp
index 4aceb0d55..dc6183989 100644
--- a/src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp
+++ b/src/quick3d/quick3danimation/items/quick3danimationcontroller.cpp
@@ -38,7 +38,7 @@
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
QQuick3DAnimationController::QQuick3DAnimationController(QObject *parent)
@@ -90,6 +90,6 @@ void QQuick3DAnimationController::clearAnimationGroups(QQmlListProperty<QAnimati
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h b/src/quick3d/quick3danimation/items/quick3danimationcontroller_p.h
index 82ad29e2c..a3033e537 100644
--- a/src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h
+++ b/src/quick3d/quick3danimation/items/quick3danimationcontroller_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QUICK_QUICK3DANIMATIONCONTROLLER_P_H
-#define QT3DEXTRAS_QUICK_QUICK3DANIMATIONCONTROLLER_P_H
+#ifndef QT3DANIMATION_QUICK_QUICK3DANIMATIONCONTROLLER_P_H
+#define QT3DANIMATION_QUICK_QUICK3DANIMATIONCONTROLLER_P_H
//
// W A R N I N G
@@ -48,41 +48,41 @@
// We mean it.
//
-#include <Qt3DQuickExtras/qt3dquickextras_global.h>
-#include <QQmlListProperty>
-#include <Qt3DExtras/QAnimationController>
+#include <private/qt3dquickanimation_global_p.h>
+#include <QtQml/QQmlListProperty>
+#include <Qt3DAnimation/QAnimationController>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
-class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DAnimationController : public QObject
+class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT QQuick3DAnimationController : public QObject
{
Q_OBJECT
- Q_PROPERTY(QQmlListProperty<Qt3DExtras::QAnimationGroup> animationGroups READ animationGroups)
+ Q_PROPERTY(QQmlListProperty<Qt3DAnimation::QAnimationGroup> animationGroups READ animationGroups)
public:
explicit QQuick3DAnimationController(QObject *parent = nullptr);
- inline Qt3DExtras::QAnimationController *parentAnimationController() const
+ inline Qt3DAnimation::QAnimationController *parentAnimationController() const
{
- return qobject_cast<Qt3DExtras::QAnimationController *>(parent());
+ return qobject_cast<Qt3DAnimation::QAnimationController *>(parent());
}
- QQmlListProperty<Qt3DExtras::QAnimationGroup> animationGroups();
+ QQmlListProperty<Qt3DAnimation::QAnimationGroup> animationGroups();
private:
- static void appendAnimationGroup(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list, Qt3DExtras::QAnimationGroup *bar);
- static QAnimationGroup *animationGroupAt(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list, int index);
- static int animationGroupCount(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list);
- static void clearAnimationGroups(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list);
+ static void appendAnimationGroup(QQmlListProperty<Qt3DAnimation::QAnimationGroup> *list, Qt3DAnimation::QAnimationGroup *bar);
+ static QAnimationGroup *animationGroupAt(QQmlListProperty<Qt3DAnimation::QAnimationGroup> *list, int index);
+ static int animationGroupCount(QQmlListProperty<Qt3DAnimation::QAnimationGroup> *list);
+ static void clearAnimationGroups(QQmlListProperty<Qt3DAnimation::QAnimationGroup> *list);
};
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3danimationgroup.cpp b/src/quick3d/quick3danimation/items/quick3danimationgroup.cpp
index 3e3813227..f10450280 100644
--- a/src/quick3d/quick3dextras/items/quick3danimationgroup.cpp
+++ b/src/quick3d/quick3danimation/items/quick3danimationgroup.cpp
@@ -36,11 +36,11 @@
#include "quick3danimationgroup_p.h"
-#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DAnimation/qabstractanimation.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
QQuick3DAnimationGroup::QQuick3DAnimationGroup(QObject *parent)
@@ -48,9 +48,9 @@ QQuick3DAnimationGroup::QQuick3DAnimationGroup(QObject *parent)
{
}
-QQmlListProperty<Qt3DExtras::QAbstractAnimation> QQuick3DAnimationGroup::animations()
+QQmlListProperty<Qt3DAnimation::QAbstractAnimation> QQuick3DAnimationGroup::animations()
{
- return QQmlListProperty<Qt3DExtras::QAbstractAnimation>(this, 0,
+ return QQmlListProperty<Qt3DAnimation::QAbstractAnimation>(this, 0,
&QQuick3DAnimationGroup::appendAnimation,
&QQuick3DAnimationGroup::animationCount,
&QQuick3DAnimationGroup::animationAt,
@@ -58,15 +58,15 @@ QQmlListProperty<Qt3DExtras::QAbstractAnimation> QQuick3DAnimationGroup::animati
}
-void QQuick3DAnimationGroup::appendAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list,
- Qt3DExtras::QAbstractAnimation *animation)
+void QQuick3DAnimationGroup::appendAnimation(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list,
+ Qt3DAnimation::QAbstractAnimation *animation)
{
QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
if (animationGroup)
animationGroup->parentAnimationGroup()->addAnimation(animation);
}
-int QQuick3DAnimationGroup::animationCount(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list)
+int QQuick3DAnimationGroup::animationCount(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list)
{
QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
if (animationGroup)
@@ -74,26 +74,26 @@ int QQuick3DAnimationGroup::animationCount(QQmlListProperty<Qt3DExtras::QAbstrac
return 0;
}
-Qt3DExtras::QAbstractAnimation *QQuick3DAnimationGroup::animationAt(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list, int index)
+Qt3DAnimation::QAbstractAnimation *QQuick3DAnimationGroup::animationAt(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list, int index)
{
QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
if (animationGroup) {
- return qobject_cast<Qt3DExtras::QAbstractAnimation *>(
+ return qobject_cast<Qt3DAnimation::QAbstractAnimation *>(
animationGroup->parentAnimationGroup()->animationList().at(index));
}
return nullptr;
}
-void QQuick3DAnimationGroup::clearAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list)
+void QQuick3DAnimationGroup::clearAnimation(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list)
{
QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
if (animationGroup) {
- QVector<Qt3DExtras::QAbstractAnimation *> emptyList;
+ QVector<Qt3DAnimation::QAbstractAnimation *> emptyList;
animationGroup->parentAnimationGroup()->setAnimations(emptyList);
}
}
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3danimationgroup_p.h b/src/quick3d/quick3danimation/items/quick3danimationgroup_p.h
index c7140c946..aef202480 100644
--- a/src/quick3d/quick3dextras/items/quick3danimationgroup_p.h
+++ b/src/quick3d/quick3danimation/items/quick3danimationgroup_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QUICK_QUICK3DANIMATIONGROUP_P_H
-#define QT3DEXTRAS_QUICK_QUICK3DANIMATIONGROUP_P_H
+#ifndef QT3DANIMATION_QUICK_QUICK3DANIMATIONGROUP_P_H
+#define QT3DANIMATION_QUICK_QUICK3DANIMATIONGROUP_P_H
//
// W A R N I N G
@@ -49,42 +49,42 @@
//
#include <QtQml/qqmllist.h>
-#include <Qt3DExtras/qabstractanimation.h>
-#include <Qt3DExtras/qanimationgroup.h>
+#include <Qt3DAnimation/qabstractanimation.h>
+#include <Qt3DAnimation/qanimationgroup.h>
-#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <private/qt3dquickanimation_global_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
-class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DAnimationGroup : public QObject
+class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT QQuick3DAnimationGroup : public QObject
{
Q_OBJECT
- Q_PROPERTY(QQmlListProperty<Qt3DExtras::QAbstractAnimation> animations READ animations)
+ Q_PROPERTY(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> animations READ animations)
public:
explicit QQuick3DAnimationGroup(QObject *parent = nullptr);
- inline Qt3DExtras::QAnimationGroup *parentAnimationGroup() const
+ inline Qt3DAnimation::QAnimationGroup *parentAnimationGroup() const
{
- return qobject_cast<Qt3DExtras::QAnimationGroup *>(parent());
+ return qobject_cast<Qt3DAnimation::QAnimationGroup *>(parent());
}
- QQmlListProperty<Qt3DExtras::QAbstractAnimation> animations();
+ QQmlListProperty<Qt3DAnimation::QAbstractAnimation> animations();
private:
- static void appendAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list, Qt3DExtras::QAbstractAnimation *animation);
- static Qt3DExtras::QAbstractAnimation *animationAt(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list, int index);
- static int animationCount(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list);
- static void clearAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list);
+ static void appendAnimation(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list, Qt3DAnimation::QAbstractAnimation *animation);
+ static Qt3DAnimation::QAbstractAnimation *animationAt(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list, int index);
+ static int animationCount(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list);
+ static void clearAnimation(QQmlListProperty<Qt3DAnimation::QAbstractAnimation> *list);
};
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3danimation/items/quick3dchannelmapper_p.h b/src/quick3d/quick3danimation/items/quick3dchannelmapper_p.h
index fddaae72d..e44efad68 100644
--- a/src/quick3d/quick3danimation/items/quick3dchannelmapper_p.h
+++ b/src/quick3d/quick3danimation/items/quick3dchannelmapper_p.h
@@ -66,6 +66,8 @@ class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT Quick3DChannelMapper : public QOb
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Qt3DAnimation::QChannelMapping> mappings READ qmlMappings CONSTANT)
+ Q_CLASSINFO("DefaultProperty", "mappings")
+
public:
explicit Quick3DChannelMapper(QObject *parent = nullptr);
diff --git a/src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp b/src/quick3d/quick3danimation/items/quick3dkeyframeanimation.cpp
index cfd9ca7d2..f7cf133fe 100644
--- a/src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp
+++ b/src/quick3d/quick3danimation/items/quick3dkeyframeanimation.cpp
@@ -38,7 +38,7 @@
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
QQuick3DKeyframeAnimation::QQuick3DKeyframeAnimation(QObject *parent)
@@ -96,6 +96,6 @@ void QQuick3DKeyframeAnimation::clearKeyframes(QQmlListProperty<Qt3DCore::QTrans
}
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h b/src/quick3d/quick3danimation/items/quick3dkeyframeanimation_p.h
index e8309de9e..944cdbe67 100644
--- a/src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h
+++ b/src/quick3d/quick3danimation/items/quick3dkeyframeanimation_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
-#define QT3DEXTRAS_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
+#ifndef QT3DANIMATION_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
+#define QT3DANIMATION_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
//
// W A R N I N G
@@ -50,16 +50,16 @@
#include <QtQml/qqmllist.h>
-#include <Qt3DExtras/qkeyframeanimation.h>
+#include <Qt3DAnimation/qkeyframeanimation.h>
-#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <private/qt3dquickanimation_global_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
-class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DKeyframeAnimation : public QObject
+class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT QQuick3DKeyframeAnimation : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Qt3DCore::QTransform> keyframes READ keyframes)
@@ -85,8 +85,8 @@ private:
};
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
+#endif // QT3DANIMATION_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp b/src/quick3d/quick3danimation/items/quick3dmorphinganimation.cpp
index 61636f06d..997e2e215 100644
--- a/src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp
+++ b/src/quick3d/quick3danimation/items/quick3dmorphinganimation.cpp
@@ -38,7 +38,7 @@
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
QQuick3DMorphingAnimation::QQuick3DMorphingAnimation(QObject *parent)
@@ -46,24 +46,24 @@ QQuick3DMorphingAnimation::QQuick3DMorphingAnimation(QObject *parent)
{
}
-QQmlListProperty<Qt3DExtras::QMorphTarget> QQuick3DMorphingAnimation::morphTargets()
+QQmlListProperty<Qt3DAnimation::QMorphTarget> QQuick3DMorphingAnimation::morphTargets()
{
- return QQmlListProperty<Qt3DExtras::QMorphTarget>(this, 0,
+ return QQmlListProperty<Qt3DAnimation::QMorphTarget>(this, 0,
&QQuick3DMorphingAnimation::appendMorphTarget,
&QQuick3DMorphingAnimation::morphTargetCount,
&QQuick3DMorphingAnimation::morphTargetAt,
&QQuick3DMorphingAnimation::clearMorphTargets);
}
-void QQuick3DMorphingAnimation::appendMorphTarget(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
- Qt3DExtras::QMorphTarget *morphTarget)
+void QQuick3DMorphingAnimation::appendMorphTarget(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
+ Qt3DAnimation::QMorphTarget *morphTarget)
{
QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
if (animation)
animation->parentMorphingAnimation()->addMorphTarget(morphTarget);
}
-int QQuick3DMorphingAnimation::morphTargetCount(QQmlListProperty<Qt3DExtras::QMorphTarget> *list)
+int QQuick3DMorphingAnimation::morphTargetCount(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list)
{
QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
if (animation)
@@ -71,27 +71,27 @@ int QQuick3DMorphingAnimation::morphTargetCount(QQmlListProperty<Qt3DExtras::QMo
return 0;
}
-Qt3DExtras::QMorphTarget *QQuick3DMorphingAnimation::morphTargetAt(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
+Qt3DAnimation::QMorphTarget *QQuick3DMorphingAnimation::morphTargetAt(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
int index)
{
QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
if (animation) {
- return qobject_cast<Qt3DExtras::QMorphTarget *>(
+ return qobject_cast<Qt3DAnimation::QMorphTarget *>(
animation->parentMorphingAnimation()->morphTargetList().at(index));
}
return nullptr;
}
-void QQuick3DMorphingAnimation::clearMorphTargets(QQmlListProperty<Qt3DExtras::QMorphTarget> *list)
+void QQuick3DMorphingAnimation::clearMorphTargets(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list)
{
QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
if (animation) {
- QVector<Qt3DExtras::QMorphTarget *> emptyList;
+ QVector<Qt3DAnimation::QMorphTarget *> emptyList;
animation->parentMorphingAnimation()->setMorphTargets(emptyList);
}
}
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h b/src/quick3d/quick3danimation/items/quick3dmorphinganimation_p.h
index 5f052fd04..31d008a89 100644
--- a/src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h
+++ b/src/quick3d/quick3danimation/items/quick3dmorphinganimation_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QUICK_QUICK3DMORPHINGANIMATION_P_H
-#define QT3DEXTRAS_QUICK_QUICK3DMORPHINGANIMATION_P_H
+#ifndef QT3DANIMATION_QUICK_QUICK3DMORPHINGANIMATION_P_H
+#define QT3DANIMATION_QUICK_QUICK3DMORPHINGANIMATION_P_H
//
// W A R N I N G
@@ -50,19 +50,19 @@
#include <QtQml/qqmllist.h>
-#include <Qt3DExtras/qmorphinganimation.h>
+#include <Qt3DAnimation/qmorphinganimation.h>
-#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <private/qt3dquickanimation_global_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
-class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DMorphingAnimation : public QObject
+class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT QQuick3DMorphingAnimation : public QObject
{
Q_OBJECT
- Q_PROPERTY(QQmlListProperty<Qt3DExtras::QMorphTarget> morphTargets READ morphTargets)
+ Q_PROPERTY(QQmlListProperty<Qt3DAnimation::QMorphTarget> morphTargets READ morphTargets)
public:
QQuick3DMorphingAnimation(QObject *parent = nullptr);
@@ -72,21 +72,21 @@ public:
return qobject_cast<QMorphingAnimation *>(parent());
}
- QQmlListProperty<Qt3DExtras::QMorphTarget> morphTargets();
+ QQmlListProperty<Qt3DAnimation::QMorphTarget> morphTargets();
private:
- static void appendMorphTarget(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
- Qt3DExtras::QMorphTarget *morphTarget);
- static Qt3DExtras::QMorphTarget *morphTargetAt(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
+ static void appendMorphTarget(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
+ Qt3DAnimation::QMorphTarget *morphTarget);
+ static Qt3DAnimation::QMorphTarget *morphTargetAt(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
int index);
- static int morphTargetCount(QQmlListProperty<Qt3DExtras::QMorphTarget> *list);
- static void clearMorphTargets(QQmlListProperty<Qt3DExtras::QMorphTarget> *list);
+ static int morphTargetCount(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list);
+ static void clearMorphTargets(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list);
};
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QUICK_QUICK3DMORPHINGANIMATION_P_H
+#endif // QT3DANIMATION_QUICK_QUICK3DMORPHINGANIMATION_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp b/src/quick3d/quick3danimation/items/quick3dmorphtarget.cpp
index 8c1b9f0c1..81144e186 100644
--- a/src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp
+++ b/src/quick3d/quick3danimation/items/quick3dmorphtarget.cpp
@@ -38,7 +38,7 @@
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
QQuick3DMorphTarget::QQuick3DMorphTarget(QObject *parent)
@@ -88,6 +88,6 @@ void QQuick3DMorphTarget::clearAttributes(QQmlListProperty<Qt3DRender::QAttribut
}
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h b/src/quick3d/quick3danimation/items/quick3dmorphtarget_p.h
index e5c664370..03b52dfeb 100644
--- a/src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h
+++ b/src/quick3d/quick3danimation/items/quick3dmorphtarget_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QT3DEXTRAS_QUICK_QUICK3DMORPHTARGET_P_H
-#define QT3DEXTRAS_QUICK_QUICK3DMORPHTARGET_P_H
+#ifndef QT3DANIMATION_QUICK_QUICK3DMORPHTARGET_P_H
+#define QT3DANIMATION_QUICK_QUICK3DMORPHTARGET_P_H
//
// W A R N I N G
@@ -48,16 +48,16 @@
// We mean it.
//
-#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <private/qt3dquickanimation_global_p.h>
#include <QQmlListProperty>
-#include <Qt3DExtras/QMorphTarget>
+#include <Qt3DAnimation/QMorphTarget>
QT_BEGIN_NAMESPACE
-namespace Qt3DExtras {
+namespace Qt3DAnimation {
namespace Quick {
-class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DMorphTarget : public QObject
+class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT QQuick3DMorphTarget : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Qt3DRender::QAttribute> attributes READ attributes)
@@ -78,8 +78,8 @@ private:
};
} // namespace Quick
-} // namespace Qt3DExtras
+} // namespace Qt3DAnimation
QT_END_NAMESPACE
-#endif // QT3DEXTRAS_QUICK_QUICK3DMORPHTARGET_P_H
+#endif // QT3DANIMATION_QUICK_QUICK3DMORPHTARGET_P_H
diff --git a/src/quick3d/quick3danimation/items/quick3dvertexblendanimation.cpp b/src/quick3d/quick3danimation/items/quick3dvertexblendanimation.cpp
new file mode 100644
index 000000000..2dffb7858
--- /dev/null
+++ b/src/quick3d/quick3danimation/items/quick3dvertexblendanimation.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dvertexblendanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Quick {
+
+QQuick3DVertexBlendAnimation::QQuick3DVertexBlendAnimation(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DAnimation::QMorphTarget> QQuick3DVertexBlendAnimation::morphTargets()
+{
+ return QQmlListProperty<Qt3DAnimation::QMorphTarget>(this, 0,
+ &QQuick3DVertexBlendAnimation::appendMorphTarget,
+ &QQuick3DVertexBlendAnimation::morphTargetCount,
+ &QQuick3DVertexBlendAnimation::morphTargetAt,
+ &QQuick3DVertexBlendAnimation::clearMorphTargets);
+}
+
+void QQuick3DVertexBlendAnimation::appendMorphTarget(
+ QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
+ Qt3DAnimation::QMorphTarget *morphTarget)
+{
+ QQuick3DVertexBlendAnimation *animation
+ = qobject_cast<QQuick3DVertexBlendAnimation *>(list->object);
+ if (animation)
+ animation->parentVertexBlendAnimation()->addMorphTarget(morphTarget);
+}
+
+int QQuick3DVertexBlendAnimation::morphTargetCount(
+ QQmlListProperty<Qt3DAnimation::QMorphTarget> *list)
+{
+ QQuick3DVertexBlendAnimation *animation
+ = qobject_cast<QQuick3DVertexBlendAnimation *>(list->object);
+ if (animation)
+ return animation->parentVertexBlendAnimation()->morphTargetList().count();
+ return 0;
+}
+
+Qt3DAnimation::QMorphTarget *QQuick3DVertexBlendAnimation::morphTargetAt(
+ QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
+ int index)
+{
+ QQuick3DVertexBlendAnimation *animation
+ = qobject_cast<QQuick3DVertexBlendAnimation *>(list->object);
+ if (animation) {
+ return qobject_cast<Qt3DAnimation::QMorphTarget *>(
+ animation->parentVertexBlendAnimation()->morphTargetList().at(index));
+ }
+ return nullptr;
+}
+
+void QQuick3DVertexBlendAnimation::clearMorphTargets(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list)
+{
+ QQuick3DVertexBlendAnimation *animation
+ = qobject_cast<QQuick3DVertexBlendAnimation *>(list->object);
+ if (animation) {
+ QVector<Qt3DAnimation::QMorphTarget *> emptyList;
+ animation->parentVertexBlendAnimation()->setMorphTargets(emptyList);
+ }
+}
+
+} // namespace Quick
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3danimation/items/quick3dvertexblendanimation_p.h b/src/quick3d/quick3danimation/items/quick3dvertexblendanimation_p.h
new file mode 100644
index 000000000..6be2d662f
--- /dev/null
+++ b/src/quick3d/quick3danimation/items/quick3dvertexblendanimation_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QUICK_QUICK3DVERTEXBLENDANIMATION_P_H
+#define QT3DANIMATION_QUICK_QUICK3DVERTEXBLENDANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmllist.h>
+
+#include <Qt3DAnimation/qvertexblendanimation.h>
+
+#include <private/qt3dquickanimation_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Quick {
+
+class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT QQuick3DVertexBlendAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DAnimation::QMorphTarget> morphTargets READ morphTargets)
+
+public:
+ QQuick3DVertexBlendAnimation(QObject *parent = nullptr);
+
+ inline QVertexBlendAnimation *parentVertexBlendAnimation() const
+ {
+ return qobject_cast<QVertexBlendAnimation *>(parent());
+ }
+
+ QQmlListProperty<Qt3DAnimation::QMorphTarget> morphTargets();
+
+private:
+
+ static void appendMorphTarget(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
+ Qt3DAnimation::QMorphTarget *morphTarget);
+ static Qt3DAnimation::QMorphTarget *morphTargetAt(
+ QQmlListProperty<Qt3DAnimation::QMorphTarget> *list,
+ int index);
+ static int morphTargetCount(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list);
+ static void clearMorphTargets(QQmlListProperty<Qt3DAnimation::QMorphTarget> *list);
+};
+
+} // namespace Quick
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QUICK_QUICK3DMORPHINGANIMATION_P_H
diff --git a/src/quick3d/quick3dextras/items/items.pri b/src/quick3d/quick3dextras/items/items.pri
index cdb1e1245..b6f5d1877 100644
--- a/src/quick3d/quick3dextras/items/items.pri
+++ b/src/quick3d/quick3dextras/items/items.pri
@@ -1,15 +1,8 @@
HEADERS += \
- $$PWD/quick3danimationcontroller_p.h \
- $$PWD/quick3danimationgroup_p.h \
- $$PWD/quick3dkeyframeanimation_p.h \
- $$PWD/quick3dmorphinganimation_p.h \
- $$PWD/quick3dmorphtarget_p.h
+ $$PWD/quick3dlevelofdetailloader_p.h \
+ $$PWD/quick3dlevelofdetailloader_p_p.h
SOURCES += \
- $$PWD/quick3danimationcontroller.cpp \
- $$PWD/quick3danimationgroup.cpp \
- $$PWD/quick3dkeyframeanimation.cpp \
- $$PWD/quick3dmorphinganimation.cpp \
- $$PWD/quick3dmorphtarget.cpp
+ $$PWD/quick3dlevelofdetailloader.cpp
INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader.cpp b/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader.cpp
new file mode 100644
index 000000000..087342063
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dlevelofdetailloader_p_p.h"
+#include <Qt3DRender/qlevelofdetailboundingsphere.h>
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DQuick/private/quick3dentityloader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Extras {
+namespace Quick {
+
+Quick3DLevelOfDetailLoaderPrivate::Quick3DLevelOfDetailLoaderPrivate()
+ : QEntityPrivate()
+ , m_loader(new Qt3DCore::Quick::Quick3DEntityLoader)
+ , m_lod(new Qt3DRender::QLevelOfDetail)
+{
+}
+
+Quick3DLevelOfDetailLoader::Quick3DLevelOfDetailLoader(QNode *parent)
+ : QEntity(*new Quick3DLevelOfDetailLoaderPrivate, parent)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ d->m_loader->setParent(this);
+ d->m_loader->addComponent(d->m_lod);
+
+ connect(d->m_lod, &Qt3DRender::QLevelOfDetail::cameraChanged,
+ this, &Quick3DLevelOfDetailLoader::cameraChanged);
+ connect(d->m_lod, &Qt3DRender::QLevelOfDetail::currentIndexChanged,
+ this, &Quick3DLevelOfDetailLoader::currentIndexChanged);
+ connect(d->m_lod, &Qt3DRender::QLevelOfDetail::thresholdTypeChanged,
+ this, &Quick3DLevelOfDetailLoader::thresholdTypeChanged);
+ connect(d->m_lod, &Qt3DRender::QLevelOfDetail::thresholdsChanged,
+ this, &Quick3DLevelOfDetailLoader::thresholdsChanged);
+ connect(d->m_lod, &Qt3DRender::QLevelOfDetail::volumeOverrideChanged,
+ this, &Quick3DLevelOfDetailLoader::volumeOverrideChanged);
+ connect(d->m_loader, &Qt3DCore::Quick::Quick3DEntityLoader::entityChanged,
+ this, &Quick3DLevelOfDetailLoader::entityChanged);
+ connect(d->m_loader, &Qt3DCore::Quick::Quick3DEntityLoader::sourceChanged,
+ this, &Quick3DLevelOfDetailLoader::sourceChanged);
+
+ connect(this, &Quick3DLevelOfDetailLoader::enabledChanged,
+ d->m_lod, &Qt3DRender::QLevelOfDetail::setEnabled);
+
+ auto applyCurrentSource = [this] {
+ Q_D(Quick3DLevelOfDetailLoader);
+ const auto index = currentIndex();
+ if (index >= 0 && index < d->m_sources.size())
+ d->m_loader->setSource(d->m_sources.at(index).toUrl());
+ };
+
+ connect(this, &Quick3DLevelOfDetailLoader::sourcesChanged,
+ this, applyCurrentSource);
+ connect(this, &Quick3DLevelOfDetailLoader::currentIndexChanged,
+ this, applyCurrentSource);
+}
+
+QVariantList Quick3DLevelOfDetailLoader::sources() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_sources;
+}
+
+void Quick3DLevelOfDetailLoader::setSources(const QVariantList &sources)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ if (d->m_sources != sources) {
+ d->m_sources = sources;
+ emit sourcesChanged();
+ }
+}
+
+Qt3DRender::QCamera *Quick3DLevelOfDetailLoader::camera() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_lod->camera();
+}
+
+void Quick3DLevelOfDetailLoader::setCamera(Qt3DRender::QCamera *camera)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ d->m_lod->setCamera(camera);
+}
+
+int Quick3DLevelOfDetailLoader::currentIndex() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_lod->currentIndex();
+}
+
+void Quick3DLevelOfDetailLoader::setCurrentIndex(int currentIndex)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ d->m_lod->setCurrentIndex(currentIndex);
+}
+
+Qt3DRender::QLevelOfDetail::ThresholdType Quick3DLevelOfDetailLoader::thresholdType() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_lod->thresholdType();
+}
+
+void Quick3DLevelOfDetailLoader::setThresholdType(Qt3DRender::QLevelOfDetail::ThresholdType thresholdType)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ d->m_lod->setThresholdType(thresholdType);
+}
+
+QVector<qreal> Quick3DLevelOfDetailLoader::thresholds() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_lod->thresholds();
+}
+
+void Quick3DLevelOfDetailLoader::setThresholds(const QVector<qreal> &thresholds)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ d->m_lod->setThresholds(thresholds);
+}
+
+Qt3DRender::QLevelOfDetailBoundingSphere Quick3DLevelOfDetailLoader::createBoundingSphere(const QVector3D &center, float radius)
+{
+ return Qt3DRender::QLevelOfDetailBoundingSphere(center, radius);
+}
+
+Qt3DRender::QLevelOfDetailBoundingSphere Quick3DLevelOfDetailLoader::volumeOverride() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_lod->volumeOverride();
+}
+
+void Quick3DLevelOfDetailLoader::setVolumeOverride(const Qt3DRender::QLevelOfDetailBoundingSphere &volumeOverride)
+{
+ Q_D(Quick3DLevelOfDetailLoader);
+ d->m_lod->setVolumeOverride(volumeOverride);
+}
+
+QObject *Quick3DLevelOfDetailLoader::entity() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_loader->entity();
+}
+
+QUrl Quick3DLevelOfDetailLoader::source() const
+{
+ Q_D(const Quick3DLevelOfDetailLoader);
+ return d->m_loader->source();
+}
+
+} // namespace Quick
+} // namespace Extras
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+
diff --git a/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p.h b/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p.h
new file mode 100644
index 000000000..445e7bca6
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_EXTRAS_QUICK_QUICK3DLEVELOFDETAILLOADER_P_H
+#define QT3DEXTRAS_EXTRAS_QUICK_QUICK3DLEVELOFDETAILLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickExtras/private/qt3dquickextras_global_p.h>
+#include <Qt3DCore/qentity.h>
+#include <Qt3DRender/qlevelofdetail.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Extras {
+namespace Quick {
+
+class Quick3DLevelOfDetailLoaderPrivate;
+
+class QT3DQUICKEXTRASSHARED_PRIVATE_EXPORT Quick3DLevelOfDetailLoader : public Qt3DCore::QEntity
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariantList sources READ sources WRITE setSources NOTIFY sourcesChanged)
+
+ Q_PROPERTY(Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(Qt3DRender::QLevelOfDetail::ThresholdType thresholdType READ thresholdType WRITE setThresholdType NOTIFY thresholdTypeChanged)
+ Q_PROPERTY(QVector<qreal> thresholds READ thresholds WRITE setThresholds NOTIFY thresholdsChanged)
+ Q_PROPERTY(Qt3DRender::QLevelOfDetailBoundingSphere volumeOverride READ volumeOverride WRITE setVolumeOverride NOTIFY volumeOverrideChanged)
+
+ Q_PROPERTY(QObject *entity READ entity NOTIFY entityChanged)
+ Q_PROPERTY(QUrl source READ source NOTIFY sourceChanged)
+public:
+ explicit Quick3DLevelOfDetailLoader(QNode *parent = 0);
+
+ QVariantList sources() const;
+ void setSources(const QVariantList &sources);
+
+ Qt3DRender::QCamera *camera() const;
+ void setCamera(Qt3DRender::QCamera *camera);
+ int currentIndex() const;
+ void setCurrentIndex(int currentIndex);
+ Qt3DRender::QLevelOfDetail::ThresholdType thresholdType() const;
+ void setThresholdType(Qt3DRender::QLevelOfDetail::ThresholdType thresholdType);
+ QVector<qreal> thresholds() const;
+ void setThresholds(const QVector<qreal> &thresholds);
+ Qt3DRender::QLevelOfDetailBoundingSphere volumeOverride() const;
+ void setVolumeOverride(const Qt3DRender::QLevelOfDetailBoundingSphere &volumeOverride);
+
+ Q_INVOKABLE Qt3DRender::QLevelOfDetailBoundingSphere createBoundingSphere(const QVector3D &center, float radius);
+
+ QObject *entity() const;
+ QUrl source() const;
+
+Q_SIGNALS:
+ void sourcesChanged();
+ void cameraChanged();
+ void currentIndexChanged();
+ void thresholdTypeChanged();
+ void thresholdsChanged();
+ void volumeOverrideChanged();
+ void entityChanged();
+ void sourceChanged();
+
+private:
+ Q_DECLARE_PRIVATE(Quick3DLevelOfDetailLoader)
+};
+
+} // namespace Quick
+} // namespace Extras
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_EXTRAS_QUICK_QUICK3DLEVELOFDETAILLOADER_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p_p.h b/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p_p.h
new file mode 100644
index 000000000..b123ea30b
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dlevelofdetailloader_p_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_EXTRAS_QUICK_QUICK3DLEVELOFDETAILLOADER_P_P_H
+#define QT3DEXTRAS_EXTRAS_QUICK_QUICK3DLEVELOFDETAILLOADER_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "quick3dlevelofdetailloader_p.h"
+#include <Qt3DCore/private/qentity_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+namespace Quick {
+class Quick3DEntityLoader;
+}
+}
+
+namespace Qt3DExtras {
+namespace Extras {
+namespace Quick {
+
+class Quick3DLevelOfDetailLoaderPrivate : public Qt3DCore::QEntityPrivate
+{
+public:
+ Quick3DLevelOfDetailLoaderPrivate();
+
+ Q_DECLARE_PUBLIC(Quick3DLevelOfDetailLoader)
+
+ QVariantList m_sources;
+ Qt3DCore::Quick::Quick3DEntityLoader *m_loader;
+ Qt3DRender::QLevelOfDetail *m_lod;
+};
+
+} // namespace Quick
+} // namespace Extras
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_EXTRAS_QUICK_QUICK3DLEVELOFDETAILLOADER_P_P_H
diff --git a/src/render/frontend/qboundingsphere_p.h b/src/quick3d/quick3dextras/qt3dquickextras_global_p.h
index 171e4440f..524393743 100644
--- a/src/render/frontend/qboundingsphere_p.h
+++ b/src/quick3d/quick3dextras/qt3dquickextras_global_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_QBOUNDINGSPHERE_P_H
-#define QT3DRENDER_QBOUNDINGSPHERE_P_H
+#ifndef QT3DQUICKEXTRAS_GLOBAL_P_H
+#define QT3DQUICKEXTRAS_GLOBAL_P_H
//
// W A R N I N G
@@ -51,26 +51,13 @@
// We mean it.
//
-#include <private/qobject_p.h>
-#include <qboundingsphere.h>
+#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <QtQml/qqml.h>
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-class QT3DRENDERSHARED_EXPORT QBoundingSpherePrivate : public QObjectPrivate
-{
-public:
- QBoundingSpherePrivate();
+#define QT3DQUICKEXTRASSHARED_PRIVATE_EXPORT QT3DQUICKEXTRASSHARED_EXPORT
- Q_DECLARE_PUBLIC(QBoundingSphere)
-
- QVector3D m_center;
- float m_radius;
-};
-
-} // namespace Qt3DRender
+QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-#endif // QT3DRENDER_QBOUNDINGSPHERE_P_H
+#endif // QT3DQUICKEXTRAS_GLOBAL_P_H
diff --git a/src/quick3d/quick3dextras/qt3dquickwindow.cpp b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
index 8a7921d8e..91773bb66 100644
--- a/src/quick3d/quick3dextras/qt3dquickwindow.cpp
+++ b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
@@ -49,21 +49,23 @@
****************************************************************************/
#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include "qt3dquickwindow_p.h"
#include <Qt3DQuick/QQmlAspectEngine>
-#include <Qt3DRender/qcamera.h>
-#include <Qt3DRender/qrenderaspect.h>
-#include <Qt3DRender/qrendersurfaceselector.h>
-#include <Qt3DRender/private/qrendersurfaceselector_p.h>
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
#include <Qt3DInput/qinputaspect.h>
#include <Qt3DInput/qinputsettings.h>
#include <Qt3DLogic/qlogicaspect.h>
-
-#include <QQmlContext>
-#include <qqmlincubator.h>
-#include <QGuiApplication>
-#include <QScreen>
-
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DRender/qrenderaspect.h>
+#include <Qt3DRender/qrendersurfaceselector.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
#include <QtGui/qopenglcontext.h>
+#include <QtQml/QQmlContext>
+#include <QtQml/qqmlincubator.h>
+
+#include <Qt3DQuickExtras/private/qt3dquickwindowlogging_p.h>
+#include <Qt3DRender/private/qrendersurfaceselector_p.h>
QT_BEGIN_NAMESPACE
@@ -95,16 +97,21 @@ private:
} // anonymous
-Qt3DQuickWindow::Qt3DQuickWindow(QWindow *parent)
- : QWindow(parent)
- , m_engine(nullptr)
+Qt3DQuickWindowPrivate::Qt3DQuickWindowPrivate()
+ : m_engine(nullptr)
, m_renderAspect(nullptr)
, m_inputAspect(nullptr)
, m_logicAspect(nullptr)
, m_initialized(false)
- , m_cameraAspectRatioMode(AutomaticAspectRatio)
+ , m_cameraAspectRatioMode(Qt3DQuickWindow::AutomaticAspectRatio)
, m_incubationController(nullptr)
{
+}
+
+Qt3DQuickWindow::Qt3DQuickWindow(QWindow *parent)
+ : QWindow(*new Qt3DQuickWindowPrivate(), parent)
+{
+ Q_D(Qt3DQuickWindow);
setSurfaceType(QSurface::OpenGLSurface);
resize(1024, 768);
@@ -123,80 +130,88 @@ Qt3DQuickWindow::Qt3DQuickWindow(QWindow *parent)
format.setStencilBufferSize(8);
setFormat(format);
QSurfaceFormat::setDefaultFormat(format);
- create();
- m_engine.reset(new Qt3DCore::Quick::QQmlAspectEngine);
- m_renderAspect = new Qt3DRender::QRenderAspect;
- m_inputAspect = new Qt3DInput::QInputAspect;
- m_logicAspect = new Qt3DLogic::QLogicAspect;
+ d->m_engine = new Qt3DCore::Quick::QQmlAspectEngine;
+ d->m_renderAspect = new Qt3DRender::QRenderAspect;
+ d->m_inputAspect = new Qt3DInput::QInputAspect;
+ d->m_logicAspect = new Qt3DLogic::QLogicAspect;
- m_engine->aspectEngine()->registerAspect(m_renderAspect);
- m_engine->aspectEngine()->registerAspect(m_inputAspect);
- m_engine->aspectEngine()->registerAspect(m_logicAspect);
+ d->m_engine->aspectEngine()->registerAspect(d->m_renderAspect);
+ d->m_engine->aspectEngine()->registerAspect(d->m_inputAspect);
+ d->m_engine->aspectEngine()->registerAspect(d->m_logicAspect);
}
Qt3DQuickWindow::~Qt3DQuickWindow()
{
+ Q_D(Qt3DQuickWindow);
+ delete d->m_engine;
}
void Qt3DQuickWindow::registerAspect(Qt3DCore::QAbstractAspect *aspect)
{
Q_ASSERT(!isVisible());
- m_engine->aspectEngine()->registerAspect(aspect);
+ Q_D(Qt3DQuickWindow);
+ d->m_engine->aspectEngine()->registerAspect(aspect);
}
void Qt3DQuickWindow::registerAspect(const QString &name)
{
Q_ASSERT(!isVisible());
- m_engine->aspectEngine()->registerAspect(name);
+ Q_D(Qt3DQuickWindow);
+ d->m_engine->aspectEngine()->registerAspect(name);
}
void Qt3DQuickWindow::setSource(const QUrl &source)
{
- m_source = source;
+ Q_D(Qt3DQuickWindow);
+ d->m_source = source;
}
Qt3DCore::Quick::QQmlAspectEngine *Qt3DQuickWindow::engine() const
{
- return m_engine.data();
+ Q_D(const Qt3DQuickWindow);
+ return d->m_engine;
}
void Qt3DQuickWindow::setCameraAspectRatioMode(CameraAspectRatioMode mode)
{
- if (m_cameraAspectRatioMode == mode)
+ Q_D(Qt3DQuickWindow);
+ if (d->m_cameraAspectRatioMode == mode)
return;
- m_cameraAspectRatioMode = mode;
+ d->m_cameraAspectRatioMode = mode;
setCameraAspectModeHelper();
emit cameraAspectRatioModeChanged(mode);
}
Qt3DQuickWindow::CameraAspectRatioMode Qt3DQuickWindow::cameraAspectRatioMode() const
{
- return m_cameraAspectRatioMode;
+ Q_D(const Qt3DQuickWindow);
+ return d->m_cameraAspectRatioMode;
}
void Qt3DQuickWindow::showEvent(QShowEvent *e)
{
- if (!m_initialized) {
+ Q_D(Qt3DQuickWindow);
+ if (!d->m_initialized) {
// Connect to the QQmlAspectEngine's statusChanged signal so that when the QML is loaded
// and th eobjects hav ebeen instantiated, but before we set them on the QAspectEngine we
// can swoop in and set the window surface and camera on the framegraph and ensure the camera
// respects the window's aspect ratio
- connect(m_engine.data(), &Qt3DCore::Quick::QQmlAspectEngine::sceneCreated,
+ connect(d->m_engine, &Qt3DCore::Quick::QQmlAspectEngine::sceneCreated,
this, &Qt3DQuickWindow::onSceneCreated);
- m_engine->setSource(m_source);
+ d->m_engine->setSource(d->m_source);
// Set the QQmlIncubationController on the window
// to benefit from asynchronous incubation
- if (!m_incubationController)
- m_incubationController = new Qt3DQuickWindowIncubationController(this);
+ if (!d->m_incubationController)
+ d->m_incubationController = new Qt3DQuickWindowIncubationController(this);
- m_engine->qmlEngine()->setIncubationController(m_incubationController);
+ d->m_engine->qmlEngine()->setIncubationController(d->m_incubationController);
- m_initialized = true;
+ d->m_initialized = true;
}
QWindow::showEvent(e);
}
@@ -204,17 +219,18 @@ void Qt3DQuickWindow::showEvent(QShowEvent *e)
void Qt3DQuickWindow::onSceneCreated(QObject *rootObject)
{
Q_ASSERT(rootObject);
+ Q_D(Qt3DQuickWindow);
setWindowSurface(rootObject);
- if (m_cameraAspectRatioMode == AutomaticAspectRatio) {
+ if (d->m_cameraAspectRatioMode == AutomaticAspectRatio) {
// Set aspect ratio of first camera to match the window
QList<Qt3DRender::QCamera *> cameras
= rootObject->findChildren<Qt3DRender::QCamera *>();
if (cameras.isEmpty()) {
- qWarning() << "No camera found";
+ qCDebug(QuickWindow) << "No camera found";
} else {
- m_camera = cameras.first();
+ d->m_camera = cameras.first();
setCameraAspectModeHelper();
}
}
@@ -224,7 +240,7 @@ void Qt3DQuickWindow::onSceneCreated(QObject *rootObject)
if (inputSettings) {
inputSettings->setEventSource(this);
} else {
- qWarning() << "No Input Settings found, keyboard and mouse events won't be handled";
+ qCDebug(QuickWindow) << "No Input Settings found, keyboard and mouse events won't be handled";
}
}
@@ -237,7 +253,8 @@ void Qt3DQuickWindow::setWindowSurface(QObject *rootObject)
void Qt3DQuickWindow::setCameraAspectModeHelper()
{
- switch (m_cameraAspectRatioMode) {
+ Q_D(Qt3DQuickWindow);
+ switch (d->m_cameraAspectRatioMode) {
case AutomaticAspectRatio:
connect(this, &QWindow::widthChanged, this, &Qt3DQuickWindow::updateCameraAspectRatio);
connect(this, &QWindow::heightChanged, this, &Qt3DQuickWindow::updateCameraAspectRatio);
@@ -253,9 +270,10 @@ void Qt3DQuickWindow::setCameraAspectModeHelper()
void Qt3DQuickWindow::updateCameraAspectRatio()
{
- if (m_camera) {
- m_camera->setAspectRatio(static_cast<float>(width()) /
- static_cast<float>(height()));
+ Q_D(Qt3DQuickWindow);
+ if (d->m_camera) {
+ d->m_camera->setAspectRatio(static_cast<float>(width()) /
+ static_cast<float>(height()));
}
}
diff --git a/src/quick3d/quick3dextras/qt3dquickwindow.h b/src/quick3d/quick3dextras/qt3dquickwindow.h
index a8703093e..0880fc160 100644
--- a/src/quick3d/quick3dextras/qt3dquickwindow.h
+++ b/src/quick3d/quick3dextras/qt3dquickwindow.h
@@ -52,9 +52,9 @@
#define QT3DEXTRAS_QUICK_QT3DQUICKWINDOW_H
#include <Qt3DQuickExtras/qt3dquickextras_global.h>
-#include <QQuickWindow>
+#include <QtCore/QUrl>
#include <QtCore/qpointer.h>
-#include <QUrl>
+#include <QtQuick/QQuickWindow>
QT_BEGIN_NAMESPACE
@@ -84,6 +84,7 @@ namespace Qt3DExtras {
namespace Quick {
+class Qt3DQuickWindowPrivate;
class QT3DQUICKEXTRASSHARED_EXPORT Qt3DQuickWindow : public QWindow
{
@@ -121,18 +122,7 @@ private:
void setCameraAspectModeHelper();
void updateCameraAspectRatio();
- QScopedPointer<Qt3DCore::Quick::QQmlAspectEngine> m_engine;
-
- // Aspects
- Qt3DRender::QRenderAspect *m_renderAspect;
- Qt3DInput::QInputAspect *m_inputAspect;
- Qt3DLogic::QLogicAspect *m_logicAspect;
-
- QUrl m_source;
- bool m_initialized;
- QPointer<Qt3DRender::QCamera> m_camera;
- CameraAspectRatioMode m_cameraAspectRatioMode;
- QQmlIncubationController *m_incubationController;
+ Q_DECLARE_PRIVATE(Qt3DQuickWindow)
};
} // Quick
diff --git a/src/quick3d/quick3dextras/qt3dquickwindow_p.h b/src/quick3d/quick3dextras/qt3dquickwindow_p.h
new file mode 100644
index 000000000..f2f8d0492
--- /dev/null
+++ b/src/quick3d/quick3dextras/qt3dquickwindow_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DQUICKWINDOW_P_H
+#define QT3DQUICKWINDOW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qwindow_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+namespace Quick {
+
+class Qt3DQuickWindowPrivate : public QWindowPrivate
+{
+public:
+ Qt3DQuickWindowPrivate();
+
+ Qt3DCore::Quick::QQmlAspectEngine *m_engine;
+
+ // Aspects
+ Qt3DRender::QRenderAspect *m_renderAspect;
+ Qt3DInput::QInputAspect *m_inputAspect;
+ Qt3DLogic::QLogicAspect *m_logicAspect;
+
+ QUrl m_source;
+ bool m_initialized;
+ QPointer<Qt3DRender::QCamera> m_camera;
+ Qt3DQuickWindow::CameraAspectRatioMode m_cameraAspectRatioMode;
+ QQmlIncubationController *m_incubationController;
+
+ Q_DECLARE_PUBLIC(Qt3DQuickWindow)
+};
+
+} // Quick
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DQUICKWINDOW_P_H
diff --git a/src/quick3d/quick3dextras/qt3dquickwindowlogging.cpp b/src/quick3d/quick3dextras/qt3dquickwindowlogging.cpp
new file mode 100644
index 000000000..cd74d6b3e
--- /dev/null
+++ b/src/quick3d/quick3dextras/qt3dquickwindowlogging.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquickwindowlogging_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+Q_LOGGING_CATEGORY(QuickWindow, "Qt3D.QuickWindow", QtWarningMsg)
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/qt3dquickwindowlogging_p.h b/src/quick3d/quick3dextras/qt3dquickwindowlogging_p.h
new file mode 100644
index 000000000..75a774dda
--- /dev/null
+++ b/src/quick3d/quick3dextras/qt3dquickwindowlogging_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QUICKWINDOWLOGGING_P_H
+#define QT3D_QUICKWINDOWLOGGING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+Q_DECLARE_LOGGING_CATEGORY(QuickWindow)
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3D_QUICKWINDOWLOGGING_P_H
diff --git a/src/quick3d/quick3dextras/quick3dextras.pro b/src/quick3d/quick3dextras/quick3dextras.pro
index 4f103765c..976430eba 100644
--- a/src/quick3d/quick3dextras/quick3dextras.pro
+++ b/src/quick3d/quick3dextras/quick3dextras.pro
@@ -1,7 +1,8 @@
TARGET = Qt3DQuickExtras
MODULE = 3dquickextras
-QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3drender 3drender-private 3dlogic 3dextras
+QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3dquick-private 3drender 3drender-private 3dlogic 3dextras
+
CONFIG -= precompile_header
# Qt3D is free of Q_FOREACH - make sure it stays that way:
@@ -13,12 +14,15 @@ gcov {
}
SOURCES += \
- qt3dquickwindow.cpp
-
+ qt3dquickwindow.cpp \
+ qt3dquickwindowlogging.cpp
HEADERS += \
qt3dquickextras_global.h \
- qt3dquickwindow.h
+ qt3dquickextras_global_p.h \
+ qt3dquickwindow.h \
+ qt3dquickwindow_p.h \
+ qt3dquickwindowlogging_p.h
# otherwise mingw headers do not declare common functions like ::strcasecmp
win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
diff --git a/src/quick3d/quick3dinput/items/quick3daction.cpp b/src/quick3d/quick3dinput/items/quick3daction.cpp
index b3b99e504..33752c6e0 100644
--- a/src/quick3d/quick3dinput/items/quick3daction.cpp
+++ b/src/quick3d/quick3dinput/items/quick3daction.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3daction_p.h"
+#include <Qt3DQuickInput/private/quick3daction_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3daction_p.h b/src/quick3d/quick3dinput/items/quick3daction_p.h
index 8394f9c48..86e52eb33 100644
--- a/src/quick3d/quick3dinput/items/quick3daction_p.h
+++ b/src/quick3d/quick3dinput/items/quick3daction_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
#include <Qt3DInput/QAction>
#include <Qt3DInput/QAbstractActionInput>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3daxis.cpp b/src/quick3d/quick3dinput/items/quick3daxis.cpp
index 2857e4c48..966aa250d 100644
--- a/src/quick3d/quick3dinput/items/quick3daxis.cpp
+++ b/src/quick3d/quick3dinput/items/quick3daxis.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3daxis_p.h"
+#include <Qt3DQuickInput/private/quick3daxis_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3daxis_p.h b/src/quick3d/quick3dinput/items/quick3daxis_p.h
index 400bd5ea0..58ba32ae7 100644
--- a/src/quick3d/quick3dinput/items/quick3daxis_p.h
+++ b/src/quick3d/quick3dinput/items/quick3daxis_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
-#include <Qt3DInput/QAxis>
#include <Qt3DInput/QAbstractAxisInput>
-#include <QQmlListProperty>
+#include <Qt3DInput/QAxis>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dinputchord.cpp b/src/quick3d/quick3dinput/items/quick3dinputchord.cpp
index 0d214a5ec..16a5e8181 100644
--- a/src/quick3d/quick3dinput/items/quick3dinputchord.cpp
+++ b/src/quick3d/quick3dinput/items/quick3dinputchord.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dinputchord_p.h"
+#include <Qt3DQuickInput/private/quick3dinputchord_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dinputchord_p.h b/src/quick3d/quick3dinput/items/quick3dinputchord_p.h
index d9759b856..3380fefa4 100644
--- a/src/quick3d/quick3dinput/items/quick3dinputchord_p.h
+++ b/src/quick3d/quick3dinput/items/quick3dinputchord_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
#include <Qt3DInput/qinputchord.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dinputsequence.cpp b/src/quick3d/quick3dinput/items/quick3dinputsequence.cpp
index 02539443e..4f4eed9d3 100644
--- a/src/quick3d/quick3dinput/items/quick3dinputsequence.cpp
+++ b/src/quick3d/quick3dinput/items/quick3dinputsequence.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dinputsequence_p.h"
+#include <Qt3DQuickInput/private/quick3dinputsequence_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dinputsequence_p.h b/src/quick3d/quick3dinput/items/quick3dinputsequence_p.h
index ccf872675..aea671f12 100644
--- a/src/quick3d/quick3dinput/items/quick3dinputsequence_p.h
+++ b/src/quick3d/quick3dinput/items/quick3dinputsequence_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
#include <Qt3DInput/qinputsequence.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dlogicaldevice.cpp b/src/quick3d/quick3dinput/items/quick3dlogicaldevice.cpp
index 72be7e7ac..50218dd25 100644
--- a/src/quick3d/quick3dinput/items/quick3dlogicaldevice.cpp
+++ b/src/quick3d/quick3dinput/items/quick3dlogicaldevice.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dlogicaldevice_p.h"
+#include <Qt3DQuickInput/private/quick3dlogicaldevice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dlogicaldevice_p.h b/src/quick3d/quick3dinput/items/quick3dlogicaldevice_p.h
index 5b3b36039..050d81ab8 100644
--- a/src/quick3d/quick3dinput/items/quick3dlogicaldevice_p.h
+++ b/src/quick3d/quick3dinput/items/quick3dlogicaldevice_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
#include <Qt3DInput/QAxis>
#include <Qt3DInput/QAction>
#include <Qt3DInput/QLogicalDevice>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dphysicaldevice.cpp b/src/quick3d/quick3dinput/items/quick3dphysicaldevice.cpp
index ead311135..5c8d55b54 100644
--- a/src/quick3d/quick3dinput/items/quick3dphysicaldevice.cpp
+++ b/src/quick3d/quick3dinput/items/quick3dphysicaldevice.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dphysicaldevice_p.h"
+#include <Qt3DQuickInput/private/quick3dphysicaldevice_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/items/quick3dphysicaldevice_p.h b/src/quick3d/quick3dinput/items/quick3dphysicaldevice_p.h
index 9a97d152c..b4c96ac14 100644
--- a/src/quick3d/quick3dinput/items/quick3dphysicaldevice_p.h
+++ b/src/quick3d/quick3dinput/items/quick3dphysicaldevice_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <QObject>
-#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/qaxissetting.h>
-#include <QQmlListProperty>
+#include <QtCore/QObject>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/qt3dquickinput_global.cpp b/src/quick3d/quick3dinput/qt3dquickinput_global.cpp
index dd84f9fa4..724a5db86 100644
--- a/src/quick3d/quick3dinput/qt3dquickinput_global.cpp
+++ b/src/quick3d/quick3dinput/qt3dquickinput_global.cpp
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#include "qt3dquickinput_global_p.h"
-#include "qt3dquickinputnodefactory_p.h"
+#include <Qt3DQuickInput/private/qt3dquickinput_global_p.h>
+#include <Qt3DQuickInput/private/qt3dquickinputnodefactory_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/qt3dquickinputnodefactory.cpp b/src/quick3d/quick3dinput/qt3dquickinputnodefactory.cpp
index 8f9fe81ec..b158e30d5 100644
--- a/src/quick3d/quick3dinput/qt3dquickinputnodefactory.cpp
+++ b/src/quick3d/quick3dinput/qt3dquickinputnodefactory.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qt3dquickinputnodefactory_p.h"
+#include <Qt3DQuickInput/private/qt3dquickinputnodefactory_p.h>
#include <QtQml/private/qqmlmetatype_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3dinput/qt3dquickinputnodefactory_p.h b/src/quick3d/quick3dinput/qt3dquickinputnodefactory_p.h
index 3473cf038..f4d4aee27 100644
--- a/src/quick3d/quick3dinput/qt3dquickinputnodefactory_p.h
+++ b/src/quick3d/quick3dinput/qt3dquickinputnodefactory_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qabstractnodefactory_p.h>
#include <QtCore/qhash.h>
+#include <Qt3DCore/private/qabstractnodefactory_p.h>
+
QT_BEGIN_NAMESPACE
class QQmlType;
diff --git a/src/quick3d/quick3drender/items/quick3dbuffer.cpp b/src/quick3d/quick3drender/items/quick3dbuffer.cpp
index d36ce8341..362e60328 100644
--- a/src/quick3d/quick3drender/items/quick3dbuffer.cpp
+++ b/src/quick3d/quick3drender/items/quick3dbuffer.cpp
@@ -37,10 +37,10 @@
**
****************************************************************************/
-#include <QJSValue>
-#include <QQmlEngine>
+#include <QtQml/QJSValue>
+#include <QtQml/QQmlEngine>
-#include "quick3dbuffer_p.h"
+#include <Qt3DQuickRender/private/quick3dbuffer_p.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qjsvalue_p.h>
#include <QtQml/private/qv4typedarray_p.h>
diff --git a/src/quick3d/quick3drender/items/quick3dbuffer_p.h b/src/quick3d/quick3drender/items/quick3dbuffer_p.h
index d8dbafcb2..712e11078 100644
--- a/src/quick3d/quick3drender/items/quick3dbuffer_p.h
+++ b/src/quick3d/quick3drender/items/quick3dbuffer_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/QBuffer>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+
QT_BEGIN_NAMESPACE
class QQmlEngine;
diff --git a/src/quick3d/quick3drender/items/quick3deffect.cpp b/src/quick3d/quick3drender/items/quick3deffect.cpp
index 9d4ce934a..fa82c6eff 100644
--- a/src/quick3d/quick3drender/items/quick3deffect.cpp
+++ b/src/quick3d/quick3drender/items/quick3deffect.cpp
@@ -37,9 +37,10 @@
**
****************************************************************************/
-#include "quick3deffect_p.h"
#include <Qt3DRender/qeffect.h>
+#include <Qt3DQuickRender/private/quick3deffect_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/quick3drender/items/quick3deffect_p.h b/src/quick3d/quick3drender/items/quick3deffect_p.h
index 50152e2af..3b778563d 100644
--- a/src/quick3d/quick3drender/items/quick3deffect_p.h
+++ b/src/quick3d/quick3drender/items/quick3deffect_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <QQmlListProperty>
#include <Qt3DRender/qeffect.h>
#include <Qt3DRender/qtechnique.h>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dgeometry.cpp b/src/quick3d/quick3drender/items/quick3dgeometry.cpp
index 84c02d7c9..3f70ea572 100644
--- a/src/quick3d/quick3drender/items/quick3dgeometry.cpp
+++ b/src/quick3d/quick3drender/items/quick3dgeometry.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dgeometry_p.h"
+#include <Qt3DQuickRender/private/quick3dgeometry_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dgeometry_p.h b/src/quick3d/quick3drender/items/quick3dgeometry_p.h
index 4c020b0e2..6bf7faf58 100644
--- a/src/quick3d/quick3drender/items/quick3dgeometry_p.h
+++ b/src/quick3d/quick3drender/items/quick3dgeometry_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <QQmlListProperty>
#include <Qt3DRender/QGeometry>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dlayerfilter.cpp b/src/quick3d/quick3drender/items/quick3dlayerfilter.cpp
index 6f7efcd23..951b4f82f 100644
--- a/src/quick3d/quick3drender/items/quick3dlayerfilter.cpp
+++ b/src/quick3d/quick3drender/items/quick3dlayerfilter.cpp
@@ -37,9 +37,10 @@
**
****************************************************************************/
-#include "quick3dlayerfilter_p.h"
#include <Qt3DRender/qtexture.h>
+#include <Qt3DQuickRender/private/quick3dlayerfilter_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/quick3drender/items/quick3dlayerfilter_p.h b/src/quick3d/quick3drender/items/quick3dlayerfilter_p.h
index b2e7e2d11..f59be2787 100644
--- a/src/quick3d/quick3drender/items/quick3dlayerfilter_p.h
+++ b/src/quick3d/quick3drender/items/quick3dlayerfilter_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qlayerfilter.h>
#include <Qt3DRender/qlayer.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dmaterial.cpp b/src/quick3d/quick3drender/items/quick3dmaterial.cpp
index 50b064bc2..3dfbec83e 100644
--- a/src/quick3d/quick3drender/items/quick3dmaterial.cpp
+++ b/src/quick3d/quick3drender/items/quick3dmaterial.cpp
@@ -37,9 +37,10 @@
**
****************************************************************************/
-#include "quick3dmaterial_p.h"
#include <Qt3DRender/qtexture.h>
+#include <Qt3DQuickRender/private/quick3dmaterial_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/quick3drender/items/quick3dmaterial_p.h b/src/quick3d/quick3drender/items/quick3dmaterial_p.h
index 48b60df62..646e3b154 100644
--- a/src/quick3d/quick3drender/items/quick3dmaterial_p.h
+++ b/src/quick3d/quick3drender/items/quick3dmaterial_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qmaterial.h>
#include <Qt3DRender/qparameter.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dmemorybarrier.cpp b/src/quick3d/quick3drender/items/quick3dmemorybarrier.cpp
index a899d36c5..0754a0cf5 100644
--- a/src/quick3d/quick3drender/items/quick3dmemorybarrier.cpp
+++ b/src/quick3d/quick3drender/items/quick3dmemorybarrier.cpp
@@ -55,16 +55,16 @@ Quick3DMemoryBarrier::~Quick3DMemoryBarrier()
{
}
-void Quick3DMemoryBarrier::setBarrierTypesInt(int barrierTypes)
+void Quick3DMemoryBarrier::setWaitFor(int barrierTypes)
{
- QMemoryBarrier::BarrierTypes types(QMemoryBarrier::AllBarrier);
+ QMemoryBarrier::Operations types(QMemoryBarrier::All);
types &= barrierTypes; // Will only keep flags that are actually set
- parentBarrier()->setBarrierTypes(types);
+ parentBarrier()->setWaitOperations(types);
}
-int Quick3DMemoryBarrier::barrierTypesInt() const
+int Quick3DMemoryBarrier::waitFor() const
{
- return QMemoryBarrier::BarrierTypes::Int(parentBarrier()->barrierTypes());
+ return QMemoryBarrier::Operations::Int(parentBarrier()->waitOperations());
}
} // namespace Quick
diff --git a/src/quick3d/quick3drender/items/quick3dmemorybarrier_p.h b/src/quick3d/quick3drender/items/quick3dmemorybarrier_p.h
index 5e402f006..ab8f72a76 100644
--- a/src/quick3d/quick3drender/items/quick3dmemorybarrier_p.h
+++ b/src/quick3d/quick3drender/items/quick3dmemorybarrier_p.h
@@ -65,15 +65,15 @@ namespace Quick {
class QT3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DMemoryBarrier : public QObject
{
Q_OBJECT
- Q_PROPERTY(int barrierTypes READ barrierTypesInt WRITE setBarrierTypesInt)
+ Q_PROPERTY(int waitFor READ waitFor WRITE setWaitFor)
public:
explicit Quick3DMemoryBarrier(QObject *parent = nullptr);
~Quick3DMemoryBarrier();
inline QMemoryBarrier *parentBarrier() const { return qobject_cast<QMemoryBarrier*>(parent()); }
- void setBarrierTypesInt(int barrierTypes);
- int barrierTypesInt() const;
+ void setWaitFor(int waitOperations);
+ int waitFor() const;
};
} // namespace Quick
diff --git a/src/quick3d/quick3drender/items/quick3dparameter.cpp b/src/quick3d/quick3drender/items/quick3dparameter.cpp
index 783f152c1..2ef95a4d4 100644
--- a/src/quick3d/quick3drender/items/quick3dparameter.cpp
+++ b/src/quick3d/quick3drender/items/quick3dparameter.cpp
@@ -37,10 +37,10 @@
**
****************************************************************************/
-#include <QJSValue>
-#include <QJSValueIterator>
+#include <QtQml/QJSValue>
+#include <QtQml/QJSValueIterator>
-#include "quick3dparameter_p_p.h"
+#include <Qt3DQuickRender/private/quick3dparameter_p_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dparameter_p.h b/src/quick3d/quick3drender/items/quick3dparameter_p.h
index 60493973d..948df22a7 100644
--- a/src/quick3d/quick3drender/items/quick3dparameter_p.h
+++ b/src/quick3d/quick3drender/items/quick3dparameter_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qparameter.h>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/quick3drender/items/quick3dparameter_p_p.h b/src/quick3d/quick3drender/items/quick3dparameter_p_p.h
index 0432642f3..2e680b852 100644
--- a/src/quick3d/quick3drender/items/quick3dparameter_p_p.h
+++ b/src/quick3d/quick3drender/items/quick3dparameter_p_p.h
@@ -51,10 +51,10 @@
// We mean it.
//
-#include "quick3dparameter_p.h"
-
+#include <Qt3DQuickRender/private/quick3dparameter_p.h>
#include <Qt3DRender/private/qparameter_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/quick3drender/items/quick3drenderpass.cpp b/src/quick3d/quick3drender/items/quick3drenderpass.cpp
index d5f16fab6..7bd50a0d5 100644
--- a/src/quick3d/quick3drender/items/quick3drenderpass.cpp
+++ b/src/quick3d/quick3drender/items/quick3drenderpass.cpp
@@ -38,7 +38,7 @@
**
****************************************************************************/
-#include "quick3drenderpass_p.h"
+#include <Qt3DQuickRender/private/quick3drenderpass_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drenderpass_p.h b/src/quick3d/quick3drender/items/quick3drenderpass_p.h
index 6ac940e23..c9d2fce59 100644
--- a/src/quick3d/quick3drender/items/quick3drenderpass_p.h
+++ b/src/quick3d/quick3drender/items/quick3drenderpass_p.h
@@ -52,9 +52,10 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qrenderpass.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drenderpassfilter.cpp b/src/quick3d/quick3drender/items/quick3drenderpassfilter.cpp
index 8b51a79ef..0a8fa8a3a 100644
--- a/src/quick3d/quick3drender/items/quick3drenderpassfilter.cpp
+++ b/src/quick3d/quick3drender/items/quick3drenderpassfilter.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3drenderpassfilter_p.h"
+#include <Qt3DQuickRender/private/quick3drenderpassfilter_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drenderpassfilter_p.h b/src/quick3d/quick3drender/items/quick3drenderpassfilter_p.h
index 3acd32270..cab75f4a6 100644
--- a/src/quick3d/quick3drender/items/quick3drenderpassfilter_p.h
+++ b/src/quick3d/quick3drender/items/quick3drenderpassfilter_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <Qt3DQuick/private/quick3dnode_p.h>
-#include <Qt3DRender/qrenderpassfilter.h>
#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qrenderpassfilter.h>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuick/private/quick3dnode_p.h>
#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <QQmlListProperty>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drendertargetoutput.cpp b/src/quick3d/quick3drender/items/quick3drendertargetoutput.cpp
index e3b40243a..024789a4c 100644
--- a/src/quick3d/quick3drender/items/quick3drendertargetoutput.cpp
+++ b/src/quick3d/quick3drender/items/quick3drendertargetoutput.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3drendertargetoutput_p.h"
+#include <Qt3DQuickRender/private/quick3drendertargetoutput_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drendertargetoutput_p.h b/src/quick3d/quick3drender/items/quick3drendertargetoutput_p.h
index 5a2c8ea54..7626a2db7 100644
--- a/src/quick3d/quick3drender/items/quick3drendertargetoutput_p.h
+++ b/src/quick3d/quick3drender/items/quick3drendertargetoutput_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qrendertarget.h>
#include <Qt3DRender/qrendertargetoutput.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drendertargetselector.cpp b/src/quick3d/quick3drender/items/quick3drendertargetselector.cpp
index b61c7ed12..1ace5950a 100644
--- a/src/quick3d/quick3drender/items/quick3drendertargetselector.cpp
+++ b/src/quick3d/quick3drender/items/quick3drendertargetselector.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3drendertargetselector_p.h"
+#include <Qt3DQuickRender/private/quick3drendertargetselector_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3drendertargetselector_p.h b/src/quick3d/quick3drender/items/quick3drendertargetselector_p.h
index a24a6a71f..610ea1a49 100644
--- a/src/quick3d/quick3drender/items/quick3drendertargetselector_p.h
+++ b/src/quick3d/quick3drender/items/quick3drendertargetselector_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qrendertargetoutput.h>
#include <Qt3DRender/qrendertargetselector.h>
-#include <QQmlListProperty>
-#include <QVariantList>
+#include <QtCore/QVariantList>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dscene.cpp b/src/quick3d/quick3drender/items/quick3dscene.cpp
index 4062904f2..af4f44f0e 100644
--- a/src/quick3d/quick3drender/items/quick3dscene.cpp
+++ b/src/quick3d/quick3drender/items/quick3dscene.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dscene_p.h"
+#include <Qt3DQuickRender/private/quick3dscene_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dscene_p.h b/src/quick3d/quick3drender/items/quick3dscene_p.h
index 60c2d2ab5..a7173a6c7 100644
--- a/src/quick3d/quick3drender/items/quick3dscene_p.h
+++ b/src/quick3d/quick3drender/items/quick3dscene_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <Qt3DQuick/private/quick3dentity_p.h>
#include <Qt3DRender/qsceneloader.h>
+#include <Qt3DQuick/private/quick3dentity_p.h>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/quick3d/quick3drender/items/quick3dshaderdata.cpp b/src/quick3d/quick3drender/items/quick3dshaderdata.cpp
index dbf351695..cd6e2a81e 100644
--- a/src/quick3d/quick3drender/items/quick3dshaderdata.cpp
+++ b/src/quick3d/quick3drender/items/quick3dshaderdata.cpp
@@ -37,11 +37,11 @@
**
****************************************************************************/
-#include <Qt3DQuickRender/private/quick3dshaderdataarray_p.h>
-#include <QMetaProperty>
+#include <QtCore/QMetaProperty>
-#include "quick3dshaderdata_p.h"
-#include <private/qshaderdata_p.h>
+#include <Qt3DQuickRender/private/quick3dshaderdataarray_p.h>
+#include <Qt3DQuickRender/private/quick3dshaderdata_p.h>
+#include <Qt3DRender/private/qshaderdata_p.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +53,7 @@ namespace {
const int qjsValueTypeId = qMetaTypeId<QJSValue>();
const int quick3DShaderDataArrayTypeId = qMetaTypeId<Quick3DShaderDataArray*>();
-const int quick3DShaderDataTypeId = qMetaTypeId<Quick3DShaderData*>();
+Q_DECL_UNUSED const int quick3DShaderDataTypeId = qMetaTypeId<Quick3DShaderData*>();
}
@@ -84,11 +84,9 @@ public:
}
}
return innerValues;
- } else if (v.userType() == quick3DShaderDataTypeId) {
- Qt3DCore::QNodeId id;
- QShaderData *shaderData = v.value<Quick3DShaderData *>();
- if (shaderData)
- id = shaderData->id();
+ } else if (v.canConvert<Qt3DCore::QNode*>()) {
+ const auto node = v.value<Qt3DCore::QNode *>();
+ const auto id = Qt3DCore::qIdForNode(node);
return QVariant::fromValue(id);
}
return v;
diff --git a/src/quick3d/quick3drender/items/quick3dshaderdata_p.h b/src/quick3d/quick3drender/items/quick3dshaderdata_p.h
index 15e127b78..207096149 100644
--- a/src/quick3d/quick3drender/items/quick3dshaderdata_p.h
+++ b/src/quick3d/quick3drender/items/quick3dshaderdata_p.h
@@ -51,11 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <Qt3DRender/qshaderdata.h>
+#include <QtQml/QJSValue>
+#include <QtQml/QJSValueIterator>
-#include <QJSValue>
-#include <QJSValueIterator>
+#include <Qt3DRender/qshaderdata.h>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dshaderdataarray.cpp b/src/quick3d/quick3drender/items/quick3dshaderdataarray.cpp
index 21dd2525a..9dac7bbc6 100644
--- a/src/quick3d/quick3drender/items/quick3dshaderdataarray.cpp
+++ b/src/quick3d/quick3drender/items/quick3dshaderdataarray.cpp
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#include "quick3dshaderdataarray_p.h"
-#include <private/qshaderdata_p.h>
+#include <Qt3DQuickRender/private/quick3dshaderdataarray_p.h>
+#include <Qt3DRender/private/qshaderdata_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dshaderdataarray_p.h b/src/quick3d/quick3drender/items/quick3dshaderdataarray_p.h
index 9d33df208..162f402aa 100644
--- a/src/quick3d/quick3drender/items/quick3dshaderdataarray_p.h
+++ b/src/quick3d/quick3drender/items/quick3dshaderdataarray_p.h
@@ -52,9 +52,10 @@
//
#include <Qt3DCore/qnode.h>
+#include <QtQml/QQmlListProperty>
+
#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DQuickRender/private/quick3dshaderdata_p.h>
-#include <QQmlListProperty>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dstateset.cpp b/src/quick3d/quick3drender/items/quick3dstateset.cpp
index d7d74e5ad..468364493 100644
--- a/src/quick3d/quick3drender/items/quick3dstateset.cpp
+++ b/src/quick3d/quick3drender/items/quick3dstateset.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dstateset_p.h"
+#include <Qt3DQuickRender/private/quick3dstateset_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dstateset_p.h b/src/quick3d/quick3drender/items/quick3dstateset_p.h
index 4bb9b6cec..b2e63c066 100644
--- a/src/quick3d/quick3drender/items/quick3dstateset_p.h
+++ b/src/quick3d/quick3drender/items/quick3dstateset_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DRender/qrenderstateset.h>
-#include <QQmlListProperty>
+#include <QtQml/QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dtechnique.cpp b/src/quick3d/quick3drender/items/quick3dtechnique.cpp
index 123050645..0a15c9f7e 100644
--- a/src/quick3d/quick3drender/items/quick3dtechnique.cpp
+++ b/src/quick3d/quick3drender/items/quick3dtechnique.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dtechnique_p.h"
+#include <Qt3DQuickRender/private/quick3dtechnique_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dtechnique_p.h b/src/quick3d/quick3drender/items/quick3dtechnique_p.h
index 203befcb7..9cdfdfefe 100644
--- a/src/quick3d/quick3drender/items/quick3dtechnique_p.h
+++ b/src/quick3d/quick3drender/items/quick3dtechnique_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+#include <QtQml/QQmlListProperty>
#include <Qt3DRender/qtechnique.h>
-#include <QQmlListProperty>
+
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dtechniquefilter.cpp b/src/quick3d/quick3drender/items/quick3dtechniquefilter.cpp
index b27d46c31..2019093c9 100644
--- a/src/quick3d/quick3drender/items/quick3dtechniquefilter.cpp
+++ b/src/quick3d/quick3drender/items/quick3dtechniquefilter.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dtechniquefilter_p.h"
+#include <Qt3DQuickRender/private/quick3dtechniquefilter_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dtechniquefilter_p.h b/src/quick3d/quick3drender/items/quick3dtechniquefilter_p.h
index 27d637e23..2b10bc108 100644
--- a/src/quick3d/quick3drender/items/quick3dtechniquefilter_p.h
+++ b/src/quick3d/quick3drender/items/quick3dtechniquefilter_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <Qt3DRender/qtechniquefilter.h>
#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qtechniquefilter.h>
+#include <QtQml/QQmlListProperty>
+
#include <Qt3DQuick/private/quick3dnode_p.h>
-#include <QQmlListProperty>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dtexture.cpp b/src/quick3d/quick3drender/items/quick3dtexture.cpp
index 9c528996c..7627a3283 100644
--- a/src/quick3d/quick3drender/items/quick3dtexture.cpp
+++ b/src/quick3d/quick3drender/items/quick3dtexture.cpp
@@ -37,8 +37,9 @@
**
****************************************************************************/
-#include "quick3dtexture_p.h"
-#include <QDebug>
+#include <QtCore/QDebug>
+
+#include <Qt3DQuickRender/private/quick3dtexture_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dtexture_p.h b/src/quick3d/quick3drender/items/quick3dtexture_p.h
index a1e2ad6b8..6b0430211 100644
--- a/src/quick3d/quick3drender/items/quick3dtexture_p.h
+++ b/src/quick3d/quick3drender/items/quick3dtexture_p.h
@@ -51,11 +51,11 @@
// We mean it.
//
-#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
-#include <Qt3DQuick/private/quick3dnode_p.h>
#include <Qt3DRender/qtexture.h>
+#include <QtCore/QUrl>
-#include <QUrl>
+#include <Qt3DQuick/private/quick3dnode_p.h>
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dviewport.cpp b/src/quick3d/quick3drender/items/quick3dviewport.cpp
index 5d490018f..3b4bf33f5 100644
--- a/src/quick3d/quick3drender/items/quick3dviewport.cpp
+++ b/src/quick3d/quick3drender/items/quick3dviewport.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quick3dviewport_p.h"
+#include <Qt3DQuickRender/private/quick3dviewport_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/items/quick3dviewport_p.h b/src/quick3d/quick3drender/items/quick3dviewport_p.h
index 877900365..adf0c983f 100644
--- a/src/quick3d/quick3drender/items/quick3dviewport_p.h
+++ b/src/quick3d/quick3drender/items/quick3dviewport_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
+#include <Qt3DRender/qviewport.h>
+
#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
#include <Qt3DQuick/private/quick3dnode_p.h>
-#include <Qt3DRender/qviewport.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/qt3dquickrender_global.cpp b/src/quick3d/quick3drender/qt3dquickrender_global.cpp
index 0706185fe..bf7d68e71 100644
--- a/src/quick3d/quick3drender/qt3dquickrender_global.cpp
+++ b/src/quick3d/quick3drender/qt3dquickrender_global.cpp
@@ -38,8 +38,8 @@
**
****************************************************************************/
-#include "qt3dquickrender_global_p.h"
-#include "qt3dquickrendernodefactory_p.h"
+#include <Qt3DQuickRender/private/qt3dquickrender_global_p.h>
+#include <Qt3DQuickRender/private/qt3dquickrendernodefactory_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/qt3dquickrendernodefactory.cpp b/src/quick3d/quick3drender/qt3dquickrendernodefactory.cpp
index 2d9456d12..f57451379 100644
--- a/src/quick3d/quick3drender/qt3dquickrendernodefactory.cpp
+++ b/src/quick3d/quick3drender/qt3dquickrendernodefactory.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qt3dquickrendernodefactory_p.h"
+#include <Qt3DQuickRender/private/qt3dquickrendernodefactory_p.h>
#include <QtQml/private/qqmlmetatype_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3drender/qt3dquickrendernodefactory_p.h b/src/quick3d/quick3drender/qt3dquickrendernodefactory_p.h
index 863a97f0b..6068124e5 100644
--- a/src/quick3d/quick3drender/qt3dquickrendernodefactory_p.h
+++ b/src/quick3d/quick3drender/qt3dquickrendernodefactory_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
-#include <Qt3DCore/private/qabstractnodefactory_p.h>
#include <QtCore/qhash.h>
+#include <Qt3DCore/private/qabstractnodefactory_p.h>
+
QT_BEGIN_NAMESPACE
class QQmlType;
diff --git a/src/quick3d/quick3dscene2d/items/items.pri b/src/quick3d/quick3dscene2d/items/items.pri
new file mode 100644
index 000000000..45d18dc40
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/items.pri
@@ -0,0 +1,17 @@
+HEADERS += \
+ $$PWD/scene2d_p.h \
+ $$PWD/qscene2d_p.h \
+ $$PWD/qscene2d.h \
+ $$PWD/scene2dmanager_p.h \
+ $$PWD/scene2dsharedobject_p.h \
+ $$PWD/scene2devent_p.h \
+ $$PWD/qt3dquick3dscene2d_p.h
+
+SOURCES += \
+ $$PWD/qscene2d.cpp \
+ $$PWD/scene2d.cpp \
+ $$PWD/scene2dmanager.cpp \
+ $$PWD/scene2dsharedobject.cpp \
+ $$PWD/qt3dquick3dscene2d.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.cpp b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
new file mode 100644
index 000000000..52e2be094
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
@@ -0,0 +1,365 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+#include "scene2dmanager_p.h"
+#include "scene2devent_p.h"
+
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qpropertynodeaddedchange.h>
+#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+/*!
+ \class Qt3DRender::Quick::QScene2D
+ \inmodule Qt3DScene2D
+
+ \brief This class enables rendering qml into a texture, which then can be
+ used as a part of 3D scene.
+
+ This class uses QQuickRenderControl to render the given QQuickItem into an
+ offscreen surface, which is attached to a texture provided by the user. This allows the
+ component to directly render into the texture without intermediate copy and the user to
+ freely specify how the texture is used in the 3D scene.
+
+ The entities using the QScene2D can be associated with the class to enable interaction
+ with the item; if an entity has a QObjectPicker component, the pick events from that picker
+ are sent to the QScene2D and converted to mouse events and finally sent to the item.
+
+ \since 5.9
+*/
+
+/*!
+ \qmltype Scene2D
+ \inqmlmodule Qt3D.Scene2D
+ \since 5.9
+ \instantiates Qt3DRender::Quick::QScene2D
+
+ \brief This type enables rendering qml into a texture, which then can be
+ used as a part of 3D scene.
+
+ This object uses RenderControl to render the given Item into an
+ offscreen surface, which is attached to a texture provided by the user. This allows the
+ component to directly render into the texture without intermediate copy and the user to
+ freely specify how the texture is used in the 3D scene.
+
+ The entities using the Scene2D can be associated with the type to enable interaction
+ with the item; if an entity has an ObjectPicker component, the pick events from that picker
+ are sent to the Scene2D and converted to mouse events and finally sent to the item.
+
+ Usage:
+ \qml
+ Entity {
+ id: sceneRoot
+
+ // specify Scene2D inside the entity hierarchy
+ Scene2D {
+ // specify output
+ output: RenderTargetOutput {
+ attachmentPoint: RenderTargetOutput.Color0
+ texture: Texture2D {
+ id: textureId
+ width: 1024
+ height: 1024
+ format: Texture.RGBA8_UNorm
+ }
+ }
+ // specify entities
+ entities: [entityId]
+
+ // specify rendered content
+ Rectangle {
+ color: "red"
+ }
+ }
+
+ Entity {
+ id: entityId
+
+ property Material material: TextureMaterial {
+ texture: textureId
+ }
+ property ObjectPicker picker: ObjectPicker {
+ hoverEnabled: true
+ dragEnabled: true
+ }
+ ...
+
+ \endqml
+ */
+
+/*!
+ \enum QScene2D::RenderPolicy
+
+ This enum type describes types of render policies available.
+ \value Continuous The Scene2D is rendering continuously. This is the default render policy.
+ \value SingleShot The Scene2D renders to the texture only once after which the resources
+ allocated for rendering are released.
+*/
+
+/*!
+ \qmlproperty RenderTargetOutput Qt3D.Render::Scene2D::output
+ Holds the RenderTargetOutput, which specifies where the Scene2D is rendering to.
+ */
+
+/*!
+ \qmlproperty enumeration Qt3D.Render::Scene2D::renderPolicy
+ Holds the render policy of this Scene2D.
+
+ \list
+ \li Continuous The Scene2D is rendering continuously. This is the default render policy.
+ \li SingleShot The Scene2D renders to the texture only once after which the resources
+ allocated for rendering are released.
+ \endlist
+ */
+/*!
+ \qmlproperty Item Qt3D.Render::Scene2D::item
+ Holds the Item, which is rendered by Scene2D to the texture.
+ */
+
+/*!
+ \qmlproperty bool Qt3D.Render::Scene2D::mouseEnabled
+ Holds whether mouse events are enabled for the rendered item. The mouse events are
+ generated from object picking events of the entities added to the Scene2D.
+ Mouse is enabled by default.
+
+ \note Events sent to items are delayed by one frame due to object picking
+ happening in the backend.
+ */
+/*!
+ \qmlproperty list<Entity> Qt3D.Render::Scene2D::entities
+ Holds the list of entities which are associated with the Scene2D object. If the
+ entities have ObjectPicker, the pick events from that entity are sent to Scene2D
+ and converted to mouse events.
+ */
+
+QScene2DPrivate::QScene2DPrivate()
+ : Qt3DCore::QNodePrivate()
+ , m_renderManager(new Scene2DManager(this))
+ , m_output(nullptr)
+{
+}
+
+QScene2DPrivate::~QScene2DPrivate()
+{
+ m_renderManager->cleanup();
+ delete m_renderManager;
+}
+
+void QScene2DPrivate::setScene(Qt3DCore::QScene *scene)
+{
+ Q_Q(QScene2D);
+ QNodePrivate::setScene(scene);
+ const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
+ change->setPropertyName("sceneInitialized");
+ notifyObservers(change);
+}
+
+
+/*!
+ The constructor creates a new QScene2D instance with the specified \a parent.
+ */
+QScene2D::QScene2D(Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(*new QScene2DPrivate, parent)
+{
+}
+
+/*!
+ \property QScene2D::item
+ Holds the QQuickItem, which is rendered by QScene2D to the texture.
+ */
+QQuickItem* QScene2D::item() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_item;
+}
+
+void QScene2D::setItem(QQuickItem *item)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_initialized) {
+ qWarning() << "Unable to set item after initialization.";
+ return;
+ }
+ if (d->m_renderManager->m_item != item) {
+ d->m_renderManager->setItem(item);
+ emit itemChanged(item);
+ }
+}
+
+/*!
+ \property QScene2D::renderPolicy
+
+ Holds the render policy of this Scene2D.
+ */
+QScene2D::RenderPolicy QScene2D::renderPolicy() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_renderPolicy;
+}
+
+void QScene2D::setRenderPolicy(QScene2D::RenderPolicy renderPolicy)
+{
+ Q_D(const QScene2D);
+ if (d->m_renderManager->m_renderPolicy != renderPolicy) {
+ d->m_renderManager->m_renderPolicy = renderPolicy;
+ emit renderPolicyChanged(renderPolicy);
+ }
+}
+
+/*!
+ \property QScene2D::output
+ Holds the QRenderTargetOutput, which specifies where the QScene2D is
+ rendering to.
+ */
+Qt3DRender::QRenderTargetOutput *QScene2D::output() const
+{
+ Q_D(const QScene2D);
+ return d->m_output;
+}
+
+void QScene2D::setOutput(Qt3DRender::QRenderTargetOutput *output)
+{
+ Q_D(QScene2D);
+ if (d->m_output != output) {
+ if (d->m_output)
+ d->unregisterDestructionHelper(d->m_output);
+ d->m_output = output;
+ if (output)
+ d->registerDestructionHelper(output, &QScene2D::setOutput, d->m_output);
+ emit outputChanged(output);
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QScene2D::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QScene2DData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QScene2D);
+ data.renderPolicy = d->m_renderManager->m_renderPolicy;
+ data.sharedObject = d->m_renderManager->m_sharedObject;
+ data.output = d->m_output ? d->m_output->id() : Qt3DCore::QNodeId();
+ for (Qt3DCore::QEntity *e : d->m_entities)
+ data.entityIds.append(e->id());
+ data.mouseEnabled = d->m_renderManager->m_mouseEnabled;
+ return creationChange;
+}
+
+bool QScene2D::isMouseEnabled() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_mouseEnabled;
+}
+
+/*!
+ Retrieve entities associated with the QScene2D.
+ */
+QVector<Qt3DCore::QEntity*> QScene2D::entities()
+{
+ Q_D(const QScene2D);
+ return d->m_entities;
+}
+
+/*!
+ Adds an \a entity to the the QScene2D object. If the entities have QObjectPicker,
+ the pick events from that entity are sent to QScene2D and converted to mouse events.
+*/
+void QScene2D::addEntity(Qt3DCore::QEntity *entity)
+{
+ Q_D(QScene2D);
+ if (!d->m_entities.contains(entity)) {
+ d->m_entities.append(entity);
+
+ d->registerDestructionHelper(entity, &QScene2D::removeEntity, d->m_entities);
+
+ if (d->m_changeArbiter != nullptr) {
+ const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), entity);
+ change->setPropertyName("entities");
+ d->notifyObservers(change);
+ }
+ }
+}
+
+/*!
+ Removes an \a entity from the the QScene2D object.
+*/
+void QScene2D::removeEntity(Qt3DCore::QEntity *entity)
+{
+ Q_D(QScene2D);
+ if (d->m_entities.contains(entity)) {
+ d->m_entities.removeAll(entity);
+
+ d->unregisterDestructionHelper(entity);
+
+ if (d->m_changeArbiter != nullptr) {
+ const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), entity);
+ change->setPropertyName("entities");
+ d->notifyObservers(change);
+ }
+ }
+}
+
+/*!
+ \property QScene2D::mouseEnabled
+ Holds whether mouse events are enabled for the rendered item. The mouse events are
+ generated from object picking events of the entities added to the QScene2D.
+ Mouse is enabled by default.
+
+ \note Events are delayed by one frame due to object picking happening in the backend.
+ */
+void QScene2D::setMouseEnabled(bool enabled)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_mouseEnabled != enabled) {
+ d->m_renderManager->m_mouseEnabled = enabled;
+ emit mouseEnabledChanged(enabled);
+ }
+}
+
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.h b/src/quick3d/quick3dscene2d/items/qscene2d.h
new file mode 100644
index 000000000..73322a9e9
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_H
+#define QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_H
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <Qt3DRender/qrendertargetoutput.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QEvent>
+
+#include <Qt3DCore/qnode.h>
+
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2DPrivate;
+
+class QT3DQUICKSCENE2DSHARED_EXPORT QScene2D : public Qt3DCore::QNode
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Qt3DRender::QRenderTargetOutput *output READ output WRITE setOutput NOTIFY outputChanged)
+ Q_PROPERTY(QScene2D::RenderPolicy renderPolicy READ renderPolicy WRITE setRenderPolicy NOTIFY renderPolicyChanged)
+ Q_PROPERTY(QQuickItem *item READ item WRITE setItem NOTIFY itemChanged)
+ Q_PROPERTY(bool mouseEnabled READ isMouseEnabled WRITE setMouseEnabled NOTIFY mouseEnabledChanged)
+
+ Q_CLASSINFO("DefaultProperty", "item")
+
+public:
+
+ enum RenderPolicy {
+ Continuous,
+ SingleShot
+ };
+ Q_ENUM(RenderPolicy)
+
+ explicit QScene2D(Qt3DCore::QNode *parent = nullptr);
+
+ Qt3DRender::QRenderTargetOutput *output() const;
+ QScene2D::RenderPolicy renderPolicy() const;
+ QQuickItem *item() const;
+ bool isMouseEnabled() const;
+
+ QVector<Qt3DCore::QEntity *> entities();
+ void addEntity(Qt3DCore::QEntity *entity);
+ void removeEntity(Qt3DCore::QEntity *entity);
+
+public Q_SLOTS:
+ void setOutput(Qt3DRender::QRenderTargetOutput *output);
+ void setRenderPolicy(QScene2D::RenderPolicy policy);
+ void setItem(QQuickItem *item);
+ void setMouseEnabled(bool enabled);
+
+Q_SIGNALS:
+ void outputChanged(Qt3DRender::QRenderTargetOutput *output);
+ void renderPolicyChanged(QScene2D::RenderPolicy policy);
+ void itemChanged(QQuickItem *item);
+ void mouseEnabledChanged(bool enabled);
+
+protected:
+ Q_DECLARE_PRIVATE(QScene2D)
+
+private:
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_H
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d_p.h b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
new file mode 100644
index 000000000..217058f5c
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_P_H
+#define QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <private/qnode_p.h>
+#include <private/scene2dsharedobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QScene;
+}
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2D;
+class Scene2DManager;
+
+class Q_AUTOTEST_EXPORT QScene2DPrivate : public Qt3DCore::QNodePrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QScene2D)
+
+ QScene2DPrivate();
+ ~QScene2DPrivate();
+
+ void setScene(Qt3DCore::QScene *scene) Q_DECL_OVERRIDE;
+
+ Scene2DManager *m_renderManager;
+ QMetaObject::Connection m_textureDestroyedConnection;
+ Qt3DRender::QRenderTargetOutput *m_output;
+ QVector<Qt3DCore::QEntity *> m_entities;
+};
+
+struct QScene2DData
+{
+ QScene2D::RenderPolicy renderPolicy;
+ Scene2DSharedObjectPtr sharedObject;
+ Qt3DCore::QNodeId output;
+ QVector<Qt3DCore::QNodeId> entityIds;
+ bool mouseEnabled;
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DSCENE2D_QSCENE2D_P_H
diff --git a/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp
new file mode 100644
index 000000000..83cbefc59
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquick3dscene2d_p.h"
+#include <Qt3DCore/qentity.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+namespace Quick {
+
+QQuick3DScene2D::QQuick3DScene2D(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DCore::QEntity> QQuick3DScene2D::entities()
+{
+ return QQmlListProperty<Qt3DCore::QEntity>(this, 0,
+ &QQuick3DScene2D::appendEntity,
+ &QQuick3DScene2D::entityCount,
+ &QQuick3DScene2D::entityAt,
+ &QQuick3DScene2D::clearEntities);
+}
+
+void QQuick3DScene2D::appendEntity(QQmlListProperty<Qt3DCore::QEntity> *list,
+ Qt3DCore::QEntity *entity)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d)
+ scene2d->parentScene2D()->addEntity(entity);
+}
+
+int QQuick3DScene2D::entityCount(QQmlListProperty<Qt3DCore::QEntity> *list)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d)
+ return scene2d->parentScene2D()->entities().count();
+ return 0;
+}
+
+Qt3DCore::QEntity *QQuick3DScene2D::entityAt(QQmlListProperty<Qt3DCore::QEntity> *list, int index)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d) {
+ return qobject_cast<Qt3DCore::QEntity *>(
+ scene2d->parentScene2D()->entities().at(index));
+ }
+ return nullptr;
+}
+
+void QQuick3DScene2D::clearEntities(QQmlListProperty<Qt3DCore::QEntity> *list)
+{
+ QQuick3DScene2D *scene2d = qobject_cast<QQuick3DScene2D *>(list->object);
+ if (scene2d) {
+ QVector<Qt3DCore::QEntity*> entities = scene2d->parentScene2D()->entities();
+ for (Qt3DCore::QEntity *e : entities)
+ scene2d->parentScene2D()->removeEntity(e);
+ }
+}
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h
new file mode 100644
index 000000000..57734223b
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/qt3dquick3dscene2d_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSCENE2D_QUICK_QUICK3DSCENE2D_P_H
+#define QT3DSCENE2D_QUICK_QUICK3DSCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmllist.h>
+
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <private/qt3dquickscene2d_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+namespace Quick {
+
+class QT3DQUICKSCENE2DSHARED_EXPORT QQuick3DScene2D : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DCore::QEntity> entities READ entities)
+
+public:
+ QQuick3DScene2D(QObject *parent = nullptr);
+
+ inline Qt3DRender::Quick::QScene2D *parentScene2D() const
+ {
+ return qobject_cast<Qt3DRender::Quick::QScene2D *>(parent());
+ }
+
+ QQmlListProperty<Qt3DCore::QEntity> entities();
+
+private:
+
+ static void appendEntity(QQmlListProperty<Qt3DCore::QEntity> *list, Qt3DCore::QEntity *entity);
+ static Qt3DCore::QEntity *entityAt(QQmlListProperty<Qt3DCore::QEntity> *list, int index);
+ static int entityCount(QQmlListProperty<Qt3DCore::QEntity> *list);
+ static void clearEntities(QQmlListProperty<Qt3DCore::QEntity> *list);
+};
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QUICK_QUICK3DMORPHINGANIMATION_P_H
+
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp
new file mode 100644
index 000000000..b0c58c6c5
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qpropertynodeaddedchange.h>
+#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+#include <Qt3DRender/qpicktriangleevent.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qatomic.h>
+#include <QtGui/qevent.h>
+
+#include <private/qscene2d_p.h>
+#include <private/scene2d_p.h>
+#include <private/scene2dmanager_p.h>
+#include <private/scene2devent_p.h>
+#include <private/graphicscontext_p.h>
+#include <private/texture_p.h>
+#include <private/nodemanagers_p.h>
+#include <private/resourceaccessor_p.h>
+#include <private/attachmentpack_p.h>
+#include <private/qt3dquickscene2d_logging_p.h>
+#include <private/qbackendnode_p.h>
+#include <private/qpickevent_p.h>
+#include <private/entity_p.h>
+#include <private/platformsurfacefilter_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
+using namespace Qt3DRender::Quick;
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace Quick {
+
+Q_GLOBAL_STATIC(QThread, renderThread)
+Q_GLOBAL_STATIC(QAtomicInt, renderThreadClientCount)
+
+RenderQmlEventHandler::RenderQmlEventHandler(Scene2D *node)
+ : QObject()
+ , m_node(node)
+{
+}
+
+// Event handler for the RenderQmlToTexture::renderThread
+bool RenderQmlEventHandler::event(QEvent *e)
+{
+ switch (static_cast<Scene2DEvent::Type>(e->type())) {
+
+ case Scene2DEvent::Render: {
+ m_node->render();
+ return true;
+ }
+
+ case Scene2DEvent::Initialize: {
+ m_node->initializeRender();
+ return true;
+ }
+
+ case Scene2DEvent::Quit: {
+ m_node->cleanup();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+Scene2D::Scene2D()
+ : Qt3DRender::Render::BackendNode(Qt3DCore::QBackendNode::ReadWrite)
+ , m_context(nullptr)
+ , m_shareContext(nullptr)
+ , m_renderThread(nullptr)
+ , m_sharedObject(nullptr)
+ , m_fbo(0)
+ , m_rbo(0)
+ , m_initialized(false)
+ , m_renderInitialized(false)
+ , m_mouseEnabled(true)
+ , m_renderPolicy(Qt3DRender::Quick::QScene2D::Continuous)
+{
+ renderThreadClientCount->fetchAndAddAcquire(1);
+}
+
+Scene2D::~Scene2D()
+{
+ stopGrabbing();
+}
+
+void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
+{
+ m_outputId = outputId;
+}
+
+void Scene2D::initializeSharedObject()
+{
+ if (!m_initialized) {
+
+ // bail out if we're running autotests
+ if (!m_sharedObject->m_renderManager
+ || m_sharedObject->m_renderManager->thread() == QThread::currentThread()) {
+ return;
+ }
+
+ renderThread->setObjectName(QStringLiteral("Scene2D::renderThread"));
+ m_renderThread = renderThread;
+ m_sharedObject->m_renderThread = m_renderThread;
+
+ // Create event handler for the render thread
+ m_sharedObject->m_renderObject = new RenderQmlEventHandler(this);
+ m_sharedObject->m_renderObject->moveToThread(m_sharedObject->m_renderThread);
+ if (!m_sharedObject->m_renderThread->isRunning())
+ m_sharedObject->m_renderThread->start();
+
+ // Notify main thread we have been initialized
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager,
+ new Scene2DEvent(Scene2DEvent::Initialized));
+ // Initialize render thread
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject,
+ new Scene2DEvent(Scene2DEvent::Initialize));
+
+ m_initialized = true;
+ }
+}
+
+void Scene2D::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+{
+ const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QScene2DData>>(change);
+ const auto &data = typedChange->data;
+ m_renderPolicy = data.renderPolicy;
+ setSharedObject(data.sharedObject);
+ setOutput(data.output);
+ m_entities = data.entityIds;
+ m_mouseEnabled = data.mouseEnabled;
+}
+
+void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+{
+ switch (e->type()) {
+
+ case Qt3DCore::PropertyUpdated: {
+
+ Qt3DCore::QPropertyUpdatedChangePtr propertyChange
+ = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
+ if (propertyChange->propertyName() == QByteArrayLiteral("renderPolicy")) {
+ m_renderPolicy = propertyChange->value().value<QScene2D::RenderPolicy>();
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("output")) {
+ Qt3DCore::QNodeId outputId = propertyChange->value().value<Qt3DCore::QNodeId>();
+ setOutput(outputId);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("pressed")) {
+ QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
+ handlePickEvent(QEvent::MouseButtonPress, ev);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("released")) {
+ QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
+ handlePickEvent(QEvent::MouseButtonRelease, ev);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("moved")) {
+ QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
+ handlePickEvent(QEvent::MouseMove, ev);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("mouseEnabled")) {
+ m_mouseEnabled = propertyChange->value().toBool();
+ if (m_mouseEnabled && !m_cachedPickEvent.isNull()) {
+ handlePickEvent(QEvent::MouseButtonPress, m_cachedPickEvent);
+ m_cachedPickEvent.clear();
+ }
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("sceneInitialized")) {
+ startGrabbing();
+ }
+ break;
+ }
+
+ case Qt3DCore::PropertyValueAdded: {
+ const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("entities")) {
+ m_entities.push_back(change->addedNodeId());
+ registerObjectPickerEvents(change->addedNodeId());
+ }
+ break;
+ }
+
+ case Qt3DCore::PropertyValueRemoved: {
+ const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("entities")) {
+ m_entities.removeOne(change->removedNodeId());
+ unregisterObjectPickerEvents(change->removedNodeId());
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ BackendNode::sceneChangeEvent(e);
+}
+
+void Scene2D::setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject)
+{
+ m_sharedObject = sharedObject;
+ if (!m_initialized)
+ initializeSharedObject();
+}
+
+void Scene2D::initializeRender()
+{
+ if (!m_renderInitialized && m_sharedObject.data() != nullptr) {
+ m_shareContext = renderer()->shareContext();
+ if (!m_shareContext){
+ qCDebug(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Renderer not initialized.";
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject,
+ new Scene2DEvent(Scene2DEvent::Initialize));
+ return;
+ }
+ m_context = new QOpenGLContext();
+#ifdef Q_OS_MACOS
+ m_context->setFormat(m_shareContext->format());
+#else
+ QSurfaceFormat format;
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+ m_context->setFormat(format);
+#endif
+ m_context->setShareContext(m_shareContext);
+ m_context->create();
+
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ m_sharedObject->m_renderControl->initialize(m_context);
+ m_context->doneCurrent();
+
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager,
+ new Scene2DEvent(Scene2DEvent::Prepare));
+ m_renderInitialized = true;
+ }
+}
+
+bool Scene2D::updateFbo(QOpenGLTexture *texture)
+{
+ QOpenGLFunctions *gl = m_context->functions();
+ if (m_fbo == 0) {
+ gl->glGenFramebuffers(1, &m_fbo);
+ gl->glGenRenderbuffers(1, &m_rbo);
+ }
+ // TODO: Add another codepath when GL_DEPTH24_STENCIL8 is not supported
+ gl->glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
+ gl->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+ m_textureSize.width(), m_textureSize.height());
+ gl->glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ gl->glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+ gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture->textureId(), 0);
+ gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo);
+ GLenum status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ gl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ return false;
+ return true;
+}
+
+void Scene2D::syncRenderControl()
+{
+ if (m_sharedObject->isSyncRequested()) {
+
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+
+ // gui thread can now continue
+ m_sharedObject->wake();
+ }
+}
+
+void Scene2D::render()
+{
+ if (m_initialized && m_renderInitialized && m_sharedObject.data() != nullptr) {
+
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+
+ QOpenGLTexture *texture = nullptr;
+ const Qt3DRender::Render::Attachment *attachmentData = nullptr;
+ QMutex *textureLock = nullptr;
+
+#ifdef QT_OPENGL_ES_2_ANGLE
+ SurfaceLocker surfaceLocker(m_sharedObject->m_surface);
+#endif
+ m_context->makeCurrent(m_sharedObject->m_surface);
+
+ if (resourceAccessor()->accessResource(RenderBackendResourceAccessor::OutputAttachment,
+ m_outputId, (void**)&attachmentData, nullptr)) {
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::OGLTexture,
+ attachmentData->m_textureUuid,
+ (void**)&texture, &textureLock)) {
+ // Need to call sync even if the texture is not in use
+ syncRenderControl();
+ m_context->doneCurrent();
+ qCDebug(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Texture not in use.";
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject,
+ new Scene2DEvent(Scene2DEvent::Render));
+ return;
+ }
+ textureLock->lock();
+ const QSize textureSize = QSize(texture->width(), texture->height());
+ if (m_attachmentData.m_textureUuid != attachmentData->m_textureUuid
+ || m_attachmentData.m_point != attachmentData->m_point
+ || m_attachmentData.m_face != attachmentData->m_face
+ || m_attachmentData.m_layer != attachmentData->m_layer
+ || m_attachmentData.m_mipLevel != attachmentData->m_mipLevel
+ || m_textureSize != textureSize) {
+ m_textureSize = textureSize;
+ m_attachmentData = *attachmentData;
+ if (!updateFbo(texture)) {
+ // Need to call sync even if the fbo is not usable
+ syncRenderControl();
+ textureLock->unlock();
+ m_context->doneCurrent();
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Fbo not initialized.";
+ return;
+ }
+ }
+ }
+
+ if (m_fbo != m_sharedObject->m_quickWindow->renderTargetId())
+ m_sharedObject->m_quickWindow->setRenderTarget(m_fbo, m_textureSize);
+
+ // Call disallow rendering while mutex is locked
+ if (m_renderPolicy == QScene2D::SingleShot)
+ m_sharedObject->disallowRender();
+
+ // Sync
+ if (m_sharedObject->isSyncRequested()) {
+
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+ }
+
+ // Render
+ m_sharedObject->m_renderControl->render();
+
+ // Tell main thread we are done so it can begin cleanup if this is final frame
+ if (m_renderPolicy == QScene2D::SingleShot)
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager,
+ new Scene2DEvent(Scene2DEvent::Rendered));
+
+ m_sharedObject->m_quickWindow->resetOpenGLState();
+ m_context->functions()->glFlush();
+ if (texture->isAutoMipMapGenerationEnabled())
+ texture->generateMipMaps();
+ textureLock->unlock();
+ m_context->doneCurrent();
+
+ // gui thread can now continue
+ m_sharedObject->wake();
+ }
+}
+
+// this function gets called while the main thread is waiting
+void Scene2D::cleanup()
+{
+ if (m_renderInitialized && m_initialized) {
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ m_sharedObject->m_renderControl->invalidate();
+ m_context->functions()->glDeleteFramebuffers(1, &m_fbo);
+ m_context->functions()->glDeleteRenderbuffers(1, &m_rbo);
+ m_context->doneCurrent();
+ m_renderInitialized = false;
+ }
+ if (m_initialized) {
+ delete m_sharedObject->m_renderObject;
+ m_sharedObject->m_renderObject = nullptr;
+ delete m_context;
+ m_context = nullptr;
+ m_initialized = false;
+ }
+ if (m_sharedObject) {
+ // wake up the main thread
+ m_sharedObject->wake();
+ m_sharedObject = nullptr;
+ }
+
+ renderThreadClientCount->fetchAndSubAcquire(1);
+ if (renderThreadClientCount->load() == 0)
+ renderThread->quit();
+}
+
+
+bool Scene2D::registerObjectPickerEvents(Qt3DCore::QNodeId entityId)
+{
+ Entity *entity = nullptr;
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
+ entityId, (void**)&entity, nullptr)) {
+ return false;
+ }
+ if (!entity->containsComponentsOfType<ObjectPicker>() ||
+ !entity->containsComponentsOfType<GeometryRenderer>()) {
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO
+ << "Entity does not contain required components: ObjectPicker and GeometryRenderer";
+ return false;
+ }
+ Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
+ Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
+ arbiter->registerObserver(d_ptr, entity->componentUuid<ObjectPicker>());
+ return true;
+}
+
+void Scene2D::unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId)
+{
+ Entity *entity = nullptr;
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
+ entityId, (void**)&entity, nullptr)) {
+ return;
+ }
+ Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
+ Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
+ arbiter->unregisterObserver(d_ptr, entity->componentUuid<ObjectPicker>());
+}
+
+void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev)
+{
+ if (!isEnabled())
+ return;
+ if (m_mouseEnabled) {
+ QPickTriangleEvent *pickTriangle = static_cast<QPickTriangleEvent *>(ev.data());
+ Entity *entity = nullptr;
+ if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
+ QPickEventPrivate::get(pickTriangle)->m_entity,
+ (void**)&entity, nullptr)) {
+ return;
+ }
+ CoordinateReader reader(renderer()->nodeManagers());
+ if (reader.setGeometry(entity->renderComponent<GeometryRenderer>(),
+ QAttribute::defaultTextureCoordinateAttributeName())) {
+ QVector4D c0 = reader.getCoordinate(pickTriangle->vertex1Index());
+ QVector4D c1 = reader.getCoordinate(pickTriangle->vertex2Index());
+ QVector4D c2 = reader.getCoordinate(pickTriangle->vertex3Index());
+ QVector4D ci = c0 * pickTriangle->uvw().x()
+ + c1 * pickTriangle->uvw().y() + c2 * pickTriangle->uvw().z();
+ ci.setW(1.0f);
+
+ const QSize size = m_sharedObject->m_quickWindow->size();
+ QPointF pos = QPointF(ci.x() * size.width(), (1.0f - ci.y()) * size.height());
+ QMouseEvent *mouseEvent
+ = new QMouseEvent(static_cast<QEvent::Type>(type),
+ pos, pos, pos,
+ static_cast<Qt::MouseButton>(pickTriangle->button()),
+ static_cast<Qt::MouseButtons>(pickTriangle->buttons()),
+ static_cast<Qt::KeyboardModifiers>(pickTriangle->modifiers()),
+ Qt::MouseEventSynthesizedByApplication);
+
+ QCoreApplication::postEvent(m_sharedObject->m_quickWindow, mouseEvent);
+ }
+ } else if (type == QEvent::MouseButtonPress) {
+ m_cachedPickEvent = ev;
+ } else {
+ m_cachedPickEvent.clear();
+ }
+}
+
+void Scene2D::startGrabbing()
+{
+ for (Qt3DCore::QNodeId e : qAsConst(m_entities))
+ registerObjectPickerEvents(e);
+}
+
+void Scene2D::stopGrabbing()
+{
+ for (Qt3DCore::QNodeId e : qAsConst(m_entities))
+ unregisterObjectPickerEvents(e);
+}
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.pri b/src/quick3d/quick3dscene2d/items/scene2d.pri
new file mode 100644
index 000000000..4635c43e1
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2d.pri
@@ -0,0 +1,10 @@
+HEADERS += \
+ $$PWD/qscene2d.h \
+ $$PWD/qscene2d_p.h \
+ $$PWD/scene2d_p.h
+
+SOURCES += \
+ $$PWD/qscene2d.cpp \
+ $$PWD/scene2d.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dscene2d/items/scene2d_p.h b/src/quick3d/quick3dscene2d/items/scene2d_p.h
new file mode 100644
index 000000000..b42089306
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2d_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QUICK3DSCENE2D_SCENE2D_P_H
+#define QT3DRENDER_RENDER_QUICK3DSCENE2D_SCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DRender/qpickevent.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <private/qscene2d_p.h>
+#include <private/qrendertargetoutput_p.h>
+#include <private/backendnode_p.h>
+#include <private/attachmentpack_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class GraphicsContext;
+
+namespace Quick {
+
+class Scene2D;
+
+class RenderQmlEventHandler : public QObject
+{
+ Q_OBJECT
+public:
+ RenderQmlEventHandler(Scene2D *node);
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
+private:
+ Scene2D *m_node;
+};
+
+class QT3DQUICKSCENE2DSHARED_EXPORT Scene2D : public Qt3DRender::Render::BackendNode
+{
+public:
+ Scene2D();
+ ~Scene2D();
+
+ void render();
+ void initializeRender();
+ void setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject);
+ void cleanup();
+ void setOutput(Qt3DCore::QNodeId outputId);
+ void initializeSharedObject();
+
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_OVERRIDE;
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+ bool updateFbo(QOpenGLTexture *texture);
+ void syncRenderControl();
+ void startGrabbing();
+ void stopGrabbing();
+ bool registerObjectPickerEvents(Qt3DCore::QNodeId entityId);
+ void unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId);
+ void handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev);
+
+ QOpenGLContext *m_context;
+ QOpenGLContext *m_shareContext;
+ QThread *m_renderThread;
+ Qt3DCore::QNodeId m_outputId;
+ QSharedPointer<Qt3DRender::Quick::Scene2DSharedObject> m_sharedObject;
+ Qt3DCore::QNodeId m_peerId;
+ Qt3DRender::Render::Attachment m_attachmentData;
+
+ GLuint m_fbo;
+ GLuint m_rbo;
+ QSize m_textureSize;
+
+ bool m_initialized;
+ bool m_renderInitialized;
+ bool m_mouseEnabled;
+ Qt3DRender::Quick::QScene2D::RenderPolicy m_renderPolicy;
+ QVector<Qt3DCore::QNodeId> m_entities;
+ Qt3DRender::QPickEventPtr m_cachedPickEvent;
+};
+
+} // Quick
+} // Render
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QUICK3DSCENE2D_SCENE2D_P_H
diff --git a/src/quick3d/quick3dscene2d/items/scene2devent_p.h b/src/quick3d/quick3dscene2d/items/scene2devent_p.h
new file mode 100644
index 000000000..bcc808a4d
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2devent_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_SCENE2DEVENT_P_H
+#define QT3DRENDER_QUICK3DRENDER_SCENE2DEVENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+
+#include <QtCore/QEvent>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class Scene2DEvent : public QEvent
+{
+public:
+ enum Type {
+ Initialize = QEvent::User + 1,
+ Render,
+ RenderSync,
+ Prepare,
+ Initialized,
+ Rendered,
+ Quit
+ };
+ Scene2DEvent(Type type)
+ : QEvent(static_cast<QEvent::Type>(type))
+ {
+ }
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DRENDER_SCENE2DEVENT_P_H
diff --git a/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
new file mode 100644
index 000000000..20c080dec
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+#include "scene2dmanager_p.h"
+#include "scene2devent_p.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class RenderControl : public QQuickRenderControl
+{
+public:
+ RenderControl(QWindow *w) : m_window(w) { }
+ QWindow *renderWindow(QPoint *offset) Q_DECL_OVERRIDE;
+
+private:
+ QWindow *m_window;
+};
+
+QWindow *RenderControl::renderWindow(QPoint *offset)
+{
+ if (offset)
+ *offset = QPoint(0, 0);
+ return m_window;
+}
+
+/*!
+ \internal
+ Constructs qml render manager.
+ */
+Scene2DManager::Scene2DManager(QScene2DPrivate *priv)
+ : m_rootItem(nullptr)
+ , m_item(nullptr)
+ , m_priv(priv)
+ , m_sharedObject(new Scene2DSharedObject(this))
+ , m_renderPolicy(QScene2D::Continuous)
+ , m_requested(false)
+ , m_initialized(false)
+ , m_renderSyncRequested(false)
+ , m_backendInitialized(false)
+ , m_mouseEnabled(true)
+{
+ m_sharedObject->m_surface = new QOffscreenSurface;
+ m_sharedObject->m_surface->setFormat(QSurfaceFormat::defaultFormat());
+ m_sharedObject->m_surface->create();
+
+ // Create render control
+ m_sharedObject->m_renderControl = new RenderControl(nullptr);
+
+ // Create window to render the QML with
+ m_sharedObject->m_quickWindow = new QQuickWindow(m_sharedObject->m_renderControl);
+ m_sharedObject->m_quickWindow->setClearBeforeRendering(false);
+
+ connect(m_sharedObject->m_renderControl, &QQuickRenderControl::renderRequested,
+ this, &Scene2DManager::requestRender);
+ connect(m_sharedObject->m_renderControl, &QQuickRenderControl::sceneChanged,
+ this, &Scene2DManager::requestRenderSync);
+}
+
+Scene2DManager::~Scene2DManager()
+{
+ m_sharedObject = nullptr;
+}
+
+void Scene2DManager::requestRender()
+{
+ // Don't request render until the backend is initialized.
+ if (m_sharedObject->canRender()) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new Scene2DEvent(Scene2DEvent::Render));
+ }
+ }
+}
+
+void Scene2DManager::requestRenderSync()
+{
+ // Don't request render until the backed is initialized.
+ if (m_sharedObject->canRender()) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new Scene2DEvent(Scene2DEvent::RenderSync));
+ }
+ } else {
+ m_renderSyncRequested = true;
+ }
+}
+
+void Scene2DManager::startIfInitialized()
+{
+ if (!m_initialized && m_backendInitialized && m_item != nullptr) {
+ m_rootItem = m_item;
+
+ // Associate root item with the window.
+ m_rootItem->setParentItem(m_sharedObject->m_quickWindow->contentItem());
+
+ // Update window size.
+ updateSizes();
+
+ m_initialized = true;
+ m_sharedObject->setInitialized();
+ }
+}
+
+void Scene2DManager::stopAndClean()
+{
+ if (m_sharedObject->isInitialized()) {
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+ m_sharedObject->requestQuit();
+ m_sharedObject->wait();
+ m_sharedObject->cleanup();
+ }
+}
+
+void Scene2DManager::updateSizes()
+{
+ const int width = m_rootItem->width();
+ const int height = m_rootItem->height();
+ if (width == 0 || height == 0) {
+ qWarning() << "QScene2D: Root item size not set.";
+ return;
+ }
+ m_sharedObject->m_quickWindow->setGeometry(0, 0, width, height);
+}
+
+void Scene2DManager::setItem(QQuickItem *item)
+{
+ m_item = item;
+ startIfInitialized();
+}
+
+bool Scene2DManager::event(QEvent *e)
+{
+ switch (static_cast<Scene2DEvent::Type>(e->type())) {
+
+ case Scene2DEvent::Render: {
+ // just render request, don't need to call sync in render thread
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+ m_sharedObject->requestRender(false);
+ m_requested = false;
+ return true;
+ }
+
+ case Scene2DEvent::RenderSync: {
+ // sync and render request, main and render threads must be synchronized
+ if (!m_sharedObject->isQuit())
+ doRenderSync();
+ m_requested = false;
+ return true;
+ }
+
+ case Scene2DEvent::Prepare: {
+ m_sharedObject->m_renderControl->prepareThread(m_sharedObject->m_renderThread);
+ m_sharedObject->setPrepared();
+
+ if (m_renderSyncRequested) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new Scene2DEvent(Scene2DEvent::RenderSync));
+ }
+ m_renderSyncRequested = false;
+ }
+ return true;
+ }
+
+ case Scene2DEvent::Initialized: {
+ // backend is initialized, start the qml
+ m_backendInitialized = true;
+ startIfInitialized();
+ return true;
+ }
+
+ case Scene2DEvent::Rendered: {
+ // render is done, excellent, now clean anything not needed anymore.
+ stopAndClean();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+void Scene2DManager::doRenderSync()
+{
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+
+ m_sharedObject->requestRender(true);
+ m_sharedObject->m_renderControl->polishItems();
+
+ // begin waiting render thread
+ m_sharedObject->wait();
+ m_requested = false;
+}
+
+void Scene2DManager::cleanup()
+{
+ stopAndClean();
+}
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/scene2dmanager_p.h b/src/quick3d/quick3dscene2d/items/scene2dmanager_p.h
new file mode 100644
index 000000000..821616f47
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dmanager_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_SCENE2DMANAGER_P_H
+#define QT3DRENDER_QUICK3DRENDER_SCENE2DMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlComponent>
+#include <QtQuick/QQuickItem>
+
+#include <private/qnode_p.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2DPrivate;
+class Scene2DSharedObject;
+
+class Scene2DManager : public QObject
+{
+ Q_OBJECT
+public:
+ Scene2DManager(QScene2DPrivate *priv);
+ ~Scene2DManager();
+
+ QQuickItem *m_rootItem;
+ QQuickItem *m_item;
+
+ QScene2DPrivate *m_priv;
+ QSharedPointer<Scene2DSharedObject> m_sharedObject;
+
+ Qt3DCore::QNodeId m_id;
+ QScene2D::RenderPolicy m_renderPolicy;
+
+ bool m_requested;
+ bool m_initialized;
+ bool m_renderSyncRequested;
+ bool m_backendInitialized;
+ bool m_mouseEnabled;
+
+ void requestRender();
+ void requestRenderSync();
+ void doRenderSync();
+ void startIfInitialized();
+ void stopAndClean();
+ void updateSizes();
+
+ void setItem(QQuickItem *item);
+
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
+ void cleanup();
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DRENDER_SCENE2DMANAGER_P_H
diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
new file mode 100644
index 000000000..1dd798d94
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+#include "scene2dmanager_p.h"
+#include "scene2devent_p.h"
+#include "scene2dsharedobject_p.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+
+/*!
+ \internal
+ Constructs object shared by the front-end and back-end to synchronize the rendering.
+ */
+Scene2DSharedObject::Scene2DSharedObject(Scene2DManager *manager)
+ : m_renderControl(nullptr)
+ , m_quickWindow(nullptr)
+ , m_renderManager(manager)
+ , m_surface(nullptr)
+ , m_renderObject(nullptr)
+ , m_disallowed(false)
+ , m_quit(false)
+ , m_requestSync(false)
+ , m_prepared(false)
+ , m_initialized(false)
+{
+}
+
+Scene2DSharedObject::~Scene2DSharedObject()
+{
+}
+
+void Scene2DSharedObject::cleanup()
+{
+ delete m_renderControl;
+ delete m_quickWindow;
+ delete m_surface;
+ m_renderControl = nullptr;
+ m_quickWindow = nullptr;
+ m_surface = nullptr;
+ m_initialized = false;
+}
+
+bool Scene2DSharedObject::canRender() const
+{
+ return m_initialized && m_prepared && !m_disallowed;
+}
+
+bool Scene2DSharedObject::isInitialized() const
+{
+ return m_initialized;
+}
+
+void Scene2DSharedObject::disallowRender()
+{
+ m_disallowed = true;
+}
+
+void Scene2DSharedObject::setInitialized()
+{
+ m_initialized = true;
+}
+
+bool Scene2DSharedObject::isPrepared() const
+{
+ return m_prepared;
+}
+
+void Scene2DSharedObject::setPrepared()
+{
+ m_prepared = true;
+}
+
+// not protected, call only from main thread
+bool Scene2DSharedObject::isQuit() const
+{
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ return m_quit;
+}
+
+// not protected, call only from main thread
+void Scene2DSharedObject::requestQuit()
+{
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ m_quit = true;
+ QCoreApplication::postEvent(m_renderObject, new Scene2DEvent(Scene2DEvent::Quit));
+}
+
+bool Scene2DSharedObject::isSyncRequested() const
+{
+ return m_requestSync;
+}
+
+void Scene2DSharedObject::requestRender(bool sync)
+{
+ m_requestSync = sync;
+ QCoreApplication::postEvent(m_renderObject, new Scene2DEvent(Scene2DEvent::Render));
+}
+
+void Scene2DSharedObject::wait()
+{
+ m_cond.wait(&m_mutex);
+}
+
+void Scene2DSharedObject::wake()
+{
+ m_cond.wakeOne();
+}
+
+void Scene2DSharedObject::clearSyncRequest()
+{
+ m_requestSync = false;
+}
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h b/src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h
new file mode 100644
index 000000000..83863be20
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_SCENE2DSHAREDOBJECT_P_H
+#define QT3DRENDER_QUICK3DRENDER_SCENE2DSHAREDOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <Qt3DQuickScene2D/qscene2d.h>
+
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/QQuickRenderControl>
+#include <QtGui/QOffscreenSurface>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QThread>
+
+#include <private/qnode_p.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class Scene2DManager;
+
+class Q_AUTOTEST_EXPORT Scene2DSharedObject
+{
+public:
+ Scene2DSharedObject(Scene2DManager *manager);
+ ~Scene2DSharedObject();
+
+ QQuickRenderControl *m_renderControl;
+ QQuickWindow *m_quickWindow;
+ Scene2DManager *m_renderManager;
+ QOffscreenSurface *m_surface;
+
+ QThread *m_renderThread;
+ QObject *m_renderObject;
+
+ QWaitCondition m_cond;
+ QMutex m_mutex;
+
+ bool isInitialized() const;
+ void setInitialized();
+
+ void requestQuit();
+ bool isQuit() const;
+
+ void requestRender(bool sync);
+
+ bool isSyncRequested() const;
+ void clearSyncRequest();
+
+ void wait();
+ void wake();
+
+ bool isPrepared() const;
+ void setPrepared();
+
+ void disallowRender();
+ bool canRender() const;
+
+ void cleanup();
+
+private:
+
+ bool m_disallowed;
+ bool m_quit;
+ bool m_requestSync;
+ bool m_prepared;
+ bool m_initialized;
+};
+
+typedef QSharedPointer<Scene2DSharedObject> Scene2DSharedObjectPtr;
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::Quick::Scene2DSharedObjectPtr)
+
+#endif // QT3DRENDER_QUICK3DRENDER_SCENE2DSHAREDOBJECT_P_H
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2d_global.cpp b/src/quick3d/quick3dscene2d/qt3dquickscene2d_global.cpp
new file mode 100644
index 000000000..da5698d52
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2d_global.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquickscene2d_global_p.h"
+#include "qt3dquickscene2dnodefactory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Quick {
+
+void Quick3DScene2D_initialize()
+{
+ Qt3DCore::QAbstractNodeFactory::registerNodeFactory(QuickScene2DNodeFactory::instance());
+}
+
+void Quick3DScene2D_registerType(const char *className, const char *quickName, int major, int minor)
+{
+ QuickScene2DNodeFactory::instance()->registerType(className, quickName, major, minor);
+}
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2d_global.h b/src/quick3d/quick3dscene2d/qt3dquickscene2d_global.h
new file mode 100644
index 000000000..509a62024
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2d_global.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DQUICKSCENE2D_GLOBAL_H
+#define QT3DQUICKSCENE2D_GLOBAL_H
+
+#include <Qt3DCore/qt3dcore_global.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_SHARED) || !defined(QT_STATIC)
+# if defined(QT_BUILD_3DQUICKSCENE2D_LIB)
+# define QT3DQUICKSCENE2DSHARED_EXPORT Q_DECL_EXPORT
+# else
+# define QT3DQUICKSCENE2DSHARED_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QT3DQUICKSCENE2DSHARED_EXPORT
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT3DQUICKSCENE2D_GLOBAL_H
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2d_global_p.h b/src/quick3d/quick3dscene2d/qt3dquickscene2d_global_p.h
new file mode 100644
index 000000000..e115e3d5e
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2d_global_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DQUICKSCENE2D_GLOBAL_P_H
+#define QT3DQUICKSCENE2D_GLOBAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickScene2D/qt3dquickscene2d_global.h>
+#include <QtQml/qqml.h>
+
+#define QT3DQUICKSCENE2DSHARED_PRIVATE_EXPORT QT3DQUICKSCENE2DSHARED_EXPORT
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+QT3DQUICKSCENE2DSHARED_PRIVATE_EXPORT void Quick3DScene2D_initialize();
+QT3DQUICKSCENE2DSHARED_PRIVATE_EXPORT void Quick3DScene2D_registerType(const char *className,
+ const char *quickName,
+ int major, int minor);
+
+template<class T, class E> void registerExtendedType(const char *className, const char *quickName,
+ const char *uri, int major, int minor,
+ const char *name)
+{
+ qmlRegisterExtendedType<T, E>(uri, major, minor, name);
+ Quick3DScene2D_registerType(className, quickName, major, minor);
+}
+
+template<class T> void registerType(const char *className, const char *quickName,
+ const char *uri, int major, int minor, const char *name)
+{
+ qmlRegisterType<T>(uri, major, minor, name);
+ Quick3DScene2D_registerType(className, quickName, major, minor);
+}
+
+} // Quick
+
+} // Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3DQUICKSCENE2D_GLOBAL_P_H
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2d_logging.cpp b/src/quick3d/quick3dscene2d/qt3dquickscene2d_logging.cpp
new file mode 100644
index 000000000..e60ba0fde
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2d_logging.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquickscene2d_logging_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Quick {
+
+Q_LOGGING_CATEGORY(Scene2D, "Qt3D.Scene2D", QtWarningMsg)
+
+} // Quick
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2d_logging_p.h b/src/quick3d/quick3dscene2d/qt3dquickscene2d_logging_p.h
new file mode 100644
index 000000000..3120e9919
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2d_logging_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DQUICKSCENE2D_LOGGING_P_H
+#define QT3DQUICKSCENE2D_LOGGING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Quick {
+
+Q_DECLARE_LOGGING_CATEGORY(Scene2D)
+
+} // Quick
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DQUICKRENDER_LOGGING_P_H
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory.cpp b/src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory.cpp
new file mode 100644
index 000000000..5d092501e
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquickscene2dnodefactory_p.h"
+#include <QtQml/private/qqmlmetatype_p.h>
+
+#include <private/qrenderaspect_p.h>
+
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+Q_GLOBAL_STATIC(QuickScene2DNodeFactory, quick_scene2d_node_factory)
+
+static void initScene2dPlugin()
+{
+ Qt3DRender::QRenderAspectPrivate::configurePlugin(QLatin1String("scene2d"));
+}
+
+Q_COREAPP_STARTUP_FUNCTION(initScene2dPlugin)
+
+QuickScene2DNodeFactory *QuickScene2DNodeFactory::instance()
+{
+ return quick_scene2d_node_factory();
+}
+
+void QuickScene2DNodeFactory::registerType(const char *className, const char *quickName,
+ int major, int minor)
+{
+ m_types.insert(className, Type(quickName, major, minor));
+}
+
+Qt3DCore::QNode *QuickScene2DNodeFactory::createNode(const char *type)
+{
+ if (!m_types.contains(type))
+ return nullptr;
+
+ Type &typeInfo(m_types[type]);
+
+ if (!typeInfo.resolved) {
+ typeInfo.resolved = true;
+ typeInfo.t = QQmlMetaType::qmlType(QString::fromLatin1(typeInfo.quickName),
+ typeInfo.version.first, typeInfo.version.second);
+ }
+
+ return typeInfo.t ? qobject_cast<Qt3DCore::QNode *>(typeInfo.t->create()) : nullptr;
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory_p.h b/src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory_p.h
new file mode 100644
index 000000000..b5eb82aa1
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/qt3dquickscene2dnodefactory_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUICKSCENENODEFACTORY_H
+#define QUICKSCENENODEFACTORY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qabstractnodefactory_p.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlType;
+
+namespace Qt3DRender {
+
+class QuickScene2DNodeFactory : public Qt3DCore::QAbstractNodeFactory
+{
+public:
+ Qt3DCore::QNode *createNode(const char *type) Q_DECL_OVERRIDE;
+
+ void registerType(const char *className, const char *quickName, int major, int minor);
+
+ static QuickScene2DNodeFactory *instance();
+
+private:
+ struct Type {
+ Type() : t(nullptr), resolved(false) { }
+ Type(const char *quickName, int major, int minor)
+ : quickName(quickName), version(major, minor), t(nullptr), resolved(false) { }
+ QByteArray quickName;
+ QPair<int, int> version;
+ QQmlType *t;
+ bool resolved;
+ };
+ QHash<QByteArray, Type> m_types;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QUICKRENDERERNODEFACTORY_H
diff --git a/src/quick3d/quick3dscene2d/quick3dscene2d.pro b/src/quick3d/quick3dscene2d/quick3dscene2d.pro
new file mode 100644
index 000000000..7d2d59392
--- /dev/null
+++ b/src/quick3d/quick3dscene2d/quick3dscene2d.pro
@@ -0,0 +1,31 @@
+TARGET = Qt3DQuickScene2D
+MODULE = 3dquickscene2d
+
+QT += core core-private qml qml-private 3dcore 3drender 3dquick 3dquick-private 3dcore-private 3drender-private
+CONFIG -= precompile_header
+
+# Qt3D is free of Q_FOREACH - make sure it stays that way:
+DEFINES += QT_NO_FOREACH
+
+gcov {
+ QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
+ QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
+}
+
+SOURCES += \
+ qt3dquickscene2d_global.cpp \
+ qt3dquickscene2dnodefactory.cpp \
+ qt3dquickscene2d_logging.cpp
+
+HEADERS += \
+ qt3dquickscene2dnodefactory_p.h \
+ qt3dquickscene2d_global_p.h \
+ qt3dquickscene2d_global.h \
+ qt3dquickscene2d_logging_p.h
+
+# otherwise mingw headers do not declare common functions like ::strcasecmp
+win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
+
+include(./items/items.pri)
+
+load(qt_module)
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 8b17cbf45..2f7545454 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -56,6 +56,8 @@
#include <Qt3DCore/qnodeid.h>
#include <QtGui/qsurfaceformat.h>
+#include <QtGui/qopenglcontext.h>
+
QT_BEGIN_NAMESPACE
class QSurface;
@@ -137,6 +139,7 @@ public:
virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0;
virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0;
virtual Qt3DCore::QAspectJobPtr syncTextureLoadingJob() = 0;
+ virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0;
virtual void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *root) = 0;
@@ -153,6 +156,7 @@ public:
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
virtual QSurfaceFormat format() = 0;
+ virtual QOpenGLContext *shareContext() const = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractRenderer::BackendNodeDirtySet)
diff --git a/src/render/backend/attachmentpack.cpp b/src/render/backend/attachmentpack.cpp
index d2bb5ee9a..6dee7587b 100644
--- a/src/render/backend/attachmentpack.cpp
+++ b/src/render/backend/attachmentpack.cpp
@@ -60,7 +60,7 @@ AttachmentPack::AttachmentPack(const RenderTargetSelector *selector, const Rende
for (Qt3DCore::QNodeId outputId : outputIds) {
const RenderTargetOutput *output = attachmentManager->lookupResource(outputId);
if (output)
- m_attachments.append(output->attachment());
+ m_attachments.append(*output->attachment());
}
// Create actual DrawBuffers list that is used for glDrawBuffers
diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp
index 7054db6a4..0dc8da237 100644
--- a/src/render/backend/backendnode.cpp
+++ b/src/render/backend/backendnode.cpp
@@ -37,7 +37,10 @@
**
****************************************************************************/
-#include "backendnode_p.h"
+#include <private/backendnode_p.h>
+#include <private/renderer_p.h>
+#include <private/resourceaccessor_p.h>
+#include <private/nodemanagers_p.h>
QT_BEGIN_NAMESPACE
@@ -61,12 +64,23 @@ void BackendNode::setRenderer(AbstractRenderer *renderer)
m_renderer = renderer;
}
+AbstractRenderer *BackendNode::renderer() const
+{
+ return m_renderer;
+}
+
void BackendNode::markDirty(AbstractRenderer::BackendNodeDirtySet changes)
{
Q_ASSERT(m_renderer);
m_renderer->markDirty(changes, this);
}
+QSharedPointer<RenderBackendResourceAccessor> BackendNode::resourceAccessor()
+{
+ Render::Renderer *r = static_cast<Render::Renderer *>(renderer());
+ return r->nodeManagers()->resourceAccessor();
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h
index 5688c2412..8db68b11d 100644
--- a/src/render/backend/backendnode_p.h
+++ b/src/render/backend/backendnode_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/qt3drender_global.h>
#include <Qt3DCore/qbackendnode.h>
#include <Qt3DRender/private/abstractrenderer_p.h>
+#include <private/qt3drender_global_p.h>
QT_BEGIN_NAMESPACE
@@ -61,13 +62,18 @@ namespace Qt3DRender {
namespace Render {
-class Q_AUTOTEST_EXPORT BackendNode : public Qt3DCore::QBackendNode
+class RenderBackendResourceAccessor;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT BackendNode : public Qt3DCore::QBackendNode
{
public:
BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly);
~BackendNode();
void setRenderer(AbstractRenderer *renderer);
+ AbstractRenderer *renderer() const;
+
+ QSharedPointer<RenderBackendResourceAccessor> resourceAccessor();
protected:
void markDirty(AbstractRenderer::BackendNodeDirtySet changes);
diff --git a/src/render/backend/bufferutils_p.h b/src/render/backend/bufferutils_p.h
new file mode 100644
index 000000000..2bb35fac6
--- /dev/null
+++ b/src/render/backend/bufferutils_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Paul Lemire paul.lemire350@gmail.com
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_BUFFERUTILS_P_H
+#define QT3DRENDER_RENDER_BUFFERUTILS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/QAttribute>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class GeometryRenderer;
+class NodeManagers;
+class Attribute;
+class Buffer;
+
+struct BufferInfo
+{
+ BufferInfo()
+ : type(QAttribute::VertexBaseType::Float)
+ , dataSize(0)
+ , count(0)
+ , byteStride(0)
+ , byteOffset(0)
+ {}
+
+ QByteArray data;
+ QAttribute::VertexBaseType type;
+ uint dataSize;
+ uint count;
+ uint byteStride;
+ uint byteOffset;
+};
+
+
+namespace BufferTypeInfo {
+
+ template <QAttribute::VertexBaseType> struct EnumToType;
+ template <> struct EnumToType<QAttribute::Byte> { typedef const char type; };
+ template <> struct EnumToType<QAttribute::UnsignedByte> { typedef const uchar type; };
+ template <> struct EnumToType<QAttribute::Short> { typedef const short type; };
+ template <> struct EnumToType<QAttribute::UnsignedShort> { typedef const ushort type; };
+ template <> struct EnumToType<QAttribute::Int> { typedef const int type; };
+ template <> struct EnumToType<QAttribute::UnsignedInt> { typedef const uint type; };
+ template <> struct EnumToType<QAttribute::Float> { typedef const float type; };
+ template <> struct EnumToType<QAttribute::Double> { typedef const double type; };
+
+ template<QAttribute::VertexBaseType v>
+ typename EnumToType<v>::type *castToType(const QByteArray &u, uint byteOffset)
+ {
+ return reinterpret_cast< typename EnumToType<v>::type *>(u.constData() + byteOffset);
+ }
+
+} // namespace BufferTypeInfo
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+
+#endif // QT3DRENDER_RENDER_BUFFERUTILS_P_H
diff --git a/src/render/backend/buffervisitor_p.h b/src/render/backend/buffervisitor_p.h
new file mode 100644
index 000000000..7149e21ae
--- /dev/null
+++ b/src/render/backend/buffervisitor_p.h
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_BUFFERVISITOR_P_H
+#define QT3DRENDER_RENDER_BUFFERVISITOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qnodeid.h>
+#include <Qt3DRender/QAttribute>
+#include <Qt3DRender/private/trianglesvisitor_p.h>
+#include <Qt3DRender/private/attribute_p.h>
+#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/bufferutils_p.h>
+#include <Qt3DRender/private/geometryrenderer_p.h>
+#include <Qt3DRender/private/geometry_p.h>
+#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QEntity;
+}
+
+namespace Qt3DRender {
+namespace Render {
+
+
+template <typename ValueType, QAttribute::VertexBaseType VertexBaseType, uint dataSize>
+class Q_AUTOTEST_EXPORT BufferVisitor
+{
+public:
+ explicit BufferVisitor(NodeManagers *manager)
+ : m_manager(manager)
+ {
+ }
+ virtual ~BufferVisitor() { }
+
+ virtual void visit(uint ndx, ValueType x) {
+ Q_UNUSED(ndx); Q_UNUSED(x);
+ }
+ virtual void visit(uint ndx, ValueType x, ValueType y) {
+ Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y);
+ }
+ virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z) {
+ Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z);
+ }
+ virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z, ValueType w) {
+ Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z); Q_UNUSED(w);
+ }
+
+ bool apply(const GeometryRenderer *renderer, const QString &attributeName)
+ {
+ if (renderer == nullptr || renderer->instanceCount() != 1) {
+ return false;
+ }
+
+ Geometry *geom = m_manager->lookupResource<Geometry, GeometryManager>(renderer->geometryId());
+
+ if (!geom)
+ return false;
+
+ Attribute *attribute = nullptr;
+
+ const auto attrIds = geom->attributes();
+ for (const Qt3DCore::QNodeId attrId : attrIds) {
+ attribute = m_manager->lookupResource<Attribute, AttributeManager>(attrId);
+ if (attribute){
+ if (attribute->name() == attributeName
+ || (attributeName == QStringLiteral("default")
+ && attribute->name() == QAttribute::defaultTextureCoordinateAttributeName())) {
+ break;
+ }
+ }
+ attribute = nullptr;
+ }
+
+ if (!attribute)
+ return false;
+
+ return apply(attribute);
+ }
+
+ bool apply(Qt3DRender::Render::Attribute *attribute)
+ {
+ if (attribute->vertexBaseType() != VertexBaseType)
+ return false;
+ if (attribute->vertexSize() < dataSize)
+ return false;
+
+ auto data = m_manager->lookupResource<Buffer, BufferManager>(attribute->bufferId())->data();
+ auto buffer = BufferTypeInfo::castToType<VertexBaseType>(data, attribute->byteOffset());
+ switch (dataSize) {
+ case 1: traverseCoordinates1(buffer, attribute->byteStride(), attribute->count()); break;
+ case 2: traverseCoordinates2(buffer, attribute->byteStride(), attribute->count()); break;
+ case 3: traverseCoordinates3(buffer, attribute->byteStride(), attribute->count()); break;
+ case 4: traverseCoordinates4(buffer, attribute->byteStride(), attribute->count()); break;
+ default: Q_UNREACHABLE();
+ }
+
+ return true;
+ }
+
+protected:
+
+ template <typename Coordinate>
+ void traverseCoordinates1(Coordinate *coordinates,
+ const uint byteStride,
+ const uint count)
+ {
+ const uint stride = byteStride / sizeof(Coordinate);
+ for (uint ndx = 0; ndx < count; ++ndx) {
+ visit(ndx, coordinates[0]);
+ coordinates += stride;
+ }
+ }
+
+ template <typename Coordinate>
+ void traverseCoordinates2(Coordinate *coordinates,
+ const uint byteStride,
+ const uint count)
+ {
+ const uint stride = byteStride / sizeof(Coordinate);
+ for (uint ndx = 0; ndx < count; ++ndx) {
+ visit(ndx, coordinates[0], coordinates[1]);
+ coordinates += stride;
+ }
+ }
+
+ template <typename Coordinate>
+ void traverseCoordinates3(Coordinate *coordinates,
+ const uint byteStride,
+ const uint count)
+ {
+ const uint stride = byteStride / sizeof(Coordinate);
+ for (uint ndx = 0; ndx < count; ++ndx) {
+ visit(ndx, coordinates[0], coordinates[1], coordinates[2]);
+ coordinates += stride;
+ }
+ }
+
+ template <typename Coordinate>
+ void traverseCoordinates4(Coordinate *coordinates,
+ const uint byteStride,
+ const uint count)
+ {
+ const uint stride = byteStride / sizeof(Coordinate);
+ for (uint ndx = 0; ndx < count; ++ndx) {
+ visit(ndx, coordinates[0], coordinates[1], coordinates[2], coordinates[3]);
+ coordinates += stride;
+ }
+ }
+
+ NodeManagers *m_manager;
+};
+
+typedef BufferVisitor<float, QAttribute::Float, 3> Buffer3fVisitor;
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+
+#endif // QT3DRENDER_RENDER_BUFFERVISITOR_P_H
diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp
index e60a32422..ef71507eb 100644
--- a/src/render/backend/cameralens.cpp
+++ b/src/render/backend/cameralens.cpp
@@ -39,8 +39,14 @@
#include "cameralens_p.h"
#include <Qt3DRender/qcameralens.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/qcameralens_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
+#include <Qt3DRender/private/renderer_p.h>
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/sphere_p.h>
+#include <Qt3DRender/private/computefilteredboundingvolumejob_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qtransform.h>
@@ -52,8 +58,35 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+
+namespace {
+
+class GetBoundingVolumeWithoutCameraJob : public ComputeFilteredBoundingVolumeJob
+{
+public:
+ GetBoundingVolumeWithoutCameraJob(CameraLens *lens,
+ QNodeCommand::CommandId commandId)
+ : m_lens(lens), m_commandId(commandId)
+ {
+ }
+
+protected:
+ void finished(const Sphere &sphere) override
+ {
+ m_lens->notifySceneBoundingVolume(sphere, m_commandId);
+ }
+
+private:
+ CameraLens *m_lens;
+ QNodeCommand::CommandId m_commandId;
+};
+
+} // namespace
+
CameraLens::CameraLens()
- : BackendNode()
+ : BackendNode(QBackendNode::ReadWrite)
+ , m_renderAspect(nullptr)
+ , m_exposure(0.0f)
{
}
@@ -67,11 +100,52 @@ void CameraLens::cleanup()
QBackendNode::setEnabled(false);
}
+void CameraLens::setRenderAspect(QRenderAspect *renderAspect)
+{
+ m_renderAspect = renderAspect;
+}
+
void CameraLens::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QCameraLensData>>(change);
const auto &data = typedChange->data;
m_projection = data.projectionMatrix;
+ m_exposure = data.exposure;
+}
+
+void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
+ QNodeId cameraId,
+ QNodeCommand::CommandId commandId)
+{
+ if (!m_renderer || !m_renderAspect)
+ return;
+ NodeManagers *nodeManagers = m_renderer->nodeManagers();
+
+ Entity *root = m_renderer->sceneRoot();
+ if (!entityId.isNull())
+ root = nodeManagers->renderNodesManager()->lookupResource(entityId);
+ if (!root)
+ return;
+
+ Entity *camNode = nodeManagers->renderNodesManager()->lookupResource(cameraId);
+ ComputeFilteredBoundingVolumeJobPtr job(new GetBoundingVolumeWithoutCameraJob(this, commandId));
+ job->addDependency(m_renderer->expandBoundingVolumeJob());
+ job->setRoot(root);
+ job->ignoreSubTree(camNode);
+ m_renderAspect->scheduleSingleShotJob(job);
+}
+
+void CameraLens::notifySceneBoundingVolume(const Sphere &sphere, QNodeCommand::CommandId commandId)
+{
+ if (m_pendingViewAllCommand != commandId)
+ return;
+ if (sphere.radius() > 0.f) {
+ QVector<float> data = { sphere.center().x(), sphere.center().y(), sphere.center().z(),
+ sphere.radius() };
+ QVariant v;
+ v.setValue(data);
+ sendCommand(QLatin1Literal("ViewAll"), v, m_pendingViewAllCommand);
+ }
}
void CameraLens::setProjection(const QMatrix4x4 &projection)
@@ -79,6 +153,11 @@ void CameraLens::setProjection(const QMatrix4x4 &projection)
m_projection = projection;
}
+void CameraLens::setExposure(float exposure)
+{
+ m_exposure = exposure;
+}
+
void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
switch (e->type()) {
@@ -88,18 +167,63 @@ void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
if (propertyChange->propertyName() == QByteArrayLiteral("projectionMatrix")) {
QMatrix4x4 projectionMatrix = propertyChange->value().value<QMatrix4x4>();
m_projection = projectionMatrix;
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("exposure")) {
+ setExposure(propertyChange->value().toFloat());
}
markDirty(AbstractRenderer::AllDirty);
}
break;
+ case CommandRequested: {
+ QNodeCommandPtr command = qSharedPointerCast<QNodeCommand>(e);
+
+ if (command->name() == QLatin1Literal("QueryRootBoundingVolume")) {
+ m_pendingViewAllCommand = command->commandId();
+ QVariant v = command->data();
+ QNodeId id = v.value<QNodeId>();
+ computeSceneBoundingVolume({}, id, command->commandId());
+ } else if (command->name() == QLatin1Literal("QueryEntityBoundingVolume")) {
+ m_pendingViewAllCommand = command->commandId();
+ QVariant v = command->data();
+ QVector<QNodeId> ids = v.value<QVector<QNodeId>>();
+ if (ids.size() == 2)
+ computeSceneBoundingVolume(ids[0], ids[1], command->commandId());
+ }
+ }
+ break;
+
default:
break;
}
BackendNode::sceneChangeEvent(e);
}
+CameraLensFunctor::CameraLensFunctor(AbstractRenderer *renderer, QRenderAspect *renderAspect)
+ : m_manager(renderer->nodeManagers()->manager<CameraLens, CameraManager>())
+ , m_renderer(renderer)
+ , m_renderAspect(renderAspect)
+{
+}
+
+QBackendNode *CameraLensFunctor::create(const QNodeCreatedChangeBasePtr &change) const
+{
+ CameraLens *backend = m_manager->getOrCreateResource(change->subjectId());
+ backend->setRenderer(m_renderer);
+ backend->setRenderAspect(m_renderAspect);
+ return backend;
+}
+
+QBackendNode *CameraLensFunctor::get(QNodeId id) const
+{
+ return m_manager->lookupResource(id);
+}
+
+void CameraLensFunctor::destroy(QNodeId id) const
+{
+ m_manager->releaseResource(id);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/cameralens_p.h b/src/render/backend/cameralens_p.h
index e5268da53..4bf147f48 100644
--- a/src/render/backend/cameralens_p.h
+++ b/src/render/backend/cameralens_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DRender/private/backendnode_p.h>
+#include <Qt3DCore/private/qnodecommand_p.h>
#include <QMatrix4x4>
#include <QRectF>
@@ -62,6 +63,21 @@ namespace Qt3DRender {
namespace Render {
class CameraManager;
+class Sphere;
+
+class CameraLensFunctor : public Qt3DCore::QBackendNodeMapper
+{
+public:
+ explicit CameraLensFunctor(AbstractRenderer *renderer, QRenderAspect *renderAspect);
+ Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const Q_DECL_OVERRIDE;
+ Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const Q_DECL_OVERRIDE;
+ void destroy(Qt3DCore::QNodeId id) const Q_DECL_OVERRIDE;
+
+private:
+ CameraManager *m_manager;
+ AbstractRenderer *m_renderer;
+ QRenderAspect *m_renderAspect;
+};
class CameraLens : public BackendNode
{
@@ -70,15 +86,27 @@ public:
~CameraLens();
void cleanup();
+ void setRenderAspect(QRenderAspect* renderAspect);
+
void setProjection(const QMatrix4x4 &projection);
inline QMatrix4x4 projection() const { return m_projection; }
+ void setExposure(float exposure);
+ inline float exposure() const { return m_exposure; }
+
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void notifySceneBoundingVolume(const Sphere &sphere, Qt3DCore::QNodeCommand::CommandId commandId);
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void computeSceneBoundingVolume(Qt3DCore::QNodeId entityId,
+ Qt3DCore::QNodeId cameraId,
+ Qt3DCore::QNodeCommand::CommandId commandId);
+ QRenderAspect *m_renderAspect;
QMatrix4x4 m_projection;
+ Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand;
+ float m_exposure;
};
} // namespace Render
diff --git a/src/render/backend/commandexecuter.cpp b/src/render/backend/commandexecuter.cpp
index 2f13b27ea..84bf7455a 100644
--- a/src/render/backend/commandexecuter.cpp
+++ b/src/render/backend/commandexecuter.cpp
@@ -34,9 +34,8 @@
**
****************************************************************************/
-#ifdef QT3D_JOBS_RUN_STATS
-
#include "commandexecuter_p.h"
+
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DCore/qbackendnode.h>
@@ -388,5 +387,3 @@ QVariant CommandExecuter::executeCommand(const QStringList &args)
} // Qt3DRenderer
QT_END_NAMESPACE
-
-#endif
diff --git a/src/render/backend/commandexecuter_p.h b/src/render/backend/commandexecuter_p.h
index 8135d97d9..896164543 100644
--- a/src/render/backend/commandexecuter_p.h
+++ b/src/render/backend/commandexecuter_p.h
@@ -48,8 +48,6 @@
// We mean it.
//
-#ifdef QT3D_JOBS_RUN_STATS
-
#include <QVector>
#include <QVariant>
@@ -92,6 +90,4 @@ private:
QT_END_NAMESPACE
-#endif // QT3D_JOBS_RUN_STATS
-
#endif // QT3DRENDER_DEBUG_COMMANDEXECUTER_H
diff --git a/src/render/backend/commandthread.cpp b/src/render/backend/commandthread.cpp
new file mode 100644
index 000000000..f91cff017
--- /dev/null
+++ b/src/render/backend/commandthread.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "commandthread_p.h"
+#include <QOpenGLContext>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+CommandThread::CommandThread(Renderer *renderer)
+ : QThread()
+ , m_renderer(renderer)
+ , m_waitForStartSemaphore(0)
+ , m_initializedSemaphore(0)
+{
+}
+
+CommandThread::~CommandThread()
+{
+}
+
+// Called by RenderThread or MainThread (Scene3d)
+void CommandThread::initialize(QOpenGLContext *mainContext)
+{
+ // Start the thread
+ start();
+
+ // Wait for thread to be started
+ m_waitForStartSemaphore.acquire();
+
+ m_mainContext = mainContext;
+ Q_ASSERT(m_mainContext);
+
+ // Allow thread to proceed
+ m_initializedSemaphore.release();
+}
+
+// Called by RenderThread of MainThread (Scene3D)
+void CommandThread::shutdown()
+{
+ // Tell thread to exit event loop
+ QThread::quit();
+
+ // Wait for thread to exit
+ wait();
+
+ // Reset semaphores (in case we ever want to restart)
+ m_waitForStartSemaphore.release(m_waitForStartSemaphore.available());
+ m_initializedSemaphore.release(m_initializedSemaphore.available());
+ m_localContext.reset();
+}
+
+// Any thread can call this, this is a blocking command
+void CommandThread::executeCommand(Command *command)
+{
+ if (!isRunning())
+ return;
+ QMetaObject::invokeMethod(this,
+ "executeCommandInternal",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(Command *, command));
+}
+
+void CommandThread::run()
+{
+ // Allow initialize to proceed
+ m_waitForStartSemaphore.release();
+
+ // Wait for initialize to be completed
+ m_initializedSemaphore.acquire();
+
+ // Initialize shared context and resources for the thread
+ m_localContext.reset(new QOpenGLContext());
+ m_localContext->setShareContext(m_mainContext);
+
+ // Launch exec loop
+ QThread::exec();
+}
+
+// Executed in the Command Thread
+void CommandThread::executeCommandInternal(Command *command)
+{
+ command->execute(m_renderer, m_localContext.data());
+}
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3danimation/items/quick3dabstractclipblendnode_p.h b/src/render/backend/commandthread_p.h
index bfb1825a7..1955d13ac 100644
--- a/src/quick3d/quick3danimation/items/quick3dabstractclipblendnode_p.h
+++ b/src/render/backend/commandthread_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DANIMATION_ANIMATION_QUICK3DABSTRACTCLIPBLENDNODE_P_H
-#define QT3DANIMATION_ANIMATION_QUICK3DABSTRACTCLIPBLENDNODE_P_H
+#ifndef QT3DRENDER_RENDER_COMMANDTHREAD_P_H
+#define QT3DRENDER_RENDER_COMMANDTHREAD_P_H
//
// W A R N I N G
@@ -51,39 +51,55 @@
// We mean it.
//
-#include <Qt3DQuickAnimation/private/qt3dquickanimation_global_p.h>
-#include <Qt3DAnimation/qabstractclipblendnode.h>
-#include <Qt3DAnimation/qanimationclip.h>
-#include <QQmlListProperty>
+#include <QtCore/QThread>
+#include <QtCore/QSemaphore>
QT_BEGIN_NAMESPACE
-namespace Qt3DAnimation {
-namespace Animation {
-namespace Quick {
+class QOpenGLContext;
-class QT3DQUICKANIMATIONSHARED_PRIVATE_EXPORT Quick3DAbstractClipBlendNode : public QObject
+namespace Qt3DRender {
+
+namespace Render {
+
+class Renderer;
+
+class Command
{
- Q_OBJECT
- Q_PROPERTY(QQmlListProperty<Qt3DAnimation::QAnimationClip> clips READ clipList CONSTANT)
+public:
+ virtual void execute(Renderer *renderer, QOpenGLContext *localContext) = 0;
+};
+class CommandThread : public QThread
+{
+ Q_OBJECT
public:
- explicit Quick3DAbstractClipBlendNode(QObject *parent = nullptr);
+ explicit CommandThread(Renderer *renderer);
+ ~CommandThread();
+
+ Render::Renderer* renderer() const { return m_renderer; }
+
+ void initialize(QOpenGLContext *mainContext);
+ void shutdown();
- inline QAbstractClipBlendNode *parentAbstractClipBlendNode() const { return qobject_cast<QAbstractClipBlendNode *>(parent()); }
- QQmlListProperty<QAnimationClip> clipList();
+ void executeCommand(Command *command);
private:
- static void appendClip(QQmlListProperty<QAnimationClip> *list, QAnimationClip *clip);
- static QAnimationClip *clipAt(QQmlListProperty<QAnimationClip> *list, int index);
- static int clipCount(QQmlListProperty<QAnimationClip> *list);
- static void clearClips(QQmlListProperty<QAnimationClip> *list);
+ void run() Q_DECL_OVERRIDE;
+ Q_INVOKABLE void executeCommandInternal(Command *command);
+
+private:
+ Renderer* m_renderer;
+ QSemaphore m_waitForStartSemaphore;
+ QSemaphore m_initializedSemaphore;
+ QOpenGLContext *m_mainContext;
+ QScopedPointer<QOpenGLContext> m_localContext;
};
-} // Quick
-} // Animation
-} // Qt3DAnimation
+} // Render
+
+} // Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DANIMATION_ANIMATION_QUICK3DABSTRACTCLIPBLENDNODE_P_H
+#endif // QT3DRENDER_RENDER_COMMANDTHREAD_P_H
diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp
index 42233c85a..898c1e36e 100644
--- a/src/render/backend/entity.cpp
+++ b/src/render/backend/entity.cpp
@@ -41,6 +41,7 @@
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/qabstractlight.h>
+#include <Qt3DRender/qenvironmentlight.h>
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/qlevelofdetail.h>
#include <Qt3DRender/qmaterial.h>
@@ -118,6 +119,7 @@ void Entity::cleanup()
m_levelOfDetailComponents.clear();
m_shaderDataComponents.clear();
m_lightComponents.clear();
+ m_environmentLightComponents.clear();
m_localBoundingVolume.reset();
m_worldBoundingVolume.reset();
m_worldBoundingVolumeWithChildren.reset();
@@ -174,6 +176,7 @@ void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
m_levelOfDetailComponents.clear();
m_shaderDataComponents.clear();
m_lightComponents.clear();
+ m_environmentLightComponents.clear();
m_localBoundingVolume.reset(new Sphere(peerId()));
m_worldBoundingVolume.reset(new Sphere(peerId()));
m_worldBoundingVolumeWithChildren.reset(new Sphere(peerId()));
@@ -293,6 +296,8 @@ void Entity::addComponent(Qt3DCore::QComponent *component)
m_materialComponent = component->id();
} else if (qobject_cast<QAbstractLight *>(component) != nullptr) {
m_lightComponents.append(component->id());
+ } else if (qobject_cast<QEnvironmentLight *>(component) != nullptr) {
+ m_environmentLightComponents.append(component->id());
} else if (qobject_cast<QShaderData *>(component) != nullptr) {
m_shaderDataComponents.append(component->id());
} else if (qobject_cast<QGeometryRenderer *>(component) != nullptr) {
@@ -326,6 +331,8 @@ void Entity::addComponent(Qt3DCore::QNodeIdTypePair idAndType)
m_materialComponent = id;
} else if (type->inherits(&QAbstractLight::staticMetaObject)) { // QAbstractLight subclasses QShaderData
m_lightComponents.append(id);
+ } else if (type->inherits(&QEnvironmentLight::staticMetaObject)) {
+ m_environmentLightComponents.append(id);
} else if (type->inherits(&QShaderData::staticMetaObject)) {
m_shaderDataComponents.append(id);
} else if (type->inherits(&QGeometryRenderer::staticMetaObject)) {
@@ -363,6 +370,8 @@ void Entity::removeComponent(Qt3DCore::QNodeId nodeId)
// m_boundingVolumeDebugComponent = QNodeId();
} else if (m_lightComponents.contains(nodeId)) {
m_lightComponents.removeAll(nodeId);
+ } else if (m_environmentLightComponents.contains(nodeId)) {
+ m_environmentLightComponents.removeAll(nodeId);
} else if (m_computeComponent == nodeId) {
m_computeComponent = QNodeId();
}
@@ -457,6 +466,16 @@ QVector<HLight> Entity::componentsHandle<Light>() const
}
template<>
+QVector<HEnvironmentLight> Entity::componentsHandle<EnvironmentLight>() const
+{
+ QVector<HEnvironmentLight> lightHandles;
+ lightHandles.reserve(m_environmentLightComponents.size());
+ for (QNodeId id : m_environmentLightComponents)
+ lightHandles.append(m_nodeManagers->environmentLightManager()->lookupHandle(id));
+ return lightHandles;
+}
+
+template<>
HComputeCommand Entity::componentHandle<ComputeCommand>() const
{
return m_nodeManagers->computeJobManager()->lookupHandle(m_computeComponent);
@@ -534,6 +553,16 @@ QVector<Light *> Entity::renderComponents<Light>() const
return lights;
}
+template<>
+QVector<EnvironmentLight *> Entity::renderComponents<EnvironmentLight>() const
+{
+ QVector<EnvironmentLight *> lights;
+ lights.reserve(m_environmentLightComponents.size());
+ for (QNodeId id : m_environmentLightComponents)
+ lights.append(m_nodeManagers->environmentLightManager()->lookupResource(id));
+ return lights;
+}
+
//template<>
//BoundingVolumeDebug *Entity::renderComponent<BoundingVolumeDebug>() const
//{
@@ -581,6 +610,9 @@ QNodeId Entity::componentUuid<ComputeCommand>() const { return m_computeComponen
template<>
QVector<Qt3DCore::QNodeId> Entity::componentsUuid<Light>() const { return m_lightComponents; }
+template<>
+QVector<Qt3DCore::QNodeId> Entity::componentsUuid<EnvironmentLight>() const { return m_environmentLightComponents; }
+
RenderEntityFunctor::RenderEntityFunctor(AbstractRenderer *renderer, NodeManagers *manager)
: m_nodeManagers(manager)
, m_renderer(renderer)
diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h
index c86019444..4619314ad 100644
--- a/src/render/backend/entity_p.h
+++ b/src/render/backend/entity_p.h
@@ -190,6 +190,7 @@ private:
QVector<Qt3DCore::QNodeId> m_levelOfDetailComponents;
QVector<Qt3DCore::QNodeId> m_shaderDataComponents;
QVector<Qt3DCore::QNodeId> m_lightComponents;
+ QVector<Qt3DCore::QNodeId> m_environmentLightComponents;
Qt3DCore::QNodeId m_geometryRendererComponent;
Qt3DCore::QNodeId m_objectPickerComponent;
Qt3DCore::QNodeId m_boundingVolumeDebugComponent;
@@ -233,6 +234,9 @@ template<>
QVector<HLight> Entity::componentsHandle<Light>() const;
template<>
+QVector<HEnvironmentLight> Entity::componentsHandle<EnvironmentLight>() const;
+
+template<>
Q_AUTOTEST_EXPORT HComputeCommand Entity::componentHandle<ComputeCommand>() const;
// Render components
@@ -246,10 +250,10 @@ template<>
Transform *Entity::renderComponent<Transform>() const;
template<>
-Q_AUTOTEST_EXPORT GeometryRenderer *Entity::renderComponent<GeometryRenderer>() const;
+QT3DRENDERSHARED_PRIVATE_EXPORT GeometryRenderer *Entity::renderComponent<GeometryRenderer>() const;
template<>
-Q_AUTOTEST_EXPORT ObjectPicker *Entity::renderComponent<ObjectPicker>() const;
+QT3DRENDERSHARED_PRIVATE_EXPORT ObjectPicker *Entity::renderComponent<ObjectPicker>() const;
template<>
QVector<Layer *> Entity::renderComponents<Layer>() const;
@@ -267,6 +271,9 @@ template<>
QVector<Light *> Entity::renderComponents<Light>() const;
template<>
+QVector<EnvironmentLight *> Entity::renderComponents<EnvironmentLight>() const;
+
+template<>
Q_AUTOTEST_EXPORT ComputeCommand *Entity::renderComponent<ComputeCommand>() const;
// UUid
@@ -289,10 +296,10 @@ template<>
Q_AUTOTEST_EXPORT QVector<Qt3DCore::QNodeId> Entity::componentsUuid<ShaderData>() const;
template<>
-Q_AUTOTEST_EXPORT Qt3DCore::QNodeId Entity::componentUuid<GeometryRenderer>() const;
+QT3DRENDERSHARED_PRIVATE_EXPORT Qt3DCore::QNodeId Entity::componentUuid<GeometryRenderer>() const;
template<>
-Q_AUTOTEST_EXPORT Qt3DCore::QNodeId Entity::componentUuid<ObjectPicker>() const;
+QT3DRENDERSHARED_PRIVATE_EXPORT Qt3DCore::QNodeId Entity::componentUuid<ObjectPicker>() const;
//template<>
//Q_AUTOTEST_EXPORT Qt3DCore::QNodeId Entity::componentUuid<BoundingVolumeDebug>() const;
@@ -303,6 +310,9 @@ Q_AUTOTEST_EXPORT Qt3DCore::QNodeId Entity::componentUuid<ComputeCommand>() cons
template<>
Q_AUTOTEST_EXPORT QVector<Qt3DCore::QNodeId> Entity::componentsUuid<Light>() const;
+template<>
+Q_AUTOTEST_EXPORT QVector<Qt3DCore::QNodeId> Entity::componentsUuid<EnvironmentLight>() const;
+
class RenderEntityFunctor : public Qt3DCore::QBackendNodeMapper
{
public:
diff --git a/src/render/backend/frameprofiler_p.h b/src/render/backend/frameprofiler_p.h
index 2412a8053..9e7bcd038 100644
--- a/src/render/backend/frameprofiler_p.h
+++ b/src/render/backend/frameprofiler_p.h
@@ -69,7 +69,7 @@ enum RecordingType
RenderTargetUpdate
};
-#ifdef QT3D_JOBS_RUN_STATS
+#ifdef QT3D_OPENGL_RUN_STATS
class FrameTimeRecorder
{
@@ -218,33 +218,35 @@ public:
explicit GLTimeRecorder(RecordingType type)
: m_type(type)
{
-#ifdef QT3D_JOBS_RUN_STATS
+#ifdef QT3D_OPENGL_RUN_STATS
frameProfiler.startRecordEvent();
#endif
}
~GLTimeRecorder()
{
-#ifdef QT3D_JOBS_RUN_STATS
+#ifdef QT3D_OPENGL_RUN_STATS
frameProfiler.recordEvent(m_type);
+#else
+ Q_UNUSED(m_type);
#endif
}
static void writeResults()
{
-#ifdef QT3D_JOBS_RUN_STATS
+#ifdef QT3D_OPENGL_RUN_STATS
frameProfiler.writeResults();
#endif
}
private:
-#ifdef QT3D_JOBS_RUN_STATS
+#ifdef QT3D_OPENGL_RUN_STATS
static FrameProfiler frameProfiler;
#endif
RecordingType m_type;
};
-#ifdef QT3D_JOBS_RUN_STATS
+#ifdef QT3D_OPENGL_RUN_STATS
FrameProfiler GLTimeRecorder::frameProfiler;
#endif
diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h
index c8c73b749..352519e75 100644
--- a/src/render/backend/handle_types_p.h
+++ b/src/render/backend/handle_types_p.h
@@ -90,6 +90,7 @@ class ObjectPicker;
class BoundingVolumeDebug;
class OpenGLVertexArrayObject;
class Light;
+class EnvironmentLight;
class ComputeCommand;
class GLBuffer;
class RenderStateNode;
@@ -122,6 +123,7 @@ typedef Qt3DCore::QHandle<GeometryRenderer, 16> HGeometryRenderer;
typedef Qt3DCore::QHandle<ObjectPicker, 16> HObjectPicker;
typedef Qt3DCore::QHandle<BoundingVolumeDebug, 16> HBoundingVolumeDebug;
typedef Qt3DCore::QHandle<Light, 16> HLight;
+typedef Qt3DCore::QHandle<EnvironmentLight, 16> HEnvironmentLight;
typedef Qt3DCore::QHandle<ComputeCommand, 16> HComputeCommand;
typedef Qt3DCore::QHandle<GLBuffer, 16> HGLBuffer;
typedef Qt3DCore::QHandle<RenderStateNode, 16> HRenderState;
diff --git a/src/render/backend/levelofdetail.cpp b/src/render/backend/levelofdetail.cpp
index 474133d1c..157bfc004 100644
--- a/src/render/backend/levelofdetail.cpp
+++ b/src/render/backend/levelofdetail.cpp
@@ -39,11 +39,9 @@
#include "levelofdetail_p.h"
#include <Qt3DRender/QLevelOfDetail>
-#include <Qt3DRender/QBoundingSphere>
#include <Qt3DRender/private/qlevelofdetail_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <QVariant>
QT_BEGIN_NAMESPACE
@@ -56,8 +54,8 @@ namespace Render {
LevelOfDetail::LevelOfDetail()
: BackendNode(BackendNode::ReadWrite)
, m_currentIndex(0)
- , m_thresholdType(QLevelOfDetail::DistanceToCamera)
- , m_radius(1.f)
+ , m_thresholdType(QLevelOfDetail::DistanceToCameraThreshold)
+ , m_volumeOverride()
{
}
@@ -74,8 +72,7 @@ void LevelOfDetail::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
m_currentIndex = data.currentIndex;
m_thresholdType = data.thresholdType;
m_thresholds = data.thresholds;
- m_radius = data.radius;
- m_center = data.center;
+ m_volumeOverride = data.volumeOverride;
}
void LevelOfDetail::cleanup()
@@ -87,23 +84,16 @@ void LevelOfDetail::sceneChangeEvent(const QSceneChangePtr &e)
{
if (e->type() == PropertyUpdated) {
const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("currentIndex")) {
+ if (propertyChange->propertyName() == QByteArrayLiteral("currentIndex"))
m_currentIndex = propertyChange->value().value<int>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("camera")) {
+ else if (propertyChange->propertyName() == QByteArrayLiteral("camera"))
m_camera = propertyChange->value().value<Qt3DCore::QNodeId>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("thresholdType")) {
+ else if (propertyChange->propertyName() == QByteArrayLiteral("thresholdType"))
m_thresholdType = propertyChange->value().value<QLevelOfDetail::ThresholdType>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("thresholds")) {
+ else if (propertyChange->propertyName() == QByteArrayLiteral("thresholds"))
m_thresholds = propertyChange->value().value<QVector<qreal>>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("center")) {
- m_center = propertyChange->value().value<QVector3D>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("radius")) {
- m_radius = propertyChange->value().value<float>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("volumeOverride")) {
- auto volumeOverride = propertyChange->value().value<Qt3DRender::QBoundingSphere*>();
- m_center = volumeOverride ? volumeOverride->center() : QVector3D();
- m_radius = volumeOverride ? volumeOverride->radius() : -1.f;
- }
+ else if (propertyChange->propertyName() == QByteArrayLiteral("volumeOverride"))
+ m_volumeOverride = propertyChange->value().value<Qt3DRender::QLevelOfDetailBoundingSphere>();
}
markDirty(AbstractRenderer::GeometryDirty);
@@ -119,7 +109,6 @@ void LevelOfDetail::setCurrentIndex(int currentIndex)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("currentIndex");
e->setValue(m_currentIndex);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
diff --git a/src/render/backend/levelofdetail_p.h b/src/render/backend/levelofdetail_p.h
index 83809a631..05f5686bb 100644
--- a/src/render/backend/levelofdetail_p.h
+++ b/src/render/backend/levelofdetail_p.h
@@ -79,8 +79,9 @@ public:
int currentIndex() const { return m_currentIndex; }
QLevelOfDetail::ThresholdType thresholdType() const { return m_thresholdType; }
QVector<qreal> thresholds() const { return m_thresholds; }
- float radius() const { return m_radius; }
- QVector3D center() const { return m_center; }
+ float radius() const { return m_volumeOverride.radius(); }
+ QVector3D center() const { return m_volumeOverride.center(); }
+ bool hasBoundingVolumeOverride() const { return !m_volumeOverride.isEmpty(); }
void setCurrentIndex(int currentIndex);
@@ -90,8 +91,7 @@ private:
int m_currentIndex;
QLevelOfDetail::ThresholdType m_thresholdType;
QVector<qreal> m_thresholds;
- float m_radius;
- QVector3D m_center;
+ QLevelOfDetailBoundingSphere m_volumeOverride;
};
} // namespace Render
diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h
index ce6767958..1c1a34b83 100644
--- a/src/render/backend/managers_p.h
+++ b/src/render/backend/managers_p.h
@@ -77,6 +77,7 @@
#include <Qt3DRender/private/boundingvolumedebug_p.h>
#include <Qt3DRender/private/openglvertexarrayobject_p.h>
#include <Qt3DRender/private/light_p.h>
+#include <Qt3DRender/private/environmentlight_p.h>
#include <Qt3DRender/private/computecommand_p.h>
QT_BEGIN_NAMESPACE
@@ -260,7 +261,7 @@ public:
class VAOManager : public Qt3DCore::QResourceManager<
OpenGLVertexArrayObject,
- QPair<HGeometry, HShader>,
+ VAOIdentifier,
16,
Qt3DCore::ArrayAllocatingPolicy,
Qt3DCore::NonLockingPolicy>
@@ -381,6 +382,17 @@ public:
LightManager() {}
};
+class EnvironmentLightManager : public Qt3DCore::QResourceManager<
+ EnvironmentLight,
+ Qt3DCore::QNodeId,
+ 16,
+ Qt3DCore::ArrayAllocatingPolicy,
+ Qt3DCore::NonLockingPolicy>
+{
+public:
+ EnvironmentLightManager() {}
+};
+
class ComputeCommandManager : public Qt3DCore::QResourceManager<
ComputeCommand,
Qt3DCore::QNodeId,
@@ -422,6 +434,7 @@ Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::BoundingVolumeDebug, Q_REQUIRES_CLEA
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::ComputeCommand, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Parameter, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Transform, Q_REQUIRES_CLEANUP)
+Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::OpenGLVertexArrayObject, Q_REQUIRES_CLEANUP)
QT_END_NAMESPACE
diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp
index d83623ce2..2647bbb1a 100644
--- a/src/render/backend/nodemanagers.cpp
+++ b/src/render/backend/nodemanagers.cpp
@@ -46,6 +46,7 @@
#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/techniquemanager_p.h>
+#include <private/resourceaccessor_p.h>
#include <QOpenGLVertexArrayObject>
@@ -88,8 +89,10 @@ NodeManagers::NodeManagers()
, m_objectPickerManager(new ObjectPickerManager())
// , m_boundingVolumeDebugManager(new BoundingVolumeDebugManager())
, m_lightManager(new LightManager())
+ , m_environmentLightManager(new EnvironmentLightManager())
, m_computeJobManager(new ComputeCommandManager())
, m_renderStateManager(new RenderStateManager())
+ , m_resourceAccessor(new ResourceAccessor(this))
{
}
@@ -126,11 +129,17 @@ NodeManagers::~NodeManagers()
delete m_objectPickerManager;
// delete m_boundingVolumeDebugManager;
delete m_lightManager;
+ delete m_environmentLightManager;
delete m_computeJobManager;
delete m_renderStateManager;
delete m_renderNodesManager;
}
+QSharedPointer<ResourceAccessor> NodeManagers::resourceAccessor()
+{
+ return m_resourceAccessor;
+}
+
template<>
CameraManager *NodeManagers::manager<CameraLens>() const Q_DECL_NOTHROW
{
@@ -312,6 +321,12 @@ LightManager *NodeManagers::manager<Light>() const Q_DECL_NOTHROW
}
template<>
+EnvironmentLightManager *NodeManagers::manager<EnvironmentLight>() const Q_DECL_NOTHROW
+{
+ return m_environmentLightManager;
+}
+
+template<>
ComputeCommandManager *NodeManagers::manager<ComputeCommand>() const Q_DECL_NOTHROW
{
return m_computeJobManager;
diff --git a/src/render/backend/nodemanagers_p.h b/src/render/backend/nodemanagers_p.h
index b1ea2a0de..9e913eec4 100644
--- a/src/render/backend/nodemanagers_p.h
+++ b/src/render/backend/nodemanagers_p.h
@@ -96,6 +96,7 @@ class TextureImageDataManager;
class LayerManager;
class LevelOfDetailManager;
class LightManager;
+class EnvironmentLightManager;
class ComputeCommandManager;
class RenderStateManager;
@@ -127,10 +128,13 @@ class GeometryRenderer;
class ObjectPicker;
//class BoundingVolumeDebug;
class Light;
+class EnvironmentLight;
class ComputeCommand;
class RenderStateNode;
class OpenGLVertexArrayObject;
+class ResourceAccessor;
+
class QT3DRENDERSHARED_PRIVATE_EXPORT NodeManagers
{
public:
@@ -203,9 +207,12 @@ public:
inline ObjectPickerManager *objectPickerManager() const Q_DECL_NOEXCEPT { return m_objectPickerManager; }
// inline BoundingVolumeDebugManager *boundingVolumeDebugManager() const Q_DECL_NOEXCEPT { return m_boundingVolumeDebugManager; }
inline LightManager *lightManager() const Q_DECL_NOEXCEPT { return m_lightManager; }
+ inline EnvironmentLightManager *environmentLightManager() const Q_DECL_NOEXCEPT { return m_environmentLightManager; }
inline ComputeCommandManager *computeJobManager() const Q_DECL_NOEXCEPT { return m_computeJobManager; }
inline RenderStateManager *renderStateManager() const Q_DECL_NOEXCEPT { return m_renderStateManager; }
+ QSharedPointer<ResourceAccessor> resourceAccessor();
+
private:
CameraManager *m_cameraManager;
EntityManager *m_renderNodesManager;
@@ -239,8 +246,11 @@ private:
ObjectPickerManager *m_objectPickerManager;
// BoundingVolumeDebugManager *m_boundingVolumeDebugManager;
LightManager *m_lightManager;
+ EnvironmentLightManager *m_environmentLightManager;
ComputeCommandManager *m_computeJobManager;
RenderStateManager *m_renderStateManager;
+
+ QSharedPointer<ResourceAccessor> m_resourceAccessor;
};
// Specializations
@@ -336,6 +346,9 @@ template<>
LightManager *NodeManagers::manager<Light>() const Q_DECL_NOEXCEPT;
template<>
+EnvironmentLightManager *NodeManagers::manager<EnvironmentLight>() const Q_DECL_NOEXCEPT;
+
+template<>
QT3DRENDERSHARED_PRIVATE_EXPORT ComputeCommandManager *NodeManagers::manager<ComputeCommand>() const Q_DECL_NOEXCEPT;
template<>
diff --git a/src/render/backend/openglvertexarrayobject.cpp b/src/render/backend/openglvertexarrayobject.cpp
index 6120c7233..eefc208d5 100644
--- a/src/render/backend/openglvertexarrayobject.cpp
+++ b/src/render/backend/openglvertexarrayobject.cpp
@@ -52,15 +52,8 @@ OpenGLVertexArrayObject::OpenGLVertexArrayObject()
: m_ctx(nullptr)
, m_specified(false)
, m_supportsVao(false)
- , m_createdEmulatedVAO(false)
{}
-void OpenGLVertexArrayObject::setGraphicsContext(GraphicsContext *ctx)
-{
- m_ctx = ctx;
- m_supportsVao = m_ctx->supportsVAO();
-}
-
void OpenGLVertexArrayObject::bind()
{
Q_ASSERT(m_ctx);
@@ -75,7 +68,7 @@ void OpenGLVertexArrayObject::bind()
m_ctx->m_currentVAO = this;
// We need to specify array and vertex attributes
- for (const GraphicsContext::VAOVertexAttribute &attr : m_vertexAttributes)
+ for (const GraphicsContext::VAOVertexAttribute &attr : qAsConst(m_vertexAttributes))
m_ctx->enableAttribute(attr);
if (!m_indexAttribute.isNull())
m_ctx->bindGLBuffer(m_ctx->m_renderer->nodeManagers()->glBufferManager()->data(m_indexAttribute),
@@ -92,44 +85,58 @@ void OpenGLVertexArrayObject::release()
m_vao->release();
} else {
if (m_ctx->m_currentVAO == this) {
- for (const GraphicsContext::VAOVertexAttribute &attr : m_vertexAttributes)
+ for (const GraphicsContext::VAOVertexAttribute &attr : qAsConst(m_vertexAttributes))
m_ctx->disableAttribute(attr);
m_ctx->m_currentVAO = nullptr;
}
}
}
-void OpenGLVertexArrayObject::create()
+// called from Render thread
+void OpenGLVertexArrayObject::create(GraphicsContext *ctx, const VAOIdentifier &key)
{
- Q_ASSERT(m_ctx);
- if (m_supportsVao) {
- Q_ASSERT(!m_vao.isNull());
- m_vao->create();
- } else {
- m_createdEmulatedVAO = true;
- }
+ QMutexLocker lock(&m_mutex);
+
+ Q_ASSERT(!m_ctx && !m_vao);
+
+ m_ctx = ctx;
+ m_supportsVao = m_ctx->supportsVAO();
+ m_vao.reset(m_supportsVao ? new QOpenGLVertexArrayObject() : nullptr);
+ m_vao->create();
+ m_owners = key;
}
+// called from Render thread
void OpenGLVertexArrayObject::destroy()
{
+ QMutexLocker locker(&m_mutex);
+
Q_ASSERT(m_ctx);
- if (m_supportsVao) {
- Q_ASSERT(!m_vao.isNull());
- m_vao->destroy();
- }
+ cleanup();
+}
+
+void OpenGLVertexArrayObject::cleanup()
+{
+ m_vao.reset();
+ m_ctx = nullptr;
m_specified = false;
+ m_supportsVao = false;
m_indexAttribute = GraphicsContext::VAOIndexAttribute();
m_vertexAttributes.clear();
}
-bool OpenGLVertexArrayObject::isCreated() const
+// called from job
+bool OpenGLVertexArrayObject::isAbandoned(GeometryManager *geomMgr, ShaderManager *shaderMgr)
{
- if (m_supportsVao) {
- Q_ASSERT(!m_vao.isNull());
- return m_vao->isCreated();
- } else {
- return m_createdEmulatedVAO;
- }
+ QMutexLocker lock(&m_mutex);
+
+ if (!m_ctx)
+ return false;
+
+ const bool geometryExists = (geomMgr->data(m_owners.first) != nullptr);
+ const bool shaderExists = (shaderMgr->data(m_owners.second) != nullptr);
+
+ return !geometryExists || !shaderExists;
}
void OpenGLVertexArrayObject::saveVertexAttribute(const GraphicsContext::VAOVertexAttribute &attr)
diff --git a/src/render/backend/openglvertexarrayobject_p.h b/src/render/backend/openglvertexarrayobject_p.h
index 4f21497f0..a564175f6 100644
--- a/src/render/backend/openglvertexarrayobject_p.h
+++ b/src/render/backend/openglvertexarrayobject_p.h
@@ -59,31 +59,39 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
+class GeometryManager;
+class ShaderManager;
+
+typedef QPair<HGeometry, HShader> VAOIdentifier;
+
class OpenGLVertexArrayObject
{
public:
OpenGLVertexArrayObject();
- void setGraphicsContext(GraphicsContext *ctx);
void bind();
void release();
- void create();
+
+ void create(GraphicsContext *ctx, const VAOIdentifier &key);
void destroy();
- bool isCreated() const;
+ void cleanup();
+
+ bool isAbandoned(GeometryManager *geomMgr, ShaderManager *shaderMgr);
QOpenGLVertexArrayObject *vao() { return m_vao.data(); }
const QOpenGLVertexArrayObject *vao() const { return m_vao.data(); }
- void setVao(QOpenGLVertexArrayObject *vao) { m_vao.reset(vao); }
void setSpecified(bool b) { m_specified = b; }
bool isSpecified() const { return m_specified; }
+
private:
+ QMutex m_mutex;
GraphicsContext *m_ctx;
QScopedPointer<QOpenGLVertexArrayObject> m_vao;
bool m_specified;
bool m_supportsVao;
- bool m_createdEmulatedVAO;
+ VAOIdentifier m_owners;
friend class GraphicsContext;
diff --git a/src/render/backend/platformsurfacefilter.cpp b/src/render/backend/platformsurfacefilter.cpp
index 891e30c44..7458f607d 100644
--- a/src/render/backend/platformsurfacefilter.cpp
+++ b/src/render/backend/platformsurfacefilter.cpp
@@ -107,6 +107,10 @@ bool PlatformSurfaceFilter::eventFilter(QObject *obj, QEvent *e)
// If we remove it, the call to isSurfaceValid will
// implicitely return false
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
+ if (m_obj) {
+ m_obj->removeEventFilter(this);
+ m_obj = nullptr;
+ }
break;
}
diff --git a/src/render/backend/platformsurfacefilter_p.h b/src/render/backend/platformsurfacefilter_p.h
index ec10327fe..dbdc07b01 100644
--- a/src/render/backend/platformsurfacefilter_p.h
+++ b/src/render/backend/platformsurfacefilter_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <private/qt3drender_global_p.h>
+
#include <QtCore/qobject.h>
#include <QtGui/qsurface.h>
#include <QSemaphore>
@@ -106,7 +108,7 @@ private:
void markSurfaceAsValid();
};
-class SurfaceLocker
+class QT3DRENDERSHARED_PRIVATE_EXPORT SurfaceLocker
{
public:
explicit SurfaceLocker(QSurface *surface);
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 93e323caa..5d515a173 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -1,6 +1,3 @@
-#DEFINES += QT3D_RENDER_VIEW_JOB_TIMING
-#DEFINES += QT3D_RENDER_DUMP_BACKEND_NODES
-
INCLUDEPATH += $$PWD
HEADERS += \
@@ -29,6 +26,8 @@ HEADERS += \
$$PWD/triangleboundingvolume_p.h \
$$PWD/openglvertexarrayobject_p.h \
$$PWD/trianglesextractor_p.h \
+ $$PWD/buffervisitor_p.h \
+ $$PWD/bufferutils_p.h \
$$PWD/trianglesvisitor_p.h \
$$PWD/abstractrenderer_p.h \
$$PWD/computecommand_p.h \
@@ -36,12 +35,13 @@ HEADERS += \
$$PWD/stringtoint_p.h \
$$PWD/backendnode_p.h \
$$PWD/rendertargetoutput_p.h \
- $$PWD/commandexecuter_p.h \
$$PWD/uniform_p.h \
$$PWD/shaderparameterpack_p.h \
$$PWD/renderviewbuilder_p.h \
$$PWD/frameprofiler_p.h \
- $$PWD/offscreensurfacehelper_p.h
+ $$PWD/offscreensurfacehelper_p.h \
+ $$PWD/resourceaccessor_p.h \
+ $$PWD/commandthread_p.h
SOURCES += \
$$PWD/renderthread.cpp \
@@ -70,10 +70,18 @@ SOURCES += \
$$PWD/backendnode.cpp \
$$PWD/rendertargetoutput.cpp \
$$PWD/attachmentpack.cpp \
- $$PWD/commandexecuter.cpp \
$$PWD/openglvertexarrayobject.cpp \
$$PWD/uniform.cpp \
$$PWD/shaderparameterpack.cpp \
$$PWD/renderviewbuilder.cpp \
- $$PWD/offscreensurfacehelper.cpp
+ $$PWD/offscreensurfacehelper.cpp \
+ $$PWD/resourceaccessor.cpp \
+ $$PWD/commandthread.cpp
+
+include($$OUT_PWD/../core/qt3dcore-config.pri)
+QT_FOR_CONFIG += 3dcore-private
+qtConfig(qt3d-profile-jobs): {
+ HEADERS += $$PWD/commandexecuter_p.h
+ SOURCES += $$PWD/commandexecuter.cpp
+}
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index af73b1ae5..b89f21522 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -68,6 +68,7 @@
#include <Qt3DRender/private/technique_p.h>
#include <Qt3DRender/private/renderthread_p.h>
#include <Qt3DRender/private/renderview_p.h>
+#include <Qt3DRender/private/scenemanager_p.h>
#include <Qt3DRender/private/techniquefilternode_p.h>
#include <Qt3DRender/private/viewportnode_p.h>
#include <Qt3DRender/private/vsyncframeadvanceservice_p.h>
@@ -84,13 +85,19 @@
#include <Qt3DRender/private/loadbufferjob_p.h>
#include <Qt3DRender/private/rendercapture_p.h>
#include <Qt3DRender/private/updatelevelofdetailjob_p.h>
+#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
+#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/qcameralens.h>
+#include <Qt3DCore/qt3dcore-config.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+
+#if defined(QT3D_JOBS_RUN_STATS)
#include <Qt3DCore/private/aspectcommanddebugger_p.h>
+#endif
#include <QStack>
#include <QOffscreenSurface>
@@ -146,6 +153,7 @@ namespace Render {
Renderer::Renderer(QRenderAspect::RenderType type)
: m_services(nullptr)
, m_nodesManager(nullptr)
+ , m_renderSceneRoot(nullptr)
, m_defaultRenderStateSet(nullptr)
, m_graphicsContext(nullptr)
, m_renderQueue(new RenderQueue())
@@ -157,6 +165,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_changeSet(0)
, m_lastFrameCorrect(0)
, m_glContext(nullptr)
+ , m_shareContext(nullptr)
, m_pickBoundingVolumeJob(PickBoundingVolumeJobPtr::create())
, m_time(0)
, m_settings(nullptr)
@@ -168,10 +177,12 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create())
, m_updateTreeEnabledJob(Render::UpdateTreeEnabledJobPtr::create())
, m_sendRenderCaptureJob(Render::SendRenderCaptureJobPtr::create(this))
+ , m_sendBufferCaptureJob(Render::SendBufferCaptureJobPtr::create())
, m_updateLevelOfDetailJob(Render::UpdateLevelOfDetailJobPtr::create())
, m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create())
, m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create())
, m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
+ , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
, m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
, m_shaderGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyShaders(); }, JobTypes::DirtyShaderGathering))
, m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading))
@@ -263,16 +274,35 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_pickBoundingVolumeJob->setManagers(m_nodesManager);
m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager());
m_sendRenderCaptureJob->setManagers(m_nodesManager);
+ m_sendBufferCaptureJob->setManagers(m_nodesManager);
m_updateLevelOfDetailJob->setManagers(m_nodesManager);
m_updateMeshTriangleListJob->setManagers(m_nodesManager);
m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager());
}
+void Renderer::setServices(QServiceLocator *services)
+{
+ m_services = services;
+
+ m_nodesManager->sceneManager()->setDownloadService(m_services->downloadHelperService());
+}
+
NodeManagers *Renderer::nodeManagers() const
{
return m_nodesManager;
}
+/*!
+ \internal
+
+ Return context which can be used to share resources safely
+ with qt3d main render context.
+*/
+QOpenGLContext *Renderer::shareContext() const
+{
+ return m_shareContext ? m_shareContext : m_graphicsContext->openGLContext();
+}
+
void Renderer::setOpenGLContext(QOpenGLContext *context)
{
m_glContext = context;
@@ -314,6 +344,10 @@ void Renderer::initialize()
// Context is not owned by us, so we need to know if it gets destroyed
m_contextConnection = QObject::connect(m_glContext, &QOpenGLContext::aboutToBeDestroyed,
[this] { releaseGraphicsResources(); });
+ m_shareContext = new QOpenGLContext;
+ m_shareContext->setFormat(m_glContext->format());
+ m_shareContext->setShareContext(m_glContext);
+ m_shareContext->create();
}
// Note: we don't have a surface at this point
@@ -358,6 +392,7 @@ void Renderer::shutdown()
// to be ready. The isReadyToSubmit() function checks for a shutdown
// having been requested.
m_submitRenderViewsSemaphore.release(1);
+ m_renderThread->wait();
}
}
@@ -405,6 +440,13 @@ void Renderer::releaseGraphicsResources()
buffer->destroy(m_graphicsContext.data());
}
+ // Do the same thing with VAOs
+ const QVector<HVao> activeVaos = m_nodesManager->vaoManager()->activeHandles();
+ for (const HVao &vaoHandle : activeVaos) {
+ OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(vaoHandle);
+ vao->destroy();
+ }
+
context->doneCurrent();
} else {
qWarning() << "Failed to make context current: OpenGL resources will not be destroyed";
@@ -412,6 +454,8 @@ void Renderer::releaseGraphicsResources()
if (m_ownedContext)
delete context;
+ if (m_shareContext)
+ delete m_shareContext;
m_graphicsContext.reset(nullptr);
qCDebug(Backend) << Q_FUNC_INFO << "Renderer properly shutdown";
@@ -500,17 +544,26 @@ void Renderer::render()
void Renderer::doRender()
{
- bool submissionSucceeded = false;
- bool hasCleanedQueueAndProceeded = false;
Renderer::ViewSubmissionResultData submissionData;
+ bool hasCleanedQueueAndProceeded = false;
bool preprocessingComplete = false;
-
- if (isReadyToSubmit()) {
-
- // Lock the mutex to protect access to m_surface and check if we are still set
- // to the running state and that we have a valid surface on which to draw
- // TO DO: Is that still needed given the surface changes
- QMutexLocker locker(&m_mutex);
+ bool beganDrawing = false;
+ const bool canSubmit = isReadyToSubmit();
+
+ // Lock the mutex to protect access to the renderQueue while we look for its state
+ QMutexLocker locker(&m_renderQueueMutex);
+ const bool queueIsComplete = m_renderQueue->isFrameQueueComplete();
+ const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0;
+
+ // When using synchronous rendering (QtQuick)
+ // We are not sure that the frame queue is actually complete
+ // Since a call to render may not be synched with the completions
+ // of the RenderViewJobs
+ // In such a case we return early, waiting for a next call with
+ // the frame queue complete at this point
+
+ // RenderQueue is complete (but that means it may be of size 0)
+ if (canSubmit && (queueIsComplete && !queueIsEmpty)) {
const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue();
#ifdef QT3D_JOBS_RUN_STATS
@@ -525,8 +578,7 @@ void Renderer::doRender()
submissionStatsPart2.jobId.typeAndInstance[1] = 0;
submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
#endif
-
- if (canRender() && (submissionSucceeded = renderViews.size() > 0) == true) {
+ if (canRender()) {
// Clear all dirty flags but Compute so that
// we still render every frame when a compute shader is used in a scene
BackendNodeDirtySet changesToUnset = m_changeSet;
@@ -548,7 +600,8 @@ void Renderer::doRender()
// Reset state for each draw if we don't have complete control of the context
if (!m_ownedContext)
m_graphicsContext->setCurrentStateSet(nullptr);
- if (m_graphicsContext->beginDrawing(surface)) {
+ beganDrawing = m_graphicsContext->beginDrawing(surface);
+ if (beganDrawing) {
// 1) Execute commands for buffer uploads, texture updates, shader loading first
updateGLResources();
// 2) Update VAO and copy data into commands to allow concurrent submission
@@ -559,6 +612,7 @@ void Renderer::doRender()
}
// 2) Proceed to next frame and start preparing frame n + 1
m_renderQueue->reset();
+ locker.unlock(); // Done protecting RenderQueue
m_vsyncFrameAdvanceService->proceedToNextFrame();
hasCleanedQueueAndProceeded = true;
@@ -602,61 +656,57 @@ void Renderer::doRender()
#endif
}
- // Note: submissionSucceeded is false when
- // * we cannot render because a shutdown has been scheduled
- // * the renderqueue is incomplete (only when rendering with a Scene3D)
- // Otherwise returns true even for cases like
- // * No render view
- // * No surface set
- // * OpenGLContext failed to be set current
- // This behavior is important as we need to
- // call proceedToNextFrame despite rendering errors that aren't fatal
-
// Only reset renderQueue and proceed to next frame if the submission
- // succeeded or it we are using a render thread and that is wasn't performed
+ // succeeded or if we are using a render thread and that is wasn't performed
// already
- // If submissionSucceeded isn't true this implies that something went wrong
+ // If hasCleanedQueueAndProceeded isn't true this implies that something went wrong
// with the rendering and/or the renderqueue is incomplete from some reason
// (in the case of scene3d the render jobs may be taking too long ....)
- if (m_renderThread || submissionSucceeded) {
-
- if (!hasCleanedQueueAndProceeded) {
- // Reset the m_renderQueue so that we won't try to render
- // with a queue used by a previous frame with corrupted content
- // if the current queue was correctly submitted
- m_renderQueue->reset();
-
- // We allow the RenderTickClock service to proceed to the next frame
- // In turn this will allow the aspect manager to request a new set of jobs
- // to be performed for each aspect
- m_vsyncFrameAdvanceService->proceedToNextFrame();
- }
+ // or alternatively it could be complete but empty (RenderQueue of size 0)
+ if (!hasCleanedQueueAndProceeded &&
+ (m_renderThread || queueIsComplete || queueIsEmpty)) {
+ // RenderQueue was full but something bad happened when
+ // trying to render it and therefore proceedToNextFrame was not called
+ // Note: in this case the renderQueue mutex is still locked
+
+ // Reset the m_renderQueue so that we won't try to render
+ // with a queue used by a previous frame with corrupted content
+ // if the current queue was correctly submitted
+ m_renderQueue->reset();
+
+ // We allow the RenderTickClock service to proceed to the next frame
+ // In turn this will allow the aspect manager to request a new set of jobs
+ // to be performed for each aspect
+ m_vsyncFrameAdvanceService->proceedToNextFrame();
+ }
- // Perform the last swapBuffers calls after the proceedToNextFrame
- // as this allows us to gain a bit of time for the preparation of the
- // next frame
+ // Perform the last swapBuffers calls after the proceedToNextFrame
+ // as this allows us to gain a bit of time for the preparation of the
+ // next frame
+ // Finish up with last surface used in the list of RenderViews
+ if (beganDrawing) {
+ SurfaceLocker surfaceLock(submissionData.surface);
// Finish up with last surface used in the list of RenderViews
- if (submissionSucceeded) {
- SurfaceLocker surfaceLock(submissionData.surface);
- // Finish up with last surface used in the list of RenderViews
- m_graphicsContext->endDrawing(submissionData.lastBoundFBOId == m_graphicsContext->defaultFBO() && surfaceLock.isSurfaceValid());
- }
+ m_graphicsContext->endDrawing(submissionData.lastBoundFBOId == m_graphicsContext->defaultFBO() && surfaceLock.isSurfaceValid());
}
}
// Called by RenderViewJobs
+// When the frameQueue is complete and we are using a renderThread
+// we allow the render thread to proceed
void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder)
{
- QMutexLocker locker(&m_mutex); // Prevent out of order execution
+ QMutexLocker locker(&m_renderQueueMutex); // Prevent out of order execution
// We cannot use a lock free primitive here because:
// - QVector is not thread safe
// - Even if the insert is made correctly, the isFrameComplete call
// could be invalid since depending on the order of execution
// the counter could be complete but the renderview not yet added to the
// buffer depending on whichever order the cpu decides to process this
-
- if (m_renderQueue->queueRenderView(renderView, submitOrder)) {
+ const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder);
+ locker.unlock(); // We're done protecting the queue at this point
+ if (isQueueComplete) {
if (m_renderThread && m_running.load())
Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0);
m_submitRenderViewsSemaphore.release(1);
@@ -695,16 +745,6 @@ bool Renderer::isReadyToSubmit()
// something to render
// The case of shutdown should have been handled just before
Q_ASSERT(m_renderQueue->isFrameQueueComplete());
- } else {
- // When using synchronous rendering (QtQuick)
- // We are not sure that the frame queue is actually complete
- // Since a call to render may not be synched with the completions
- // of the RenderViewJobs
- // In such a case we return early, waiting for a next call with
- // the frame queue complete at this point
- QMutexLocker locker(&m_mutex);
- if (!m_renderQueue->isFrameQueueComplete())
- return false;
}
return true;
}
@@ -898,6 +938,23 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
}
// Executed in a job
+void Renderer::lookForAbandonedVaos()
+{
+ const QVector<HVao> activeVaos = m_nodesManager->vaoManager()->activeHandles();
+ for (HVao handle : activeVaos) {
+ OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(handle);
+
+ // Make sure to only mark VAOs for deletion that were already created
+ // (ignore those that might be currently under construction in the render thread)
+ if (vao && vao->isAbandoned(m_nodesManager->geometryManager(), m_nodesManager->shaderManager())) {
+ m_abandonedVaosMutex.lock();
+ m_abandonedVaos.push_back(handle);
+ m_abandonedVaosMutex.unlock();
+ }
+ }
+}
+
+// Executed in a job
void Renderer::lookForDirtyBuffers()
{
const QVector<HBuffer> activeBufferHandles = m_nodesManager->bufferManager()->activeHandles();
@@ -908,6 +965,17 @@ void Renderer::lookForDirtyBuffers()
}
}
+void Renderer::lookForDownloadableBuffers()
+{
+ m_downloadableBuffers.clear();
+ const QVector<HBuffer> activeBufferHandles = m_nodesManager->bufferManager()->activeHandles();
+ for (HBuffer handle : activeBufferHandles) {
+ Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
+ if (buffer->access() & QBuffer::Read)
+ m_downloadableBuffers.push_back(handle);
+ }
+}
+
// Executed in a job
void Renderer::lookForDirtyTextures()
{
@@ -935,6 +1003,8 @@ void Renderer::lookForDirtyShaders()
RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId);
HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram());
Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle);
+ if (Q_UNLIKELY(shader->hasPendingNotifications()))
+ shader->submitPendingNotifications();
if (shader != nullptr && !shader->isLoaded())
m_dirtyShaders.push_back(shaderHandle);
}
@@ -951,12 +1021,11 @@ void Renderer::updateGLResources()
const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers);
for (HBuffer handle: dirtyBufferHandles) {
Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
- // Perform data upload
// Forces creation if it doesn't exit
if (!m_graphicsContext->hasGLBufferForBuffer(buffer))
m_graphicsContext->glBufferForRenderBuffer(buffer);
- else if (buffer->isDirty()) // Otherwise update the glBuffer
- m_graphicsContext->updateBuffer(buffer);
+ // Update the glBuffer data
+ m_graphicsContext->updateBuffer(buffer);
buffer->unsetDirty();
}
}
@@ -964,10 +1033,11 @@ void Renderer::updateGLResources()
{
Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload);
const QVector<HShader> dirtyShaderHandles = std::move(m_dirtyShaders);
+ ShaderManager *shaderManager = m_nodesManager->shaderManager();
for (HShader handle: dirtyShaderHandles) {
- Shader *shader = m_nodesManager->shaderManager()->data(handle);
+ Shader *shader = shaderManager->data(handle);
// Compile shader
- m_graphicsContext->loadShader(shader);
+ m_graphicsContext->loadShader(shader, shaderManager);
}
}
@@ -990,13 +1060,16 @@ void Renderer::updateGLResources()
// We can really release the texture at this point
m_nodesManager->textureManager()->releaseResource(textureCleanedUpId);
}
-
-
}
// Render Thread
void Renderer::updateTexture(Texture *texture)
{
+ // Check that the current texture images are still in place, if not, do not update
+ const bool isValid = texture->isValid();
+ if (!isValid)
+ return;
+
// For implementing unique, non-shared, non-cached textures.
// for now, every texture is shared by default
@@ -1065,10 +1138,14 @@ void Renderer::updateTexture(Texture *texture)
!glTextureManager->setParameters(glTexture, texture->parameters()))
qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setParameters failed, should be non-shared";
- if (dirtyFlags.testFlag(Texture::DirtyGenerators) &&
+ if (dirtyFlags.testFlag(Texture::DirtyImageGenerators) &&
!glTextureManager->setImages(glTexture, texture->textureImages()))
qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerators failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyDataGenerator) &&
+ !glTextureManager->setGenerator(glTexture, texture->dataGenerator()))
+ qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerator failed, should be non-shared";
+
// Unset the dirty flag on the texture
texture->unsetDirty();
}
@@ -1083,6 +1160,17 @@ void Renderer::cleanupTexture(const Texture *texture)
glTextureManager->abandon(glTexture, texture);
}
+void Renderer::downloadGLBuffers()
+{
+ lookForDownloadableBuffers();
+ const QVector<HBuffer> downloadableHandles = std::move(m_downloadableBuffers);
+ for (HBuffer handle : downloadableHandles) {
+ Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
+ QByteArray content = m_graphicsContext->downloadBufferContent(buffer);
+ m_sendBufferCaptureJob->addRequest(QPair<Buffer*, QByteArray>(buffer, content));
+ }
+}
+
// Happens in RenderThread context when all RenderViewJobs are done
// Returns the id of the last bound FBO
@@ -1221,6 +1309,9 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
addRenderCaptureSendRequest(renderView->renderCaptureNodeId());
}
+ if (renderView->isDownloadBuffersEnable())
+ downloadGLBuffers();
+
frameElapsed = timer.elapsed() - frameElapsed;
qCDebug(Rendering) << Q_FUNC_INFO << "Submitted Renderview " << i + 1 << "/" << renderViewsCount << "in " << frameElapsed << "ms";
frameElapsed = timer.elapsed();
@@ -1311,6 +1402,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
m_pickBoundingVolumeJob->setFrameGraphRoot(frameGraphRoot());
m_pickBoundingVolumeJob->setRenderSettings(settings());
m_pickBoundingVolumeJob->setMouseEvents(pendingPickingEvents());
+ m_pickBoundingVolumeJob->setKeyEvents(pendingKeyEvents());
m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot());
// Set dependencies of resource gatherer
@@ -1331,25 +1423,36 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
renderBinJobs.push_back(m_worldTransformJob);
renderBinJobs.push_back(m_cleanupJob);
renderBinJobs.push_back(m_sendRenderCaptureJob);
+ renderBinJobs.push_back(m_sendBufferCaptureJob);
renderBinJobs.push_back(m_filterCompatibleTechniqueJob);
renderBinJobs.append(bufferJobs);
// Jobs to prepare GL Resource upload
renderBinJobs.push_back(m_syncTextureLoadingJob);
+ renderBinJobs.push_back(m_vaoGathererJob);
renderBinJobs.push_back(m_bufferGathererJob);
renderBinJobs.push_back(m_textureGathererJob);
renderBinJobs.push_back(m_shaderGathererJob);
- // Traverse the current framegraph. For each leaf node create a
- // RenderView and set its configuration then create a job to
- // populate the RenderView with a set of RenderCommands that get
- // their details from the RenderNodes that are visible to the
- // Camera selected by the framegraph configuration
- FrameGraphVisitor visitor(this, m_nodesManager->frameGraphManager());
- visitor.traverse(frameGraphRoot(), &renderBinJobs);
+ QMutexLocker lock(&m_renderQueueMutex);
+ if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case)
+ // Traverse the current framegraph. For each leaf node create a
+ // RenderView and set its configuration then create a job to
+ // populate the RenderView with a set of RenderCommands that get
+ // their details from the RenderNodes that are visible to the
+ // Camera selected by the framegraph configuration
+ FrameGraphVisitor visitor(m_nodesManager->frameGraphManager());
+ const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot());
+
+ const int fgBranchCount = fgLeaves.size();
+ for (int i = 0; i < fgBranchCount; ++i) {
+ RenderViewBuilder builder(fgLeaves.at(i), i, this);
+ renderBinJobs.append(builder.buildJobHierachy());
+ }
- // Set target number of RenderViews
- m_renderQueue->setTargetRenderViewCount(visitor.leafNodeCount());
+ // Set target number of RenderViews
+ m_renderQueue->setTargetRenderViewCount(fgBranchCount);
+ }
return renderBinJobs;
}
@@ -1364,6 +1467,11 @@ QAspectJobPtr Renderer::syncTextureLoadingJob()
return m_syncTextureLoadingJob;
}
+QAspectJobPtr Renderer::expandBoundingVolumeJob()
+{
+ return m_expandBoundingVolumeJob;
+}
+
QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const
{
return static_cast<Qt3DCore::QAbstractFrameAdvanceService *>(m_vsyncFrameAdvanceService.data());
@@ -1474,16 +1582,15 @@ void Renderer::createOrUpdateVAO(RenderCommand *command,
HVao *previousVaoHandle,
OpenGLVertexArrayObject **vao)
{
+ const VAOIdentifier vaoKey(command->m_geometry, command->m_shader);
+
VAOManager *vaoManager = m_nodesManager->vaoManager();
- command->m_vao = vaoManager->lookupHandle(QPair<HGeometry, HShader>(command->m_geometry, command->m_shader));
+ command->m_vao = vaoManager->lookupHandle(vaoKey);
if (command->m_vao.isNull()) {
qCDebug(Rendering) << Q_FUNC_INFO << "Allocating new VAO";
- command->m_vao = vaoManager->getOrAcquireHandle(QPair<HGeometry, HShader>(command->m_geometry, command->m_shader));
- vaoManager->data(command->m_vao)->setGraphicsContext(m_graphicsContext.data());
- if (m_graphicsContext->supportsVAO())
- vaoManager->data(command->m_vao)->setVao(new QOpenGLVertexArrayObject());
- vaoManager->data(command->m_vao)->create();
+ command->m_vao = vaoManager->getOrAcquireHandle(vaoKey);
+ vaoManager->data(command->m_vao)->create(m_graphicsContext.data(), vaoKey);
}
if (*previousVaoHandle != command->m_vao) {
@@ -1679,11 +1786,30 @@ void Renderer::cleanGraphicsResources()
tex->destroyGLTexture();
delete tex;
}
+
+ // Delete abandoned VAOs
+ m_abandonedVaosMutex.lock();
+ const QVector<HVao> abandonedVaos = std::move(m_abandonedVaos);
+ m_abandonedVaosMutex.unlock();
+ for (HVao vaoHandle : abandonedVaos) {
+ // might have already been destroyed last frame, but added by the cleanup job before, so
+ // check if the VAO is really still existent
+ OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(vaoHandle);
+ if (vao) {
+ vao->destroy();
+ m_nodesManager->vaoManager()->release(vaoHandle);
+ }
+ }
}
QList<QMouseEvent> Renderer::pendingPickingEvents() const
{
- return m_pickEventFilter->pendingEvents();
+ return m_pickEventFilter->pendingMouseEvents();
+}
+
+QList<QKeyEvent> Renderer::pendingKeyEvents() const
+{
+ return m_pickEventFilter->pendingKeyEvents();
}
const GraphicsApiFilterData *Renderer::contextInfo() const
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index 9b5c35ed1..e311261e0 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -71,6 +71,7 @@
#include <Qt3DRender/private/updatetreeenabledjob_p.h>
#include <Qt3DRender/private/platformsurfacefilter_p.h>
#include <Qt3DRender/private/sendrendercapturejob_p.h>
+#include <Qt3DRender/private/sendbuffercapturejob_p.h>
#include <Qt3DRender/private/genericlambdajob_p.h>
#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h>
#include <Qt3DRender/private/filtercompatibletechniquejob_p.h>
@@ -156,7 +157,7 @@ public:
void setTime(qint64 time) Q_DECL_OVERRIDE;
void setNodeManagers(NodeManagers *managers) Q_DECL_OVERRIDE;
- void setServices(Qt3DCore::QServiceLocator *services) Q_DECL_OVERRIDE { m_services = services; }
+ void setServices(Qt3DCore::QServiceLocator *services) Q_DECL_OVERRIDE;
void setSurfaceExposed(bool exposed) Q_DECL_OVERRIDE;
NodeManagers *nodeManagers() const Q_DECL_OVERRIDE;
@@ -188,11 +189,11 @@ public:
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() Q_DECL_OVERRIDE;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() Q_DECL_OVERRIDE;
Qt3DCore::QAspectJobPtr syncTextureLoadingJob() Q_DECL_OVERRIDE;
+ Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() Q_DECL_OVERRIDE;
QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const;
inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; }
- inline ExpandBoundingVolumeJobPtr expandBoundingVolumeJob() const { return m_expandBoundingVolumeJob; }
inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const { return m_updateShaderDataTransformJob; }
inline CalculateBoundingVolumeJobPtr calculateBoundingVolumeJob() const { return m_calculateBoundingVolumeJob; }
inline UpdateTreeEnabledJobPtr updateTreeEnabledJob() const { return m_updateTreeEnabledJob; }
@@ -209,10 +210,12 @@ public:
virtual void setSettings(RenderSettings *settings) Q_DECL_OVERRIDE;
virtual RenderSettings *settings() const Q_DECL_OVERRIDE;
+ QOpenGLContext *shareContext() const Q_DECL_OVERRIDE;
void updateGLResources();
void updateTexture(Texture *texture);
void cleanupTexture(const Texture *texture);
+ void downloadGLBuffers();
void prepareCommandsSubmission(const QVector<RenderView *> &renderViews);
bool executeCommandsSubmission(const RenderView *rv);
@@ -230,8 +233,8 @@ public:
inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; }
-
QList<QMouseEvent> pendingPickingEvents() const;
+ QList<QKeyEvent> pendingKeyEvents() const;
void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId);
const QVector<Qt3DCore::QNodeId> takePendingRenderCaptureSendRequests();
@@ -256,12 +259,13 @@ public:
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
- QMutex* mutex() { return &m_mutex; }
+ QMutex* mutex() { return &m_renderQueueMutex; }
#ifdef QT3D_RENDER_UNIT_TESTS
public:
#else
+
private:
#endif
bool canRender() const;
@@ -286,7 +290,7 @@ private:
QScopedPointer<RenderThread> m_renderThread;
QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService;
- QMutex m_mutex;
+ QMutex m_renderQueueMutex;
QSemaphore m_submitRenderViewsSemaphore;
QSemaphore m_waitForInitializationToBeCompleted;
@@ -300,6 +304,7 @@ private:
BackendNodeDirtySet m_changeSet;
QAtomicInt m_lastFrameCorrect;
QOpenGLContext *m_glContext;
+ QOpenGLContext *m_shareContext;
PickBoundingVolumeJobPtr m_pickBoundingVolumeJob;
qint64 m_time;
@@ -314,6 +319,7 @@ private:
UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob;
UpdateTreeEnabledJobPtr m_updateTreeEnabledJob;
SendRenderCaptureJobPtr m_sendRenderCaptureJob;
+ SendBufferCaptureJobPtr m_sendBufferCaptureJob;
UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob;
UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob;
FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob;
@@ -327,16 +333,23 @@ private:
OpenGLVertexArrayObject **vao);
GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob;
+ GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
GenericLambdaJobPtr<std::function<void ()>> m_shaderGathererJob;
SynchronizerJobPtr m_syncTextureLoadingJob;
+ void lookForAbandonedVaos();
void lookForDirtyBuffers();
+ void lookForDownloadableBuffers();
void lookForDirtyTextures();
void lookForDirtyShaders();
+ QMutex m_abandonedVaosMutex;
+ QVector<HVao> m_abandonedVaos;
+
QVector<HBuffer> m_dirtyBuffers;
+ QVector<HBuffer> m_downloadableBuffers;
QVector<HShader> m_dirtyShaders;
QVector<HTexture> m_dirtyTextures;
diff --git a/src/render/backend/renderqueue.cpp b/src/render/backend/renderqueue.cpp
index 6ec7da464..2fa1cb7d2 100644
--- a/src/render/backend/renderqueue.cpp
+++ b/src/render/backend/renderqueue.cpp
@@ -49,6 +49,7 @@ namespace Render {
RenderQueue::RenderQueue()
: m_noRender(false)
+ , m_wasReset(true)
, m_targetRenderViewCount(0)
, m_currentRenderViewCount(0)
, m_currentWorkQueue(1)
@@ -70,6 +71,7 @@ void RenderQueue::reset()
m_targetRenderViewCount = 0;
m_currentWorkQueue.clear();
m_noRender = false;
+ m_wasReset = true;
}
void RenderQueue::setNoRender()
@@ -88,6 +90,7 @@ bool RenderQueue::queueRenderView(RenderView *renderView, uint submissionOrderIn
Q_ASSERT(!m_noRender);
m_currentWorkQueue[submissionOrderIndex] = renderView;
++m_currentRenderViewCount;
+ Q_ASSERT(m_currentRenderViewCount <= m_targetRenderViewCount);
return isFrameQueueComplete();
}
@@ -109,6 +112,7 @@ void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount)
Q_ASSERT(!m_noRender);
m_targetRenderViewCount = targetRenderViewCount;
m_currentWorkQueue.resize(targetRenderViewCount);
+ m_wasReset = false;
}
/*!
@@ -119,7 +123,7 @@ void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount)
bool RenderQueue::isFrameQueueComplete() const
{
return (m_noRender
- || (m_targetRenderViewCount && m_targetRenderViewCount == currentRenderViewCount()));
+ || (m_targetRenderViewCount > 0 && m_targetRenderViewCount == m_currentRenderViewCount));
}
} // namespace Render
diff --git a/src/render/backend/renderqueue_p.h b/src/render/backend/renderqueue_p.h
index 49316049b..611f5849a 100644
--- a/src/render/backend/renderqueue_p.h
+++ b/src/render/backend/renderqueue_p.h
@@ -77,9 +77,13 @@ public:
void reset();
void setNoRender();
+ inline bool isNoRender() const { return m_noRender; }
+
+ inline bool wasReset() const { return m_wasReset; }
private:
bool m_noRender;
+ bool m_wasReset;
int m_targetRenderViewCount;
int m_currentRenderViewCount;
QVector<RenderView *> m_currentWorkQueue;
diff --git a/src/render/backend/rendertargetoutput.cpp b/src/render/backend/rendertargetoutput.cpp
index faebfacb6..cba92596d 100644
--- a/src/render/backend/rendertargetoutput.cpp
+++ b/src/render/backend/rendertargetoutput.cpp
@@ -121,9 +121,14 @@ void RenderTargetOutput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
BackendNode::sceneChangeEvent(e);
}
-Attachment RenderTargetOutput::attachment() const
+Qt3DRender::Render::Attachment *RenderTargetOutput::attachment()
{
- return m_attachmentData;
+ return &m_attachmentData;
+}
+
+const Attachment *RenderTargetOutput::attachment() const
+{
+ return &m_attachmentData;
}
} // namespace Render
diff --git a/src/render/backend/rendertargetoutput_p.h b/src/render/backend/rendertargetoutput_p.h
index 14daa84e9..b7867c2cb 100644
--- a/src/render/backend/rendertargetoutput_p.h
+++ b/src/render/backend/rendertargetoutput_p.h
@@ -77,7 +77,8 @@ public:
QAbstractTexture::CubeMapFace face() const;
QRenderTargetOutput::AttachmentPoint point() const;
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
- Attachment attachment() const;
+ Attachment *attachment();
+ const Attachment *attachment() const;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
diff --git a/src/render/backend/renderthread_p.h b/src/render/backend/renderthread_p.h
index 026a98609..8d7c083ed 100644
--- a/src/render/backend/renderthread_p.h
+++ b/src/render/backend/renderthread_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef RENDERTHREAD_H
-#define RENDERTHREAD_H
+#ifndef QT3DRENDER_RENDER_RENDERTHREAD_H
+#define QT3DRENDER_RENDER_RENDERTHREAD_H
//
// W A R N I N G
@@ -75,7 +75,7 @@ public:
Render::Renderer* renderer() const { return m_renderer; }
protected:
- void run();
+ void run() Q_DECL_OVERRIDE;
private:
Renderer* m_renderer;
@@ -88,4 +88,4 @@ private:
QT_END_NAMESPACE
-#endif // RENDERTHREAD_H
+#endif // QT3DRENDER_RENDER_RENDERTHREAD_H
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index bfdb68eb1..03f61b2d9 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -66,6 +66,7 @@
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/rendercapture_p.h>
+#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <Qt3DCore/qentity.h>
#include <QtGui/qsurface.h>
@@ -128,6 +129,8 @@ RenderView::StandardUniformsNameToTypeHash RenderView::initializeStandardUniform
setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), ModelViewNormalMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("viewportMatrix")), ViewportMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseViewportMatrix")), InverseViewportMatrix);
+ setters.insert(StringToInt::lookupId(QLatin1String("exposure")), Exposure);
+ setters.insert(StringToInt::lookupId(QLatin1String("gamma")), Gamma);
setters.insert(StringToInt::lookupId(QLatin1String("time")), Time);
setters.insert(StringToInt::lookupId(QLatin1String("eyePosition")), EyePosition);
@@ -190,6 +193,10 @@ UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standa
viewportMatrix.viewport(resolveViewport(m_viewport, m_surfaceSize));
return UniformValue(viewportMatrix.inverted());
}
+ case Exposure:
+ return UniformValue(m_data.m_renderCameraLens->exposure());
+ case Gamma:
+ return UniformValue(m_gamma);
case Time:
return UniformValue(float(m_renderer->time() / 1000000000.0f));
case EyePosition:
@@ -201,9 +208,11 @@ UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standa
}
RenderView::RenderView()
- : m_renderer(nullptr)
+ : m_isDownloadBuffersEnable(false)
+ , m_renderer(nullptr)
, m_devicePixelRatio(1.)
, m_viewport(QRectF(0.0f, 0.0f, 1.0f, 1.0f))
+ , m_gamma(2.2f)
, m_surface(nullptr)
, m_clearBuffer(QClearBuffers::None)
, m_stateSet(nullptr)
@@ -211,6 +220,7 @@ RenderView::RenderView()
, m_compute(false)
, m_frustumCulling(false)
, m_memoryBarrier(QMemoryBarrier::None)
+ , m_environmentLight(nullptr)
{
m_workGroups[0] = 1;
m_workGroups[1] = 1;
@@ -352,6 +362,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit
// is only accessed from the same thread
UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
builder->shaderDataManager = m_manager->shaderDataManager();
+ builder->textureManager = m_manager->textureManager();
m_localData.setLocalData(builder);
QVector<RenderCommand *> commands;
@@ -404,7 +415,12 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit
ParameterInfoList globalParameters = passData.parameterInfo;
// setShaderAndUniforms can initialize a localData
// make sure this is cleared before we leave this function
- setShaderAndUniforms(command, pass, globalParameters, *(node->worldTransform()), lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)));
+ setShaderAndUniforms(command,
+ pass,
+ globalParameters,
+ *(node->worldTransform()),
+ lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)),
+ m_environmentLight);
// Store all necessary information for actual drawing if command is valid
command->m_isValid = !command->m_attributes.empty();
@@ -470,6 +486,7 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En
// is only accessed from the same thread
UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
builder->shaderDataManager = m_manager->shaderDataManager();
+ builder->textureManager = m_manager->textureManager();
m_localData.setLocalData(builder);
// If the RenderView contains only a ComputeDispatch then it cares about
@@ -503,7 +520,8 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En
pass,
globalParameters,
*(node->worldTransform()),
- QVector<LightSource>());
+ QVector<LightSource>(),
+ nullptr);
commands.append(command);
}
}
@@ -579,7 +597,7 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack,
// If two shaders define the same block with the exact same layout, in that case the UBO could be shared
// but how do we know that ? We'll need to compare ShaderUniformBlocks
- // Note: we assume that if a buffer is shared accross multiple shaders
+ // Note: we assume that if a buffer is shared across multiple shaders
// then it implies that they share the same layout
// Temporarly disabled
@@ -691,7 +709,7 @@ void RenderView::buildSortingKey(RenderCommand *command) const
}
void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass, ParameterInfoList &parameters, const QMatrix4x4 &worldTransform,
- const QVector<LightSource> &activeLightSources) const
+ const QVector<LightSource> &activeLightSources, EnvironmentLight *environmentLight) const
{
// The VAO Handle is set directly in the renderer thread so as to avoid having to use a mutex here
// Set shader, technique, and effect by basically doing :
@@ -812,13 +830,25 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass,
if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax(1, lightIdx)));
- if (activeLightSources.isEmpty()) {
+ // If no active light sources and no environment light, add a default light
+ if (activeLightSources.isEmpty() && !environmentLight) {
// Note: implicit conversion of values to UniformValue
setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], QVector3D(10.0f, 10.0f, 0.0f));
setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], QVector3D(1.0f, 1.0f, 1.0f));
setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
}
+
+ // Environment Light
+ int envLightCount = 0;
+ if (environmentLight && environmentLight->isEnabled()) {
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
+ if (shaderData) {
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
+ envLightCount = 1;
+ }
+ }
+ setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
}
// Set frag outputs in the shaders if hash not empty
if (!fragOutputs.isEmpty())
@@ -830,6 +860,16 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderPass *rPass,
}
}
+bool RenderView::isDownloadBuffersEnable() const
+{
+ return m_isDownloadBuffersEnable;
+}
+
+void RenderView::setIsDownloadBuffersEnable(bool isDownloadBuffersEnable)
+{
+ m_isDownloadBuffersEnable = isDownloadBuffersEnable;
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h
index 1f00e2aae..440d51638 100644
--- a/src/render/backend/renderview_p.h
+++ b/src/render/backend/renderview_p.h
@@ -181,6 +181,9 @@ public:
inline void setViewport(const QRectF &vp) Q_DECL_NOTHROW { m_viewport = vp; }
inline QRectF viewport() const Q_DECL_NOTHROW { return m_viewport; }
+ inline float gamma() const Q_DECL_NOTHROW { return m_gamma; }
+ inline void setGamma(float gamma) Q_DECL_NOTHROW { m_gamma = gamma; }
+
// depth and stencil ClearBuffers are cached locally
// color ClearBuffers are collected, as there may be multiple
// color buffers to be cleared. we need to apply all these at rendering
@@ -212,14 +215,15 @@ public:
QSurface *surface() const { return m_surface; }
void setLightSources(const QVector<LightSource> &lightSources) Q_DECL_NOTHROW { m_lightSources = lightSources; }
+ void setEnvironmentLight(EnvironmentLight *environmentLight) Q_DECL_NOTHROW { m_environmentLight = environmentLight; }
void updateMatrices();
inline void setRenderCaptureNodeId(const Qt3DCore::QNodeId nodeId) Q_DECL_NOTHROW { m_renderCaptureNodeId = nodeId; }
inline const Qt3DCore::QNodeId renderCaptureNodeId() const Q_DECL_NOTHROW { return m_renderCaptureNodeId; }
- void setMemoryBarrier(QMemoryBarrier::BarrierTypes barrier) Q_DECL_NOTHROW { m_memoryBarrier = barrier; }
- QMemoryBarrier::BarrierTypes memoryBarrier() const Q_DECL_NOTHROW { return m_memoryBarrier; }
+ void setMemoryBarrier(QMemoryBarrier::Operations barrier) Q_DECL_NOTHROW { m_memoryBarrier = barrier; }
+ QMemoryBarrier::Operations memoryBarrier() const Q_DECL_NOTHROW { return m_memoryBarrier; }
// Helps making the size of RenderView smaller
// Contains all the data needed for the actual building of the RenderView
@@ -245,13 +249,17 @@ public:
QVector3D m_eyePos;
};
+ bool isDownloadBuffersEnable() const;
+ void setIsDownloadBuffersEnable(bool isDownloadBuffersEnable);
+
private:
void setShaderAndUniforms(RenderCommand *command, RenderPass *pass, ParameterInfoList &parameters, const QMatrix4x4 &worldTransform,
- const QVector<LightSource> &activeLightSources) const;
+ const QVector<LightSource> &activeLightSources, EnvironmentLight *environmentLight) const;
mutable QThreadStorage<UniformBlockValueBuilder*> m_localData;
Qt3DCore::QNodeId m_renderCaptureNodeId;
+ bool m_isDownloadBuffersEnable;
Renderer *m_renderer;
NodeManagers *m_manager;
@@ -261,6 +269,7 @@ private:
InnerData m_data;
QRectF m_viewport;
+ float m_gamma;
Qt3DCore::QNodeId m_renderTarget;
QSurface *m_surface;
AttachmentPack m_attachmentPack;
@@ -274,13 +283,14 @@ private:
bool m_compute:1;
bool m_frustumCulling:1;
int m_workGroups[3];
- QMemoryBarrier::BarrierTypes m_memoryBarrier;
+ QMemoryBarrier::Operations m_memoryBarrier;
// We do not use pointers to RenderNodes or Drawable's here so that the
// render aspect is free to change the drawables on the next frame whilst
// the render thread is submitting these commands.
QVector<RenderCommand *> m_commands;
mutable QVector<LightSource> m_lightSources;
+ EnvironmentLight *m_environmentLight;
QHash<Qt3DCore::QNodeId, QVector<RenderPassParameterData>> m_parameters;
@@ -303,6 +313,8 @@ private:
ViewportMatrix,
InverseViewportMatrix,
Time,
+ Exposure,
+ Gamma,
EyePosition
};
diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp
index 55d8ba462..f47c6f419 100644
--- a/src/render/backend/renderviewbuilder.cpp
+++ b/src/render/backend/renderviewbuilder.cpp
@@ -66,14 +66,14 @@ public:
RenderView *rv = m_renderViewJob->renderView();
int totalCommandCount = 0;
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
totalCommandCount += renderViewCommandBuilder->commands().size();
QVector<RenderCommand *> commands;
commands.reserve(totalCommandCount);
// Reduction
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
commands += std::move(renderViewCommandBuilder->commands());
rv->setCommands(commands);
@@ -139,13 +139,13 @@ public:
m_filterEntityByLayerJob->setLayers(rv->layerFilter());
// Material Parameter building
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs)) {
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
materialGatherer->setRenderPassFilter(const_cast<RenderPassFilter *>(rv->renderPassFilter()));
materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter()));
}
// Command builders
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
renderViewCommandBuilder->setRenderView(rv);
// Set whether frustum culling is enabled or not
@@ -188,8 +188,7 @@ public:
RenderView *rv = m_renderViewJob->renderView();
if (!rv->noDraw()) {
- // Set the light sources
- rv->setLightSources(std::move(m_lightGathererJob->lights()));
+ rv->setEnvironmentLight(m_lightGathererJob->takeEnvironmentLight());
// We sort the vector so that the removal can then be performed linearly
@@ -207,6 +206,14 @@ public:
QVector<Entity *> filteredEntities = m_filterEntityByLayerJob->filteredEntities();
RenderViewBuilder::removeEntitiesNotInSubset(renderableEntities, filteredEntities);
+ // Set the light sources, with layer filters applied.
+ QVector<LightSource> lightSources = m_lightGathererJob->lights();
+ for (int i = 0; i < lightSources.count(); ++i) {
+ if (!filteredEntities.contains(lightSources[i].entity))
+ lightSources.removeAt(i--);
+ }
+ rv->setLightSources(lightSources);
+
// Filter out frustum culled entity for drawable entities
if (isDraw && rv->frustumCulling())
RenderViewBuilder::removeEntitiesNotInSubset(renderableEntities, m_frustumCullingJob->visibleEntities());
@@ -224,7 +231,7 @@ public:
// Reduction
QHash<Qt3DCore::QNodeId, QVector<RenderPassParameterData>> params;
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs))
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs))
params.unite(materialGatherer->materialToPassAndParameter());
// Set all required data on the RenderView for final processing
rv->setMaterialParameterTable(std::move(params));
@@ -424,7 +431,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob);
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs)) {
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
materialGatherer->addDependency(m_syncRenderViewInitializationJob);
materialGatherer->addDependency(m_renderer->filterCompatibleTechniqueJob());
m_syncRenderCommandBuildingJob->addDependency(materialGatherer);
@@ -435,7 +442,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
m_syncRenderCommandBuildingJob->addDependency(m_lightGathererJob);
m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob);
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob);
m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder);
}
@@ -457,13 +464,13 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
jobs.push_back(m_filterEntityByLayerJob); // Step 3
jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3
- for (const auto materialGatherer : qAsConst(m_materialGathererJobs)) // Step3
+ for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) // Step3
jobs.push_back(materialGatherer);
jobs.push_back(m_frustumCullingJob); // Step 4
jobs.push_back(m_syncRenderCommandBuildingJob); // Step 4
- for (const auto renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 5
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 5
jobs.push_back(renderViewCommandBuilder);
jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 6
diff --git a/src/render/backend/resourceaccessor.cpp b/src/render/backend/resourceaccessor.cpp
new file mode 100644
index 000000000..7558eb4ad
--- /dev/null
+++ b/src/render/backend/resourceaccessor.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "resourceaccessor_p.h"
+
+#include <Qt3DRender/qrendertargetoutput.h>
+
+#include <private/qrendertargetoutput_p.h>
+#include <private/nodemanagers_p.h>
+#include <private/texture_p.h>
+#include <private/rendertargetoutput_p.h>
+#include <private/texturedatamanager_p.h>
+#include <private/gltexturemanager_p.h>
+#include <private/managers_p.h>
+#include <private/gltexture_p.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+RenderBackendResourceAccessor::~RenderBackendResourceAccessor()
+{
+
+}
+
+ResourceAccessor::ResourceAccessor(NodeManagers *mgr)
+ : m_glTextureManager(mgr->glTextureManager())
+ , m_textureManager(mgr->textureManager())
+ , m_attachmentManager(mgr->attachmentManager())
+ , m_entityManager(mgr->renderNodesManager())
+{
+
+}
+
+// called by render plugins from arbitrary thread
+bool ResourceAccessor::accessResource(ResourceType type, Qt3DCore::QNodeId nodeId, void **handle, QMutex **lock)
+{
+ switch (type) {
+
+ case RenderBackendResourceAccessor::OGLTexture: {
+ Texture *tex = m_textureManager->lookupResource(nodeId);
+ if (!tex)
+ return false;
+
+ GLTexture *glTex = m_glTextureManager->lookupResource(tex->peerId());
+ if (!glTex)
+ return false;
+
+ if (glTex->isDirty())
+ return false;
+
+ QOpenGLTexture **glTextureHandle = reinterpret_cast<QOpenGLTexture **>(handle);
+ *glTextureHandle = glTex->getOrCreateGLTexture();
+ *lock = glTex->textureLock();
+ return true;
+ }
+
+ case RenderBackendResourceAccessor::OutputAttachment: {
+ RenderTargetOutput *output = m_attachmentManager->lookupResource(nodeId);
+ if (output) {
+ Attachment **attachmentData = reinterpret_cast<Attachment **>(handle);
+ *attachmentData = output->attachment();
+ return true;
+ }
+ break;
+ }
+
+ case RenderBackendResourceAccessor::EntityHandle: {
+ Entity *entity = m_entityManager->lookupResource(nodeId);
+ if (entity) {
+ Entity **pEntity = reinterpret_cast<Entity **>(handle);
+ *pEntity = entity;
+ return true;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/backend/resourceaccessor_p.h b/src/render/backend/resourceaccessor_p.h
new file mode 100644
index 000000000..b4ed2a3eb
--- /dev/null
+++ b/src/render/backend/resourceaccessor_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_RESOURCEACCESSOR_P_H
+#define QT3DRENDER_RENDER_RESOURCEACCESSOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qnodeid.h>
+
+#include <private/qt3drender_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMutex;
+
+namespace Qt3DRender
+{
+namespace Render {
+
+class TextureManager;
+class AttachmentManager;
+class GLTextureManager;
+class EntityManager;
+class NodeManagers;
+
+class RenderBackendResourceAccessor
+{
+public:
+ enum ResourceType {
+ OGLTexture,
+ OutputAttachment,
+ EntityHandle,
+ };
+
+ virtual ~RenderBackendResourceAccessor();
+ virtual bool accessResource(ResourceType type, Qt3DCore::QNodeId nodeId, void **handle, QMutex **lock) = 0;
+};
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT ResourceAccessor : public RenderBackendResourceAccessor
+{
+public:
+ ResourceAccessor(NodeManagers *mgr);
+ bool accessResource(ResourceType type, Qt3DCore::QNodeId nodeId, void **handle, QMutex **lock) Q_DECL_FINAL;
+private:
+ GLTextureManager *m_glTextureManager;
+ TextureManager *m_textureManager;
+ AttachmentManager *m_attachmentManager;
+ EntityManager *m_entityManager;
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_RESOURCEACCESSOR_P_H
diff --git a/src/render/backend/shadervariables_p.h b/src/render/backend/shadervariables_p.h
index 2177abe0e..e0fa07dff 100644
--- a/src/render/backend/shadervariables_p.h
+++ b/src/render/backend/shadervariables_p.h
@@ -81,6 +81,7 @@ struct ShaderUniform
{
ShaderUniform()
: m_nameId(-1)
+ , m_type(GL_NONE)
, m_size(0)
, m_offset(-1)
, m_location(-1)
diff --git a/src/render/backend/triangleboundingvolume.cpp b/src/render/backend/triangleboundingvolume.cpp
index 80a23572c..ca2d26897 100644
--- a/src/render/backend/triangleboundingvolume.cpp
+++ b/src/render/backend/triangleboundingvolume.cpp
@@ -112,15 +112,18 @@ Qt3DCore::QNodeId TriangleBoundingVolume::id() const
return m_id;
}
-bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, QVector3D *q) const
+bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const
{
float t = 0.0f;
- QVector3D uvw;
- const bool intersected = intersectsSegmentTriangle(ray, m_c, m_b, m_a, uvw, t);
-
- if (intersected && q != nullptr)
- *q = ray.point(t * ray.distance());
-
+ QVector3D uvwr;
+ const float intersected = intersectsSegmentTriangle(ray, m_c, m_b, m_a, uvwr, t);
+
+ if (intersected) {
+ if (q != nullptr)
+ *q = ray.point(t);
+ if (uvw != nullptr)
+ *uvw = uvwr;
+ }
return intersected;
}
diff --git a/src/render/backend/triangleboundingvolume_p.h b/src/render/backend/triangleboundingvolume_p.h
index 1163efc46..3192ad456 100644
--- a/src/render/backend/triangleboundingvolume_p.h
+++ b/src/render/backend/triangleboundingvolume_p.h
@@ -78,7 +78,7 @@ public:
const QVector3D &c);
Qt3DCore::QNodeId id() const Q_DECL_FINAL;
- bool intersects(const RayCasting::QRay3D &ray, QVector3D *q) const Q_DECL_FINAL;
+ bool intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const Q_DECL_FINAL;
Type type() const Q_DECL_FINAL;
QVector3D a() const;
diff --git a/src/render/backend/trianglesvisitor.cpp b/src/render/backend/trianglesvisitor.cpp
index 35cdecc29..036f43fa0 100644
--- a/src/render/backend/trianglesvisitor.cpp
+++ b/src/render/backend/trianglesvisitor.cpp
@@ -48,6 +48,7 @@
#include <Qt3DRender/private/geometry_p.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/bufferutils_p.h>
QT_BEGIN_NAMESPACE
@@ -71,24 +72,6 @@ bool isTriangleBased(Qt3DRender::QGeometryRenderer::PrimitiveType type) Q_DECL_N
}
}
-struct BufferInfo
-{
- BufferInfo()
- : type(QAttribute::VertexBaseType::Float)
- , dataSize(0)
- , count(0)
- , byteStride(0)
- , byteOffset(0)
- {}
-
- QByteArray data;
- QAttribute::VertexBaseType type;
- uint dataSize;
- uint count;
- uint byteStride;
- uint byteOffset;
-};
-
// TO DO: Add methods for triangle strip adjacency
// What about primitive restart ?
@@ -328,48 +311,67 @@ void traverseTriangleAdjacency(Vertex *vertices,
}
}
-
-template <QAttribute::VertexBaseType> struct EnumToType;
-template <> struct EnumToType<QAttribute::Byte> { typedef const char type; };
-template <> struct EnumToType<QAttribute::UnsignedByte> { typedef const uchar type; };
-template <> struct EnumToType<QAttribute::Short> { typedef const short type; };
-template <> struct EnumToType<QAttribute::UnsignedShort> { typedef const ushort type; };
-template <> struct EnumToType<QAttribute::Int> { typedef const int type; };
-template <> struct EnumToType<QAttribute::UnsignedInt> { typedef const uint type; };
-template <> struct EnumToType<QAttribute::Float> { typedef const float type; };
-template <> struct EnumToType<QAttribute::Double> { typedef const double type; };
-
-template<QAttribute::VertexBaseType v>
-typename EnumToType<v>::type *castToType(const QByteArray &u, uint byteOffset)
+template<typename Coordinate>
+QVector4D readCoordinate(const BufferInfo &info, Coordinate *coordinates, uint index)
{
- return reinterpret_cast< typename EnumToType<v>::type *>(u.constData() + byteOffset);
+ const uint stride = info.byteStride / sizeof(Coordinate);
+ QVector4D ret(0, 0, 0, 1.0f);
+ coordinates += stride * index;
+ for (uint e = 0; e < info.dataSize; ++e)
+ ret[e] = coordinates[e];
+ return ret;
}
template<typename Func>
void processBuffer(const BufferInfo &info, Func &f)
{
switch (info.type) {
- case QAttribute::Byte: f(info, castToType<QAttribute::Byte>(info.data, info.byteOffset));
+ case QAttribute::Byte: f(info, BufferTypeInfo::castToType<QAttribute::Byte>(info.data, info.byteOffset));
return;
- case QAttribute::UnsignedByte: f(info, castToType<QAttribute::UnsignedByte>(info.data, info.byteOffset));
+ case QAttribute::UnsignedByte: f(info, BufferTypeInfo::castToType<QAttribute::UnsignedByte>(info.data, info.byteOffset));
return;
- case QAttribute::Short: f(info, castToType<QAttribute::Short>(info.data, info.byteOffset));
+ case QAttribute::Short: f(info, BufferTypeInfo::castToType<QAttribute::Short>(info.data, info.byteOffset));
return;
- case QAttribute::UnsignedShort: f(info, castToType<QAttribute::UnsignedShort>(info.data, info.byteOffset));
+ case QAttribute::UnsignedShort: f(info, BufferTypeInfo::castToType<QAttribute::UnsignedShort>(info.data, info.byteOffset));
return;
- case QAttribute::Int: f(info, castToType<QAttribute::Int>(info.data, info.byteOffset));
+ case QAttribute::Int: f(info, BufferTypeInfo::castToType<QAttribute::Int>(info.data, info.byteOffset));
return;
- case QAttribute::UnsignedInt: f(info, castToType<QAttribute::UnsignedInt>(info.data, info.byteOffset));
+ case QAttribute::UnsignedInt: f(info, BufferTypeInfo::castToType<QAttribute::UnsignedInt>(info.data, info.byteOffset));
return;
- case QAttribute::Float: f(info, castToType<QAttribute::Float>(info.data, info.byteOffset));
+ case QAttribute::Float: f(info, BufferTypeInfo::castToType<QAttribute::Float>(info.data, info.byteOffset));
return;
- case QAttribute::Double: f(info, castToType<QAttribute::Double>(info.data, info.byteOffset));
+ case QAttribute::Double: f(info, BufferTypeInfo::castToType<QAttribute::Double>(info.data, info.byteOffset));
return;
default:
return;
}
}
+QVector4D readBuffer(const BufferInfo &info, uint index)
+{
+ switch (info.type) {
+ case QAttribute::Byte:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::Byte>(info.data, info.byteOffset), index);
+ case QAttribute::UnsignedByte:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::UnsignedByte>(info.data, info.byteOffset), index);
+ case QAttribute::Short:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::Short>(info.data, info.byteOffset), index);
+ case QAttribute::UnsignedShort:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::UnsignedShort>(info.data, info.byteOffset), index);
+ case QAttribute::Int:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::Int>(info.data, info.byteOffset), index);
+ case QAttribute::UnsignedInt:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::UnsignedInt>(info.data, info.byteOffset), index);
+ case QAttribute::Float:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::Float>(info.data, info.byteOffset), index);
+ case QAttribute::Double:
+ return readCoordinate(info, BufferTypeInfo::castToType<QAttribute::Double>(info.data, info.byteOffset), index);
+ default:
+ break;
+ }
+ return QVector4D();
+}
+
template<typename Index>
struct IndexedVertexExecutor
{
@@ -530,6 +532,53 @@ void TrianglesVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::Q
}
}
+bool CoordinateReader::setGeometry(const GeometryRenderer *renderer, const QString &attributeName)
+{
+ if (renderer == nullptr || renderer->instanceCount() != 1
+ || !isTriangleBased(renderer->primitiveType())) {
+ return false;
+ }
+
+ Geometry *geom = m_manager->lookupResource<Geometry, GeometryManager>(renderer->geometryId());
+
+ if (!geom)
+ return false;
+
+ Attribute *attribute = nullptr;
+
+ const auto attrIds = geom->attributes();
+ for (const Qt3DCore::QNodeId attrId : attrIds) {
+ attribute = m_manager->lookupResource<Attribute, AttributeManager>(attrId);
+ if (attribute){
+ if (attribute->name() == attributeName
+ || (attributeName == QStringLiteral("default")
+ && attribute->name() == QAttribute::defaultTextureCoordinateAttributeName())) {
+ break;
+ }
+ }
+ attribute = nullptr;
+ }
+
+ if (!attribute)
+ return false;
+
+ m_attribute = attribute;
+ m_buffer = m_manager->lookupResource<Buffer, BufferManager>(attribute->bufferId());
+
+ m_bufferInfo.data = m_buffer->data();
+ m_bufferInfo.type = m_attribute->vertexBaseType();
+ m_bufferInfo.byteOffset = m_attribute->byteOffset();
+ m_bufferInfo.byteStride = m_attribute->byteStride();
+ m_bufferInfo.dataSize = m_attribute->vertexSize();
+ m_bufferInfo.count = m_attribute->count();
+ return true;
+}
+
+QVector4D CoordinateReader::getCoordinate(uint vertexIndex)
+{
+ return readBuffer(m_bufferInfo, vertexIndex);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/trianglesvisitor_p.h b/src/render/backend/trianglesvisitor_p.h
index 5f7cff9c0..9428857ac 100644
--- a/src/render/backend/trianglesvisitor_p.h
+++ b/src/render/backend/trianglesvisitor_p.h
@@ -52,6 +52,10 @@
//
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DRender/QAttribute>
+#include <Qt3DRender/private/bufferutils_p.h>
+
+#include <private/qt3drender_global_p.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +69,8 @@ namespace Render {
class GeometryRenderer;
class NodeManagers;
+class Attribute;
+class Buffer;
class Q_AUTOTEST_EXPORT TrianglesVisitor
{
@@ -84,6 +90,27 @@ protected:
Qt3DCore::QNodeId m_nodeId;
};
+class QT3DRENDERSHARED_PRIVATE_EXPORT CoordinateReader
+{
+public:
+ explicit CoordinateReader(NodeManagers *manager)
+ : m_manager(manager)
+ , m_attribute(nullptr)
+ , m_buffer(nullptr)
+ {
+ }
+
+ bool setGeometry(const GeometryRenderer *renderer, const QString &attributeName);
+
+ QVector4D getCoordinate(uint vertexIndex);
+
+protected:
+ NodeManagers *m_manager;
+ Attribute *m_attribute;
+ Buffer *m_buffer;
+ BufferInfo m_bufferInfo;
+};
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/quick3d/imports/extras/defaults/qml/PhongMaterial.qml b/src/render/framegraph/buffercapture.cpp
index 5b770a56d..4e89150df 100644
--- a/src/quick3d/imports/extras/defaults/qml/PhongMaterial.qml
+++ b/src/render/framegraph/buffercapture.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2017 Juan José Casafranca
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,23 +37,25 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.0
-Material {
- id:root
- property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 )
- property color diffuse: Qt.rgba( 0.7, 0.7, 0.7, 1.0 )
- property color specular: Qt.rgba( 0.01, 0.01, 0.01, 1.0 )
- property real shininess: 150.0
+#include <Qt3DRender/private/qbuffercapture_p.h>
+#include <Qt3DRender/private/buffercapture_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
- parameters: [
- Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
- Parameter { name: "kd"; value: Qt.vector3d(root.diffuse.r, root.diffuse.g, root.diffuse.b) },
- Parameter { name: "ks"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) },
- Parameter { name: "shininess"; value: root.shininess }
- ]
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+BufferCapture::BufferCapture()
+ : FrameGraphNode(FrameGraphNode::BufferCapture, QBackendNode::ReadWrite)
+{
- effect: DefaultEffect {}
}
+} //Render
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/framegraph/buffercapture_p.h b/src/render/framegraph/buffercapture_p.h
new file mode 100644
index 000000000..d638f35d5
--- /dev/null
+++ b/src/render/framegraph/buffercapture_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Juan José Casafranca
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUFFERCAPTURE_P_H
+#define BUFFERCAPTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qbuffercapture_p.h>
+#include <Qt3DRender/private/framegraphnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class Q_AUTOTEST_EXPORT BufferCapture : public FrameGraphNode
+{
+public:
+ BufferCapture();
+};
+
+} //Render
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // BUFFERCAPTURE_P_H
diff --git a/src/render/framegraph/framegraph.pri b/src/render/framegraph/framegraph.pri
index 77d7dbc71..5e9ce68bf 100644
--- a/src/render/framegraph/framegraph.pri
+++ b/src/render/framegraph/framegraph.pri
@@ -45,6 +45,9 @@ HEADERS += \
$$PWD/qrendercapture.h \
$$PWD/qrendercapture_p.h \
$$PWD/rendercapture_p.h \
+ $$PWD/qbuffercapture.h \
+ $$PWD/qbuffercapture_p.h \
+ $$PWD/buffercapture_p.h \
$$PWD/qframegraphnodecreatedchange.h \
$$PWD/qframegraphnodecreatedchange_p.h \
$$PWD/qmemorybarrier.h \
@@ -83,6 +86,8 @@ SOURCES += \
$$PWD/rendersurfaceselector.cpp \
$$PWD/qrendercapture.cpp \
$$PWD/rendercapture.cpp \
+ $$PWD/qbuffercapture.cpp \
+ $$PWD/buffercapture.cpp \
$$PWD/qframegraphnodecreatedchange.cpp \
$$PWD/qmemorybarrier.cpp \
$$PWD/memorybarrier.cpp
diff --git a/src/render/framegraph/framegraphnode_p.h b/src/render/framegraph/framegraphnode_p.h
index ccdc47f12..c7b399f89 100644
--- a/src/render/framegraph/framegraphnode_p.h
+++ b/src/render/framegraph/framegraphnode_p.h
@@ -98,6 +98,7 @@ public:
ComputeDispatch,
Surface,
RenderCapture,
+ BufferCapture,
MemoryBarrier
};
FrameGraphNodeType nodeType() const { return m_nodeType; }
diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp
index d31e9cddd..cd8b08219 100644
--- a/src/render/framegraph/framegraphvisitor.cpp
+++ b/src/render/framegraph/framegraphvisitor.cpp
@@ -43,7 +43,6 @@
#include "framegraphnode_p.h"
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <QThreadPool>
QT_BEGIN_NAMESPACE
@@ -53,24 +52,16 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-FrameGraphVisitor::FrameGraphVisitor(Renderer *renderer,
- const FrameGraphManager *manager)
- : m_renderer(renderer)
- , m_manager(manager)
- , m_jobs(nullptr)
- , m_renderviewIndex(0)
-
+FrameGraphVisitor::FrameGraphVisitor(const FrameGraphManager *manager)
+ : m_manager(manager)
{
+ m_leaves.reserve(8);
}
-void FrameGraphVisitor::traverse(FrameGraphNode *root,
- QVector<Qt3DCore::QAspectJobPtr> *jobs)
+QVector<FrameGraphNode *> FrameGraphVisitor::traverse(FrameGraphNode *root)
{
- m_jobs = jobs;
- m_renderviewIndex = 0;
+ m_leaves.clear();
- Q_ASSERT(m_renderer);
- Q_ASSERT(m_jobs);
Q_ASSERT_X(root, Q_FUNC_INFO, "The FrameGraphRoot is null");
// Kick off the traversal
@@ -78,6 +69,7 @@ void FrameGraphVisitor::traverse(FrameGraphNode *root,
if (node == nullptr)
qCritical() << Q_FUNC_INFO << "FrameGraph is null";
visit(node);
+ return m_leaves;
}
void FrameGraphVisitor::visit(Render::FrameGraphNode *node)
@@ -97,10 +89,8 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node)
// Leaf node - create a RenderView ready to be populated
// TODO: Pass in only framegraph config that has changed from previous
// index RenderViewJob.
- if (fgChildIds.empty()) {
- RenderViewBuilder builder(node, m_renderviewIndex++, m_renderer);
- m_jobs->append(builder.buildJobHierachy());
- }
+ if (fgChildIds.empty())
+ m_leaves.push_back(node);
}
} // namespace Render
diff --git a/src/render/framegraph/framegraphvisitor_p.h b/src/render/framegraph/framegraphvisitor_p.h
index af8f4caab..f4c0d7796 100644
--- a/src/render/framegraph/framegraphvisitor_p.h
+++ b/src/render/framegraph/framegraphvisitor_p.h
@@ -66,24 +66,18 @@ class FrameGraphNode;
class Renderer;
class FrameGraphManager;
-class FrameGraphVisitor
+class Q_AUTOTEST_EXPORT FrameGraphVisitor
{
public:
- explicit FrameGraphVisitor(Renderer *renderer,
- const FrameGraphManager *nodeManager);
+ explicit FrameGraphVisitor(const FrameGraphManager *nodeManager);
- void traverse(FrameGraphNode *root,
- QVector<Qt3DCore::QAspectJobPtr> *jobs);
-
- inline int leafNodeCount() Q_DECL_NOTHROW { return m_renderviewIndex; }
+ QVector<FrameGraphNode *> traverse(FrameGraphNode *root);
private:
void visit(Render::FrameGraphNode *node);
- Renderer *m_renderer;
const FrameGraphManager *m_manager;
- QVector<Qt3DCore::QAspectJobPtr> *m_jobs;
- int m_renderviewIndex;
+ QVector<FrameGraphNode *> m_leaves;
};
} // namespace Render
diff --git a/src/render/framegraph/memorybarrier.cpp b/src/render/framegraph/memorybarrier.cpp
index c82f6eae8..ee8f156e3 100644
--- a/src/render/framegraph/memorybarrier.cpp
+++ b/src/render/framegraph/memorybarrier.cpp
@@ -49,7 +49,7 @@ namespace Render {
MemoryBarrier::MemoryBarrier()
: FrameGraphNode(FrameGraphNode::MemoryBarrier)
- , m_barrierTypes(QMemoryBarrier::None)
+ , m_waitOperations(QMemoryBarrier::None)
{
}
@@ -57,17 +57,17 @@ MemoryBarrier::~MemoryBarrier()
{
}
-QMemoryBarrier::BarrierTypes MemoryBarrier::barrierTypes() const
+QMemoryBarrier::Operations MemoryBarrier::waitOperations() const
{
- return m_barrierTypes;
+ return m_waitOperations;
}
void MemoryBarrier::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == Qt3DCore::PropertyUpdated) {
Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("barrierTypes")) {
- m_barrierTypes = propertyChange->value().value<QMemoryBarrier::BarrierTypes>();
+ if (propertyChange->propertyName() == QByteArrayLiteral("waitOperations")) {
+ m_waitOperations = propertyChange->value().value<QMemoryBarrier::Operations>();
markDirty(AbstractRenderer::AllDirty);
}
}
@@ -79,7 +79,7 @@ void MemoryBarrier::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr
FrameGraphNode::initializeFromPeer(change);
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMemoryBarrierData>>(change);
const QMemoryBarrierData &data = typedChange->data;
- m_barrierTypes = data.barrierTypes;
+ m_waitOperations = data.waitOperations;
}
} // Render
diff --git a/src/render/framegraph/memorybarrier_p.h b/src/render/framegraph/memorybarrier_p.h
index 4c0242476..66a3ae823 100644
--- a/src/render/framegraph/memorybarrier_p.h
+++ b/src/render/framegraph/memorybarrier_p.h
@@ -66,12 +66,12 @@ public:
MemoryBarrier();
~MemoryBarrier();
- QMemoryBarrier::BarrierTypes barrierTypes() const;
+ QMemoryBarrier::Operations waitOperations() const;
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
- QMemoryBarrier::BarrierTypes m_barrierTypes;
+ QMemoryBarrier::Operations m_waitOperations;
};
} // Render
diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp
new file mode 100644
index 000000000..602ad5d6d
--- /dev/null
+++ b/src/render/framegraph/qbuffercapture.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Juan José Casafranca
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DRender/qbuffercapture.h>
+#include <Qt3DRender/private/qbuffercapture_p.h>
+#include <Qt3DCore/QSceneChange>
+#include <Qt3DCore/QPropertyUpdatedChange>
+#include <Qt3DRender/QFrameGraphNodeCreatedChange>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+//Documentation here
+
+/*!
+ * \internal
+ */
+QBufferCapturePrivate::QBufferCapturePrivate()
+ : QFrameGraphNodePrivate()
+{
+
+}
+
+QBufferCapture::QBufferCapture(Qt3DCore::QNode *parent)
+ : QFrameGraphNode(*new QBufferCapturePrivate, parent)
+{
+
+}
+
+QBufferCapture::~QBufferCapture()
+{
+}
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/framegraph/qbuffercapture.h b/src/render/framegraph/qbuffercapture.h
new file mode 100644
index 000000000..d77266828
--- /dev/null
+++ b/src/render/framegraph/qbuffercapture.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Juan José Casafranca
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QBUFFERCAPTURE_H
+#define QT3DRENDER_QBUFFERCAPTURE_H
+
+#include <Qt3DRender/QFrameGraphNode>
+#include <Qt3DRender/QBuffer>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+class QBufferCapturePrivate;
+
+class QT3DRENDERSHARED_EXPORT QBufferCapture : public QFrameGraphNode
+{
+ Q_OBJECT
+public:
+ explicit QBufferCapture(Qt3DCore::QNode *parent = nullptr);
+ ~QBufferCapture();
+
+private:
+ Q_DECLARE_PRIVATE(QBufferCapture)
+};
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QBUFFERCAPTURE_H
diff --git a/src/render/framegraph/qbuffercapture_p.h b/src/render/framegraph/qbuffercapture_p.h
new file mode 100644
index 000000000..5e642aca3
--- /dev/null
+++ b/src/render/framegraph/qbuffercapture_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Juan José Casafranca
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QBUFFERCAPTURE_P_H
+#define QT3DRENDER_QBUFFERCAPTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/qbuffercapture.h>
+#include <Qt3DRender/private/qframegraphnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+class QBufferCapturePrivate : public QFrameGraphNodePrivate
+{
+public:
+ QBufferCapturePrivate();
+
+ Q_DECLARE_PUBLIC(QBufferCapture)
+};
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QBUFFERCAPTURE_P_H
diff --git a/src/render/framegraph/qmemorybarrier.cpp b/src/render/framegraph/qmemorybarrier.cpp
index 9aa3ba560..4c1685ef7 100644
--- a/src/render/framegraph/qmemorybarrier.cpp
+++ b/src/render/framegraph/qmemorybarrier.cpp
@@ -97,30 +97,31 @@ namespace Qt3DRender {
*/
/*!
- \enum QMemoryBarrier::BarrierType
+ \enum QMemoryBarrier::Operation
This enum type describes types of buffer to be cleared.
\value None
- \value ElementArrayBarrier
- \value UniformBarrier
- \value TextureFetchBarrier
- \value ShaderImageAccessBarrier
- \value CommandBarrier
- \value PixelBufferBarrier
- \value TextureUpdateBarrier
- \value BufferUpdateBarrier
- \value FrameBufferBarrier
- \value TransformFeedbackBarrier
- \value AtomicCounterBarrier
- \value ShaderStorageBarrier
- \value QueryBufferBarrier
- \value AllBarrier
+ \value ElementArray
+ \value Uniform
+ \value TextureFetch
+ \value ShaderImageAccess
+ \value Command
+ \value PixelBuffer
+ \value TextureUpdate
+ \value BufferUpdate
+ \value FrameBuffer
+ \value TransformFeedback
+ \value AtomicCounter
+ \value ShaderStorage
+ \value QueryBuffer
+ \value VertexAttributeArray
+ \value All
*/
QMemoryBarrierPrivate::QMemoryBarrierPrivate()
: QFrameGraphNodePrivate()
- , m_barrierTypes(QMemoryBarrier::None)
+ , m_waitOperations(QMemoryBarrier::None)
{
}
@@ -133,20 +134,20 @@ QMemoryBarrier::~QMemoryBarrier()
{
}
-void QMemoryBarrier::setBarrierTypes(QMemoryBarrier::BarrierTypes barrierTypes)
+void QMemoryBarrier::setWaitOperations(QMemoryBarrier::Operations waitOperations)
{
Q_D(QMemoryBarrier);
- if (barrierTypes != d->m_barrierTypes) {
- d->m_barrierTypes = barrierTypes;
- emit barrierTypesChanged(barrierTypes);
- d->notifyPropertyChange("barrierTypes", QVariant::fromValue(barrierTypes));
+ if (waitOperations != d->m_waitOperations) {
+ d->m_waitOperations = waitOperations;
+ emit waitOperationsChanged(waitOperations);
+ d->notifyPropertyChange("waitOperations", QVariant::fromValue(waitOperations));
}
}
-QMemoryBarrier::BarrierTypes QMemoryBarrier::barrierTypes() const
+QMemoryBarrier::Operations QMemoryBarrier::waitOperations() const
{
Q_D(const QMemoryBarrier);
- return d->m_barrierTypes;
+ return d->m_waitOperations;
}
QMemoryBarrier::QMemoryBarrier(QMemoryBarrierPrivate &dd, Qt3DCore::QNode *parent)
@@ -159,7 +160,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QMemoryBarrier::createNodeCreationChange() c
auto creationChange = QFrameGraphNodeCreatedChangePtr<QMemoryBarrierData>::create(this);
QMemoryBarrierData &data = creationChange->data;
Q_D(const QMemoryBarrier);
- data.barrierTypes = d->m_barrierTypes;
+ data.waitOperations = d->m_waitOperations;
return creationChange;
}
diff --git a/src/render/framegraph/qmemorybarrier.h b/src/render/framegraph/qmemorybarrier.h
index 8b73c86bf..bb439a9a5 100644
--- a/src/render/framegraph/qmemorybarrier.h
+++ b/src/render/framegraph/qmemorybarrier.h
@@ -55,33 +55,34 @@ public:
explicit QMemoryBarrier(Qt3DCore::QNode *parent = nullptr);
~QMemoryBarrier();
- enum BarrierType {
+ enum Operation {
None = 0,
- VertexAttributeArrayBarrier = (1 << 0),
- ElementArrayBarrier = (1 << 1),
- UniformBarrier = (1 << 2),
- TextureFetchBarrier = (1 << 3),
- ShaderImageAccessBarrier = (1 << 4),
- CommandBarrier = (1 << 5),
- PixelBufferBarrier = (1 << 6),
- TextureUpdateBarrier = (1 << 7),
- BufferUpdateBarrier = (1 << 8),
- FrameBufferBarrier = (1 << 9),
- TransformFeedbackBarrier = (1 << 10),
- AtomicCounterBarrier = (1 << 11),
- ShaderStorageBarrier = (1 << 12),
- QueryBufferBarrier = (1 << 13),
- AllBarrier = 0xFFFFFFFF
+ VertexAttributeArray = (1 << 0),
+ ElementArray = (1 << 1),
+ Uniform = (1 << 2),
+ TextureFetch = (1 << 3),
+ ShaderImageAccess = (1 << 4),
+ Command = (1 << 5),
+ PixelBuffer = (1 << 6),
+ TextureUpdate = (1 << 7),
+ BufferUpdate = (1 << 8),
+ FrameBuffer = (1 << 9),
+ TransformFeedback = (1 << 10),
+ AtomicCounter = (1 << 11),
+ ShaderStorage = (1 << 12),
+ QueryBuffer = (1 << 13),
+ All = 0xFFFFFFFF
};
- Q_ENUM(BarrierType)
- Q_DECLARE_FLAGS(BarrierTypes, BarrierType)
+ Q_ENUM(Operation)
+ Q_DECLARE_FLAGS(Operations, Operation)
+
+ Operations waitOperations() const;
public Q_SLOTS:
- void setBarrierTypes(QMemoryBarrier::BarrierTypes barrierTypes);
- BarrierTypes barrierTypes() const;
+ void setWaitOperations(QMemoryBarrier::Operations operations);
Q_SIGNALS:
- void barrierTypesChanged(QMemoryBarrier::BarrierTypes barrierTypes);
+ void waitOperationsChanged(QMemoryBarrier::Operations barrierTypes);
protected:
explicit QMemoryBarrier(QMemoryBarrierPrivate &dd, Qt3DCore::QNode *parent = nullptr);
@@ -95,6 +96,6 @@ private:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(Qt3DRender::QMemoryBarrier::BarrierTypes)
+Q_DECLARE_METATYPE(Qt3DRender::QMemoryBarrier::Operations)
#endif // QT3DRENDER_QMEMORYBARRIER_H
diff --git a/src/render/framegraph/qmemorybarrier_p.h b/src/render/framegraph/qmemorybarrier_p.h
index 09df0c89c..384dbee3d 100644
--- a/src/render/framegraph/qmemorybarrier_p.h
+++ b/src/render/framegraph/qmemorybarrier_p.h
@@ -63,12 +63,12 @@ public:
QMemoryBarrierPrivate();
Q_DECLARE_PUBLIC(QMemoryBarrier)
- QMemoryBarrier::BarrierTypes m_barrierTypes;
+ QMemoryBarrier::Operations m_waitOperations;
};
struct QMemoryBarrierData
{
- QMemoryBarrier::BarrierTypes barrierTypes;
+ QMemoryBarrier::Operations waitOperations;
};
} // namespace Qt3DRender
diff --git a/src/render/framegraph/qrendercapture.cpp b/src/render/framegraph/qrendercapture.cpp
index a4a5dabcb..f3e5d53ee 100644
--- a/src/render/framegraph/qrendercapture.cpp
+++ b/src/render/framegraph/qrendercapture.cpp
@@ -40,6 +40,8 @@
#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
+#include <QPointer>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
@@ -108,19 +110,41 @@ namespace Qt3DRender {
*/
/*!
+ * \qmlmethod bool Qt3D.Render::RenderCaptureReply::saveImage(fileName)
+ *
+ * Saves the render capture result as an image to \a fileName.
+ * Returns true if the image was successfully saved; otherwise returns false.
+ *
+ * \since 5.9
+ */
+
+/*!
* \qmlmethod void Qt3D.Render::RenderCaptureReply::saveToFile(fileName)
+ * \deprecated
*
* Saves the render capture result as an image to \a fileName.
+ *
+ * Deprecated in 5.9. Use saveImage().
*/
/*!
* \qmlmethod RenderCaptureReply Qt3D.Render::RenderCapture::requestCapture(int captureId)
+ * \deprecated
*
* Used to request render capture. User can specify a \a captureId to identify
* the request. The requestId does not have to be unique. Only one render capture result
* is produced per requestCapture call even if the frame graph has multiple leaf nodes.
* The function returns a QRenderCaptureReply object, which receives the captured image
- * when it is done. The user is reponsible for deallocating the returned object.
+ * when it is done. The user is responsible for deallocating the returned object.
+ */
+
+/*!
+ * \qmlmethod RenderCaptureReply Qt3D.Render::RenderCapture::requestCapture()
+ *
+ * Used to request render capture. Only one render capture result is produced per
+ * requestCapture call even if the frame graph has multiple leaf nodes.
+ * The function returns a QRenderCaptureReply object, which receives the captured image
+ * when it is done. The user is responsible for deallocating the returned object.
*/
/*!
@@ -178,6 +202,25 @@ bool QRenderCaptureReply::isComplete() const
/*!
* Saves the render capture result as an image to \a fileName.
+ *
+ * Returns true if the image was successfully saved; otherwise returns false.
+ * \since 5.9
+ */
+bool QRenderCaptureReply::saveImage(const QString &fileName) const
+{
+ Q_D(const QRenderCaptureReply);
+ if (d->m_complete)
+ {
+ return d->m_image.save(fileName);
+ }
+ return false;
+}
+
+/*!
+ * \deprecated
+ * Saves the render capture result as an image to \a fileName.
+ *
+ * Deprecated in 5.9. Use saveImage().
*/
void QRenderCaptureReply::saveToFile(const QString &fileName) const
{
@@ -212,7 +255,7 @@ QRenderCaptureReply *QRenderCapturePrivate::takeReply(int captureId)
{
QRenderCaptureReply *reply = nullptr;
for (int i = 0; i < m_waitingReplies.size(); ++i) {
- if (m_waitingReplies[i]->captureId() == captureId) {
+ if (m_waitingReplies[i]->d_func()->m_captureId == captureId) {
reply = m_waitingReplies[i];
m_waitingReplies.remove(i);
break;
@@ -239,11 +282,12 @@ QRenderCapture::QRenderCapture(Qt3DCore::QNode *parent)
}
/*!
+ * \deprecated
* Used to request render capture. User can specify a \a captureId to identify
* the request. The requestId does not have to be unique. Only one render capture result
* is produced per requestCapture call even if the frame graph has multiple leaf nodes.
* The function returns a QRenderCaptureReply object, which receives the captured image
- * when it is done. The user is reponsible for deallocating the returned object.
+ * when it is done. The user is responsible for deallocating the returned object.
*/
QRenderCaptureReply *QRenderCapture::requestCapture(int captureId)
{
@@ -259,6 +303,28 @@ QRenderCaptureReply *QRenderCapture::requestCapture(int captureId)
}
/*!
+ * Used to request render capture. Only one render capture result is produced per
+ * requestCapture call even if the frame graph has multiple leaf nodes.
+ * The function returns a QRenderCaptureReply object, which receives the captured image
+ * when it is done. The user is responsible for deallocating the returned object.
+ */
+QRenderCaptureReply *QRenderCapture::requestCapture()
+{
+ Q_D(QRenderCapture);
+ static int captureId = 1;
+ QRenderCaptureReply *reply = d->createReply(captureId);
+
+ Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(id()));
+ change->setPropertyName(QByteArrayLiteral("renderCaptureRequest"));
+ change->setValue(QVariant::fromValue(captureId));
+ d->notifyObservers(change);
+
+ captureId++;
+
+ return reply;
+}
+
+/*!
* \internal
*/
void QRenderCapture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
@@ -268,10 +334,15 @@ void QRenderCapture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
if (propertyChange->type() == Qt3DCore::PropertyUpdated) {
if (propertyChange->propertyName() == QByteArrayLiteral("renderCaptureData")) {
RenderCaptureDataPtr data = propertyChange->value().value<RenderCaptureDataPtr>();
- QRenderCaptureReply *reply = d->takeReply(data.data()->captureId);
+ QPointer<QRenderCaptureReply> reply = d->takeReply(data.data()->captureId);
if (reply) {
d->setImage(reply, data.data()->image);
- emit reply->completeChanged(true);
+ emit reply->completed();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ if (reply)
+ emit reply->completeChanged(true);
+QT_WARNING_POP
}
}
}
diff --git a/src/render/framegraph/qrendercapture.h b/src/render/framegraph/qrendercapture.h
index f3be273f3..5b768b593 100644
--- a/src/render/framegraph/qrendercapture.h
+++ b/src/render/framegraph/qrendercapture.h
@@ -52,18 +52,23 @@ class QT3DRENDERSHARED_EXPORT QRenderCaptureReply : public QObject
Q_OBJECT
Q_PROPERTY(QImage image READ image CONSTANT)
Q_PROPERTY(int captureId READ captureId CONSTANT)
- Q_PROPERTY(bool complete READ isComplete NOTIFY completeChanged)
+ Q_PROPERTY(bool complete READ isComplete NOTIFY completed)
public:
QImage image() const;
- int captureId() const;
+ Q_DECL_DEPRECATED int captureId() const;
bool isComplete() const;
- Q_INVOKABLE void saveToFile(const QString &fileName) const;
+ Q_INVOKABLE bool saveImage(const QString &fileName) const;
+#if QT_DEPRECATED_SINCE(5, 9)
+ // ### Qt 6: remove this
+ Q_DECL_DEPRECATED_X("Use saveImage instead") Q_INVOKABLE void saveToFile(const QString &fileName) const;
+#endif
Q_SIGNALS:
- void completeChanged(bool isComplete);
+ Q_DECL_DEPRECATED_X("Use completed instead") void completeChanged(bool isComplete);
+ void completed();
private:
Q_DECLARE_PRIVATE(QRenderCaptureReply)
@@ -79,7 +84,9 @@ class QT3DRENDERSHARED_EXPORT QRenderCapture : public QFrameGraphNode
public:
explicit QRenderCapture(Qt3DCore::QNode *parent = nullptr);
- Q_INVOKABLE Qt3DRender::QRenderCaptureReply *requestCapture(int captureId);
+ Q_INVOKABLE Q_DECL_DEPRECATED_X("Use the overload with no parameter")
+ Qt3DRender::QRenderCaptureReply *requestCapture(int captureId);
+ Q_REVISION(9) Q_INVOKABLE Qt3DRender::QRenderCaptureReply *requestCapture();
protected:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
diff --git a/src/render/framegraph/qsortpolicy.cpp b/src/render/framegraph/qsortpolicy.cpp
index 2eb0dff19..b1e0f4956 100644
--- a/src/render/framegraph/qsortpolicy.cpp
+++ b/src/render/framegraph/qsortpolicy.cpp
@@ -65,7 +65,7 @@ QSortPolicyPrivate::QSortPolicyPrivate()
The sort types determine how drawable entities are sorted before drawing to
determine the drawing order. When QSortPolicy is present in the FrameGraph,
the sorting mechanism is determined by the SortTypes list. Multiple sort types
- can be used simultanously. If QSortPolicy is not present in the FrameGraph,
+ can be used simultaneously. If QSortPolicy is not present in the FrameGraph,
entities are drawn in the order they appear in the entity hierarchy.
*/
@@ -81,7 +81,7 @@ QSortPolicyPrivate::QSortPolicyPrivate()
The sort types determine how drawable entities are sorted before drawing to
determine the drawing order. When SortPolicy is present in the FrameGraph,
the sorting mechanism is determined by the SortTypes list. Multiple sort
- types can be used simultanously. If SortPolicy is not present in the FrameGraph,
+ types can be used simultaneously. If SortPolicy is not present in the FrameGraph,
entities are drawn in the order they appear in the entity hierarchy.
*/
diff --git a/src/render/framegraph/qviewport.cpp b/src/render/framegraph/qviewport.cpp
index a78e260a5..8c1ebe67c 100644
--- a/src/render/framegraph/qviewport.cpp
+++ b/src/render/framegraph/qviewport.cpp
@@ -50,6 +50,7 @@ namespace Qt3DRender {
QViewportPrivate::QViewportPrivate()
: QFrameGraphNodePrivate()
, m_normalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f))
+ , m_gamma(2.2f)
{
}
@@ -62,7 +63,8 @@ QViewportPrivate::QViewportPrivate()
\inherits Qt3DRender::QFrameGraphNode
Qt3DRender::QViewport of the scene specifies at which portion of the render surface Qt3D
- is rendering to. Area outside the viewport is left untouched.
+ is rendering to. Area outside the viewport is left untouched. It also controls global parameters
+ to the rendering in that viewport like gamma.
*/
/*!
@@ -74,7 +76,8 @@ QViewportPrivate::QViewportPrivate()
\brief A viewport on the Qt3D Scene
Viewport of the scene specifies at which portion of the render surface Qt3D is
- rendering to. Area outside the viewport is left untouched.
+ rendering to. Area outside the viewport is left untouched. It also controls global parameters
+ to the rendering in that viewport like gamma.
*/
/*!
@@ -86,6 +89,12 @@ QViewportPrivate::QViewportPrivate()
*/
/*!
+ \qmlproperty rect Viewport::gamma
+
+ Specifies the gamma factor for the viewport. The default is 2.2 which should give proper result on most screens.
+ */
+
+/*!
Constructs QViewport with given \a parent.
*/
QViewport::QViewport(QNode *parent)
@@ -111,6 +120,12 @@ QRectF QViewport::normalizedRect() const
return d->m_normalizedRect;
}
+float QViewport::gamma() const
+{
+ Q_D(const QViewport);
+ return d->m_gamma;
+}
+
/*!
\property QViewport::normalizedRect
@@ -127,12 +142,27 @@ void QViewport::setNormalizedRect(const QRectF &normalizedRect)
}
}
+/*!
+ \property QViewport::gamma
+
+ Specifies the gamma factor for the viewport. The default is 2.2 which should give proper result on most screens.
+ */
+void QViewport::setGamma(float gamma)
+{
+ Q_D(QViewport);
+ if (gamma != d->m_gamma) {
+ d->m_gamma = gamma;
+ emit gammaChanged(gamma);
+ }
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QViewport::createNodeCreationChange() const
{
auto creationChange = QFrameGraphNodeCreatedChangePtr<QViewportData>::create(this);
auto &data = creationChange->data;
Q_D(const QViewport);
data.normalizedRect = d->m_normalizedRect;
+ data.gamma = d->m_gamma;
return creationChange;
}
diff --git a/src/render/framegraph/qviewport.h b/src/render/framegraph/qviewport.h
index 5959ed791..66a3428c5 100644
--- a/src/render/framegraph/qviewport.h
+++ b/src/render/framegraph/qviewport.h
@@ -54,18 +54,22 @@ class QT3DRENDERSHARED_EXPORT QViewport : public QFrameGraphNode
{
Q_OBJECT
Q_PROPERTY(QRectF normalizedRect READ normalizedRect WRITE setNormalizedRect NOTIFY normalizedRectChanged)
+ Q_PROPERTY(float gamma READ gamma WRITE setGamma NOTIFY gammaChanged REVISION 9)
public:
explicit QViewport(Qt3DCore::QNode *parent = nullptr);
~QViewport();
QRectF normalizedRect() const;
+ float gamma() const;
public Q_SLOTS:
void setNormalizedRect(const QRectF& normalizedRect);
+ void setGamma(float gamma);
Q_SIGNALS:
void normalizedRectChanged(const QRectF& normalizedRect);
+ void gammaChanged(float gamma);
protected:
explicit QViewport(QViewportPrivate &dd, Qt3DCore::QNode *parent = nullptr);
diff --git a/src/render/framegraph/qviewport_p.h b/src/render/framegraph/qviewport_p.h
index 790cd3d06..4c82f38b3 100644
--- a/src/render/framegraph/qviewport_p.h
+++ b/src/render/framegraph/qviewport_p.h
@@ -67,11 +67,13 @@ public :
Q_DECLARE_PUBLIC(QViewport)
QRectF m_normalizedRect;
QColor m_clearColor;
+ float m_gamma;
};
struct QViewportData
{
QRectF normalizedRect;
+ float gamma;
};
} // namespace Qt3DRender
diff --git a/src/render/framegraph/rendercapture.cpp b/src/render/framegraph/rendercapture.cpp
index 6b6c48375..dea1cf565 100644
--- a/src/render/framegraph/rendercapture.cpp
+++ b/src/render/framegraph/rendercapture.cpp
@@ -92,7 +92,7 @@ void RenderCapture::sendRenderCaptures()
{
QMutexLocker lock(&m_mutex);
- for (const RenderCaptureDataPtr data : m_renderCaptureData) {
+ for (const RenderCaptureDataPtr &data : qAsConst(m_renderCaptureData)) {
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("renderCaptureData");
diff --git a/src/render/framegraph/viewportnode.cpp b/src/render/framegraph/viewportnode.cpp
index ccdb68918..b68f7b55b 100644
--- a/src/render/framegraph/viewportnode.cpp
+++ b/src/render/framegraph/viewportnode.cpp
@@ -55,6 +55,7 @@ ViewportNode::ViewportNode()
, m_yMin(0.0f)
, m_xMax(1.0f)
, m_yMax(1.0f)
+ , m_gamma(2.2f)
{
}
@@ -67,6 +68,7 @@ void ViewportNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr
m_xMax = data.normalizedRect.width();
m_yMin = data.normalizedRect.y();
m_yMax = data.normalizedRect.height();
+ m_gamma = data.gamma;
}
float ViewportNode::xMin() const
@@ -106,16 +108,28 @@ void ViewportNode::setYMax(float yMax)
m_yMax = yMax;
}
+float ViewportNode::gamma() const
+{
+ return m_gamma;
+}
+
+void ViewportNode::setGamma(float gamma)
+{
+ m_gamma = gamma;
+}
+
void ViewportNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == PropertyUpdated) {
QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
if (propertyChange->propertyName() == QByteArrayLiteral("normalizedRect")) {
- QRectF normalizedRect = propertyChange->value().value<QRectF>();
+ QRectF normalizedRect = propertyChange->value().toRectF();
setXMin(normalizedRect.x());
setYMin(normalizedRect.y());
setXMax(normalizedRect.width());
setYMax(normalizedRect.height());
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("gamma")) {
+ setGamma(propertyChange->value().toFloat());
}
markDirty(AbstractRenderer::AllDirty);
}
diff --git a/src/render/framegraph/viewportnode_p.h b/src/render/framegraph/viewportnode_p.h
index 882aa4d86..85003ff36 100644
--- a/src/render/framegraph/viewportnode_p.h
+++ b/src/render/framegraph/viewportnode_p.h
@@ -81,6 +81,9 @@ public:
float yMax() const;
void setYMax(float yMax);
+ float gamma() const;
+ void setGamma(float gamma);
+
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
private:
@@ -90,6 +93,7 @@ private:
float m_yMin;
float m_xMax;
float m_yMax;
+ float m_gamma;
};
QRectF computeViewport(const QRectF &childViewport, const ViewportNode *parentViewport);
diff --git a/src/render/frontend/qabstractfunctor.h b/src/render/frontend/qabstractfunctor.h
index d9c4d65a4..95f6aee51 100644
--- a/src/render/frontend/qabstractfunctor.h
+++ b/src/render/frontend/qabstractfunctor.h
@@ -80,6 +80,7 @@ public:
virtual ~QAbstractFunctor();
virtual qintptr id() const = 0;
+ // TODO: Remove when moving a copy of this to Qt3DCore
template<class T>
const T *functor_cast(const QAbstractFunctor *other) const
{
diff --git a/src/render/frontend/qcamera.cpp b/src/render/frontend/qcamera.cpp
index b9e180b97..13d689e0e 100644
--- a/src/render/frontend/qcamera.cpp
+++ b/src/render/frontend/qcamera.cpp
@@ -40,6 +40,8 @@
#include "qcamera.h"
#include "qcamera_p.h"
+#include <QtMath>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
@@ -199,6 +201,36 @@ QCameraPrivate::QCameraPrivate()
*/
/*!
+ * \qmlmethod void Qt3D.Render::Camera::viewAll()
+ *
+ * Rotates and moves the camera so that it's viewCenter is the center of the scene's bounding volume
+ * and the entire scene fits in the view port.
+ *
+ * \note Only works if the lens is in perspective projection mode.
+ * \sa Qt3D.Render::Camera::projectionType
+ */
+
+/*!
+ * \qmlmethod void Qt3D.Render::Camera::viewEntity(Entity entity)
+ *
+ * Rotates and moves the camera so that it's viewCenter is the center of the entity's bounding volume
+ * and the entire entity fits in the view port.
+ *
+ * \note Only works if the lens is in perspective projection mode.
+ * \sa Qt3D.Render::Camera::projectionType
+ */
+
+/*!
+ * \qmlmethod void Qt3D.Render::Camera::viewSphere(vector3d center, real radius)
+ *
+ * Rotates and moves the camera so that it's viewCenter is \a center
+ * and a sphere of \a radius fits in the view port.
+ *
+ * \note Only works if the lens is in perspective projection mode.
+ * \sa Qt3D.Render::Camera::projectionType
+ */
+
+/*!
* \qmlproperty enumeration Qt3D.Render::Camera::projectionType
*
* Holds the type of the camera projection.
@@ -346,6 +378,11 @@ QCameraPrivate::QCameraPrivate()
*/
/*!
+ * \property QCamera::exposure
+ * Holds the current exposure of the camera.
+ */
+
+/*!
* \property QCamera::position
* Holds the camera's position.
*/
@@ -387,6 +424,8 @@ QCamera::QCamera(Qt3DCore::QNode *parent)
QObject::connect(d_func()->m_lens, SIGNAL(bottomChanged(float)), this, SIGNAL(bottomChanged(float)));
QObject::connect(d_func()->m_lens, SIGNAL(topChanged(float)), this, SIGNAL(topChanged(float)));
QObject::connect(d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
+ QObject::connect(d_func()->m_lens, SIGNAL(exposureChanged(float)), this, SIGNAL(exposureChanged(float)));
+ QObject::connect(d_func()->m_lens, &QCameraLens::viewSphere, this, &QCamera::viewSphere);
QObject::connect(d_func()->m_transform, SIGNAL(matrixChanged()), this, SIGNAL(viewMatrixChanged()));
addComponent(d_func()->m_lens);
addComponent(d_func()->m_transform);
@@ -415,6 +454,7 @@ QCamera::QCamera(QCameraPrivate &dd, Qt3DCore::QNode *parent)
QObject::connect(d_func()->m_lens, SIGNAL(bottomChanged(float)), this, SIGNAL(bottomChanged(float)));
QObject::connect(d_func()->m_lens, SIGNAL(topChanged(float)), this, SIGNAL(topChanged(float)));
QObject::connect(d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
+ QObject::connect(d_func()->m_lens, &QCameraLens::viewSphere, this, &QCamera::viewSphere);
QObject::connect(d_func()->m_transform, SIGNAL(matrixChanged()), this, SIGNAL(viewMatrixChanged()));
addComponent(d_func()->m_lens);
addComponent(d_func()->m_transform);
@@ -630,6 +670,54 @@ void QCamera::rotateAboutViewCenter(const QQuaternion& q)
}
/*!
+ * Rotates and moves the camera so that it's viewCenter is the center of the scene's bounding volume
+ * and the entire scene fits in the view port.
+ *
+ * \note Only works if the lens is in perspective projection mode.
+ * \sa Qt3D.Render::Camera::projectionType
+ */
+void QCamera::viewAll()
+{
+ Q_D(QCamera);
+ d->m_lens->viewAll(id());
+}
+
+/*!
+ * Rotates and moves the camera so that it's viewCenter is \a center
+ * and a sphere of \a radius fits in the view port.
+ *
+ * \note Only works if the lens is in perspective projection mode.
+ * \sa Qt3D.Render::Camera::projectionType
+ */
+void QCamera::viewSphere(const QVector3D &center, float radius)
+{
+ Q_D(QCamera);
+ if (d->m_lens->projectionType() != QCameraLens::PerspectiveProjection || radius <= 0.f)
+ return;
+ double dist = radius / std::tan(qDegreesToRadians(d->m_lens->fieldOfView()) / 2.0f);
+ QVector3D dir = (d->m_viewCenter - d->m_position).normalized();
+ QVector3D newPos = center - (dir * dist);
+ setViewCenter(center);
+ setPosition(newPos);
+}
+
+/*!
+ * Rotates and moves the camera so that it's viewCenter is the center of the entity's bounding volume
+ * and the entire entity fits in the view port.
+ *
+ * \note Only works if the lens is in perspective projection mode.
+ * \sa Qt3D.Render::Camera::projectionType
+ */
+void QCamera::viewEntity(Qt3DCore::QEntity *entity)
+{
+ if (!entity)
+ return;
+
+ Q_D(QCamera);
+ d->m_lens->viewEntity(entity->id(), id());
+}
+
+/*!
* Sets the camera's projection type to \a type.
*/
void QCamera::setProjectionType(QCameraLens::ProjectionType type)
@@ -773,12 +861,27 @@ void QCamera::setProjectionMatrix(const QMatrix4x4 &projectionMatrix)
d->m_lens->setProjectionMatrix(projectionMatrix);
}
+/*!
+ * Sets the camera's exposure to \a exposure.
+ */
+void QCamera::setExposure(float exposure)
+{
+ Q_D(QCamera);
+ d->m_lens->setExposure(exposure);
+}
+
QMatrix4x4 QCamera::projectionMatrix() const
{
Q_D(const QCamera);
return d->m_lens->projectionMatrix();
}
+float QCamera::exposure() const
+{
+ Q_D(const QCamera);
+ return d->m_lens->exposure();
+}
+
/*!
* Sets the camera's position in 3D space to \a position.
*/
diff --git a/src/render/frontend/qcamera.h b/src/render/frontend/qcamera.h
index f5bd49fa2..5c86ea122 100644
--- a/src/render/frontend/qcamera.h
+++ b/src/render/frontend/qcamera.h
@@ -72,6 +72,7 @@ class QT3DRENDERSHARED_EXPORT QCamera : public Qt3DCore::QEntity
Q_PROPERTY(float bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
Q_PROPERTY(float top READ top WRITE setTop NOTIFY topChanged)
Q_PROPERTY(QMatrix4x4 projectionMatrix READ projectionMatrix WRITE setProjectionMatrix NOTIFY projectionMatrixChanged)
+ Q_PROPERTY(float exposure READ exposure WRITE setExposure NOTIFY exposureChanged REVISION 9)
// LookAt
Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(QVector3D upVector READ upVector WRITE setUpVector NOTIFY upVectorChanged)
@@ -126,6 +127,7 @@ public:
float bottom() const;
float top() const;
QMatrix4x4 projectionMatrix() const;
+ float exposure() const;
QVector3D position() const;
QVector3D upVector() const;
QVector3D viewCenter() const;
@@ -143,10 +145,15 @@ public Q_SLOTS:
void setBottom(float bottom);
void setTop(float top);
void setProjectionMatrix(const QMatrix4x4 &projectionMatrix);
+ void setExposure(float exposure);
void setPosition(const QVector3D &position);
void setUpVector(const QVector3D &upVector);
void setViewCenter(const QVector3D &viewCenter);
+ void viewAll();
+ void viewSphere(const QVector3D &center, float radius);
+ void viewEntity(Qt3DCore::QEntity *entity);
+
Q_SIGNALS:
void projectionTypeChanged(QCameraLens::ProjectionType projectionType);
void nearPlaneChanged(float nearPlane);
@@ -158,6 +165,7 @@ Q_SIGNALS:
void bottomChanged(float bottom);
void topChanged(float top);
void projectionMatrixChanged(const QMatrix4x4 &projectionMatrix);
+ void exposureChanged(float exposure);
void positionChanged(const QVector3D &position);
void upVectorChanged(const QVector3D &upVector);
void viewCenterChanged(const QVector3D &viewCenter);
diff --git a/src/render/frontend/qcameralens.cpp b/src/render/frontend/qcameralens.cpp
index 269bc8d16..c9be49484 100644
--- a/src/render/frontend/qcameralens.cpp
+++ b/src/render/frontend/qcameralens.cpp
@@ -202,6 +202,11 @@ namespace Qt3DRender {
*/
/*!
+ * \property QCameraLens::exposure
+ * Holds the current exposure of the camera lens.
+ */
+
+/*!
* \internal
*/
QCameraLensPrivate::QCameraLensPrivate()
@@ -215,7 +220,45 @@ QCameraLensPrivate::QCameraLensPrivate()
, m_right(0.5f)
, m_bottom(-0.5f)
, m_top(0.5f)
+ , m_exposure(0.0f)
+{
+}
+
+void QCameraLens::viewAll(Qt3DCore::QNodeId cameraId)
{
+ Q_D(QCameraLens);
+ if (d->m_projectionType == PerspectiveProjection) {
+ QVariant v;
+ v.setValue(cameraId);
+ d->m_pendingViewAllCommand = sendCommand(QLatin1Literal("QueryRootBoundingVolume"), v);
+ }
+}
+
+void QCameraLens::viewEntity(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId cameraId)
+{
+ Q_D(QCameraLens);
+ if (d->m_projectionType == PerspectiveProjection) {
+ QVector<Qt3DCore::QNodeId> ids = {entityId, cameraId};
+ QVariant v;
+ v.setValue(ids);
+ d->m_pendingViewAllCommand = sendCommand(QLatin1Literal("QueryEntityBoundingVolume"), v);
+ }
+}
+
+void QCameraLensPrivate::processViewAllCommand(Qt3DCore::QNodeCommand::CommandId commandId,
+ const QVariant &data)
+{
+ Q_Q(QCameraLens);
+ if (m_pendingViewAllCommand != commandId)
+ return;
+
+ QVector<float> boundingVolumeData = data.value< QVector<float> >();
+ if (boundingVolumeData.size() != 4)
+ return;
+ QVector3D center(boundingVolumeData[0], boundingVolumeData[1], boundingVolumeData[2]);
+ float radius = boundingVolumeData[3];
+ Q_EMIT q->viewSphere(center, radius);
+ m_pendingViewAllCommand = Qt3DCore::QNodeCommand::CommandId();
}
/*!
@@ -559,14 +602,50 @@ QMatrix4x4 QCameraLens::projectionMatrix() const
return d->m_projectionMatrix;
}
+/*!
+ * Sets the camera lens' \a exposure
+ */
+void QCameraLens::setExposure(float exposure)
+{
+ Q_D(QCameraLens);
+ if (qFuzzyCompare(d->m_exposure, exposure))
+ return;
+ d->m_exposure = exposure;
+
+ emit exposureChanged(exposure);
+}
+
+float QCameraLens::exposure() const
+{
+ Q_D(const QCameraLens);
+ return d->m_exposure;
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QCameraLens::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QCameraLensData>::create(this);
auto &data = creationChange->data;
data.projectionMatrix = d_func()->m_projectionMatrix;
+ data.exposure = d_func()->m_exposure;
return creationChange;
}
+void QCameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+{
+ Q_D(QCameraLens);
+ switch (change->type()) {
+ case Qt3DCore::CommandRequested: {
+ Qt3DCore::QNodeCommandPtr command = qSharedPointerCast<Qt3DCore::QNodeCommand>(change);
+
+ if (command->name() == QLatin1Literal("ViewAll"))
+ d->processViewAllCommand(command->inReplyTo(), command->data());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/frontend/qcameralens.h b/src/render/frontend/qcameralens.h
index ad414cada..0cd22e348 100644
--- a/src/render/frontend/qcameralens.h
+++ b/src/render/frontend/qcameralens.h
@@ -66,6 +66,7 @@ class QT3DRENDERSHARED_EXPORT QCameraLens : public Qt3DCore::QComponent
Q_PROPERTY(float bottom READ bottom WRITE setBottom NOTIFY bottomChanged)
Q_PROPERTY(float top READ top WRITE setTop NOTIFY topChanged)
Q_PROPERTY(QMatrix4x4 projectionMatrix READ projectionMatrix WRITE setProjectionMatrix NOTIFY projectionMatrixChanged)
+ Q_PROPERTY(float exposure READ exposure WRITE setExposure NOTIFY exposureChanged REVISION 9)
public:
explicit QCameraLens(QNode *parent = nullptr);
@@ -102,6 +103,11 @@ public:
void setPerspectiveProjection(float fieldOfView, float aspect,
float nearPlane, float farPlane);
+ float exposure() const;
+
+ void viewAll(Qt3DCore::QNodeId cameraId);
+ void viewEntity(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId cameraId);
+
public Q_SLOTS:
void setProjectionType(ProjectionType projectionType);
void setNearPlane(float nearPlane);
@@ -113,6 +119,7 @@ public Q_SLOTS:
void setBottom(float bottom);
void setTop(float top);
void setProjectionMatrix(const QMatrix4x4 &projectionMatrix);
+ void setExposure(float exposure);
Q_SIGNALS:
void projectionTypeChanged(QCameraLens::ProjectionType projectionType);
@@ -125,6 +132,8 @@ Q_SIGNALS:
void bottomChanged(float bottom);
void topChanged(float top);
void projectionMatrixChanged(const QMatrix4x4 &projectionMatrix);
+ void exposureChanged(float exposure);
+ void viewSphere(const QVector3D &center, float radius);
protected:
explicit QCameraLens(QCameraLensPrivate &dd, QNode *parent = nullptr);
@@ -132,6 +141,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QCameraLens)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
};
} // Qt3DRender
diff --git a/src/render/frontend/qcameralens_p.h b/src/render/frontend/qcameralens_p.h
index ecaa45b68..d78579b70 100644
--- a/src/render/frontend/qcameralens_p.h
+++ b/src/render/frontend/qcameralens_p.h
@@ -51,7 +51,8 @@
// We mean it.
//
-#include <Qt3DCore/private/qcomponent_p.h>
+#include <private/qcomponent_p.h>
+#include <private/qnodecommand_p.h>
#include "qcameralens.h"
#include <Qt3DCore/qpropertyupdatedchange.h>
@@ -101,6 +102,11 @@ public:
mutable QMatrix4x4 m_projectionMatrix;
+ float m_exposure;
+
+ Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand;
+ void processViewAllCommand(Qt3DCore::QNodeCommand::CommandId commandId, const QVariant &data);
+
private:
inline void updatePerpectiveProjection()
{
@@ -130,6 +136,7 @@ private:
struct QCameraLensData
{
QMatrix4x4 projectionMatrix;
+ float exposure;
};
} // namespace Qt3DRender
diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp
index 0d70803ca..03df4e6a8 100644
--- a/src/render/frontend/qlevelofdetail.cpp
+++ b/src/render/frontend/qlevelofdetail.cpp
@@ -37,7 +37,6 @@
**
****************************************************************************/
-#include "qboundingsphere.h"
#include "qlevelofdetail.h"
#include "qlevelofdetail_p.h"
#include "qcamera.h"
@@ -51,23 +50,9 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate()
: QComponentPrivate()
, m_camera(nullptr)
, m_currentIndex(0)
- , m_thresholdType(QLevelOfDetail::DistanceToCamera)
- , m_volumeOverride(nullptr)
+ , m_thresholdType(QLevelOfDetail::DistanceToCameraThreshold)
+ , m_volumeOverride()
{
- Q_Q(QLevelOfDetail);
- m_volumeOverride = new QBoundingSphere(q);
- QObject::connect(m_volumeOverride, SIGNAL(radiusChanged(float)), q, SLOT(_q_radiusChanged(float)));
- QObject::connect(m_volumeOverride, SIGNAL(centerChanged(const QVector3D &)), q, SLOT(_q_centerChanged(const QVector3D&)));
-}
-
-void QLevelOfDetailPrivate::_q_radiusChanged(float radius)
-{
- notifyPropertyChange("radius", radius);
-}
-
-void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
-{
- notifyPropertyChange("center", center);
}
/*!
@@ -92,7 +77,7 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
The currentIndex property can then be used, for example, to enable or
disable entities, change material, etc.
- The LevelOfDetail component is not shareable between multiple Entity's.
+ The LevelOfDetail component is not shareable between multiple \l [QML]{Entity}{entities}.
\code
#include <Qt3DCore/QEntity>
@@ -156,7 +141,7 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
id: lod
camera: mainCamera
thresholds: [20, 35, 50, 65]
- thresholdType: LevelOfDetail.DistanceToCamera
+ thresholdType: LevelOfDetail.DistanceToCameraThreshold
}
CylinderMesh {
@@ -180,8 +165,8 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
*
* Specifies how the values in the thresholds are interpreted
*
- * \value DistanceToCamera Distance from the entity to the selected camera
- * \value ProjectedScreenPixelSize Size of the entity when projected on the
+ * \value DistanceToCameraThreshold Distance from the entity to the selected camera
+ * \value ProjectedScreenPixelSizeThreshold Size of the entity when projected on the
* screen as seen from the selected camera, expressed in number of
* pixels on the side of the bounding square in screen space.
*/
@@ -192,43 +177,14 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
* Specifies how the values in the thresholds are interpreted
*
* \list
- * \li DistanceToCamera Distance from the entity to the selected camera
- * \li ProjectedScreenPixelSize Size of the entity when projected on the
+ * \li DistanceToCameraThreshold Distance from the entity to the selected camera
+ * \li ProjectedScreenPixelSizeThreshold Size of the entity when projected on the
* screen as seen from the selected camera, expressed in number of
* pixels on the side of the bounding square in screen space.
* \endlist
* \sa Qt3DRender::QLevelOfDetail::ThresholdType
*/
-
-/*!
- * \enum Qt3DRender::QLevelOfDetail::SizeProxyMode
- *
- * Specifies what is used as a proxy for the entity when computing distance
- * or size.
- *
- * \value BoundingSphere use the bounding sphere specified by the center
- * and radius properties.
- * \value ChildrenBoundingSphere use the bounding sphere of the entity the
- * component is attached to.
- */
-
-/*!
- * \qmlproperty enumeration LevelOfDetail::SizeProxyMode
- *
- * Specifies what is used as a proxy for the entity when computing distance
- * or size.
- *
- * \list
- * \li BoundingSphere use the bounding sphere specified by the center
- * and radius properties.
- * \li ChildrenBoundingSphere use the bounding sphere of the entity the
- * component is attached to.
- * \endlist
- * \sa Qt3DRender::QLevelOfDetail::SizeProxyMode
- */
-
-
/*!
* \qmlproperty Camera LevelOfDetail::camera
*
@@ -272,11 +228,11 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
* Array of range values as float point numbers. The value for the most detailed representation
* should be specified first.
*
- * If LevelOfDetail::thresholdType is set to LevelOfDetail.Distance, values should be specified in
- * ascending order, in camera space coordinates
+ * If LevelOfDetail::thresholdType is set to LevelOfDetail.DistanceToCameraThreshold, values should
+ * be specified in ascending order, in camera space coordinates
*
- * If LevelOfDetail::thresholdType is set to LevelOfDetail.ProjectedScreenPixelSize, values should
- * be specified in descending order, in screen space pixels.
+ * If LevelOfDetail::thresholdType is set to LevelOfDetail.ProjectedScreenPixelSizeThreshold, values
+ * should be specified in descending order, in screen space pixels.
*/
/*!
@@ -285,10 +241,12 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
* Array of range values as float point numbers. The value for the most detailed representation
* should be specified first.
*
- * If Qt3DRender::QLevelOfDetail::thresholdType is set to Qt3DRender::QLevelOfDetail::Distance, values should be specified in
+ * If Qt3DRender::QLevelOfDetail::thresholdType is set to
+ * Qt3DRender::QLevelOfDetail::DistanceToCameraThreshold, values should be specified in
* ascending order, in camera space coordinates
*
- * If Qt3DRender::QLevelOfDetail::thresholdType is set to Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize, values should
+ * If Qt3DRender::QLevelOfDetail::thresholdType is set to
+ * Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold, values should
* be specified in descending order, in screen space pixels.
*
* \sa Qt3DRender::QLevelOfDetail::ThresholdType
@@ -306,7 +264,7 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
* If this value to null, the bounding volume of the entity is used. Care must be
* taken that this bounding volume never becomes invalid.
*
- * \sa BoundingSphere
+ * \sa Qt3DRender::QLevelOfDetailBoundingSphere
*/
/*!
@@ -319,7 +277,7 @@ void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D &center)
* If this value to nullptr, the bounding volume of the entity is used. Care must be
* taken that this bounding volume never becomes invalid.
*
- * \sa QBoundingSphere
+ * \sa Qt3dRender::QLevelOfDetailBoundingSphere
*/
@@ -354,8 +312,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() c
data.currentIndex = d->m_currentIndex;
data.thresholdType = d->m_thresholdType;
data.thresholds = d->m_thresholds;
- data.radius = d->m_volumeOverride ? d->m_volumeOverride->radius() : -1.f;
- data.center = d->m_volumeOverride ? d->m_volumeOverride->center() : QVector3D();
+ data.volumeOverride = d->m_volumeOverride;
return creationChange;
}
@@ -381,7 +338,7 @@ QCamera *QLevelOfDetail::camera() const
}
/*!
- * Sets the camera relative to which distance and size are computed.
+ * Sets the \a camera relative to which distance and size are computed.
*/
void QLevelOfDetail::setCamera(QCamera *camera)
{
@@ -399,7 +356,7 @@ int QLevelOfDetail::currentIndex() const
}
/*!
- * Sets the current index.
+ * Sets the \a currentIndex.
*
* \note This should not normally be set by the user.
*
@@ -424,6 +381,7 @@ QLevelOfDetail::ThresholdType QLevelOfDetail::thresholdType() const
/*!
* Sets the way thresholds values are interpreted
+ * with parameter \a thresholdType
* \sa Qt3DRender::QLevelOfDetail::ThresholdType
*/
void QLevelOfDetail::setThresholdType(QLevelOfDetail::ThresholdType thresholdType)
@@ -441,36 +399,35 @@ QVector<qreal> QLevelOfDetail::thresholds() const
return d->m_thresholds;
}
+QLevelOfDetailBoundingSphere QLevelOfDetail::createBoundingSphere(const QVector3D &center, float radius)
+{
+ return QLevelOfDetailBoundingSphere(center, radius);
+}
+
/*!
- * Sets the range values.
+ * Sets the range values in \a thresholds.
* \sa Qt3DRender::QLevelOfDetail::thresholdType
*/
-void QLevelOfDetail::setThresholds(QVector<qreal> thresholds)
+void QLevelOfDetail::setThresholds(const QVector<qreal> &thresholds)
{
Q_D(QLevelOfDetail);
if (d->m_thresholds != thresholds) {
d->m_thresholds = thresholds;
- thresholdsChanged(d->m_thresholds);
+ emit thresholdsChanged(d->m_thresholds);
}
}
-QBoundingSphere *QLevelOfDetail::volumeOverride() const
+QLevelOfDetailBoundingSphere QLevelOfDetail::volumeOverride() const
{
Q_D(const QLevelOfDetail);
return d->m_volumeOverride;
}
-void QLevelOfDetail::setVolumeOverride(QBoundingSphere *volumeOverride)
+void QLevelOfDetail::setVolumeOverride(const QLevelOfDetailBoundingSphere &volumeOverride)
{
Q_D(QLevelOfDetail);
if (d->m_volumeOverride != volumeOverride) {
- if (d->m_volumeOverride)
- disconnect(d->m_volumeOverride);
d->m_volumeOverride = volumeOverride;
- if (d->m_volumeOverride) {
- connect(d->m_volumeOverride, SIGNAL(radiusChanged(float)), this, SLOT(_q_radiusChanged(float)));
- connect(d->m_volumeOverride, SIGNAL(centerChanged(const QVector3D &)), this, SLOT(_q_centerChanged(const QVector3D&)));
- }
emit volumeOverrideChanged(volumeOverride);
}
}
diff --git a/src/render/frontend/qlevelofdetail.h b/src/render/frontend/qlevelofdetail.h
index f3325aea0..2e752d962 100644
--- a/src/render/frontend/qlevelofdetail.h
+++ b/src/render/frontend/qlevelofdetail.h
@@ -42,6 +42,7 @@
#include <Qt3DCore/qcomponent.h>
#include <Qt3DRender/qt3drender_global.h>
+#include <Qt3DRender/qlevelofdetailboundingsphere.h>
#include <QVector3D>
@@ -50,7 +51,6 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
class QCamera;
-class QBoundingSphere;
class QLevelOfDetailPrivate;
class QT3DRENDERSHARED_EXPORT QLevelOfDetail : public Qt3DCore::QComponent
@@ -60,12 +60,12 @@ class QT3DRENDERSHARED_EXPORT QLevelOfDetail : public Qt3DCore::QComponent
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(ThresholdType thresholdType READ thresholdType WRITE setThresholdType NOTIFY thresholdTypeChanged)
Q_PROPERTY(QVector<qreal> thresholds READ thresholds WRITE setThresholds NOTIFY thresholdsChanged)
- Q_PROPERTY(Qt3DRender::QBoundingSphere *volumeOverride READ volumeOverride WRITE setVolumeOverride NOTIFY volumeOverrideChanged)
+ Q_PROPERTY(Qt3DRender::QLevelOfDetailBoundingSphere volumeOverride READ volumeOverride WRITE setVolumeOverride NOTIFY volumeOverrideChanged)
public:
enum ThresholdType {
- DistanceToCamera,
- ProjectedScreenPixelSize,
+ DistanceToCameraThreshold,
+ ProjectedScreenPixelSizeThreshold,
};
Q_ENUM(ThresholdType) // LCOV_EXCL_LINE
@@ -76,21 +76,23 @@ public:
int currentIndex() const;
ThresholdType thresholdType() const;
QVector<qreal> thresholds() const;
- QBoundingSphere *volumeOverride() const;
+ QLevelOfDetailBoundingSphere volumeOverride() const;
+
+ Q_INVOKABLE QLevelOfDetailBoundingSphere createBoundingSphere(const QVector3D &center, float radius);
public Q_SLOTS:
void setCamera(QCamera *camera);
void setCurrentIndex(int currentIndex);
void setThresholdType(ThresholdType thresholdType);
- void setThresholds(QVector<qreal> thresholds);
- void setVolumeOverride(QBoundingSphere *volumeOverride);
+ void setThresholds(const QVector<qreal> &thresholds);
+ void setVolumeOverride(const QLevelOfDetailBoundingSphere &volumeOverride);
Q_SIGNALS:
void cameraChanged(QCamera *camera);
void currentIndexChanged(int currentIndex);
void thresholdTypeChanged(ThresholdType thresholdType);
- void thresholdsChanged(QVector<qreal> thresholds);
- void volumeOverrideChanged(QBoundingSphere *volumeOverride);
+ void thresholdsChanged(const QVector<qreal> &thresholds);
+ void volumeOverrideChanged(const QLevelOfDetailBoundingSphere &volumeOverride);
protected:
explicit QLevelOfDetail(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr);
@@ -99,12 +101,12 @@ protected:
private:
Q_DECLARE_PRIVATE(QLevelOfDetail)
- Q_PRIVATE_SLOT(d_func(), void _q_radiusChanged(float))
- Q_PRIVATE_SLOT(d_func(), void _q_centerChanged(const QVector3D&))
};
} // namespace Qt3DRender
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(Qt3DRender::QLevelOfDetailBoundingSphere)
+
#endif // QT3DRENDER_QLEVELOFDETAIL_H
diff --git a/src/render/frontend/qlevelofdetail_p.h b/src/render/frontend/qlevelofdetail_p.h
index ab25e9ad3..1d7a05a71 100644
--- a/src/render/frontend/qlevelofdetail_p.h
+++ b/src/render/frontend/qlevelofdetail_p.h
@@ -53,6 +53,7 @@
#include <private/qcomponent_p.h>
#include <qlevelofdetail.h>
+#include <Qt3DRender/qlevelofdetailboundingsphere.h>
#include <QVector3D>
@@ -74,7 +75,7 @@ public:
int m_currentIndex;
QLevelOfDetail::ThresholdType m_thresholdType;
QVector<qreal> m_thresholds;
- QPointer<QBoundingSphere> m_volumeOverride;
+ QLevelOfDetailBoundingSphere m_volumeOverride;
};
struct QLevelOfDetailData
@@ -83,8 +84,7 @@ struct QLevelOfDetailData
int currentIndex;
QLevelOfDetail::ThresholdType thresholdType;
QVector<qreal> thresholds;
- float radius;
- QVector3D center;
+ QLevelOfDetailBoundingSphere volumeOverride;
};
} // namespace Qt3DRender
diff --git a/src/render/frontend/qboundingsphere.cpp b/src/render/frontend/qlevelofdetailboundingsphere.cpp
index 4d8b1aba8..abf8081d3 100644
--- a/src/render/frontend/qboundingsphere.cpp
+++ b/src/render/frontend/qlevelofdetailboundingsphere.cpp
@@ -37,110 +37,121 @@
**
****************************************************************************/
-#include "qboundingsphere.h"
-#include "qboundingsphere_p.h"
+#include "qlevelofdetailboundingsphere.h"
+#include <QSharedData>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-QBoundingSpherePrivate::QBoundingSpherePrivate()
- : QObjectPrivate()
- , m_radius(1.f)
+class QLevelOfDetailBoundingSpherePrivate: public QSharedData
{
+public:
+ QLevelOfDetailBoundingSpherePrivate()
+ : QSharedData()
+ , m_radius(0.0f)
+ {}
-}
+ QLevelOfDetailBoundingSpherePrivate(QVector3D center, float radius)
+ : QSharedData()
+ , m_center(center)
+ , m_radius(radius)
+ {}
+
+ ~QLevelOfDetailBoundingSpherePrivate()
+ {}
+
+ QVector3D m_center;
+ float m_radius;
+};
/*!
- \class Qt3DRender::QBoundingSphere
+ \class Qt3DRender::QLevelOfDetailBoundingSphere
\inmodule Qt3DRender
\since 5.9
- \brief The QBoundingSphere class provides a simple spherical volume, defined by it's center and radius.
+ \brief The QLevelOfDetailBoundingSphere class provides a simple spherical volume, defined by it's center and radius.
*/
/*!
\qmltype LevelOfDetail
- \instantiates Qt3DRender::QLevelOfDetail
+ \instantiates Qt3DRender::QLevelOfDetailBoundingSphere
\inherits Component3D
\inqmlmodule Qt3D.Render
- \brief The BoundingSphere class provides a simple spherical volume, defined by it's center and radius.
+ \brief The LevelOfDetailBoundingSphere class provides a simple spherical volume, defined by it's center and radius.
*/
/*!
- * \qmlproperty QVector3D BoundingSphere::center
+ * \qmlproperty QVector3D LevelOfDetailBoundingSphere::center
*
* Specifies the center of the bounding sphere
*/
/*!
- * \property QBoundingSphere::center
+ * \property QLevelOfDetailBoundingSphere::center
*
* Specifies the center of the bounding sphere
*/
/*!
- * \qmlproperty qreal BoundingSphere::radius
+ * \qmlproperty qreal LevelOfDetailBoundingSphere::radius
*
* Specifies the radius of the bounding sphere
*/
/*!
- * \property QBoundingSphere::radius
+ * \property QLevelOfDetailBoundingSphere::radius
*
* Specifies the radius of the bounding sphere
*/
-/*! \fn Qt3DRender::QBoundingSphere::QBoundingSphere(QObject *parent)
- Constructs a new QBoundingSphere with the specified \a parent.
+/*! \fn Qt3DRender::QLevelOfDetailBoundingSphere::QLevelOfDetailBoundingSphere(const QVector3D &center = QVector3D(), float radius = -1.0f)
+ Constructs a new QLevelOfDetailBoundingSphere with the specified \a center and \a radius.
*/
-QBoundingSphere::QBoundingSphere(QObject *parent)
- : QObject(*new QBoundingSpherePrivate, parent)
+
+
+QLevelOfDetailBoundingSphere::QLevelOfDetailBoundingSphere(QVector3D center, float radius)
+ : d_ptr(new QLevelOfDetailBoundingSpherePrivate(center, radius))
{
+}
+QLevelOfDetailBoundingSphere::QLevelOfDetailBoundingSphere(const QLevelOfDetailBoundingSphere &other)
+ : d_ptr(other.d_ptr)
+{
}
-QBoundingSphere::QBoundingSphere(const QVector3D &center, float radius, QObject *parent)
- : QBoundingSphere(parent)
+QLevelOfDetailBoundingSphere::~QLevelOfDetailBoundingSphere()
{
- Q_D(QBoundingSphere);
- d->m_center = center;
- d->m_radius = radius;
}
-QVector3D QBoundingSphere::center() const
+QLevelOfDetailBoundingSphere &QLevelOfDetailBoundingSphere::operator =(const QLevelOfDetailBoundingSphere &other)
{
- Q_D(const QBoundingSphere);
- return d->m_center;
+ d_ptr = other.d_ptr;
+ return *this;
}
-float QBoundingSphere::radius() const
+QVector3D QLevelOfDetailBoundingSphere::center() const
{
- Q_D(const QBoundingSphere);
- return d->m_radius;
+ return d_ptr->m_center;
}
-/*!
- * Sets the radius of the bounding sphere.
- */
-void QBoundingSphere::setRadius(float radius)
+float QLevelOfDetailBoundingSphere::radius() const
{
- Q_D(QBoundingSphere);
- if (d->m_radius != radius) {
- d->m_radius = radius;
- emit radiusChanged(radius);
- }
+ return d_ptr->m_radius;
}
-/*!
- * Sets the center of the bounding sphere.
- */
-void QBoundingSphere::setCenter(const QVector3D &center)
+bool QLevelOfDetailBoundingSphere::isEmpty() const
+{
+ return d_ptr->m_radius <= 0.0f;
+}
+
+bool QLevelOfDetailBoundingSphere::operator ==(const QLevelOfDetailBoundingSphere &other) const
+{
+ return d_ptr->m_center == other.center() && other.d_ptr->m_radius == other.radius();
+}
+
+bool QLevelOfDetailBoundingSphere::operator !=(const QLevelOfDetailBoundingSphere &other) const
{
- Q_D(QBoundingSphere);
- if (d->m_center != center) {
- d->m_center = center;
- emit centerChanged(center);
- }
+ return !(*this == other);
}
} // namespace Qt3DRender
diff --git a/src/render/frontend/qboundingsphere.h b/src/render/frontend/qlevelofdetailboundingsphere.h
index e7f9b7784..b35df95e8 100644
--- a/src/render/frontend/qboundingsphere.h
+++ b/src/render/frontend/qlevelofdetailboundingsphere.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_QBOUNDINGSPHERE_H
-#define QT3DRENDER_QBOUNDINGSPHERE_H
+#ifndef QT3DRENDER_QLEVELOFDETAILBOUNDINGSPHERE_H
+#define QT3DRENDER_QLEVELOFDETAILBOUNDINGSPHERE_H
#include <Qt3DCore/qcomponent.h>
#include <Qt3DRender/qt3drender_global.h>
@@ -49,34 +49,33 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QBoundingSpherePrivate;
+class QLevelOfDetailBoundingSpherePrivate;
-class QT3DRENDERSHARED_EXPORT QBoundingSphere : public QObject
+class QT3DRENDERSHARED_EXPORT QLevelOfDetailBoundingSphere
{
- Q_OBJECT
- Q_PROPERTY(QVector3D center READ center WRITE setCenter NOTIFY centerChanged)
- Q_PROPERTY(float radius READ radius WRITE setRadius NOTIFY radiusChanged)
+ Q_GADGET
+ Q_PROPERTY(QVector3D center READ center CONSTANT)
+ Q_PROPERTY(float radius READ radius CONSTANT)
public:
- explicit QBoundingSphere(QObject *parent = nullptr);
- QBoundingSphere(const QVector3D &center, float radius, QObject *parent = nullptr);
+ explicit QLevelOfDetailBoundingSphere(QVector3D center = QVector3D(), float radius = 1.0f);
+ QLevelOfDetailBoundingSphere(const QLevelOfDetailBoundingSphere &other);
+ ~QLevelOfDetailBoundingSphere();
+
+ QLevelOfDetailBoundingSphere &operator =(const QLevelOfDetailBoundingSphere &other);
QVector3D center() const;
float radius() const;
-public Q_SLOTS:
- void setRadius(float radius);
- void setCenter(const QVector3D &center);
-
-Q_SIGNALS:
- void radiusChanged(float radius);
- void centerChanged(const QVector3D &center);
+ bool isEmpty() const;
+ bool operator ==(const QLevelOfDetailBoundingSphere &other) const;
+ bool operator !=(const QLevelOfDetailBoundingSphere &other) const;
private:
- Q_DECLARE_PRIVATE(QBoundingSphere)
+ QSharedDataPointer<QLevelOfDetailBoundingSpherePrivate> d_ptr;
};
} // namespace Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DRENDER_QBOUNDINGSPHERE_H
+#endif // QT3DRENDER_QLEVELOFDETAILBOUNDINGSPHERE_H
diff --git a/src/render/frontend/qlevelofdetailswitch.cpp b/src/render/frontend/qlevelofdetailswitch.cpp
index 9a63343ed..845fdd5a6 100644
--- a/src/render/frontend/qlevelofdetailswitch.cpp
+++ b/src/render/frontend/qlevelofdetailswitch.cpp
@@ -69,11 +69,17 @@ namespace Qt3DRender {
This component is assigned to an entity. When the entity changes distance relative
to the camera, the LevelOfDetailSwitch will disable all the child entities except
- the one matching index \l LevelOfDetailSwitch::currentIndex.
+ the one matching index \l currentIndex.
\sa LevelOfDetail
*/
+/*!
+ \qmlproperty int LevelOfDetailSwitch::currentIndex
+
+ The index of the presently selected child entity.
+*/
+
/*! \fn Qt3DRender::QLevelOfDetailSwitch::QLevelOfDetailSwitch(Qt3DCore::QNode *parent)
Constructs a new QLevelOfDetailSwitch with the specified \a parent.
*/
@@ -107,8 +113,10 @@ void QLevelOfDetailSwitch::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &cha
emit currentIndexChanged(ndx);
int entityIndex = 0;
- for (Qt3DCore::QEntity *entity : entities()) {
- for (Qt3DCore::QNode *childNode : entity->childNodes()) {
+ const auto entities = this->entities();
+ for (Qt3DCore::QEntity *entity : entities) {
+ const auto childNodes = entity->childNodes();
+ for (Qt3DCore::QNode *childNode : childNodes) {
Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode);
if (childEntity) {
childEntity->setEnabled(entityIndex == ndx);
diff --git a/src/render/frontend/qpickingsettings.cpp b/src/render/frontend/qpickingsettings.cpp
index db6840d7f..1cda638cb 100644
--- a/src/render/frontend/qpickingsettings.cpp
+++ b/src/render/frontend/qpickingsettings.cpp
@@ -53,6 +53,11 @@ namespace Qt3DRender {
The picking settings determine how the entity picking is handled. For more details about
entity picking, see QObjectPicker component documentation.
+
+ Picking is triggered by mouse events. It will cast a ray through the scene and look for
+ geometry intersecting the ray.
+
+ \sa QObjectPicker, QPickEvent, QPickTriangleEvent
*/
/*!
@@ -64,6 +69,11 @@ namespace Qt3DRender {
The picking settings determine how the entity picking is handled. For more details about
entity picking, see Qt3DRender::QObjectPicker component documentation.
+
+ Picking is triggered by mouse events. It will cast a ray through the scene and look for
+ geometry intersecting the ray.
+
+ \sa ObjectPicker
*/
QPickingSettingsPrivate::QPickingSettingsPrivate()
@@ -104,9 +114,6 @@ QPickingSettings::PickResultMode QPickingSettings::pickResultMode() const
return d->m_pickResultMode;
}
-/*!
- * \return the back facing picking flag
- */
QPickingSettings::FaceOrientationPickingMode QPickingSettings::faceOrientationPickingMode() const
{
Q_D(const QPickingSettings);
@@ -119,7 +126,7 @@ QPickingSettings::FaceOrientationPickingMode QPickingSettings::faceOrientationPi
* Specifies the picking method.
*
* \value BoundingVolumePicking An entity is considered picked if the picking ray intersects
- * the bounding volume of the entity.
+ * the bounding volume of the entity (default).
* \value TrianglePicking An entity is considered picked if the picking ray intersects with
* any triangle of the entity's mesh component.
*/
@@ -140,6 +147,12 @@ QPickingSettings::FaceOrientationPickingMode QPickingSettings::faceOrientationPi
\property QPickingSettings::pickMethod
Holds the current pick method.
+
+ By default, for performance reasons, ray casting will use bounding volume picking.
+ This may however lead to unexpected results if a small object is englobed
+ in the bounding sphere of a large object behind it.
+
+ Triangle picking will produce exact results but is computationally more expensive.
*/
void QPickingSettings::setPickMethod(QPickingSettings::PickMethod pickMethod)
{
@@ -157,8 +170,10 @@ void QPickingSettings::setPickMethod(QPickingSettings::PickMethod pickMethod)
* Specifies what is included into the picking results.
*
* \value NearestPick Only the nearest entity to picking ray origin intersected by the picking ray
- * is picked.
+ * is picked (default).
* \value AllPicks All entities that intersect the picking ray are picked.
+ *
+ * \sa Qt3DRender::QPickEvent
*/
/*!
@@ -177,6 +192,14 @@ void QPickingSettings::setPickMethod(QPickingSettings::PickMethod pickMethod)
\property QPickingSettings::pickResultMode
Holds the current pick results mode.
+
+ By default, pick results will only be produced for the entity closest to the camera.
+
+ When setting the pick method to AllPicks, events will be triggered for all the
+ entities with a QObjectPicker along the ray.
+
+ If a QObjectPicker is assigned to an entity with multiple children, an event will
+ be triggered for each child entity that intersects the ray.
*/
void QPickingSettings::setPickResultMode(QPickingSettings::PickResultMode pickResultMode)
{
@@ -189,8 +212,31 @@ void QPickingSettings::setPickResultMode(QPickingSettings::PickResultMode pickRe
}
/*!
- * \a faceOrientationPickingMode determines whether back facing faces are picked or not.
- */
+ \enum Qt3DRender::QPickingSettings::FaceOrientationPickingMode
+
+ Specifies how face orientation affects triangle picking
+
+ \value FrontFace Only front-facing triangles will be picked (default).
+ \value BackFace Only back-facing triangles will be picked.
+ \value FrontAndBackFace Both front- and back-facing triangles will be picked.
+*/
+
+/*!
+ \qmlproperty enumeration PickingSettings::faceOrientationPickingMode
+
+ Specifies how face orientation affects triangle picking
+
+ \list
+ \li PickingSettings.FrontFace Only front-facing triangles will be picked (default).
+ \li PickingSettings.BackFace Only back-facing triangles will be picked.
+ \li PickingSettings.FrontAndBackFace Both front- and back-facing triangles will be picked.
+ \endlist
+*/
+/*!
+ \property QPickingSettings::faceOrientationPickingMode
+
+ Specifies how face orientation affects triangle picking
+*/
void QPickingSettings::setFaceOrientationPickingMode(QPickingSettings::FaceOrientationPickingMode faceOrientationPickingMode)
{
Q_D(QPickingSettings);
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index d9b45b7a7..4d775aeb3 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -75,14 +75,18 @@
#include <Qt3DRender/qobjectpicker.h>
#include <Qt3DRender/qfrustumculling.h>
#include <Qt3DRender/qabstractlight.h>
+#include <Qt3DRender/qenvironmentlight.h>
#include <Qt3DRender/qdispatchcompute.h>
#include <Qt3DRender/qcomputecommand.h>
#include <Qt3DRender/qrendersurfaceselector.h>
#include <Qt3DRender/qrendersettings.h>
#include <Qt3DRender/qrendercapture.h>
+#include <Qt3DRender/qbuffercapture.h>
#include <Qt3DRender/qmemorybarrier.h>
+
#include <Qt3DRender/private/cameraselectornode_p.h>
#include <Qt3DRender/private/layerfilternode_p.h>
+#include <Qt3DRender/private/cameralens_p.h>
#include <Qt3DRender/private/filterkey_p.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/renderer_p.h>
@@ -118,20 +122,26 @@
#include <Qt3DRender/private/qsceneimportfactory_p.h>
#include <Qt3DRender/private/frustumculling_p.h>
#include <Qt3DRender/private/light_p.h>
+#include <Qt3DRender/private/environmentlight_p.h>
#include <Qt3DRender/private/dispatchcompute_p.h>
#include <Qt3DRender/private/computecommand_p.h>
#include <Qt3DRender/private/rendersurfaceselector_p.h>
#include <Qt3DRender/private/rendersettings_p.h>
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/rendercapture_p.h>
+#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/technique_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
#include <Qt3DRender/private/memorybarrier_p.h>
+#include <private/qrenderpluginfactory_p.h>
+#include <private/qrenderplugin_p.h>
+
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/private/qservicelocator_p.h>
#include <QDebug>
@@ -162,7 +172,7 @@ QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type)
, m_renderType(type)
, m_offscreenHelper(nullptr)
{
- // Load the scene parsers
+ m_instances.append(this);
loadSceneParsers();
}
@@ -175,6 +185,18 @@ QRenderAspectPrivate::~QRenderAspectPrivate()
if (m_renderer != nullptr)
qWarning() << Q_FUNC_INFO << "The renderer should have been deleted when reaching this point (this warning may be normal when running tests)";
delete m_nodeManagers;
+ m_instances.removeAll(this);
+}
+
+QRenderAspectPrivate *QRenderAspectPrivate::findPrivate(Qt3DCore::QAspectEngine *engine)
+{
+ const QVector<QAbstractAspect*> aspects = engine->aspects();
+ for (QAbstractAspect* aspect : aspects) {
+ QRenderAspect *renderAspect = qobject_cast<QRenderAspect *>(aspect);
+ if (renderAspect)
+ return static_cast<QRenderAspectPrivate *>(renderAspect->d_ptr.data());
+ }
+ return nullptr;
}
/*! \internal */
@@ -190,7 +212,7 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers));
q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer));
- q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::NodeFunctor<Render::CameraLens, Render::CameraManager> >::create(m_renderer));
+ q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q));
q->registerBackendType<QLayer>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer));
q->registerBackendType<QLevelOfDetail>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
q->registerBackendType<QLevelOfDetailSwitch>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
@@ -215,6 +237,7 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<QEffect>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer));
q->registerBackendType<QFilterKey>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer));
q->registerBackendType<QAbstractLight>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers));
+ q->registerBackendType<QEnvironmentLight>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer));
q->registerBackendType<QMaterial>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer));
q->registerBackendType<QParameter>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer));
q->registerBackendType<QRenderPass>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer));
@@ -238,15 +261,21 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<QTechniqueFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::TechniqueFilter, QTechniqueFilter> >::create(m_renderer));
q->registerBackendType<QViewport>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer));
q->registerBackendType<QRenderCapture>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderCapture, QRenderCapture> >::create(m_renderer));
+ q->registerBackendType<QBufferCapture>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BufferCapture, QBufferCapture> >::create(m_renderer));
q->registerBackendType<QMemoryBarrier>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::MemoryBarrier, QMemoryBarrier> >::create(m_renderer));
// Picking
q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer));
+
+ // Plugins
+ for (const QString &plugin : m_pluginConfig)
+ loadRenderPlugin(plugin);
}
/*! \internal */
void QRenderAspectPrivate::unregisterBackendTypes()
{
+ Q_Q(QRenderAspect);
unregisterBackendType<Qt3DCore::QEntity>();
unregisterBackendType<Qt3DCore::QTransform>();
@@ -273,6 +302,7 @@ void QRenderAspectPrivate::unregisterBackendTypes()
unregisterBackendType<QEffect>();
unregisterBackendType<QFilterKey>();
unregisterBackendType<QAbstractLight>();
+ unregisterBackendType<QEnvironmentLight>();
unregisterBackendType<QMaterial>();
unregisterBackendType<QParameter>();
unregisterBackendType<QRenderPass>();
@@ -295,10 +325,22 @@ void QRenderAspectPrivate::unregisterBackendTypes()
unregisterBackendType<QTechniqueFilter>();
unregisterBackendType<QViewport>();
unregisterBackendType<QRenderCapture>();
+ unregisterBackendType<QBufferCapture>();
unregisterBackendType<QMemoryBarrier>();
// Picking
unregisterBackendType<QObjectPicker>();
+
+ // Plugins
+ for (Render::QRenderPlugin *plugin : qAsConst(m_renderPlugins))
+ plugin->unregisterBackendTypes(q);
+}
+
+void QRenderAspectPrivate::registerBackendType(const QMetaObject &obj,
+ const QBackendNodeMapperPtr &functor)
+{
+ Q_Q(QRenderAspect);
+ q->registerBackendType(obj, functor);
}
/*!
@@ -360,7 +402,7 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time)
d->m_renderer->dumpInfo();
#endif
- // Create jobs that will get exectued by the threadpool
+ // Create jobs that will get executed by the threadpool
QVector<QAspectJobPtr> jobs;
// 1 LoadBufferJobs, GeometryJobs, SceneLoaderJobs, LoadTextureJobs
@@ -379,6 +421,7 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time)
// don't spawn any jobs, if the renderer decides to skip this frame
if (!d->m_renderer->shouldRender()) {
d->m_renderer->skipNextFrame();
+ QThread::msleep(1);
return jobs;
}
@@ -456,7 +499,7 @@ void QRenderAspect::onRegistered()
d->m_renderer->setNodeManagers(d->m_nodeManagers);
// Create a helper for deferring creation of an offscreen surface used during cleanup
- // to the main thread, after we knwo what the surface format in use is.
+ // to the main thread, after we know what the surface format in use is.
d->m_offscreenHelper = new Render::OffscreenSurfaceHelper(d->m_renderer);
d->m_offscreenHelper->moveToThread(QCoreApplication::instance()->thread());
d->m_renderer->setOffscreenSurfaceHelper(d->m_offscreenHelper);
@@ -475,7 +518,8 @@ void QRenderAspect::onRegistered()
advanceService);
}
- d->m_renderer->setServices(d->services());
+ if (d->services())
+ d->m_renderer->setServices(d->services());
d->m_initialized = true;
}
@@ -537,6 +581,39 @@ void QRenderAspectPrivate::loadSceneParsers()
}
}
+void QRenderAspectPrivate::loadRenderPlugin(const QString &pluginName)
+{
+ Q_Q(QRenderAspect);
+ const QStringList keys = Render::QRenderPluginFactory::keys();
+ if (!keys.contains(pluginName))
+ return;
+
+ if (m_pluginConfig.contains(pluginName) && !m_loadedPlugins.contains(pluginName)) {
+ Render::QRenderPlugin *plugin
+ = Render::QRenderPluginFactory::create(pluginName, QStringList());
+ if (plugin != nullptr) {
+ m_loadedPlugins.append(pluginName);
+ m_renderPlugins.append(plugin);
+ plugin->registerBackendTypes(q, m_renderer);
+ }
+ }
+}
+
+QVector<QString> QRenderAspectPrivate::m_pluginConfig;
+QMutex QRenderAspectPrivate::m_pluginLock;
+QVector<QRenderAspectPrivate *> QRenderAspectPrivate::m_instances;
+
+void QRenderAspectPrivate::configurePlugin(const QString &plugin)
+{
+ QMutexLocker lock(&m_pluginLock);
+ if (!m_pluginConfig.contains(plugin)) {
+ m_pluginConfig.append(plugin);
+
+ for (QRenderAspectPrivate *instance : qAsConst(m_instances))
+ instance->loadRenderPlugin(plugin);
+ }
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/frontend/qrenderaspect.h b/src/render/frontend/qrenderaspect.h
index 72e8e4bdb..48ef5b164 100644
--- a/src/render/frontend/qrenderaspect.h
+++ b/src/render/frontend/qrenderaspect.h
@@ -56,6 +56,7 @@ class TestAspect;
namespace Render {
class Renderer;
+class QRenderPlugin;
}
class QRenderAspectPrivate;
@@ -92,6 +93,7 @@ private:
void onEngineStartup() Q_DECL_OVERRIDE;
friend class Render::Renderer;
+ friend class Render::QRenderPlugin;
#if defined(QT_BUILD_INTERNAL)
friend class QRenderAspectTester;
friend class TestAspect;
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 72183ef87..b8c8538ee 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -55,6 +55,8 @@
#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <QtCore/qmutex.h>
+
QT_BEGIN_NAMESPACE
class QSurface;
@@ -62,9 +64,11 @@ class QSurface;
namespace Qt3DRender {
class QSceneImporter;
+
namespace Render {
class AbstractRenderer;
class NodeManagers;
+class QRenderPlugin;
}
namespace Render {
@@ -79,12 +83,16 @@ public:
Q_DECLARE_PUBLIC(QRenderAspect)
+ static QRenderAspectPrivate* findPrivate(Qt3DCore::QAspectEngine *engine);
+
void registerBackendTypes();
void unregisterBackendTypes();
void loadSceneParsers();
+ void loadRenderPlugin(const QString &pluginName);
void renderInitialize(QOpenGLContext *context);
void renderSynchronous();
void renderShutdown();
+ void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor);
QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs();
Render::NodeManagers *m_nodeManagers;
@@ -92,8 +100,15 @@ public:
bool m_initialized;
QList<QSceneImporter *> m_sceneImporter;
+ QVector<QString> m_loadedPlugins;
+ QVector<Render::QRenderPlugin *> m_renderPlugins;
QRenderAspect::RenderType m_renderType;
Render::OffscreenSurfaceHelper *m_offscreenHelper;
+
+ static QMutex m_pluginLock;
+ static QVector<QString> m_pluginConfig;
+ static QVector<QRenderAspectPrivate *> m_instances;
+ static void configurePlugin(const QString &plugin);
};
}
diff --git a/src/render/frontend/qrenderplugin_p.h b/src/render/frontend/qrenderplugin_p.h
new file mode 100644
index 000000000..5144448c1
--- /dev/null
+++ b/src/render/frontend/qrenderplugin_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QRENDERPLUGIN_P_H
+#define QT3DRENDER_RENDER_QRENDERPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qt3drender_global_p.h>
+
+#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DRender/qrenderaspect.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class AbstractRenderer;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderPlugin
+{
+public:
+ virtual bool registerBackendTypes(QRenderAspect *aspect, AbstractRenderer *renderer) = 0;
+ virtual bool unregisterBackendTypes(QRenderAspect *aspect) = 0;
+
+protected:
+ void registerBackendType(QRenderAspect *aspect, const QMetaObject &obj, const Qt3DCore::QBackendNodeMapperPtr &functor)
+ {
+ aspect->registerBackendType(obj, functor);
+ }
+ void unregisterBackendType(QRenderAspect *aspect, const QMetaObject &obj)
+ {
+ aspect->unregisterBackendType(obj);
+ }
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QRENDERPLUGIN_P_H
diff --git a/src/render/frontend/qrenderpluginfactory.cpp b/src/render/frontend/qrenderpluginfactory.cpp
new file mode 100644
index 000000000..51fa068c6
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactory.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrenderpluginfactory_p.h"
+#include "qrenderpluginfactoryif_p.h"
+#include "qrenderplugin_p.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+
+#include <private/qfactoryloader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QRenderPluginFactoryInterface_iid, QLatin1String("/renderplugins"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, (QRenderPluginFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
+#endif
+
+QStringList QRenderPluginFactory::keys(const QString &pluginPath)
+{
+#ifndef QT_NO_LIBRARY
+ QStringList list;
+ if (!pluginPath.isEmpty()) {
+ QCoreApplication::addLibraryPath(pluginPath);
+ list = directLoader()->keyMap().values();
+ if (!list.isEmpty()) {
+ const QString postFix = QLatin1String(" (from ")
+ + QDir::toNativeSeparators(pluginPath)
+ + QLatin1Char(')');
+ const QStringList::iterator end = list.end();
+ for (QStringList::iterator it = list.begin(); it != end; ++it)
+ (*it).append(postFix);
+ }
+ }
+ list.append(loader()->keyMap().values());
+ return list;
+#else
+ return QStringList();
+#endif
+}
+
+QRenderPlugin *QRenderPluginFactory::create(const QString &name, const QStringList &args,
+ const QString &pluginPath)
+{
+#ifndef QT_NO_LIBRARY
+ if (!pluginPath.isEmpty()) {
+ QCoreApplication::addLibraryPath(pluginPath);
+ if (QRenderPlugin *ret
+ = qLoadPlugin<QRenderPlugin, QRenderPluginFactoryIf>(directLoader(), name, args)) {
+ return ret;
+ }
+ }
+ if (QRenderPlugin *ret = qLoadPlugin<QRenderPlugin, QRenderPluginFactoryIf>(loader(), name, args))
+ return ret;
+#endif
+ return nullptr;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/frontend/qrenderpluginfactory_p.h b/src/render/frontend/qrenderpluginfactory_p.h
new file mode 100644
index 000000000..9cffd500a
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactory_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QRENDERPLUGINFACTORY_P_H
+#define QT3DRENDER_RENDER_QRENDERPLUGINFACTORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qt3drender_global_p.h>
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+class QRenderPlugin;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderPluginFactory
+{
+public:
+ static QStringList keys(const QString &pluginPath = QString());
+ static QRenderPlugin *create(const QString &name, const QStringList &args,
+ const QString &pluginPath = QString());
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QRENDERPLUGINFACTORY_P_H
diff --git a/src/render/frontend/qrenderpluginfactoryif.cpp b/src/render/frontend/qrenderpluginfactoryif.cpp
new file mode 100644
index 000000000..af567084c
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactoryif.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrenderpluginfactoryif_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+QRenderPluginFactoryIf::QRenderPluginFactoryIf(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+QRenderPluginFactoryIf::~QRenderPluginFactoryIf()
+{
+
+}
+
+QRenderPlugin *QRenderPluginFactoryIf::create(const QString &key, const QStringList &paramList)
+{
+ Q_UNUSED(key)
+ Q_UNUSED(paramList)
+ return nullptr;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/frontend/qrenderpluginfactoryif_p.h b/src/render/frontend/qrenderpluginfactoryif_p.h
new file mode 100644
index 000000000..d5f0008d2
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactoryif_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QRENDERPLUGINFACTORYIF_P_H
+#define QT3DRENDER_RENDER_QRENDERPLUGINFACTORYIF_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+#include <private/qt3drender_global_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+#define QRenderPluginFactoryInterface_iid "org.qt-project.Qt3DRender.QRenderPluginFactoryInterface 5.9"
+
+class QRenderPlugin;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderPluginFactoryIf : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QRenderPluginFactoryIf(QObject *parent = nullptr);
+ ~QRenderPluginFactoryIf();
+
+ virtual QRenderPlugin *create(const QString &key, const QStringList &paramList);
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QRENDERPLUGINFACTORYIF_P_H
diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp
index 4fb348617..b73fed77b 100644
--- a/src/render/frontend/qrendersettings.cpp
+++ b/src/render/frontend/qrendersettings.cpp
@@ -73,13 +73,6 @@ namespace Qt3DRender {
\l{Qt 3D Render Framegraph}{FrameGraph}.
*/
-/*!
- \enum QRenderSettings::RenderPolicy
-
- This enum type describes types of render policies available.
- \value Always Always try to render (default)
- \value OnDemand Only render when something changes
-*/
/*! \internal */
QRenderSettingsPrivate::QRenderSettingsPrivate()
diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri
index 0e78f9cff..75666a270 100644
--- a/src/render/frontend/render-frontend.pri
+++ b/src/render/frontend/render-frontend.pri
@@ -2,8 +2,6 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/qabstractfunctor.h \
- $$PWD/qboundingsphere.h \
- $$PWD/qboundingsphere_p.h \
$$PWD/qrenderaspect.h \
$$PWD/qrenderaspect_p.h \
$$PWD/qitemmodelbuffer_p.h \
@@ -26,11 +24,14 @@ HEADERS += \
$$PWD/qpickingsettings.h \
$$PWD/qpickingsettings_p.h \
$$PWD/qcomputecommand_p.h \
- $$PWD/qcomputecommand.h
+ $$PWD/qcomputecommand.h \
+ $$PWD/qrenderplugin_p.h \
+ $$PWD/qrenderpluginfactory_p.h \
+ $$PWD/qrenderpluginfactoryif_p.h \
+ $$PWD/qlevelofdetailboundingsphere.h
SOURCES += \
$$PWD/qabstractfunctor.cpp \
- $$PWD/qboundingsphere.cpp \
$$PWD/qrenderaspect.cpp \
$$PWD/qitemmodelbuffer.cpp \
$$PWD/sphere.cpp \
@@ -43,5 +44,8 @@ SOURCES += \
$$PWD/qrendersettings.cpp \
$$PWD/qpickingsettings.cpp \
$$PWD/qrendertargetoutput.cpp \
- $$PWD/qcomputecommand.cpp
+ $$PWD/qcomputecommand.cpp \
+ $$PWD/qrenderpluginfactory.cpp \
+ $$PWD/qrenderpluginfactoryif.cpp \
+ $$PWD/qlevelofdetailboundingsphere.cpp
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 80926efb9..2c22e0da4 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -223,8 +223,9 @@ Qt3DCore::QNodeId Sphere::id() const
return m_id;
}
-bool Sphere::intersects(const RayCasting::QRay3D &ray, QVector3D *q) const
+bool Sphere::intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const
{
+ Q_UNUSED(uvw);
return intersectRaySphere(ray, *this, q);
}
diff --git a/src/render/frontend/sphere_p.h b/src/render/frontend/sphere_p.h
index 1defbf059..1587aecab 100644
--- a/src/render/frontend/sphere_p.h
+++ b/src/render/frontend/sphere_p.h
@@ -106,7 +106,7 @@ public:
}
Qt3DCore::QNodeId id() const Q_DECL_FINAL;
- bool intersects(const RayCasting::QRay3D &ray, QVector3D *q) const Q_DECL_FINAL;
+ bool intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw = nullptr) const Q_DECL_FINAL;
Type type() const Q_DECL_FINAL;
static Sphere fromPoints(const QVector<QVector3D> &points);
diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp
index 7e1ea79dd..6c8c0113a 100644
--- a/src/render/geometry/attribute.cpp
+++ b/src/render/geometry/attribute.cpp
@@ -108,7 +108,7 @@ void Attribute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
QByteArray propertyName = propertyChange->propertyName();
if (propertyName == QByteArrayLiteral("name")) {
- m_name = propertyChange->value().value<QString>();
+ m_name = propertyChange->value().toString();
m_nameId = StringToInt::lookupId(m_name);
m_attributeDirty = true;
} else if (propertyName == QByteArrayLiteral("vertexBaseType")) {
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index df0bc3c92..55c86910f 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -41,7 +41,6 @@
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/qbuffer_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -56,6 +55,7 @@ Buffer::Buffer()
, m_usage(QBuffer::StaticDraw)
, m_bufferDirty(false)
, m_syncData(false)
+ , m_access(QBuffer::Write)
, m_manager(nullptr)
{
// Maybe it could become read write if we want to inform
@@ -75,6 +75,7 @@ void Buffer::cleanup()
m_functor.reset();
m_bufferDirty = false;
m_syncData = false;
+ m_access = QBuffer::Write;
}
@@ -87,17 +88,33 @@ void Buffer::executeFunctor()
{
Q_ASSERT(m_functor);
m_data = (*m_functor)();
+ // Request data to be loaded
+ forceDataUpload();
+
if (m_syncData) {
// Send data back to the frontend
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("data");
e->setValue(QVariant::fromValue(m_data));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
+//Called from th sendBufferJob
+void Buffer::updateDataFromGPUToCPU(QByteArray data)
+{
+ // Note: when this is called, data is what's currently in GPU memory
+ // so m_data shouldn't be reuploaded
+ m_data = data;
+ // Send data back to the frontend
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("downloadedData");
+ e->setValue(QVariant::fromValue(m_data));
+ notifyObservers(e);
+}
+
void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBufferData>>(change);
@@ -106,23 +123,40 @@ void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang
m_type = data.type;
m_usage = data.usage;
m_syncData = data.syncData;
+ m_access = data.access;
m_bufferDirty = true;
+ if (!m_data.isEmpty())
+ forceDataUpload();
+
m_functor = data.functor;
Q_ASSERT(m_manager);
if (m_functor)
m_manager->addDirtyBuffer(peerId());
}
+void Buffer::forceDataUpload()
+{
+ // We push back an update with offset = -1
+ // As this is the way to force data to be loaded
+ QBufferUpdate updateNewData;
+ updateNewData.offset = -1;
+ m_bufferUpdates.clear(); //previous updates are pointless
+ m_bufferUpdates.push_back(updateNewData);
+}
+
void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == PropertyUpdated) {
QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
QByteArray propertyName = propertyChange->propertyName();
if (propertyName == QByteArrayLiteral("data")) {
- QByteArray newData = propertyChange->value().value<QByteArray>();
- m_bufferDirty |= m_data != newData;
+ QByteArray newData = propertyChange->value().toByteArray();
+ bool dirty = m_data != newData;
+ m_bufferDirty |= dirty;
m_data = newData;
+ if (dirty)
+ forceDataUpload();
} else if (propertyName == QByteArrayLiteral("updateData")) {
Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>();
m_bufferUpdates.push_back(updateData);
@@ -133,6 +167,8 @@ void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
} else if (propertyName == QByteArrayLiteral("usage")) {
m_usage = static_cast<QBuffer::UsageType>(propertyChange->value().value<int>());
m_bufferDirty = true;
+ } else if (propertyName == QByteArrayLiteral("accessType")) {
+ m_access = static_cast<QBuffer::AccessType>(propertyChange->value().value<int>());
} else if (propertyName == QByteArrayLiteral("dataGenerator")) {
QBufferDataGeneratorPtr newGenerator = propertyChange->value().value<QBufferDataGeneratorPtr>();
m_bufferDirty |= !(newGenerator && m_functor && *newGenerator == *m_functor);
diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h
index d474c1720..691d6cc60 100644
--- a/src/render/geometry/buffer_p.h
+++ b/src/render/geometry/buffer_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QBufferUpdate;
+struct QBufferUpdate;
namespace Render {
@@ -77,6 +77,7 @@ public:
void setManager(BufferManager *manager);
void executeFunctor();
+ void updateDataFromGPUToCPU(QByteArray data);
inline QBuffer::BufferType type() const { return m_type; }
inline QBuffer::UsageType usage() const { return m_usage; }
inline QByteArray data() const { return m_data; }
@@ -84,10 +85,12 @@ public:
inline bool isDirty() const { return m_bufferDirty; }
inline QBufferDataGeneratorPtr dataGenerator() const { return m_functor; }
inline bool isSyncData() const { return m_syncData; }
+ inline QBuffer::AccessType access() const { return m_access; }
void unsetDirty();
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void forceDataUpload();
QBuffer::BufferType m_type;
QBuffer::UsageType m_usage;
@@ -95,6 +98,7 @@ private:
QVector<Qt3DRender::QBufferUpdate> m_bufferUpdates;
bool m_bufferDirty;
bool m_syncData;
+ QBuffer::AccessType m_access;
QBufferDataGeneratorPtr m_functor;
BufferManager *m_manager;
};
diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp
index 54fe61831..4f5432e1d 100644
--- a/src/render/geometry/geometryrenderer.cpp
+++ b/src/render/geometry/geometryrenderer.cpp
@@ -153,7 +153,7 @@ void GeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_verticesPerPatch = propertyChange->value().value<int>();
m_dirty = true;
} else if (propertyName == QByteArrayLiteral("primitiveRestartEnabled")) {
- m_primitiveRestartEnabled = propertyChange->value().value<bool>();
+ m_primitiveRestartEnabled = propertyChange->value().toBool();
m_dirty = true;
} else if (propertyName == QByteArrayLiteral("primitiveType")) {
m_primitiveType = static_cast<QGeometryRenderer::PrimitiveType>(propertyChange->value().value<int>());
diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp
index 0d3be8fdd..b978e0e0b 100644
--- a/src/render/geometry/qbuffer.cpp
+++ b/src/render/geometry/qbuffer.cpp
@@ -42,6 +42,7 @@
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -50,8 +51,10 @@ namespace Qt3DRender {
QBufferPrivate::QBufferPrivate()
: QNodePrivate()
+ , m_type(QBuffer::VertexBuffer)
, m_usage(QBuffer::StaticDraw)
, m_syncData(false)
+ , m_access(QBuffer::Write)
{
}
@@ -189,7 +192,8 @@ QBufferPrivate::QBufferPrivate()
/*!
\fn Qt3DRender::QBufferDataGenerator::operator ==(const QBufferDataGenerator &other) const
- Should be reimplemented to return true when two generators are identical,
+ Should be reimplemented to return true when two generators (the one you are
+ comparing against and the \a other generator) are identical,
false otherwise.
\note The renderer uses this comparison to decide whether data for a buffer
@@ -270,11 +274,19 @@ QBuffer::~QBuffer()
*/
void QBuffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
{
- QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
- if (e->type() == PropertyUpdated && e->propertyName() == QByteArrayLiteral("data")) {
- const bool blocked = blockNotifications(true);
- setData(e->value().toByteArray());
- blockNotifications(blocked);
+ if (change->type() == PropertyUpdated) {
+ QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
+ const QByteArray propertyName = e->propertyName();
+ if (propertyName == QByteArrayLiteral("data")) {
+ const bool blocked = blockNotifications(true);
+ setData(e->value().toByteArray());
+ blockNotifications(blocked);
+ } else if (propertyName == QByteArrayLiteral("downloadedData")) {
+ const bool blocked = blockNotifications(true);
+ setData(e->value().toByteArray());
+ blockNotifications(blocked);
+ Q_EMIT dataAvailable();
+ }
}
}
@@ -400,12 +412,27 @@ void QBuffer::setSyncData(bool syncData)
}
}
+void QBuffer::setAccessType(QBuffer::AccessType access)
+{
+ Q_D(QBuffer);
+ if (d->m_access != access) {
+ d->m_access = access;
+ Q_EMIT accessTypeChanged(access);
+ }
+}
+
bool QBuffer::isSyncData() const
{
Q_D(const QBuffer);
return d->m_syncData;
}
+QBuffer::AccessType QBuffer::accessType() const
+{
+ Q_D(const QBuffer);
+ return d->m_access;
+}
+
void QBuffer::setType(QBuffer::BufferType type)
{
Q_D(QBuffer);
@@ -425,6 +452,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QBuffer::createNodeCreationChange() const
data.usage = d->m_usage;
data.functor = d->m_functor;
data.syncData = d->m_syncData;
+ data.access = d->m_access;
return creationChange;
}
diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h
index 8b47de918..7cb5acb0a 100644
--- a/src/render/geometry/qbuffer.h
+++ b/src/render/geometry/qbuffer.h
@@ -59,6 +59,7 @@ class QT3DRENDERSHARED_EXPORT QBuffer : public Qt3DCore::QNode
Q_PROPERTY(BufferType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(UsageType usage READ usage WRITE setUsage NOTIFY usageChanged)
Q_PROPERTY(bool syncData READ isSyncData WRITE setSyncData NOTIFY syncDataChanged)
+ Q_PROPERTY(AccessType accessType READ accessType WRITE setAccessType NOTIFY accessTypeChanged REVISION 9)
public:
enum BufferType
@@ -87,12 +88,20 @@ public:
};
Q_ENUM(UsageType) // LCOV_EXCL_LINE
+ enum AccessType {
+ Write = 0x1,
+ Read = 0x2,
+ ReadWrite = Write|Read
+ };
+ Q_ENUM(AccessType) // LCOV_EXCL_LINE
+
explicit QBuffer(BufferType ty = QBuffer::VertexBuffer, Qt3DCore::QNode *parent = nullptr);
~QBuffer();
UsageType usage() const;
BufferType type() const;
bool isSyncData() const;
+ AccessType accessType() const;
void setData(const QByteArray &bytes);
QByteArray data() const;
@@ -106,6 +115,7 @@ public Q_SLOTS:
void setType(BufferType type);
void setUsage(UsageType usage);
void setSyncData(bool syncData);
+ void setAccessType(AccessType access);
protected:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
@@ -115,6 +125,8 @@ Q_SIGNALS:
void typeChanged(BufferType type);
void usageChanged(UsageType usage);
void syncDataChanged(bool syncData);
+ void accessTypeChanged(AccessType access);
+ void dataAvailable();
private:
Q_DECLARE_PRIVATE(QBuffer)
diff --git a/src/render/geometry/qbuffer_p.h b/src/render/geometry/qbuffer_p.h
index eb69730b8..a722675ab 100644
--- a/src/render/geometry/qbuffer_p.h
+++ b/src/render/geometry/qbuffer_p.h
@@ -74,6 +74,7 @@ public:
QBuffer::UsageType m_usage;
QBufferDataGeneratorPtr m_functor;
bool m_syncData;
+ QBuffer::AccessType m_access;
};
struct QBufferData
@@ -83,6 +84,7 @@ struct QBufferData
QBuffer::UsageType usage;
QBufferDataGeneratorPtr functor;
bool syncData;
+ QBuffer::AccessType access;
};
struct QBufferUpdate
diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp
index 95405d64d..3d281866d 100644
--- a/src/render/geometry/qgeometry.cpp
+++ b/src/render/geometry/qgeometry.cpp
@@ -94,7 +94,13 @@ QGeometryPrivate::~QGeometryPrivate()
/*!
\qmlproperty Attribute Geometry::boundingVolumePositionAttribute
- Holds the attribute used to compute the bounding volume.
+ Holds the attribute used to compute the bounding volume. The bounding volume is used internally
+ for picking and view frustum culling.
+
+ If unspecified, the system will look for the attribute using the name returned by
+ QAttribute::defaultPositionAttributeName.
+
+ \sa Attribute
*/
/*!
\qmlproperty list<Attribute> Geometry::attributes
@@ -105,7 +111,13 @@ QGeometryPrivate::~QGeometryPrivate()
/*!
\property QGeometry::boundingVolumePositionAttribute
- Holds the attribute used to compute the bounding volume.
+ Holds the attribute used to compute the bounding volume. The bounding volume is used internally
+ for picking and view frustum culling.
+
+ If unspecified, the system will look for the attribute using the name returned by
+ QAttribute::defaultPositionAttributeName.
+
+ \sa Qt3DRender::QAttribute
*/
diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp
index 2d9bb54b4..40a4c2f52 100644
--- a/src/render/geometry/qmesh.cpp
+++ b/src/render/geometry/qmesh.cpp
@@ -45,30 +45,63 @@
#include <QFile>
#include <QFileInfo>
#include <QScopedPointer>
-#include <Qt3DRender/private/qgeometryloaderinterface_p.h>
+#include <QMimeDatabase>
+#include <QMimeType>
+#include <QtCore/QBuffer>
+#include <Qt3DRender/QRenderAspect>
+#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/qgeometryloaderinterface_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DRender/private/qgeometryloaderfactory_p.h>
+#include <Qt3DRender/private/geometryrenderermanager_p.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-#ifndef QT_NO_LIBRARY
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, geometryLoader, (QGeometryLoaderFactory_iid, QLatin1String("/geometryloaders"), Qt::CaseInsensitive))
-#endif
QMeshPrivate::QMeshPrivate()
: QGeometryRendererPrivate()
{
}
+QMeshPrivate *QMeshPrivate::get(QMesh *q)
+{
+ return q->d_func();
+}
+
+void QMeshPrivate::setScene(Qt3DCore::QScene *scene)
+{
+ QGeometryRendererPrivate::setScene(scene);
+ updateFunctor();
+}
+
+void QMeshPrivate::updateFunctor()
+{
+ Q_Q(QMesh);
+ Qt3DCore::QAspectEngine *engine = m_scene ? m_scene->engine() : nullptr;
+ q->setGeometryFactory(QGeometryFactoryPtr(new MeshLoaderFunctor(q, engine)));
+}
+
/*!
* \qmltype Mesh
* \instantiates Qt3DRender::QMesh
* \inqmlmodule Qt3D.Render
- * \brief A custom mesh.
+ * \brief A custom mesh loader.
+ *
+ * Loads mesh data from external files in a variety of formats.
+ *
+ * In Qt3D 5.9, Mesh supports the following formats: Wavefront OBJ, Stanford Triangle Format PLY, STL (STereoLithography).
+ * QMesh will also support Autodesk FBX files if the SDK is installed and the fbx geometry loader plugin is built and found.
*/
/*!
@@ -80,7 +113,17 @@ QMeshPrivate::QMeshPrivate()
/*!
* \qmlproperty string Mesh::meshName
*
- * Holds the name of the mesh.
+ * Filter indicating which part of the mesh should be loaded.
+ *
+ * If meshName is empty (the default), then the entire mesh is loaded.
+ *
+ * If meshName is a plain string, then only the sub-mesh matching that name, if present, will be loaded.
+ *
+ * If meshName is a regular expression, than all sub-meshes matching the expression will be loaded.
+ *
+ * \note Only Wavefront OBJ files support sub-meshes.
+ *
+ * \sa QRegularExpression
*/
/*!
@@ -90,7 +133,17 @@ QMeshPrivate::QMeshPrivate()
*
* \inherits Qt3DRender::QGeometryRenderer
*
- * \brief A custom mesh.
+ * \brief A custom mesh loader.
+ *
+ * Loads mesh data from external files in a variety of formats.
+ * Qt3DRender::QMesh loads data into a single mesh.
+ *
+ * In Qt3D 5.9, QMesh supports the following formats: Wavefront OBJ, Stanford Triangle Format PLY, STL (STereoLithography).
+ * QMesh will also support Autodesk FBX files if the SDK is installed and the fbx geometry loader plugin is built and found.
+ *
+ * If you wish to load an entire scene made of several objects, you should rather use the Qt3DRender::QSceneLoader instead.
+ *
+ * \sa Qt3DRender::QSceneLoader
*/
/*!
@@ -118,8 +171,7 @@ void QMesh::setSource(const QUrl& source)
if (d->m_source == source)
return;
d->m_source = source;
- // update the functor
- QGeometryRenderer::setGeometryFactory(QGeometryFactoryPtr(new MeshFunctor(d->m_source, d->m_meshName)));
+ d->updateFunctor();
const bool blocked = blockNotifications(true);
emit sourceChanged(source);
blockNotifications(blocked);
@@ -142,8 +194,7 @@ void QMesh::setMeshName(const QString &meshName)
if (d->m_meshName == meshName)
return;
d->m_meshName = meshName;
- // update the functor
- QGeometryRenderer::setGeometryFactory(QGeometryFactoryPtr(new MeshFunctor(d->m_source, d->m_meshName)));
+ d->updateFunctor();
const bool blocked = blockNotifications(true);
emit meshNameChanged(meshName);
blockNotifications(blocked);
@@ -163,49 +214,89 @@ QString QMesh::meshName() const
/*!
* \internal
*/
-MeshFunctor::MeshFunctor(const QUrl &sourcePath, const QString& meshName)
+MeshLoaderFunctor::MeshLoaderFunctor(QMesh *mesh, Qt3DCore::QAspectEngine *engine, const QByteArray &sourceData)
: QGeometryFactory()
- , m_sourcePath(sourcePath)
- , m_meshName(meshName)
+ , m_mesh(mesh->id())
+ , m_sourcePath(mesh->source())
+ , m_meshName(mesh->meshName())
+ , m_engine(engine)
+ , m_sourceData(sourceData)
{
}
/*!
* \internal
*/
-QGeometry *MeshFunctor::operator()()
+QGeometry *MeshLoaderFunctor::operator()()
{
if (m_sourcePath.isEmpty()) {
qCWarning(Render::Jobs) << Q_FUNC_INFO << "Mesh is empty, nothing to load";
return nullptr;
}
- // TO DO: Handle file download if remote url
- QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_sourcePath);
+ QStringList ext;
+ if (!Qt3DCore::QDownloadHelperService::isLocal(m_sourcePath)) {
+ if (m_sourceData.isEmpty()) {
+ if (m_mesh) {
+ auto downloadService = Qt3DCore::QDownloadHelperService::getService(m_engine);
+ Qt3DCore::QDownloadRequestPtr request(new MeshDownloadRequest(m_mesh, m_sourcePath, m_engine));
+ downloadService->submitRequest(request);
+ }
+ return nullptr;
+ }
- QFileInfo finfo(filePath);
- auto ext = finfo.suffix();
+ QMimeDatabase db;
+ QMimeType mtype = db.mimeTypeForData(m_sourceData);
+ if (mtype.isValid()) {
+ ext = mtype.suffixes();
+ }
+ QFileInfo finfo(m_sourcePath.path());
+ ext << finfo.suffix();
+ ext.removeAll(QLatin1String(""));
+ if (!ext.contains(QLatin1String("obj")))
+ ext << QLatin1String("obj");
+ } else {
+ QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_sourcePath);
+ QFileInfo finfo(filePath);
+ if (finfo.suffix().isEmpty())
+ ext << QLatin1String("obj");
+ else
+ ext << finfo.suffix();
+ }
QScopedPointer<QGeometryLoaderInterface> loader;
-
- loader.reset(qLoadPlugin<QGeometryLoaderInterface, QGeometryLoaderFactory>(geometryLoader(), ext));
+ for (QString e: qAsConst(ext)) {
+ loader.reset(qLoadPlugin<QGeometryLoaderInterface, QGeometryLoaderFactory>(geometryLoader(), e));
+ if (loader)
+ break;
+ }
if (!loader) {
- qCWarning(Render::Jobs, "unsupported format encountered (%s)", qPrintable(ext));
+ qCWarning(Render::Jobs, "unsupported format encountered (%s)", qPrintable(ext.join(QLatin1String(", "))));
return nullptr;
}
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- qCDebug(Render::Jobs) << "Could not open file" << filePath << "for reading";
- return nullptr;
- }
+ if (m_sourceData.isEmpty()) {
+ QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_sourcePath);
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCDebug(Render::Jobs) << "Could not open file" << filePath << "for reading";
+ return nullptr;
+ }
- qCDebug(Render::Jobs) << Q_FUNC_INFO << "Loading mesh from" << m_sourcePath << " part:" << m_meshName;
+ if (loader->load(&file, m_meshName))
+ return loader->geometry();
+ qCWarning(Render::Jobs) << Q_FUNC_INFO << "Mesh loading failure for:" << filePath;
+ } else {
+ QT_PREPEND_NAMESPACE(QBuffer) buffer(&m_sourceData);
+ if (!buffer.open(QIODevice::ReadOnly)) {
+ return nullptr;
+ }
- if (loader->load(&file, m_meshName))
- return loader->geometry();
+ if (loader->load(&buffer, m_meshName))
+ return loader->geometry();
- qCWarning(Render::Jobs) << Q_FUNC_INFO << "Mesh loading failure for:" << filePath;
+ qCWarning(Render::Jobs) << Q_FUNC_INFO << "Mesh loading failure for:" << m_sourcePath;
+ }
return nullptr;
}
@@ -213,14 +304,47 @@ QGeometry *MeshFunctor::operator()()
/*!
* \internal
*/
-bool MeshFunctor::operator ==(const QGeometryFactory &other) const
+bool MeshLoaderFunctor::operator ==(const QGeometryFactory &other) const
{
- const MeshFunctor *otherFunctor = functor_cast<MeshFunctor>(&other);
+ const MeshLoaderFunctor *otherFunctor = functor_cast<MeshLoaderFunctor>(&other);
if (otherFunctor != nullptr)
- return (otherFunctor->m_sourcePath == m_sourcePath);
+ return (otherFunctor->m_sourcePath == m_sourcePath &&
+ otherFunctor->m_sourceData.isEmpty() == m_sourceData.isEmpty() &&
+ otherFunctor->m_engine == m_engine);
return false;
}
+/*!
+ * \internal
+ */
+MeshDownloadRequest::MeshDownloadRequest(Qt3DCore::QNodeId mesh, QUrl source, Qt3DCore::QAspectEngine *engine)
+ : Qt3DCore::QDownloadRequest(source)
+ , m_mesh(mesh)
+ , m_engine(engine)
+{
+
+}
+
+void MeshDownloadRequest::onCompleted()
+{
+ if (cancelled() || !succeeded())
+ return;
+
+ QRenderAspectPrivate* d_aspect = QRenderAspectPrivate::findPrivate(m_engine);
+ if (!d_aspect)
+ return;
+
+ Render::GeometryRenderer *renderer = d_aspect->m_nodeManagers->geometryRendererManager()->lookupResource(m_mesh);
+ if (!renderer)
+ return;
+
+ QSharedPointer<MeshLoaderFunctor> functor = qSharedPointerCast<MeshLoaderFunctor>(renderer->geometryFactory());
+ functor->m_sourceData = m_data;
+
+ // mark the component as dirty so that the functor runs again in the correct job
+ d_aspect->m_nodeManagers->geometryRendererManager()->addDirtyGeometryRenderer(m_mesh);
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/geometry/qmesh_p.h b/src/render/geometry/qmesh_p.h
index a621525cc..f7f8079eb 100644
--- a/src/render/geometry/qmesh_p.h
+++ b/src/render/geometry/qmesh_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
#include <Qt3DRender/private/qgeometryrenderer_p.h>
#include <QUrl>
@@ -66,23 +67,40 @@ public:
QMeshPrivate();
Q_DECLARE_PUBLIC(QMesh)
+ static QMeshPrivate *get(QMesh *q);
+
+ void setScene(Qt3DCore::QScene *scene) override;
+ void updateFunctor();
QUrl m_source;
QString m_meshName;
};
+class Q_AUTOTEST_EXPORT MeshDownloadRequest : public Qt3DCore::QDownloadRequest
+{
+public:
+ MeshDownloadRequest(Qt3DCore::QNodeId mesh, QUrl source, Qt3DCore::QAspectEngine *engine);
+
+ void onCompleted() Q_DECL_OVERRIDE;
-class Q_AUTOTEST_EXPORT MeshFunctor : public QGeometryFactory
+private:
+ Qt3DCore::QNodeId m_mesh;
+ Qt3DCore::QAspectEngine *m_engine;
+};
+
+class Q_AUTOTEST_EXPORT MeshLoaderFunctor : public QGeometryFactory
{
public :
- MeshFunctor(const QUrl &sourcePath, const QString &meshName = QString());
+ MeshLoaderFunctor(QMesh *mesh, Qt3DCore::QAspectEngine *engine, const QByteArray &sourceData = QByteArray());
QGeometry *operator()() Q_DECL_OVERRIDE;
bool operator ==(const QGeometryFactory &other) const Q_DECL_OVERRIDE;
- QT3D_FUNCTOR(MeshFunctor)
+ QT3D_FUNCTOR(MeshLoaderFunctor)
-private:
+ Qt3DCore::QNodeId m_mesh;
QUrl m_sourcePath;
QString m_meshName;
+ Qt3DCore::QAspectEngine *m_engine;
+ QByteArray m_sourceData;
};
diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp
index dea8c1fc6..80e8267da 100644
--- a/src/render/graphicshelpers/graphicscontext.cpp
+++ b/src/render/graphicshelpers/graphicscontext.cpp
@@ -81,6 +81,14 @@
QT_BEGIN_NAMESPACE
+#ifndef GL_READ_FRAMEBUFFER
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#endif
+
+#ifndef GL_DRAW_FRAMEBUFFER
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#endif
+
namespace {
QOpenGLShader::ShaderType shaderType(Qt3DRender::QShaderProgram::ShaderType type)
@@ -154,6 +162,7 @@ GraphicsContext::GraphicsContext()
, m_ownCurrent(true)
, m_activeShader(nullptr)
, m_activeShaderDNA(0)
+ , m_renderTargetFormat(QAbstractTexture::NoFormat)
, m_currClearStencilValue(0)
, m_currClearDepthValue(1.f)
, m_currClearColorValue(0,0,0,0)
@@ -207,7 +216,7 @@ void GraphicsContext::initialize()
void GraphicsContext::resolveRenderTargetFormat()
{
const QSurfaceFormat format = m_gl->format();
- const uint a = format.alphaBufferSize();
+ const uint a = (format.alphaBufferSize() == -1) ? 0 : format.alphaBufferSize();
const uint r = format.redBufferSize();
const uint g = format.greenBufferSize();
const uint b = format.blueBufferSize();
@@ -459,11 +468,14 @@ QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode)
// Compile shaders
const auto shaderCode = shaderNode->shaderCode();
+ QString logs;
for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) {
QShaderProgram::ShaderType type = static_cast<const QShaderProgram::ShaderType>(i);
- if (!shaderCode.at(i).isEmpty() &&
- !shaderProgram->addShaderFromSourceCode(shaderType(type), shaderCode.at(i))) {
- qWarning().noquote() << "Failed to compile shader:" << shaderProgram->log();
+ if (!shaderCode.at(i).isEmpty()) {
+ // Note: logs only return the error but not all the shader code
+ // we could append it
+ if (!shaderProgram->addShaderFromSourceCode(shaderType(type), shaderCode.at(i)))
+ logs += shaderProgram->log();
}
}
@@ -471,17 +483,31 @@ QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode)
// Since we are sharing shaders in the backend, we assume that if using custom
// fragOutputs, they should all be the same for a given shader
bindFragOutputs(shaderProgram->programId(), shaderNode->fragOutputs());
- if (!shaderProgram->link()) {
- qWarning().noquote() << "Failed to link shader program:" << shaderProgram->log();
+
+ const bool linkSucceeded = shaderProgram->link();
+ logs += shaderProgram->log();
+ shaderNode->setLog(logs);
+ shaderNode->setStatus(linkSucceeded ? QShaderProgram::Ready : QShaderProgram::Error);
+
+ if (!linkSucceeded)
return nullptr;
- }
// take from scoped-pointer so it doesn't get deleted
return shaderProgram.take();
}
// That assumes that the shaderProgram in Shader stays the same
-void GraphicsContext::loadShader(Shader *shader)
+void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderProgram *shaderProgram)
+{
+ shader->initializeUniforms(m_glHelper->programUniformsAndLocations(shaderProgram->programId()));
+ shader->initializeAttributes(m_glHelper->programAttributesAndLocations(shaderProgram->programId()));
+ if (m_glHelper->supportsFeature(GraphicsHelperInterface::UniformBufferObject))
+ shader->initializeUniformBlocks(m_glHelper->programUniformBlocks(shaderProgram->programId()));
+ if (m_glHelper->supportsFeature(GraphicsHelperInterface::ShaderStorageObject))
+ shader->initializeShaderStorageBlocks(m_glHelper->programShaderStorageBlocks(shaderProgram->programId()));
+}
+
+void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
{
QOpenGLShaderProgram *shaderProgram = m_shaderCache.getShaderProgramAndAddRef(shader->dna(), shader->peerId());
if (!shaderProgram) {
@@ -493,20 +519,31 @@ void GraphicsContext::loadShader(Shader *shader)
}
// Ensure the Shader node knows about the program interface
- // TODO: Improve this so we only introspect once per actual OpenGL shader program
- // rather than once per ShaderNode. Could cache the interface description along
- // with the QOpenGLShaderProgram in the ShaderCache.
if (Q_LIKELY(shaderProgram != nullptr) && !shader->isLoaded()) {
- // Introspect and set up interface description on Shader backend node
- shader->initializeUniforms(m_glHelper->programUniformsAndLocations(shaderProgram->programId()));
- shader->initializeAttributes(m_glHelper->programAttributesAndLocations(shaderProgram->programId()));
- if (m_glHelper->supportsFeature(GraphicsHelperInterface::UniformBufferObject))
- shader->initializeUniformBlocks(m_glHelper->programUniformBlocks(shaderProgram->programId()));
- if (m_glHelper->supportsFeature(GraphicsHelperInterface::ShaderStorageObject))
- shader->initializeShaderStorageBlocks(m_glHelper->programShaderStorageBlocks(shaderProgram->programId()));
+
+ // Find an already loaded shader that shares the same QOpenGLShaderProgram
+ Shader *refShader = nullptr;
+ const QVector<Qt3DCore::QNodeId> sharedShaderIds = m_shaderCache.shaderIdsForProgram(shader->dna());
+ for (const Qt3DCore::QNodeId sharedShaderId : sharedShaderIds) {
+ Shader *sharedShader = manager->lookupResource(sharedShaderId);
+ // Note: no need to check if shader->peerId != sharedShader->peerId
+ // as we are sure that this code path is executed only if !shared->isLoaded
+ if (sharedShader->isLoaded()) {
+ refShader = sharedShader;
+ break;
+ }
+ }
+
+ // We only introspect once per actual OpenGL shader program
+ // rather than once per ShaderNode.
+ if (refShader != nullptr)
+ shader->initializeFromReference(*refShader);
+ else // Introspect and set up interface description on Shader backend node
+ introspectShaderInterface(shader, shaderProgram);
shader->setGraphicsContext(this);
shader->setLoaded(true);
+ shader->markDirty(AbstractRenderer::AllDirty);
}
}
@@ -1045,6 +1082,16 @@ void GraphicsContext::dispatchCompute(int x, int y, int z)
m_glHelper->dispatchCompute(x, y, z);
}
+GLboolean GraphicsContext::unmapBuffer(GLenum target)
+{
+ return m_glHelper->unmapBuffer(target);
+}
+
+char *GraphicsContext::mapBuffer(GLenum target)
+{
+ return m_glHelper->mapBuffer(target);
+}
+
void GraphicsContext::enablei(GLenum cap, GLuint index)
{
m_glHelper->enablei(cap, index);
@@ -1273,16 +1320,16 @@ void GraphicsContext::applyUniform(const ShaderUniform &description, const Unifo
break;
case UniformType::UInt:
- applyUniformHelper<UniformType::Int>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UInt>(description.m_location, description.m_size, v);
break;
case UniformType::UIVec2:
- applyUniformHelper<UniformType::IVec2>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UIVec2>(description.m_location, description.m_size, v);
break;
case UniformType::UIVec3:
- applyUniformHelper<UniformType::IVec3>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UIVec3>(description.m_location, description.m_size, v);
break;
case UniformType::UIVec4:
- applyUniformHelper<UniformType::IVec4>(description.m_location, description.m_size, v);
+ applyUniformHelper<UniformType::UIVec4>(description.m_location, description.m_size, v);
break;
case UniformType::Bool:
@@ -1398,6 +1445,16 @@ void GraphicsContext::updateBuffer(Buffer *buffer)
uploadDataToGLBuffer(buffer, m_renderer->nodeManagers()->glBufferManager()->data(it.value()));
}
+QByteArray GraphicsContext::downloadBufferContent(Buffer *buffer)
+{
+ const QHash<Qt3DCore::QNodeId, HGLBuffer>::iterator it = m_renderBufferHash.find(buffer->peerId());
+ if (it != m_renderBufferHash.end())
+ return downloadDataFromGLBuffer(buffer, m_renderer->nodeManagers()->glBufferManager()->data(it.value()));
+ return QByteArray();
+}
+
+
+
void GraphicsContext::releaseBuffer(Qt3DCore::QNodeId bufferId)
{
auto it = m_renderBufferHash.find(bufferId);
@@ -1421,7 +1478,7 @@ bool GraphicsContext::hasGLBufferForBuffer(Buffer *buffer)
return (it != m_renderBufferHash.end());
}
-void GraphicsContext::memoryBarrier(QMemoryBarrier::BarrierTypes barriers)
+void GraphicsContext::memoryBarrier(QMemoryBarrier::Operations barriers)
{
m_glHelper->memoryBarrier(barriers);
}
@@ -1444,8 +1501,6 @@ HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer)
if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type())))
qCWarning(Render::Io) << Q_FUNC_INFO << "buffer binding failed";
- // TO DO: Handle usage pattern
- b->allocate(this, buffer->data().constData(), buffer->data().size(), false);
return m_renderer->nodeManagers()->glBufferManager()->lookupHandle(buffer->peerId());
}
@@ -1471,21 +1526,39 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel
// * setData was called changing the whole data or functor (or the usage pattern)
// * partial buffer updates where received
- // Note: we assume the case where both setData/functor and updates are called to be a misuse
- // with unexpected behavior
- const QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates());
- if (!updates.empty()) {
- for (const Qt3DRender::QBufferUpdate &update : updates) {
+ // TO DO: Handle usage pattern
+ QVector<Qt3DRender::QBufferUpdate> updates = std::move(buffer->pendingBufferUpdates());
+ for (auto it = updates.begin(); it != updates.end(); ++it) {
+ auto update = it;
+ // We have a partial update
+ if (update->offset >= 0) {
+ //accumulate sequential updates as single one
+ int bufferSize = update->data.size();
+ auto it2 = it + 1;
+ while ((it2 != updates.end())
+ && (it2->offset - update->offset == bufferSize)) {
+ bufferSize += it2->data.size();
+ ++it2;
+ }
+ update->data.resize(bufferSize);
+ while (it + 1 != it2) {
+ ++it;
+ update->data.replace(it->offset - update->offset, it->data.size(), it->data);
+ it->data.clear();
+ }
// TO DO: based on the number of updates .., it might make sense to
// sometime use glMapBuffer rather than glBufferSubData
- b->update(this, update.data.constData(), update.data.size(), update.offset);
+ b->update(this, update->data.constData(), update->data.size(), update->offset);
+ } else {
+ // We have an update that was done by calling QBuffer::setData
+ // which is used to resize or entirely clear the buffer
+ // Note: we use the buffer data directly in that case
+ const int bufferSize = buffer->data().size();
+ b->allocate(this, bufferSize, false); // orphan the buffer
+ b->allocate(this, buffer->data().constData(), bufferSize, false);
}
- } else {
- const int bufferSize = buffer->data().size();
- // TO DO: Handle usage pattern
- b->allocate(this, bufferSize, false); // orphan the buffer
- b->allocate(this, buffer->data().constData(), bufferSize, false);
}
+
if (releaseBuffer) {
b->release(this);
if (bufferTypeToGLBufferType(buffer->type()) == GLBuffer::ArrayBuffer)
@@ -1494,6 +1567,15 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel
qCDebug(Render::Io) << "uploaded buffer size=" << buffer->data().size();
}
+QByteArray GraphicsContext::downloadDataFromGLBuffer(Buffer *buffer, GLBuffer *b)
+{
+ if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type())))
+ qCWarning(Render::Io) << Q_FUNC_INFO << "buffer bind failed";
+
+ QByteArray data = b->download(this, buffer->data().size());
+ return data;
+}
+
GLint GraphicsContext::elementType(GLint type)
{
switch (type) {
@@ -1649,10 +1731,8 @@ QImage GraphicsContext::readFramebuffer(QSize size)
QImage::Format imageFormat;
uint stride;
-#ifndef QT_OPENGL_ES_2
/* format value should match GL internalFormat */
GLenum internalFormat = m_renderTargetFormat;
-#endif
switch (m_renderTargetFormat) {
case QAbstractTexture::RGBAFormat:
@@ -1728,18 +1808,15 @@ QImage GraphicsContext::readFramebuffer(QSize size)
return img;
}
-#ifndef QT_OPENGL_ES_2
GLint samples = 0;
m_gl->functions()->glGetIntegerv(GL_SAMPLES, &samples);
if (samples > 0 && !m_glHelper->supportsFeature(GraphicsHelperInterface::BlitFramebuffer))
return img;
-#endif
img = QImage(size.width(), size.height(), imageFormat);
QScopedArrayPointer<uchar> data(new uchar [bytes]);
-#ifndef QT_OPENGL_ES_2
if (samples > 0) {
// resolve multisample-framebuffer to renderbuffer and read pixels from it
GLuint fbo, rb;
@@ -1771,14 +1848,10 @@ QImage GraphicsContext::readFramebuffer(QSize size)
gl->glBindFramebuffer(GL_FRAMEBUFFER, m_activeFBO);
gl->glDeleteFramebuffers(1, &fbo);
} else {
-#endif
// read pixels directly from framebuffer
m_gl->functions()->glReadPixels(0,0,size.width(), size.height(), format, type, data.data());
copyGLFramebufferDataToImage(img, data.data(), stride, size.width(), size.height(), m_renderTargetFormat);
-
-#ifndef QT_OPENGL_ES_2
}
-#endif
return img;
}
diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h
index 133c84b8c..4358da999 100644
--- a/src/render/graphicshelpers/graphicscontext_p.h
+++ b/src/render/graphicshelpers/graphicscontext_p.h
@@ -91,6 +91,7 @@ class RenderTarget;
class AttachmentPack;
class Attribute;
class Buffer;
+class ShaderManager;
enum TextureScope
{
@@ -130,9 +131,10 @@ public:
bool isInitialized() const;
QOpenGLShaderProgram *createShaderProgram(Shader *shaderNode);
- void loadShader(Shader* shader);
+ void loadShader(Shader* shader, ShaderManager *manager);
bool activateShader(ProgramDNA shaderDNA);
void removeShaderProgramReference(Shader *shaderNode);
+ void introspectShaderInterface(Shader *shader, QOpenGLShaderProgram *shaderProgram);
GLuint activeFBO() const { return m_activeFBO; }
GLuint defaultFBO() const { return m_defaultFBO; }
@@ -157,10 +159,11 @@ public:
void specifyAttribute(const Attribute *attribute, Buffer *buffer, int attributeLocation);
void specifyIndices(Buffer *buffer);
void updateBuffer(Buffer *buffer);
+ QByteArray downloadBufferContent(Buffer *buffer);
void releaseBuffer(Qt3DCore::QNodeId bufferId);
bool hasGLBufferForBuffer(Buffer *buffer);
- void memoryBarrier(QMemoryBarrier::BarrierTypes barriers);
+ void memoryBarrier(QMemoryBarrier::Operations barriers);
void setParameters(ShaderParameterPack &parameterPack);
@@ -208,6 +211,8 @@ public:
void disablei(GLenum cap, GLuint index);
void disablePrimitiveRestart();
void dispatchCompute(int x, int y, int z);
+ char * mapBuffer(GLenum target);
+ GLboolean unmapBuffer(GLenum target);
void drawArrays(GLenum primitiveType, GLint first, GLsizei count);
void drawArraysIndirect(GLenum mode,void *indirect);
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances);
@@ -252,6 +257,7 @@ private:
void activateDrawBuffers(const AttachmentPack &attachments);
HGLBuffer createGLBufferFor(Buffer *buffer);
void uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool releaseBuffer = false);
+ QByteArray downloadDataFromGLBuffer(Buffer *buffer, GLBuffer *b);
bool bindGLBuffer(GLBuffer *buffer, GLBuffer::Type type);
void resolveRenderTargetFormat();
diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp
index a89f0ff8b..3b821f804 100644
--- a/src/render/graphicshelpers/graphicshelperes2.cpp
+++ b/src/render/graphicshelpers/graphicshelperes2.cpp
@@ -65,8 +65,9 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
-GraphicsHelperES2::GraphicsHelperES2() :
- m_funcs(0)
+GraphicsHelperES2::GraphicsHelperES2()
+ : m_funcs(0)
+ , m_supportFramebufferBlit(false)
{
}
@@ -80,6 +81,9 @@ void GraphicsHelperES2::initializeHelper(QOpenGLContext *context,
Q_ASSERT(context);
m_funcs = context->functions();
Q_ASSERT(m_funcs);
+ m_ext.reset(new QOpenGLExtensions(context));
+ if (m_ext->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
+ m_supportFramebufferBlit = true;
}
void GraphicsHelperES2::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType,
@@ -366,6 +370,8 @@ bool GraphicsHelperES2::supportsFeature(GraphicsHelperInterface::Feature feature
switch (feature) {
case RenderBufferDimensionRetrieval:
return true;
+ case BlitFramebuffer:
+ return m_supportFramebufferBlit;
default:
return false;
}
@@ -492,7 +498,7 @@ GLint GraphicsHelperES2::maxClipPlaneCount()
return 0;
}
-void GraphicsHelperES2::memoryBarrier(QMemoryBarrier::BarrierTypes barriers)
+void GraphicsHelperES2::memoryBarrier(QMemoryBarrier::Operations barriers)
{
Q_UNUSED(barriers);
qWarning() << "memory barrier is not supported by OpenGL ES 2.0 (since 4.3)";
@@ -575,6 +581,20 @@ void GraphicsHelperES2::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
qWarning() << "Compute Shaders are not supported by ES 2.0 (since ES 3.1)";
}
+char *GraphicsHelperES2::mapBuffer(GLenum target)
+{
+ Q_UNUSED(target);
+ qWarning() << "Map buffer is not a core requirement for ES 2.0";
+ return nullptr;
+}
+
+GLboolean GraphicsHelperES2::unmapBuffer(GLenum target)
+{
+ Q_UNUSED(target);
+ qWarning() << "unMap buffer is not a core requirement for ES 2.0";
+ return false;
+}
+
void GraphicsHelperES2::glUniform1fv(GLint location, GLsizei count, const GLfloat *values)
{
m_funcs->glUniform1fv(location, count, values);
@@ -725,17 +745,10 @@ UniformType GraphicsHelperES2::uniformTypeFromGLType(GLenum type)
void GraphicsHelperES2::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
- Q_UNUSED(srcX0);
- Q_UNUSED(srcX1);
- Q_UNUSED(srcY0);
- Q_UNUSED(srcY1);
- Q_UNUSED(dstX0);
- Q_UNUSED(dstX1);
- Q_UNUSED(dstY0);
- Q_UNUSED(dstY1);
- Q_UNUSED(mask);
- Q_UNUSED(filter);
- qWarning() << "Framebuffer blits are not supported by ES 2.0 (since ES 3.1)";
+ if (!m_supportFramebufferBlit)
+ qWarning() << "Framebuffer blits are not supported by ES 2.0 (since ES 3.1)";
+ else
+ m_ext->glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
} // namespace Render
diff --git a/src/render/graphicshelpers/graphicshelperes2_p.h b/src/render/graphicshelpers/graphicshelperes2_p.h
index 2a1f3cf05..f34eb7f87 100644
--- a/src/render/graphicshelpers/graphicshelperes2_p.h
+++ b/src/render/graphicshelpers/graphicshelperes2_p.h
@@ -57,6 +57,8 @@
QT_BEGIN_NAMESPACE
+class QOpenGLExtensions;
+
namespace Qt3DRender {
namespace Render {
@@ -89,6 +91,8 @@ public:
void disablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
+ char *mapBuffer(GLenum target) Q_DECL_OVERRIDE;
+ GLboolean unmapBuffer(GLenum target) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
@@ -106,7 +110,7 @@ public:
void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE;
void pointSize(bool programmable, GLfloat value) Q_DECL_OVERRIDE;
GLint maxClipPlaneCount() Q_DECL_OVERRIDE;
- void memoryBarrier(QMemoryBarrier::BarrierTypes barriers) Q_DECL_OVERRIDE;
+ void memoryBarrier(QMemoryBarrier::Operations barriers) Q_DECL_OVERRIDE;
QVector<ShaderUniformBlock> programUniformBlocks(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderAttribute> programAttributesAndLocations(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderUniform> programUniformsAndLocations(GLuint programId) Q_DECL_OVERRIDE;
@@ -151,6 +155,8 @@ public:
protected:
QOpenGLFunctions *m_funcs;
+ bool m_supportFramebufferBlit;
+ QScopedPointer<QOpenGLExtensions> m_ext;
};
} // namespace Render
diff --git a/src/render/graphicshelpers/graphicshelpergl2.cpp b/src/render/graphicshelpers/graphicshelpergl2.cpp
index 765a12f42..5f798f94e 100644
--- a/src/render/graphicshelpers/graphicshelpergl2.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl2.cpp
@@ -518,7 +518,7 @@ GLint GraphicsHelperGL2::maxClipPlaneCount()
return max;
}
-void GraphicsHelperGL2::memoryBarrier(QMemoryBarrier::BarrierTypes barriers)
+void GraphicsHelperGL2::memoryBarrier(QMemoryBarrier::Operations barriers)
{
Q_UNUSED(barriers);
qWarning() << "memory barrier is not supported by OpenGL 2.0 (since 4.3)";
@@ -541,15 +541,11 @@ void GraphicsHelperGL2::clearBufferf(GLint drawbuffer, const QVector4D &values)
void GraphicsHelperGL2::pointSize(bool programmable, GLfloat value)
{
- // Print a warning once for trying to set GL_PROGRAM_POINT_SIZE
- if (programmable) {
- static bool warned = false;
- if (!warned) {
- qWarning() << "GL_PROGRAM_POINT_SIZE is not supported by OpenGL 2.0 (since 3.2)";
- warned = true;
- }
- }
- m_funcs->glPointSize(value);
+ m_funcs->glEnable(GL_POINT_SPRITE);
+ if (programmable)
+ m_funcs->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ else
+ m_funcs->glPointSize(value);
}
void GraphicsHelperGL2::enablei(GLenum cap, GLuint index)
@@ -600,6 +596,16 @@ void GraphicsHelperGL2::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
qWarning() << "Compute Shaders are not supported by OpenGL 2.0 (since OpenGL 4.3)";
}
+char *GraphicsHelperGL2::mapBuffer(GLenum target)
+{
+ return static_cast<char*>(m_funcs->glMapBuffer(target, GL_READ_WRITE));
+}
+
+GLboolean GraphicsHelperGL2::unmapBuffer(GLenum target)
+{
+ return m_funcs->glUnmapBuffer(target);
+}
+
void GraphicsHelperGL2::glUniform1fv(GLint location, GLsizei count, const GLfloat *values)
{
m_funcs->glUniform1fv(location, count, values);
diff --git a/src/render/graphicshelpers/graphicshelpergl2_p.h b/src/render/graphicshelpers/graphicshelpergl2_p.h
index a6fa6dba5..8966e48b2 100644
--- a/src/render/graphicshelpers/graphicshelpergl2_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl2_p.h
@@ -91,6 +91,8 @@ public:
void disablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
+ char *mapBuffer(GLenum target) Q_DECL_OVERRIDE;
+ GLboolean unmapBuffer(GLenum target) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
@@ -108,7 +110,7 @@ public:
void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE;
void pointSize(bool programmable, GLfloat value) Q_DECL_OVERRIDE;
GLint maxClipPlaneCount() Q_DECL_OVERRIDE;
- void memoryBarrier(QMemoryBarrier::BarrierTypes barriers) Q_DECL_OVERRIDE;
+ void memoryBarrier(QMemoryBarrier::Operations barriers) Q_DECL_OVERRIDE;
QVector<ShaderUniformBlock> programUniformBlocks(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderAttribute> programAttributesAndLocations(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderUniform> programUniformsAndLocations(GLuint programId) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl3_2.cpp b/src/render/graphicshelpers/graphicshelpergl3_2.cpp
index 382078ac6..6c768e94e 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_2.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl3_2.cpp
@@ -82,7 +82,7 @@ GraphicsHelperGL3_2::~GraphicsHelperGL3_2()
}
void GraphicsHelperGL3_2::initializeHelper(QOpenGLContext *context,
- QAbstractOpenGLFunctions *functions)
+ QAbstractOpenGLFunctions *functions)
{
m_funcs = static_cast<QOpenGLFunctions_3_2_Core*>(functions);
const bool ok = m_funcs->initializeOpenGLFunctions();
@@ -96,12 +96,12 @@ void GraphicsHelperGL3_2::initializeHelper(QOpenGLContext *context,
}
void GraphicsHelperGL3_2::drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType,
- GLsizei primitiveCount,
- GLint indexType,
- void *indices,
- GLsizei instances,
- GLint baseVertex,
- GLint baseInstance)
+ GLsizei primitiveCount,
+ GLint indexType,
+ void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLint baseInstance)
{
if (baseInstance != 0)
qWarning() << "glDrawElementsInstancedBaseVertexBaseInstance is not supported with OpenGL ES 2";
@@ -116,9 +116,9 @@ void GraphicsHelperGL3_2::drawElementsInstancedBaseVertexBaseInstance(GLenum pri
}
void GraphicsHelperGL3_2::drawArraysInstanced(GLenum primitiveType,
- GLint first,
- GLsizei count,
- GLsizei instances)
+ GLint first,
+ GLsizei count,
+ GLsizei instances)
{
// glDrawArraysInstanced OpenGL 3.1 or greater
m_funcs->glDrawArraysInstanced(primitiveType,
@@ -138,10 +138,10 @@ void GraphicsHelperGL3_2::drawArraysInstancedBaseInstance(GLenum primitiveType,
}
void GraphicsHelperGL3_2::drawElements(GLenum primitiveType,
- GLsizei primitiveCount,
- GLint indexType,
- void *indices,
- GLint baseVertex)
+ GLsizei primitiveCount,
+ GLint indexType,
+ void *indices,
+ GLint baseVertex)
{
m_funcs->glDrawElementsBaseVertex(primitiveType,
primitiveCount,
@@ -151,8 +151,8 @@ void GraphicsHelperGL3_2::drawElements(GLenum primitiveType,
}
void GraphicsHelperGL3_2::drawArrays(GLenum primitiveType,
- GLint first,
- GLsizei count)
+ GLint first,
+ GLsizei count)
{
m_funcs->glDrawArrays(primitiveType,
first,
@@ -797,7 +797,7 @@ GLint GraphicsHelperGL3_2::maxClipPlaneCount()
return max;
}
-void GraphicsHelperGL3_2::memoryBarrier(QMemoryBarrier::BarrierTypes barriers)
+void GraphicsHelperGL3_2::memoryBarrier(QMemoryBarrier::Operations barriers)
{
Q_UNUSED(barriers);
qWarning() << "memory barrier is not supported by OpenGL 3.0 (since 4.3)";
@@ -882,6 +882,16 @@ void GraphicsHelperGL3_2::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
qWarning() << "Compute Shaders are not supported by OpenGL 3.2 (since OpenGL 4.3)";
}
+char *GraphicsHelperGL3_2::mapBuffer(GLenum target)
+{
+ return static_cast<char*>(m_funcs->glMapBuffer(target, GL_READ_WRITE));
+}
+
+GLboolean GraphicsHelperGL3_2::unmapBuffer(GLenum target)
+{
+ return m_funcs->glUnmapBuffer(target);
+}
+
void GraphicsHelperGL3_2::glUniform1fv(GLint location, GLsizei count, const GLfloat *values)
{
m_funcs->glUniform1fv(location, count, values);
diff --git a/src/render/graphicshelpers/graphicshelpergl3_2_p.h b/src/render/graphicshelpers/graphicshelpergl3_2_p.h
index d10bda40b..fbca14361 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_2_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl3_2_p.h
@@ -93,6 +93,8 @@ public:
void disablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
+ char *mapBuffer(GLenum target) Q_DECL_OVERRIDE;
+ GLboolean unmapBuffer(GLenum target) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
@@ -110,7 +112,7 @@ public:
void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE;
void pointSize(bool programmable, GLfloat value) Q_DECL_OVERRIDE;
GLint maxClipPlaneCount() Q_DECL_OVERRIDE;
- void memoryBarrier(QMemoryBarrier::BarrierTypes barriers) Q_DECL_OVERRIDE;
+ void memoryBarrier(QMemoryBarrier::Operations barriers) Q_DECL_OVERRIDE;
QVector<ShaderUniformBlock> programUniformBlocks(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderAttribute> programAttributesAndLocations(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderUniform> programUniformsAndLocations(GLuint programId) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/graphicshelpers/graphicshelpergl3_3.cpp
index 023e90965..6959bdc6b 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_3.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl3_3.cpp
@@ -794,7 +794,7 @@ GLint GraphicsHelperGL3_3::maxClipPlaneCount()
return max;
}
-void GraphicsHelperGL3_3::memoryBarrier(QMemoryBarrier::BarrierTypes barriers)
+void GraphicsHelperGL3_3::memoryBarrier(QMemoryBarrier::Operations barriers)
{
Q_UNUSED(barriers);
qWarning() << "memory barrier is not supported by OpenGL 3.3 (since 4.3)";
@@ -879,6 +879,16 @@ void GraphicsHelperGL3_3::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
qWarning() << "Compute Shaders are not supported by OpenGL 3.3 (since OpenGL 4.3)";
}
+char *GraphicsHelperGL3_3::mapBuffer(GLenum target)
+{
+ return static_cast<char*>(m_funcs->glMapBuffer(target, GL_READ_WRITE));
+}
+
+GLboolean GraphicsHelperGL3_3::unmapBuffer(GLenum target)
+{
+ return m_funcs->glUnmapBuffer(target);
+}
+
void GraphicsHelperGL3_3::glUniform1fv(GLint location, GLsizei count, const GLfloat *values)
{
m_funcs->glUniform1fv(location, count, values);
diff --git a/src/render/graphicshelpers/graphicshelpergl3_3_p.h b/src/render/graphicshelpers/graphicshelpergl3_3_p.h
index 9e97f3dc4..c093c801e 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_3_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl3_3_p.h
@@ -93,6 +93,8 @@ public:
void disablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
+ char *mapBuffer(GLenum target) Q_DECL_OVERRIDE;
+ GLboolean unmapBuffer(GLenum target) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
@@ -110,7 +112,7 @@ public:
void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE;
void pointSize(bool programmable, GLfloat value) Q_DECL_OVERRIDE;
GLint maxClipPlaneCount() Q_DECL_OVERRIDE;
- void memoryBarrier(QMemoryBarrier::BarrierTypes barriers) Q_DECL_OVERRIDE;
+ void memoryBarrier(QMemoryBarrier::Operations barriers) Q_DECL_OVERRIDE;
QVector<ShaderUniformBlock> programUniformBlocks(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderAttribute> programAttributesAndLocations(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderUniform> programUniformsAndLocations(GLuint programId) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelpergl4.cpp b/src/render/graphicshelpers/graphicshelpergl4.cpp
index 6972864cf..26f03ac8a 100644
--- a/src/render/graphicshelpers/graphicshelpergl4.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl4.cpp
@@ -88,42 +88,42 @@ namespace Render {
namespace {
-GLbitfield memoryBarrierGLBitfield(QMemoryBarrier::BarrierTypes barriers)
+GLbitfield memoryBarrierGLBitfield(QMemoryBarrier::Operations barriers)
{
GLbitfield bits = 0;
- if (barriers.testFlag(QMemoryBarrier::AllBarrier)) {
+ if (barriers.testFlag(QMemoryBarrier::All)) {
bits |= GL_ALL_BARRIER_BITS;
return bits;
}
- if (barriers.testFlag(QMemoryBarrier::VertexAttributeArrayBarrier))
+ if (barriers.testFlag(QMemoryBarrier::VertexAttributeArray))
bits |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::ElementArrayBarrier))
+ if (barriers.testFlag(QMemoryBarrier::ElementArray))
bits |= GL_ELEMENT_ARRAY_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::UniformBarrier))
+ if (barriers.testFlag(QMemoryBarrier::Uniform))
bits |= GL_UNIFORM_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::TextureFetchBarrier))
+ if (barriers.testFlag(QMemoryBarrier::TextureFetch))
bits |= GL_TEXTURE_FETCH_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::ShaderImageAccessBarrier))
+ if (barriers.testFlag(QMemoryBarrier::ShaderImageAccess))
bits |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::CommandBarrier))
+ if (barriers.testFlag(QMemoryBarrier::Command))
bits |= GL_COMMAND_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::PixelBufferBarrier))
+ if (barriers.testFlag(QMemoryBarrier::PixelBuffer))
bits |= GL_PIXEL_BUFFER_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::TextureUpdateBarrier))
+ if (barriers.testFlag(QMemoryBarrier::TextureUpdate))
bits |= GL_TEXTURE_UPDATE_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::BufferUpdateBarrier))
+ if (barriers.testFlag(QMemoryBarrier::BufferUpdate))
bits |= GL_BUFFER_UPDATE_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::FrameBufferBarrier))
+ if (barriers.testFlag(QMemoryBarrier::FrameBuffer))
bits |= GL_FRAMEBUFFER_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::TransformFeedbackBarrier))
+ if (barriers.testFlag(QMemoryBarrier::TransformFeedback))
bits |= GL_TRANSFORM_FEEDBACK_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::AtomicCounterBarrier))
+ if (barriers.testFlag(QMemoryBarrier::AtomicCounter))
bits |= GL_ATOMIC_COUNTER_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::ShaderStorageBarrier))
+ if (barriers.testFlag(QMemoryBarrier::ShaderStorage))
bits |= GL_SHADER_STORAGE_BARRIER_BIT;
- if (barriers.testFlag(QMemoryBarrier::QueryBufferBarrier))
+ if (barriers.testFlag(QMemoryBarrier::QueryBuffer))
bits |= GL_QUERY_BUFFER_BARRIER_BIT;
return bits;
@@ -1047,7 +1047,7 @@ GLint GraphicsHelperGL4::maxClipPlaneCount()
return max;
}
-void GraphicsHelperGL4::memoryBarrier(QMemoryBarrier::BarrierTypes barriers)
+void GraphicsHelperGL4::memoryBarrier(QMemoryBarrier::Operations barriers)
{
m_funcs->glMemoryBarrier(memoryBarrierGLBitfield(barriers));
}
@@ -1128,6 +1128,16 @@ void GraphicsHelperGL4::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
m_funcs->glDispatchCompute(wx, wy, wz);
}
+char *GraphicsHelperGL4::mapBuffer(GLenum target)
+{
+ return static_cast<char*>(m_funcs->glMapBuffer(target, GL_READ_WRITE));
+}
+
+GLboolean GraphicsHelperGL4::unmapBuffer(GLenum target)
+{
+ return m_funcs->glUnmapBuffer(target);
+}
+
void GraphicsHelperGL4::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
m_funcs->glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
diff --git a/src/render/graphicshelpers/graphicshelpergl4_p.h b/src/render/graphicshelpers/graphicshelpergl4_p.h
index df4cf5dd9..6b3385838 100644
--- a/src/render/graphicshelpers/graphicshelpergl4_p.h
+++ b/src/render/graphicshelpers/graphicshelpergl4_p.h
@@ -91,6 +91,8 @@ public:
void disablei(GLenum cap, GLuint index) Q_DECL_OVERRIDE;
void disablePrimitiveRestart() Q_DECL_OVERRIDE;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) Q_DECL_OVERRIDE;
+ char *mapBuffer(GLenum target) Q_DECL_OVERRIDE;
+ GLboolean unmapBuffer(GLenum target) Q_DECL_OVERRIDE;
void drawArrays(GLenum primitiveType, GLint first, GLsizei count) Q_DECL_OVERRIDE;
void drawArraysIndirect(GLenum mode,void *indirect) Q_DECL_OVERRIDE;
void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) Q_DECL_OVERRIDE;
@@ -108,7 +110,7 @@ public:
void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) Q_DECL_OVERRIDE;
void pointSize(bool programmable, GLfloat value) Q_DECL_OVERRIDE;
GLint maxClipPlaneCount() Q_DECL_OVERRIDE;
- void memoryBarrier(QMemoryBarrier::BarrierTypes barriers) Q_DECL_OVERRIDE;
+ void memoryBarrier(QMemoryBarrier::Operations barriers) Q_DECL_OVERRIDE;
QVector<ShaderUniformBlock> programUniformBlocks(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderAttribute> programAttributesAndLocations(GLuint programId) Q_DECL_OVERRIDE;
QVector<ShaderUniform> programUniformsAndLocations(GLuint programId) Q_DECL_OVERRIDE;
diff --git a/src/render/graphicshelpers/graphicshelperinterface_p.h b/src/render/graphicshelpers/graphicshelperinterface_p.h
index 847b2fc9e..4b2569263 100644
--- a/src/render/graphicshelpers/graphicshelperinterface_p.h
+++ b/src/render/graphicshelpers/graphicshelperinterface_p.h
@@ -80,7 +80,8 @@ public:
Compute,
DrawBuffersBlend,
BlitFramebuffer,
- IndirectDrawing
+ IndirectDrawing,
+ MapBuffer
};
virtual ~GraphicsHelperInterface() {}
@@ -106,6 +107,8 @@ public:
virtual void disablei(GLenum cap, GLuint index) = 0;
virtual void disablePrimitiveRestart() = 0;
virtual void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) = 0;
+ virtual char *mapBuffer(GLenum target) = 0;
+ virtual GLboolean unmapBuffer(GLenum target) = 0;
virtual void drawArrays(GLenum primitiveType, GLint first, GLsizei count) = 0;
virtual void drawArraysIndirect(GLenum mode,void *indirect) = 0;
virtual void drawArraysInstanced(GLenum primitiveType, GLint first, GLsizei count, GLsizei instances) = 0;
@@ -122,7 +125,7 @@ public:
virtual QSize getTextureDimensions(GLuint textureId, GLenum target, uint level = 0) = 0;
virtual void initializeHelper(QOpenGLContext *context, QAbstractOpenGLFunctions *functions) = 0;
virtual GLint maxClipPlaneCount() = 0;
- virtual void memoryBarrier(QMemoryBarrier::BarrierTypes barriers) = 0;
+ virtual void memoryBarrier(QMemoryBarrier::Operations barriers) = 0;
virtual void pointSize(bool programmable, GLfloat value) = 0;
virtual QVector<ShaderAttribute> programAttributesAndLocations(GLuint programId) = 0;
virtual QVector<ShaderUniform> programUniformsAndLocations(GLuint programId) = 0;
diff --git a/src/render/io/glbuffer.cpp b/src/render/io/glbuffer.cpp
index 074868528..4918f9a56 100644
--- a/src/render/io/glbuffer.cpp
+++ b/src/render/io/glbuffer.cpp
@@ -140,6 +140,18 @@ void GLBuffer::update(GraphicsContext *ctx, const void *data, uint size, int off
ctx->openGLContext()->functions()->glBufferSubData(m_lastTarget, offset, size, data);
}
+QByteArray GLBuffer::download(GraphicsContext *ctx, uint size)
+{
+ char *gpu_ptr = ctx->mapBuffer(m_lastTarget);
+ QByteArray data;
+ if (gpu_ptr != nullptr) {
+ data.resize(size);
+ std::copy(gpu_ptr, gpu_ptr+size, data.data());
+ }
+ ctx->unmapBuffer(m_lastTarget);
+ return data;
+}
+
void GLBuffer::bindBufferBase(GraphicsContext *ctx, int bindingPoint, GLBuffer::Type t)
{
ctx->bindBufferBase(glBufferTypes[t], bindingPoint, m_bufferId);
diff --git a/src/render/io/glbuffer_p.h b/src/render/io/glbuffer_p.h
index e800d2bc4..731634b6b 100644
--- a/src/render/io/glbuffer_p.h
+++ b/src/render/io/glbuffer_p.h
@@ -53,6 +53,7 @@
#include <QOpenGLContext>
#include <Qt3DCore/qnodeid.h>
+#include <qbytearray.h>
QT_BEGIN_NAMESPACE
@@ -85,6 +86,7 @@ public:
void allocate(GraphicsContext *ctx, uint size, bool dynamic = true);
void allocate(GraphicsContext *ctx, const void *data, uint size, bool dynamic = true);
void update(GraphicsContext *ctx, const void *data, uint size, int offset = 0);
+ QByteArray download(GraphicsContext *ctx, uint size);
void bindBufferBase(GraphicsContext *ctx, int bindingPoint, Type t);
void bindBufferBase(GraphicsContext *ctx, int bindingPoint);
diff --git a/src/render/io/qgeometryloaderfactory_p.h b/src/render/io/qgeometryloaderfactory_p.h
index c6a7344ce..6e0044c4a 100644
--- a/src/render/io/qgeometryloaderfactory_p.h
+++ b/src/render/io/qgeometryloaderfactory_p.h
@@ -68,6 +68,7 @@ class QGeometryLoaderInterface;
class QT3DRENDERSHARED_PRIVATE_EXPORT QGeometryLoaderFactory : public QObject, public QFactoryInterface
{
Q_OBJECT
+ Q_INTERFACES(QFactoryInterface)
public:
explicit QGeometryLoaderFactory(QObject *parent = nullptr);
virtual ~QGeometryLoaderFactory();
diff --git a/src/render/io/qsceneimporter_p.h b/src/render/io/qsceneimporter_p.h
index e76eb8780..8f83231c3 100644
--- a/src/render/io/qsceneimporter_p.h
+++ b/src/render/io/qsceneimporter_p.h
@@ -86,7 +86,8 @@ public:
virtual ~QSceneImporter();
virtual void setSource(const QUrl &source) = 0;
- virtual bool isFileTypeSupported(const QUrl &source) const = 0;
+ virtual void setData(const QByteArray& data, const QString &basePath) = 0;
+ virtual bool areFileTypesSupported(const QStringList &extensions) const = 0;
virtual Qt3DCore::QEntity *scene(const QString &id = QString()) = 0;
virtual Qt3DCore::QEntity *node(const QString &id) = 0;
diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp
index b9408298f..3bc842c3d 100644
--- a/src/render/io/qsceneloader.cpp
+++ b/src/render/io/qsceneloader.cpp
@@ -198,7 +198,8 @@ void QSceneLoaderPrivate::populateEntityMap(QEntity *parentEntity)
{
// Topmost parent entity is not considered part of the scene as that is typically
// an unnamed entity inserted by importer.
- for (auto childNode : parentEntity->childNodes()) {
+ const QNodeVector childNodes = parentEntity->childNodes();
+ for (auto childNode : childNodes) {
auto childEntity = qobject_cast<QEntity *>(childNode);
if (childEntity) {
m_entityMap.insert(childEntity->objectName(), childEntity);
@@ -207,6 +208,17 @@ void QSceneLoaderPrivate::populateEntityMap(QEntity *parentEntity)
}
}
+void QSceneLoaderPrivate::setStatus(QSceneLoader::Status status)
+{
+ if (m_status != status) {
+ Q_Q(QSceneLoader);
+ m_status = status;
+ const bool wasBlocked = q->blockNotifications(true);
+ emit q->statusChanged(status);
+ q->blockNotifications(wasBlocked);
+ }
+}
+
/*!
The constructor creates an instance with the specified \a parent.
*/
@@ -253,7 +265,7 @@ void QSceneLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
d->populateEntityMap(d->m_subTreeRoot);
}
} else if (e->propertyName() == QByteArrayLiteral("status")) {
- setStatus(e->value().value<QSceneLoader::Status>());
+ d->setStatus(e->value().value<QSceneLoader::Status>());
}
}
}
@@ -328,7 +340,7 @@ QStringList QSceneLoader::entityNames() const
\sa Qt3DRender::QSceneLoader::ComponentType
*/
/*!
- Returns a component matching \a componentType of a loaded entity with an \a objectName matching
+ Returns a component matching \a componentType of a loaded entity with an objectName matching
the \a entityName.
If the entity has multiple matching components, the first match in the component list of
the entity is returned.
@@ -338,7 +350,8 @@ QComponent *QSceneLoader::component(const QString &entityName,
QSceneLoader::ComponentType componentType) const
{
QEntity *e = entity(entityName);
- for (auto component : e->components()) {
+ const QComponentVector components = e->components();
+ for (auto component : components) {
switch (componentType) {
case GeometryRendererComponent:
if (qobject_cast<Qt3DRender::QGeometryRenderer *>(component))
@@ -371,12 +384,7 @@ QComponent *QSceneLoader::component(const QString &entityName,
void QSceneLoader::setStatus(QSceneLoader::Status status)
{
Q_D(QSceneLoader);
- if (d->m_status != status) {
- d->m_status = status;
- const bool wasBlocked = blockNotifications(true);
- emit statusChanged(status);
- blockNotifications(wasBlocked);
- }
+ d->setStatus(status);
}
Qt3DCore::QNodeCreatedChangeBasePtr QSceneLoader::createNodeCreationChange() const
diff --git a/src/render/io/qsceneloader.h b/src/render/io/qsceneloader.h
index 76f8c4d80..31ec47ac0 100644
--- a/src/render/io/qsceneloader.h
+++ b/src/render/io/qsceneloader.h
@@ -82,10 +82,10 @@ public:
QUrl source() const;
Status status() const;
- Q_INVOKABLE Qt3DCore::QEntity *entity(const QString &entityName) const;
- Q_INVOKABLE QStringList entityNames() const;
- Q_INVOKABLE Qt3DCore::QComponent *component(const QString &entityName,
- ComponentType componentType) const;
+ Q_REVISION(9) Q_INVOKABLE Qt3DCore::QEntity *entity(const QString &entityName) const;
+ Q_REVISION(9) Q_INVOKABLE QStringList entityNames() const;
+ Q_REVISION(9) Q_INVOKABLE Qt3DCore::QComponent *component(const QString &entityName,
+ ComponentType componentType) const;
public Q_SLOTS:
void setSource(const QUrl &arg);
diff --git a/src/render/io/qsceneloader_p.h b/src/render/io/qsceneloader_p.h
index 13569ea70..45a6a1a4e 100644
--- a/src/render/io/qsceneloader_p.h
+++ b/src/render/io/qsceneloader_p.h
@@ -66,6 +66,8 @@ class QT3DRENDERSHARED_PRIVATE_EXPORT QSceneLoaderPrivate : public Qt3DCore::QCo
public:
QSceneLoaderPrivate();
+ void setStatus(QSceneLoader::Status status);
+
Q_DECLARE_PUBLIC(QSceneLoader)
void populateEntityMap(Qt3DCore::QEntity *parentEntity);
diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp
index 2057ffd3d..7ae6f9473 100644
--- a/src/render/io/scene.cpp
+++ b/src/render/io/scene.cpp
@@ -42,11 +42,11 @@
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
#include <Qt3DRender/qsceneloader.h>
#include <Qt3DRender/private/qsceneloader_p.h>
#include <Qt3DRender/private/scenemanager_p.h>
#include <QtCore/qcoreapplication.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -73,7 +73,6 @@ void Scene::setStatus(QSceneLoader::Status status)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("status");
e->setValue(QVariant::fromValue(status));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -83,7 +82,10 @@ void Scene::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change
const auto &data = typedChange->data;
m_source = data.source;
Q_ASSERT(m_sceneManager);
- m_sceneManager->addSceneData(m_source, peerId());
+ if (Qt3DCore::QDownloadHelperService::isLocal(m_source))
+ m_sceneManager->addSceneData(m_source, peerId());
+ else
+ m_sceneManager->startSceneDownload(m_source, peerId());
}
void Scene::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
@@ -92,7 +94,10 @@ void Scene::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
if (propertyChange->propertyName() == QByteArrayLiteral("source")) {
m_source = propertyChange->value().toUrl();
- m_sceneManager->addSceneData(m_source, peerId());
+ if (Qt3DCore::QDownloadHelperService::isLocal(m_source))
+ m_sceneManager->addSceneData(m_source, peerId());
+ else
+ m_sceneManager->startSceneDownload(m_source, peerId());
}
}
markDirty(AbstractRenderer::AllDirty);
@@ -116,7 +121,6 @@ void Scene::setSceneSubtree(Qt3DCore::QEntity *subTree)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("scene");
e->setValue(QVariant::fromValue(subTree));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
diff --git a/src/render/io/scenemanager.cpp b/src/render/io/scenemanager.cpp
index d59391a87..b0a595905 100644
--- a/src/render/io/scenemanager.cpp
+++ b/src/render/io/scenemanager.cpp
@@ -44,18 +44,34 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
-SceneManager::SceneManager() : Qt3DCore::QResourceManager<Scene,
- Qt3DCore::QNodeId,
- 8,
- Qt3DCore::ArrayAllocatingPolicy,
- Qt3DCore::ObjectLevelLockingPolicy>()
+SceneManager::SceneManager()
+ : Qt3DCore::QResourceManager<Scene,
+ Qt3DCore::QNodeId,
+ 8,
+ Qt3DCore::ArrayAllocatingPolicy,
+ Qt3DCore::ObjectLevelLockingPolicy>()
+ , m_service(nullptr)
{
}
-void SceneManager::addSceneData(const QUrl &source, Qt3DCore::QNodeId sceneUuid)
+SceneManager::~SceneManager()
+{
+}
+
+void SceneManager::setDownloadService(Qt3DCore::QDownloadHelperService *service)
+{
+ m_service = service;
+}
+
+void SceneManager::addSceneData(const QUrl &source,
+ Qt3DCore::QNodeId sceneUuid,
+ const QByteArray &data)
{
LoadSceneJobPtr newJob(new LoadSceneJob(source, sceneUuid));
+ if (!data.isEmpty())
+ newJob->setData(data);
+
// We cannot run two jobs that use the same scene loader plugin
// in two different threads at the same time
if (!m_pendingJobs.isEmpty())
@@ -70,6 +86,43 @@ QVector<LoadSceneJobPtr> SceneManager::pendingSceneLoaderJobs()
return std::move(m_pendingJobs);
}
+void SceneManager::startSceneDownload(const QUrl &source, Qt3DCore::QNodeId sceneUuid)
+{
+ if (!m_service)
+ return;
+ SceneDownloaderPtr request = SceneDownloaderPtr::create(source, sceneUuid, this);
+ m_pendingDownloads << request;
+ m_service->submitRequest(request);
+}
+
+void SceneManager::clearSceneDownload(SceneDownloader *downloader)
+{
+ for (auto it = m_pendingDownloads.begin(); it != m_pendingDownloads.end(); ++it) {
+ if ((*it).data() == downloader) {
+ m_pendingDownloads.erase(it);
+ return;
+ }
+ }
+}
+
+
+SceneDownloader::SceneDownloader(const QUrl &source, Qt3DCore::QNodeId sceneComponent, SceneManager *manager)
+ : Qt3DCore::QDownloadRequest(source)
+ , m_sceneComponent(sceneComponent)
+ , m_manager(manager)
+{
+
+}
+
+void SceneDownloader::onCompleted()
+{
+ if (!m_manager)
+ return;
+ if (succeeded())
+ m_manager->addSceneData(url(), m_sceneComponent, m_data);
+ m_manager->clearSceneDownload(this);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/io/scenemanager_p.h b/src/render/io/scenemanager_p.h
index 164f82590..9993c85fc 100644
--- a/src/render/io/scenemanager_p.h
+++ b/src/render/io/scenemanager_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/private/qresourcemanager_p.h>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
#include <Qt3DRender/private/scene_p.h>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DRender/private/loadscenejob_p.h>
@@ -65,6 +66,22 @@ class QEntity;
namespace Qt3DRender {
namespace Render {
+class SceneManager;
+
+class SceneDownloader : public Qt3DCore::QDownloadRequest {
+public:
+ SceneDownloader(const QUrl &source, Qt3DCore::QNodeId sceneComponent, SceneManager* manager);
+
+ void onCompleted() Q_DECL_OVERRIDE;
+
+private:
+ Qt3DCore::QNodeId m_sceneComponent;
+ SceneManager* m_manager;
+};
+
+typedef QSharedPointer<SceneDownloader> SceneDownloaderPtr;
+
+
class Q_AUTOTEST_EXPORT SceneManager : public Qt3DCore::QResourceManager<
Scene,
Qt3DCore::QNodeId,
@@ -74,12 +91,21 @@ class Q_AUTOTEST_EXPORT SceneManager : public Qt3DCore::QResourceManager<
{
public:
SceneManager();
+ ~SceneManager();
- void addSceneData(const QUrl &source, Qt3DCore::QNodeId sceneUuid);
+ void setDownloadService(Qt3DCore::QDownloadHelperService *service);
+
+ void addSceneData(const QUrl &source, Qt3DCore::QNodeId sceneUuid,
+ const QByteArray &data = QByteArray());
QVector<LoadSceneJobPtr> pendingSceneLoaderJobs();
+ void startSceneDownload(const QUrl &source, Qt3DCore::QNodeId sceneUuid);
+ void clearSceneDownload(SceneDownloader *downloader);
+
private:
+ Qt3DCore::QDownloadHelperService *m_service;
QVector<LoadSceneJobPtr> m_pendingJobs;
+ QVector<SceneDownloaderPtr> m_pendingDownloads;
};
} // namespace Render
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 9e373c655..e81836502 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -50,6 +50,7 @@
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/buffer_p.h>
#include <Qt3DRender/private/sphere_p.h>
+#include <Qt3DRender/private/buffervisitor_p.h>
#include <QtCore/qmath.h>
#include <QtConcurrent/QtConcurrent>
@@ -73,6 +74,114 @@ struct UpdateBoundFunctor {
}
};
+class BoundingVolumeCalculator
+{
+public:
+ BoundingVolumeCalculator(NodeManagers *manager) : m_manager(manager) { }
+
+ const Sphere& result() { return m_volume; }
+
+ bool apply(Qt3DRender::Render::Attribute *positionAttribute)
+ {
+ FindExtremePoints findExtremePoints(m_manager);
+ if (!findExtremePoints.apply(positionAttribute))
+ return false;
+
+ // Calculate squared distance for the pairs of points
+ const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared();
+ const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared();
+ const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared();
+
+ // Select most distant pair
+ QVector3D p = findExtremePoints.xMinPt;
+ QVector3D q = findExtremePoints.xMaxPt;
+ if (yDist2 > xDist2 && yDist2 > zDist2) {
+ p = findExtremePoints.yMinPt;
+ q = findExtremePoints.yMaxPt;
+ }
+ if (zDist2 > xDist2 && zDist2 > yDist2) {
+ p = findExtremePoints.zMinPt;
+ q = findExtremePoints.zMaxPt;
+ }
+
+ const QVector3D c = 0.5f * (p + q);
+ m_volume.setCenter(c);
+ m_volume.setRadius((q - c).length());
+
+ ExpandSphere expandSphere(m_manager, m_volume);
+ if (!expandSphere.apply(positionAttribute))
+ return false;
+
+ return true;
+ }
+
+private:
+ Sphere m_volume;
+ NodeManagers *m_manager;
+
+ class FindExtremePoints : public Buffer3fVisitor
+ {
+ public:
+ FindExtremePoints(NodeManagers *manager)
+ : Buffer3fVisitor(manager)
+ , xMin(0.0f), xMax(0.0f), yMin(0.0f), yMax(0.0f), zMin(0.0f), zMax(0.0f)
+ { }
+
+ float xMin, xMax, yMin, yMax, zMin, zMax;
+ QVector3D xMinPt, xMaxPt, yMinPt, yMaxPt, zMinPt, zMaxPt;
+
+ void visit(uint ndx, float x, float y, float z) override
+ {
+ if (ndx) {
+ if (x < xMin) {
+ xMin = x;
+ xMinPt = QVector3D(x, y, z);
+ }
+ if (x > xMax) {
+ xMax = x;
+ xMaxPt = QVector3D(x, y, z);
+ }
+ if (y < yMin) {
+ yMin = y;
+ yMinPt = QVector3D(x, y, z);
+ }
+ if (y > yMax) {
+ yMax = y;
+ yMaxPt = QVector3D(x, y, z);
+ }
+ if (z < zMin) {
+ zMin = z;
+ zMinPt = QVector3D(x, y, z);
+ }
+ if (z > zMax) {
+ zMax = z;
+ zMaxPt = QVector3D(x, y, z);
+ }
+ } else {
+ xMin = xMax = x;
+ yMin = yMax = y;
+ zMin = zMax = z;
+ xMinPt = xMaxPt = yMinPt = yMaxPt = zMinPt = zMaxPt = QVector3D(x, y, z);
+ }
+ }
+ };
+
+ class ExpandSphere : public Buffer3fVisitor
+ {
+ public:
+ ExpandSphere(NodeManagers *manager, Sphere& volume)
+ : Buffer3fVisitor(manager), m_volume(volume)
+ { }
+
+ Sphere& m_volume;
+ void visit(uint ndx, float x, float y, float z) override
+ {
+ Q_UNUSED(ndx);
+ m_volume.expandToContain(QVector3D(x, y, z));
+ }
+ };
+};
+
void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
{
// The Bounding volume will only be computed if the position Buffer
@@ -86,63 +195,48 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
Geometry *geom = manager->lookupResource<Geometry, GeometryManager>(gRenderer->geometryId());
if (geom) {
- Qt3DRender::Render::Attribute *pickVolumeAttribute = manager->lookupResource<Attribute, AttributeManager>(geom->boundingPositionAttribute());
+ Qt3DRender::Render::Attribute *positionAttribute = manager->lookupResource<Attribute, AttributeManager>(geom->boundingPositionAttribute());
// Use the default position attribute if attribute is null
- if (!pickVolumeAttribute) {
+ if (!positionAttribute) {
const auto attrIds = geom->attributes();
for (const Qt3DCore::QNodeId attrId : attrIds) {
- pickVolumeAttribute = manager->lookupResource<Attribute, AttributeManager>(attrId);
- if (pickVolumeAttribute &&
- pickVolumeAttribute->name() == QAttribute::defaultPositionAttributeName())
+ positionAttribute = manager->lookupResource<Attribute, AttributeManager>(attrId);
+ if (positionAttribute &&
+ positionAttribute->name() == QAttribute::defaultPositionAttributeName())
break;
}
}
- if (pickVolumeAttribute) {
- if (!pickVolumeAttribute
- || pickVolumeAttribute->attributeType() != QAttribute::VertexAttribute
- || pickVolumeAttribute->vertexBaseType() != QAttribute::Float
- || pickVolumeAttribute->vertexSize() < 3) {
- qWarning() << "QGeometry::boundingVolumePositionAttribute pickVolume Attribute not suited for bounding volume computation";
- return;
- }
+ if (!positionAttribute
+ || positionAttribute->attributeType() != QAttribute::VertexAttribute
+ || positionAttribute->vertexBaseType() != QAttribute::Float
+ || positionAttribute->vertexSize() < 3) {
+ qWarning() << "QGeometry::boundingVolumePositionAttribute position Attribute not suited for bounding volume computation";
+ return;
+ }
- Buffer *buf = manager->lookupResource<Buffer, BufferManager>(pickVolumeAttribute->bufferId());
- // No point in continuing if the positionAttribute doesn't have a suitable buffer
- if (!buf) {
- qWarning() << "ObjectPicker pickVolume Attribute not referencing a valid buffer";
- return;
- }
+ Buffer *buf = manager->lookupResource<Buffer, BufferManager>(positionAttribute->bufferId());
+ // No point in continuing if the positionAttribute doesn't have a suitable buffer
+ if (!buf) {
+ qWarning() << "ObjectPicker position Attribute not referencing a valid buffer";
+ return;
+ }
+
+ // Buf will be set to not dirty once it's loaded
+ // in a job executed after this one
+ // We need to recompute the bounding volume
+ // If anything in the GeometryRenderer has changed
+ if (buf->isDirty() ||
+ node->isBoundingVolumeDirty() ||
+ positionAttribute->isDirty() ||
+ geom->isDirty() ||
+ gRenderer->isDirty()) {
- // Buf will be set to not dirty once it's loaded
- // in a job executed after this one
- // We need to recompute the bounding volume
- // If anything in the GeometryRenderer has changed
- if (buf->isDirty() ||
- node->isBoundingVolumeDirty() ||
- pickVolumeAttribute->isDirty() ||
- geom->isDirty() ||
- gRenderer->isDirty()) {
-
- const QByteArray buffer = buf->data();
- const char *rawBuffer = buffer.constData();
- rawBuffer += pickVolumeAttribute->byteOffset();
- const int stride = pickVolumeAttribute->byteStride() ? pickVolumeAttribute->byteStride() : sizeof(float) * pickVolumeAttribute->vertexSize();
- QVector<QVector3D> vertices(pickVolumeAttribute->count());
-
- // TODO avoid copying the vertices
- for (int c = 0, vC = vertices.size(); c < vC; ++c) {
- QVector3D v;
- const float *fptr = reinterpret_cast<const float*>(rawBuffer);
- // TODO unwrap loop (switch?)
- for (uint i = 0, m = qMin(pickVolumeAttribute->vertexSize(), 3U); i < m; ++i)
- v[i] = fptr[i];
- vertices[c] = v;
- rawBuffer += stride;
- }
-
- node->localBoundingVolume()->initializeFromPoints(vertices);
+ BoundingVolumeCalculator reader(manager);
+ if (reader.apply(positionAttribute)) {
+ node->localBoundingVolume()->setCenter(reader.result().center());
+ node->localBoundingVolume()->setRadius(reader.result().radius());
node->unsetBoundingVolumeDirty();
}
}
diff --git a/src/render/jobs/computefilteredboundingvolumejob.cpp b/src/render/jobs/computefilteredboundingvolumejob.cpp
new file mode 100644
index 000000000..d8a7b5094
--- /dev/null
+++ b/src/render/jobs/computefilteredboundingvolumejob.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "computefilteredboundingvolumejob_p.h"
+
+#include <Qt3DRender/private/renderer_p.h>
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/renderlogging_p.h>
+#include <Qt3DRender/private/sphere_p.h>
+#include <Qt3DRender/private/job_common_p.h>
+
+#include <QThread>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+namespace {
+
+void expandWorldBoundingVolume(Qt3DRender::Render::Sphere *sphere,
+ Qt3DRender::Render::Entity *node,
+ Qt3DRender::Render::Entity *excludeSubTree)
+{
+ Qt3DRender::Render::Sphere childSphere(*node->worldBoundingVolume());
+ // Go to the nodes that have the most depth
+ const auto children = node->children();
+ for (Entity *c : children) {
+ if (c != excludeSubTree)
+ expandWorldBoundingVolume(&childSphere, c, excludeSubTree);
+ }
+ sphere->expandToContain(childSphere);
+}
+
+} // namespace
+
+ComputeFilteredBoundingVolumeJob::ComputeFilteredBoundingVolumeJob()
+ : m_root(nullptr)
+ , m_ignoreSubTree(nullptr)
+{
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0);
+}
+
+void ComputeFilteredBoundingVolumeJob::setRoot(Entity *root)
+{
+ m_root = root;
+}
+
+void ComputeFilteredBoundingVolumeJob::ignoreSubTree(Entity *node)
+{
+ m_ignoreSubTree = node;
+}
+
+void ComputeFilteredBoundingVolumeJob::run()
+{
+ qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread();
+
+ if (!m_root)
+ return;
+ if (!m_ignoreSubTree) {
+ finished(*m_root->worldBoundingVolumeWithChildren());
+ return;
+ }
+
+ bool isFilterChildOfRoot = false;
+ Entity *parent = m_ignoreSubTree->parent();
+ while (parent) {
+ if (parent == m_root) {
+ isFilterChildOfRoot = true;
+ break;
+ }
+ parent = parent->parent();
+ }
+ if (!isFilterChildOfRoot) {
+ finished(*m_root->worldBoundingVolumeWithChildren());
+ return;
+ }
+
+ Qt3DRender::Render::Sphere sphere;
+ expandWorldBoundingVolume(&sphere, m_root, m_ignoreSubTree);
+ finished(sphere);
+
+ qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
+}
+
+void ComputeFilteredBoundingVolumeJob::finished(const Qt3DRender::Render::Sphere &sphere)
+{
+ Q_UNUSED(sphere);
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/jobs/computefilteredboundingvolumejob_p.h b/src/render/jobs/computefilteredboundingvolumejob_p.h
new file mode 100644
index 000000000..d7681e604
--- /dev/null
+++ b/src/render/jobs/computefilteredboundingvolumejob_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_COMPUTEFILTEREDBOUNDINGVOLUMEJOB_H
+#define QT3DRENDER_RENDER_COMPUTEFILTEREDBOUNDINGVOLUMEJOB_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qaspectjob.h>
+#include <private/qt3drender_global_p.h>
+
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+class Entity;
+class Sphere;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT ComputeFilteredBoundingVolumeJob : public Qt3DCore::QAspectJob
+{
+public:
+ ComputeFilteredBoundingVolumeJob();
+
+ void setRoot(Entity *root);
+ void ignoreSubTree(Entity *node);
+ void run() Q_DECL_OVERRIDE;
+
+protected:
+ virtual void finished(const Qt3DRender::Render::Sphere &sphere);
+
+private:
+ Entity *m_root;
+ Entity *m_ignoreSubTree;
+};
+
+typedef QSharedPointer<ComputeFilteredBoundingVolumeJob> ComputeFilteredBoundingVolumeJobPtr;
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_COMPUTEFILTEREDBOUNDINGVOLUMEJOB_H
diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h
index 90e29d0dc..332b62547 100644
--- a/src/render/jobs/job_common_p.h
+++ b/src/render/jobs/job_common_p.h
@@ -86,9 +86,11 @@ namespace JobTypes {
UpdateWorldBoundingVolume,
FrameSubmissionPart2,
DirtyBufferGathering,
+ DirtyVaoGathering,
DirtyTextureGathering,
DirtyShaderGathering,
SendRenderCapture,
+ SendBufferCapture,
SyncRenderViewCommandBuilding,
SyncRenderViewInitialization,
SyncRenderViewCommandBuilder,
diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri
index d7f05ec4c..66c98b1c0 100644
--- a/src/render/jobs/jobs.pri
+++ b/src/render/jobs/jobs.pri
@@ -11,6 +11,7 @@ HEADERS += \
$$PWD/calcboundingvolumejob_p.h \
$$PWD/pickboundingvolumejob_p.h \
$$PWD/calcgeometrytrianglevolumes_p.h \
+ $$PWD/computefilteredboundingvolumejob_p.h \
$$PWD/job_common_p.h \
$$PWD/filterlayerentityjob_p.h \
$$PWD/filterentitybycomponentjob_p.h \
@@ -28,7 +29,8 @@ HEADERS += \
$$PWD/updatemeshtrianglelistjob_p.h \
$$PWD/pickboundingvolumeutils_p.h \
$$PWD/filtercompatibletechniquejob_p.h \
- $$PWD/updatetreeenabledjob_p.h
+ $$PWD/updatetreeenabledjob_p.h \
+ $$PWD/sendbuffercapturejob_p.h
SOURCES += \
$$PWD/updateworldtransformjob.cpp \
@@ -41,6 +43,7 @@ SOURCES += \
$$PWD/calcboundingvolumejob.cpp \
$$PWD/pickboundingvolumejob.cpp \
$$PWD/calcgeometrytrianglevolumes.cpp \
+ $$PWD/computefilteredboundingvolumejob.cpp \
$$PWD/filterlayerentityjob.cpp \
$$PWD/materialparametergathererjob.cpp \
$$PWD/renderviewbuilderjob.cpp \
@@ -55,4 +58,6 @@ SOURCES += \
$$PWD/updatelevelofdetailjob.cpp \
$$PWD/pickboundingvolumeutils.cpp \
$$PWD/filtercompatibletechniquejob.cpp \
- $$PWD/updatetreeenabledjob.cpp
+ $$PWD/updatetreeenabledjob.cpp \
+ $$PWD/sendbuffercapturejob.cpp
+
diff --git a/src/render/jobs/lightgatherer.cpp b/src/render/jobs/lightgatherer.cpp
index 39023bc35..e62544f15 100644
--- a/src/render/jobs/lightgatherer.cpp
+++ b/src/render/jobs/lightgatherer.cpp
@@ -51,6 +51,7 @@ namespace Render {
LightGatherer::LightGatherer()
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
+ , m_environmentLight(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::LightGathering, 0);
}
@@ -58,13 +59,21 @@ LightGatherer::LightGatherer()
void LightGatherer::run()
{
const QVector<HEntity> handles = m_manager->activeHandles();
+ int envLightCount = 0;
for (const HEntity handle : handles) {
Entity *node = m_manager->data(handle);
const QVector<Light *> lights = node->renderComponents<Light>();
if (!lights.isEmpty())
m_lights.push_back(LightSource(node, lights));
+ const QVector<EnvironmentLight *> envLights = node->renderComponents<EnvironmentLight>();
+ envLightCount += envLights.size();
+ if (!envLights.isEmpty() && !m_environmentLight)
+ m_environmentLight = envLights.first();
}
+
+ if (envLightCount > 1)
+ qWarning() << "More than one environment light found, extra instances are ignored";
}
} // Render
diff --git a/src/render/jobs/lightgatherer_p.h b/src/render/jobs/lightgatherer_p.h
index e2954fd07..4eaeb8f19 100644
--- a/src/render/jobs/lightgatherer_p.h
+++ b/src/render/jobs/lightgatherer_p.h
@@ -61,6 +61,7 @@ namespace Qt3DRender {
namespace Render {
class EntityManager;
+class EnvironmentLight;
class Q_AUTOTEST_EXPORT LightGatherer : public Qt3DCore::QAspectJob
{
@@ -69,12 +70,19 @@ public:
inline void setManager(EntityManager *manager) Q_DECL_NOTHROW { m_manager = manager; }
inline QVector<LightSource> &lights() { return m_lights; }
+ inline EnvironmentLight *takeEnvironmentLight()
+ {
+ auto envLight = m_environmentLight;
+ m_environmentLight = nullptr;
+ return envLight;
+ }
void run() Q_DECL_FINAL;
private:
EntityManager *m_manager;
QVector<LightSource> m_lights;
+ EnvironmentLight *m_environmentLight;
};
typedef QSharedPointer<LightGatherer> LightGathererPtr;
diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp
index 9b3374627..3d6326e93 100644
--- a/src/render/jobs/loadscenejob.cpp
+++ b/src/render/jobs/loadscenejob.cpp
@@ -44,6 +44,7 @@
#include <Qt3DCore/qentity.h>
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/qsceneimporter_p.h>
+#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DRender/qsceneloader.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +61,11 @@ LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId m_sceneComponen
SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0);
}
+void LoadSceneJob::setData(const QByteArray &data)
+{
+ m_data = data;
+}
+
NodeManagers *LoadSceneJob::nodeManagers() const
{
return m_managers;
@@ -95,20 +101,54 @@ void LoadSceneJob::run()
// Perform the loading only if the source wasn't explicitly set to empty
if (!m_source.isEmpty()) {
finalStatus = QSceneLoader::Error;
- for (QSceneImporter *sceneImporter : qAsConst(m_sceneImporters)) {
- if (!sceneImporter->isFileTypeSupported(m_source))
- continue;
-
- // If the file type is supported -> enter Loading status
- scene->setStatus(QSceneLoader::Loading);
-
- // File type is supported, try to load it
- sceneImporter->setSource(m_source);
- sceneSubTree = sceneImporter->scene();
- if (sceneSubTree != nullptr) {
- // Successfully built a subtree
- finalStatus = QSceneLoader::Ready;
- break;
+
+ if (m_data.isEmpty()) {
+ const QString path = QUrlHelper::urlToLocalFileOrQrc(m_source);
+ QFileInfo finfo(path);
+ if (finfo.exists()) {
+ QStringList extensions(finfo.suffix());
+
+ for (QSceneImporter *sceneImporter : qAsConst(m_sceneImporters)) {
+ if (!sceneImporter->areFileTypesSupported(extensions))
+ continue;
+
+ // If the file type is supported -> enter Loading status
+ scene->setStatus(QSceneLoader::Loading);
+
+ // File type is supported, try to load it
+ sceneImporter->setSource(m_source);
+ sceneSubTree = sceneImporter->scene();
+ if (sceneSubTree != nullptr) {
+ // Successfully built a subtree
+ finalStatus = QSceneLoader::Ready;
+ break;
+ }
+ }
+ }
+ } else {
+ QStringList extensions;
+ QMimeDatabase db;
+ QMimeType mtype = db.mimeTypeForData(m_data);
+ if (mtype.isValid()) {
+ extensions = mtype.suffixes();
+ }
+
+ QString basePath = m_source.adjusted(QUrl::RemoveFilename).toString();
+ for (QSceneImporter *sceneImporter : qAsConst(m_sceneImporters)) {
+ if (!sceneImporter->areFileTypesSupported(extensions))
+ continue;
+
+ // If the file type is supported -> enter Loading status
+ scene->setStatus(QSceneLoader::Loading);
+
+ // File type is supported, try to load it
+ sceneImporter->setData(m_data, basePath);
+ sceneSubTree = sceneImporter->scene();
+ if (sceneSubTree != nullptr) {
+ // Successfully built a subtree
+ finalStatus = QSceneLoader::Ready;
+ break;
+ }
}
}
}
diff --git a/src/render/jobs/loadscenejob_p.h b/src/render/jobs/loadscenejob_p.h
index 7538c6eb0..5217c6f43 100644
--- a/src/render/jobs/loadscenejob_p.h
+++ b/src/render/jobs/loadscenejob_p.h
@@ -70,6 +70,7 @@ class Q_AUTOTEST_EXPORT LoadSceneJob : public Qt3DCore::QAspectJob
{
public:
explicit LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent);
+ void setData(const QByteArray &data);
void setNodeManagers(NodeManagers *managers) { m_managers = managers; }
void setSceneImporters(const QList<QSceneImporter *> sceneImporters) { m_sceneImporters = sceneImporters; }
@@ -82,6 +83,7 @@ public:
private:
QUrl m_source;
+ QByteArray m_data;
Qt3DCore::QNodeId m_sceneComponent;
NodeManagers *m_managers;
QList<QSceneImporter *> m_sceneImporters;
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index 6b8b93647..f9c7a390c 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -49,6 +49,7 @@
#include <Qt3DRender/private/rendersettings_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DRender/private/qpickevent_p.h>
QT_BEGIN_NAMESPACE
@@ -59,6 +60,8 @@ namespace Render {
namespace {
+typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList;
+
void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers)
{
switch (event.button()) {
@@ -120,6 +123,11 @@ void PickBoundingVolumeJob::setMouseEvents(const QList<QMouseEvent> &pendingEven
m_pendingMouseEvents = pendingEvents;
}
+void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
+{
+ m_pendingKeyEvents = pendingEvents;
+}
+
void PickBoundingVolumeJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot)
{
m_frameGraphRoot = frameGraphRoot;
@@ -159,7 +167,8 @@ bool PickBoundingVolumeJob::runHelper()
m_oneEnabledAtLeast = false;
m_oneHoverAtLeast = false;
- for (auto handle : m_manager->objectPickerManager()->activeHandles()) {
+ const auto activeHandles = m_manager->objectPickerManager()->activeHandles();
+ for (auto handle : activeHandles) {
auto picker = m_manager->objectPickerManager()->data(handle);
m_oneEnabledAtLeast |= picker->isEnabled();
m_oneHoverAtLeast |= picker->isHoverEnabled();
@@ -214,11 +223,6 @@ bool PickBoundingVolumeJob::runHelper()
// If we have move or hover move events that someone cares about, we try to avoid expensive computations
// by compressing them into a single one
- // Gather the entities for the frame
- // TO DO: We could skip doing that every frame and only do it when we know for sure
- // that the tree structure has changed
- PickingUtils::EntityGatherer entitiesGatherer(m_node);
-
// Store the reducer function which varies depending on the picking settings set on the renderer
using ReducerFunction = PickingUtils::CollisionVisitor::HitList (*)(PickingUtils::CollisionVisitor::HitList &results, const PickingUtils::CollisionVisitor::HitList &intermediate);
@@ -244,25 +248,30 @@ bool PickBoundingVolumeJob::runHelper()
// For each triplet of Viewport / Camera and Area
for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) {
- typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList;
HitList sphereHits;
QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId);
- if (trianglePickingRequested) {
- PickingUtils::TriangleCollisionGathererFunctor gathererFunctor;
- gathererFunctor.m_frontFaceRequested = frontFaceRequested;
- gathererFunctor.m_backFaceRequested = backFaceRequested;
- gathererFunctor.m_manager = m_manager;
- gathererFunctor.m_ray = ray;
- sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entitiesGatherer.entities(), gathererFunctor, reducerOp);
- } else {
- PickingUtils::EntityCollisionGathererFunctor gathererFunctor;
- gathererFunctor.m_manager = m_manager;
- gathererFunctor.m_ray = ray;
- sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entitiesGatherer.entities(), gathererFunctor, reducerOp);
+
+ PickingUtils::HierarchicalEntityPicker entityPicker(ray);
+ if (entityPicker.collectHits(m_node)) {
+ if (trianglePickingRequested) {
+ PickingUtils::TriangleCollisionGathererFunctor gathererFunctor;
+ gathererFunctor.m_frontFaceRequested = frontFaceRequested;
+ gathererFunctor.m_backFaceRequested = backFaceRequested;
+ gathererFunctor.m_manager = m_manager;
+ gathererFunctor.m_ray = ray;
+ sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entityPicker.entities(),
+ gathererFunctor, reducerOp);
+ } else {
+ sphereHits = entityPicker.hits();
+ PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits);
+ if (!allHitsRequested)
+ sphereHits = { sphereHits.front() };
+ }
}
// Dispatch events based on hit results
- dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, trianglePickingRequested, allHitsRequested);
+ dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers,
+ trianglePickingRequested, allHitsRequested);
}
}
@@ -331,17 +340,18 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
// Send the corresponding event
QVector3D localIntersection = hit.m_intersection;
if (entity && entity->worldTransform())
- localIntersection = hit.m_intersection * entity->worldTransform()->inverted();
+ localIntersection = entity->worldTransform()->inverted() * hit.m_intersection;
QPickEventPtr pickEvent;
- if (trianglePickingRequested)
+ if (trianglePickingRequested) {
pickEvent.reset(new QPickTriangleEvent(event.localPos(), hit.m_intersection, localIntersection, hit.m_distance,
hit.m_triangleIndex, hit.m_vertexIndex[0], hit.m_vertexIndex[1], hit.m_vertexIndex[2],
- eventButton, eventButtons, eventModifiers));
- else
+ eventButton, eventButtons, eventModifiers, hit.m_uvw));
+ QPickEventPrivate::get(pickEvent.data())->m_entity = hit.m_entityId;
+ } else {
pickEvent.reset(new QPickEvent(event.localPos(), hit.m_intersection, localIntersection, hit.m_distance,
eventButton, eventButtons, eventModifiers));
-
+ }
switch (event.type()) {
case QEvent::MouseButtonPress: {
// Store pressed object handle
@@ -352,24 +362,23 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
}
case QEvent::MouseButtonRelease: {
- if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle)
- m_currentPicker = HObjectPicker();
// Only send the release event if it was pressed
- if (objectPicker->isPressed()) {
- if (lastCurrentPicker == objectPicker)
- objectPicker->onClicked(pickEvent);
+ if (objectPicker->isPressed())
objectPicker->onReleased(pickEvent);
+ if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) {
+ objectPicker->onClicked(pickEvent);
+ m_currentPicker = HObjectPicker();
}
break;
}
-
+#if QT_CONFIG(gestures)
case Qt::TapGesture: {
objectPicker->onClicked(pickEvent);
break;
}
-
+#endif
case QEvent::MouseMove: {
- if (objectPicker->isPressed() && objectPicker->isDragEnabled()) {
+ if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) {
objectPicker->onMoved(pickEvent);
}
// fallthrough
diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h
index 9f52943d1..5239c5c6c 100644
--- a/src/render/jobs/pickboundingvolumejob_p.h
+++ b/src/render/jobs/pickboundingvolumejob_p.h
@@ -59,6 +59,7 @@
#include <Qt3DRender/private/pickboundingvolumeutils_p.h>
#include <Qt3DRender/qpickevent.h>
#include <QMouseEvent>
+#include <QKeyEvent>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -82,6 +83,7 @@ public:
void setRoot(Entity *root);
void setMouseEvents(const QList<QMouseEvent> &pendingEvents);
+ void setKeyEvents(const QList<QKeyEvent> &pendingEvents);
void setFrameGraphRoot(FrameGraphNode *frameGraphRoot);
void setRenderSettings(RenderSettings *settings);
void setManagers(NodeManagers *manager);
@@ -102,8 +104,10 @@ protected:
void run() Q_DECL_FINAL;
void dispatchPickEvents(const QMouseEvent &event, const PickingUtils::CollisionVisitor::HitList &sphereHits,
QPickEvent::Buttons eventButton,
- int eventButtons, int eventModifiers,
- bool trianglePickingRequested, bool allHitsRequested);
+ int eventButtons,
+ int eventModifiers,
+ bool trianglePickingRequested,
+ bool allHitsRequested);
private:
NodeManagers *m_manager;
@@ -115,6 +119,8 @@ private:
bool m_oneEnabledAtLeast;
bool m_oneHoverAtLeast;
+ QList<QKeyEvent> m_pendingKeyEvents;
+
void viewMatrixForCamera(Qt3DCore::QNodeId cameraId,
QMatrix4x4 &viewMatrix,
QMatrix4x4 &projectionMatrix) const;
diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp
index 1573aa112..f08398a5a 100644
--- a/src/render/jobs/pickboundingvolumeutils.cpp
+++ b/src/render/jobs/pickboundingvolumeutils.cpp
@@ -175,6 +175,7 @@ bool CollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a,
queryResult.m_vertexIndex[0] = andx;
queryResult.m_vertexIndex[1] = bndx;
queryResult.m_vertexIndex[2] = cndx;
+ queryResult.m_uvw = uvw;
queryResult.m_intersection = m_ray.point(t * m_ray.distance());
queryResult.m_distance = m_ray.projectedDistance(queryResult.m_intersection);
hits.push_back(queryResult);
@@ -212,6 +213,15 @@ AbstractCollisionGathererFunctor::result_type AbstractCollisionGathererFunctor::
return pick(&rayCasting, entity);
}
+void AbstractCollisionGathererFunctor::sortHits(CollisionVisitor::HitList &results)
+{
+ auto compareHitsDistance = [](const CollisionVisitor::HitList::value_type &a,
+ const CollisionVisitor::HitList::value_type &b) {
+ return a.m_distance < b.m_distance;
+ };
+ std::sort(results.begin(), results.end(), compareHitsDistance);
+}
+
AbstractCollisionGathererFunctor::result_type EntityCollisionGathererFunctor::pick(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const
{
result_type result;
@@ -236,14 +246,7 @@ AbstractCollisionGathererFunctor::result_type TriangleCollisionGathererFunctor::
visitor.apply(gRenderer, entity->peerId());
result = visitor.hits;
- struct
- {
- bool operator()(const result_type::value_type &a, const result_type::value_type &b)
- {
- return a.m_distance < b.m_distance;
- }
- } compareHitsDistance;
- std::sort(result.begin(), result.end(), compareHitsDistance);
+ sortHits(result);
}
return result;
@@ -281,6 +284,44 @@ CollisionVisitor::HitList reduceToAllHits(CollisionVisitor::HitList &results, co
return results;
}
+HierarchicalEntityPicker::HierarchicalEntityPicker(const QRay3D &ray)
+ : m_ray(ray)
+{
+
+}
+
+bool HierarchicalEntityPicker::collectHits(Entity *root)
+{
+ m_hits.clear();
+ m_entities.clear();
+
+ QRayCastingService rayCasting;
+ QVector<Entity *> worklist;
+ worklist << root;
+
+ while (!worklist.empty()) {
+ Entity *current = worklist.takeLast();
+
+ // first pick entry sub-scene-graph
+ QCollisionQueryResult::Hit queryResult =
+ rayCasting.query(m_ray, current->worldBoundingVolumeWithChildren());
+ if (queryResult.m_distance < 0.f)
+ continue;
+
+ // if we get a hit, we check again for this specific entity
+ queryResult = rayCasting.query(m_ray, current->worldBoundingVolume());
+ if (queryResult.m_distance >= 0.f) {
+ m_entities.push_back(current);
+ m_hits.push_back(queryResult);
+ }
+
+ // and pick children
+ worklist << current->children();
+ }
+
+ return !m_hits.empty();
+}
+
} // PickingUtils
} // Render
diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h
index 0a65c58cc..08615c094 100644
--- a/src/render/jobs/pickboundingvolumeutils_p.h
+++ b/src/render/jobs/pickboundingvolumeutils_p.h
@@ -136,6 +136,21 @@ private:
uint cndx, const QVector3D &c);
};
+class Q_AUTOTEST_EXPORT HierarchicalEntityPicker
+{
+public:
+ explicit HierarchicalEntityPicker(const RayCasting::QRay3D &ray);
+
+ bool collectHits(Entity *root);
+ inline CollisionVisitor::HitList hits() const { return m_hits; }
+ inline QVector<Entity *> entities() const { return m_entities; }
+
+private:
+ RayCasting::QRay3D m_ray;
+ CollisionVisitor::HitList m_hits;
+ QVector<Entity *> m_entities;
+};
+
struct Q_AUTOTEST_EXPORT AbstractCollisionGathererFunctor
{
AbstractCollisionGathererFunctor();
@@ -148,6 +163,8 @@ struct Q_AUTOTEST_EXPORT AbstractCollisionGathererFunctor
typedef CollisionVisitor::HitList result_type;
result_type operator ()(const Entity *entity) const;
virtual result_type pick(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const = 0;
+
+ static void sortHits(CollisionVisitor::HitList &results);
};
struct Q_AUTOTEST_EXPORT EntityCollisionGathererFunctor : public AbstractCollisionGathererFunctor
diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp
index e587dd828..9f1b51cc1 100644
--- a/src/render/jobs/renderviewjobutils.cpp
+++ b/src/render/jobs/renderviewjobutils.cpp
@@ -63,6 +63,7 @@
#include <Qt3DRender/private/dispatchcompute_p.h>
#include <Qt3DRender/private/rendersurfaceselector_p.h>
#include <Qt3DRender/private/rendercapture_p.h>
+#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <Qt3DRender/private/techniquemanager_p.h>
#include <Qt3DRender/private/memorybarrier_p.h>
@@ -164,6 +165,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
// a subregion relative to that of the parent viewport
const ViewportNode *vpNode = static_cast<const ViewportNode *>(node);
rv->setViewport(computeViewport(rv->viewport(), vpNode));
+ rv->setGamma(vpNode->gamma());
break;
}
@@ -238,7 +240,15 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
case FrameGraphNode::MemoryBarrier: {
const Render::MemoryBarrier *barrier = static_cast<const Render::MemoryBarrier *>(node);
- rv->setMemoryBarrier(barrier->barrierTypes()|rv->memoryBarrier());
+ rv->setMemoryBarrier(barrier->waitOperations()|rv->memoryBarrier());
+ break;
+ }
+
+ case FrameGraphNode::BufferCapture: {
+ auto *bufferCapture = const_cast<Render::BufferCapture *>(
+ static_cast<const Render::BufferCapture *>(node));
+ if (bufferCapture != nullptr)
+ rv->setIsDownloadBuffersEnable(bufferCapture->isEnabled());
break;
}
@@ -404,7 +414,9 @@ const int qNodeIdTypeId = qMetaTypeId<QNodeId>();
}
UniformBlockValueBuilder::UniformBlockValueBuilder()
- : shaderDataManager(nullptr)
+ : updatedPropertiesOnly(false)
+ , shaderDataManager(nullptr)
+ , textureManager(nullptr)
{
}
@@ -420,12 +432,16 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
QVariantList list = value.value<QVariantList>();
if (list.at(0).userType() == qNodeIdTypeId) { // Array of struct qmlPropertyName[i].structMember
for (int i = 0; i < list.size(); ++i) {
+ const QVariant variantElement = list.at(i);
if (list.at(i).userType() == qNodeIdTypeId) {
- ShaderData *subShaderData = shaderDataManager->lookupResource(list.at(i).value<QNodeId>());
- if (subShaderData)
+ const auto nodeId = variantElement.value<QNodeId>();
+ ShaderData *subShaderData = shaderDataManager->lookupResource(nodeId);
+ if (subShaderData) {
buildActiveUniformNameValueMapStructHelper(subShaderData,
blockName + QLatin1Char('.') + qmlPropertyName + blockArray.arg(i),
QLatin1String(""));
+ }
+ // Note: we only handle ShaderData as nested container nodes here
}
}
} else { // Array of scalar/vec qmlPropertyName[0]
@@ -436,11 +452,16 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
}
}
} else if (value.userType() == qNodeIdTypeId) { // Struct qmlPropertyName.structMember
- ShaderData *rSubShaderData = shaderDataManager->lookupResource(value.value<QNodeId>());
- if (rSubShaderData)
+ const auto nodeId = value.value<QNodeId>();
+ ShaderData *rSubShaderData = shaderDataManager->lookupResource(nodeId);
+ if (rSubShaderData) {
buildActiveUniformNameValueMapStructHelper(rSubShaderData,
blockName,
qmlPropertyName);
+ } else if (textureManager->contains(nodeId)) {
+ const auto varId = StringToInt::lookupId(blockName + QLatin1Char('.') + qmlPropertyName);
+ activeUniformNamesToValue.insert(varId, value);
+ }
} else { // Scalar / Vec
QString varName = blockName + QLatin1Char('.') + qmlPropertyName;
if (uniforms.contains(varName)) {
diff --git a/src/render/jobs/renderviewjobutils_p.h b/src/render/jobs/renderviewjobutils_p.h
index bc042a582..c1d37b28a 100644
--- a/src/render/jobs/renderviewjobutils_p.h
+++ b/src/render/jobs/renderviewjobutils_p.h
@@ -83,6 +83,7 @@ class NodeManagers;
class ShaderDataManager;
struct ShaderUniform;
class ShaderData;
+class TextureManager;
class RenderStateManager;
class RenderStateCollection;
@@ -169,6 +170,7 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder
QHash<QString, ShaderUniform> uniforms;
UniformBlockValueBuilderHash activeUniformNamesToValue;
ShaderDataManager *shaderDataManager;
+ TextureManager *textureManager;
QMatrix4x4 viewMatrix;
};
diff --git a/src/render/framegraph/qsortcriterion.h b/src/render/jobs/sendbuffercapturejob.cpp
index 230f111f9..7829931f7 100644
--- a/src/render/framegraph/qsortcriterion.h
+++ b/src/render/jobs/sendbuffercapturejob.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2017 Juan José Casafranca
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,49 +37,53 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_QSORTCRITERION_H
-#define QT3DRENDER_QSORTCRITERION_H
+#include "sendbuffercapturejob_p.h"
-#include <Qt3DCore/qnode.h>
-#include <Qt3DRender/qt3drender_global.h>
+
+#include "Qt3DRender/private/renderer_p.h"
+#include "Qt3DRender/private/nodemanagers_p.h"
+#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DRender/private/buffer_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QSortCriterionPrivate;
+namespace Render {
-class QT3DRENDERSHARED_EXPORT QSortCriterion : public Qt3DCore::QNode
+SendBufferCaptureJob::SendBufferCaptureJob()
+ : Qt3DCore::QAspectJob()
{
- Q_OBJECT
- Q_PROPERTY(Qt3DRender::QSortCriterion::SortType sort READ sort WRITE setSort NOTIFY sortChanged)
-public:
- explicit QSortCriterion(Qt3DCore::QNode *parent = Q_NULLPTR);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0);
+}
- enum SortType {
- StateChangeCost = (1 << 0),
- BackToFront = (1 << 1),
- Material = (1 << 2)
- };
- Q_ENUM(SortType) // LCOV_EXCL_LINE
+SendBufferCaptureJob::~SendBufferCaptureJob()
+{
+}
- SortType sort() const;
+void SendBufferCaptureJob::setManagers(NodeManagers *managers)
+{
+ m_managers = managers;
+}
-public Q_SLOTS:
- void setSort(SortType sort);
+void SendBufferCaptureJob::addRequest(QPair<Buffer *, QByteArray> request)
+{
+ QMutexLocker locker(&m_mutex);
+ m_pendingSendBufferCaptures.push_back(request);
+}
-Q_SIGNALS:
- void sortChanged(SortType sort);
+void SendBufferCaptureJob::run()
+{
+ QMutexLocker locker(&m_mutex);
+ for (const QPair<Buffer*, QByteArray> &pendingCapture : qAsConst(m_pendingSendBufferCaptures)) {
+ pendingCapture.first->updateDataFromGPUToCPU(pendingCapture.second);
+ }
-protected:
- QSortCriterion(QSortCriterionPrivate &dd, Qt3DCore::QNode *parent = Q_NULLPTR);
+ m_pendingSendBufferCaptures.clear();
+}
-private:
- Q_DECLARE_PRIVATE(QSortCriterion)
-};
+} // Render
-} // namespace Qt3DRender
+} // Qt3DRender
QT_END_NAMESPACE
-
-#endif // QSORTCRITERION_H
diff --git a/src/render/jobs/sendbuffercapturejob_p.h b/src/render/jobs/sendbuffercapturejob_p.h
new file mode 100644
index 000000000..d01ecec72
--- /dev/null
+++ b/src/render/jobs/sendbuffercapturejob_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Juan José Casafranca
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_SENDBUFFERCAPTUREJOB_P_H
+#define QT3DRENDER_SENDBUFFERCAPTUREJOB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DRender/qt3drender_global.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <QMutex>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class NodeManagers;
+class Entity;
+class Renderer;
+class Buffer;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT SendBufferCaptureJob : public Qt3DCore::QAspectJob
+{
+public:
+ explicit SendBufferCaptureJob();
+ ~SendBufferCaptureJob();
+
+ void setManagers(NodeManagers *managers);
+
+ void addRequest(QPair<Buffer*, QByteArray> request);
+
+ void run() Q_DECL_FINAL;
+
+private:
+ NodeManagers *m_managers;
+ QMutex m_mutex;
+
+ QVector<QPair<Buffer*, QByteArray> > m_pendingSendBufferCaptures;
+};
+
+typedef QSharedPointer<SendBufferCaptureJob> SendBufferCaptureJobPtr;
+
+} //Render
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
+
+
+#endif // QT3DRENDER_SENDBUFFERCAPTUREJOB_P_H
diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp
index 940d26850..24891f9b8 100644
--- a/src/render/jobs/updatelevelofdetailjob.cpp
+++ b/src/render/jobs/updatelevelofdetailjob.cpp
@@ -135,10 +135,10 @@ void UpdateLevelOfDetailJob::updateEntityLod(Entity *entity)
if (lod->isEnabled() && !lod->thresholds().isEmpty()) {
switch (lod->thresholdType()) {
- case QLevelOfDetail::DistanceToCamera:
+ case QLevelOfDetail::DistanceToCameraThreshold:
updateEntityLodByDistance(entity, lod);
break;
- case QLevelOfDetail::ProjectedScreenPixelSize:
+ case QLevelOfDetail::ProjectedScreenPixelSizeThreshold:
updateEntityLodByScreenArea(entity, lod);
break;
default:
@@ -162,7 +162,7 @@ void UpdateLevelOfDetailJob::updateEntityLodByDistance(Entity *entity, LevelOfDe
const QVector<qreal> thresholds = lod->thresholds();
QVector3D center = lod->center();
- if (lod->radius() > 0.f || entity->worldBoundingVolume() == nullptr) {
+ if (lod->hasBoundingVolumeOverride() || entity->worldBoundingVolume() == nullptr) {
center = *entity->worldTransform() * center;
} else {
center = entity->worldBoundingVolume()->center();
@@ -198,7 +198,7 @@ void UpdateLevelOfDetailJob::updateEntityLodByScreenArea(Entity *entity, LevelOf
const QVector<qreal> thresholds = lod->thresholds();
Sphere bv(lod->center(), lod->radius());
- if (lod->radius() <= 0.f && entity->worldBoundingVolume() != nullptr) {
+ if (!lod->hasBoundingVolumeOverride() && entity->worldBoundingVolume() != nullptr) {
bv = *(entity->worldBoundingVolume());
} else {
bv.transform(*entity->worldTransform());
diff --git a/src/render/framegraph/qsortcriterion.cpp b/src/render/lights/environmentlight.cpp
index f5252b1f7..d4245fb6e 100644
--- a/src/render/framegraph/qsortcriterion.cpp
+++ b/src/render/lights/environmentlight.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,46 +37,30 @@
**
****************************************************************************/
-#include "qsortcriterion.h"
-#include "qsortcriterion_p.h"
-#include <Qt3DCore/qnodepropertychange.h>
+#include "environmentlight_p.h"
+#include "qenvironmentlight.h"
+#include "qenvironmentlight_p.h"
QT_BEGIN_NAMESPACE
-namespace Qt3DRender {
-
-QSortCriterionPrivate::QSortCriterionPrivate()
- : QNodePrivate()
- , m_sort(QSortCriterion::StateChangeCost)
-{
-}
-
-QSortCriterion::QSortCriterion(QNode *parent)
- : QNode(*new QSortCriterionPrivate, parent)
-{
-}
+using namespace Qt3DCore;
-QSortCriterion::SortType QSortCriterion::sort() const
-{
- Q_D(const QSortCriterion);
- return d->m_sort;
-}
+namespace Qt3DRender {
+namespace Render {
-void QSortCriterion::setSort(QSortCriterion::SortType sort)
+QNodeId EnvironmentLight::shaderData() const
{
- Q_D(QSortCriterion);
- if (d->m_sort != sort) {
- d->m_sort = sort;
- emit sortChanged(sort);
- }
+ return m_shaderDataId;
}
-/*! \internal */
-QSortCriterion::QSortCriterion(QSortCriterionPrivate &dd, QNode *parent)
- : QNode(dd, parent)
+void EnvironmentLight::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
{
+ const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEnvironmentLightData>>(change);
+ const auto &data = typedChange->data;
+ m_shaderDataId = data.shaderDataId;
}
+} // namespace Render
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/lights/environmentlight_p.h b/src/render/lights/environmentlight_p.h
new file mode 100644
index 000000000..2ebe72b12
--- /dev/null
+++ b/src/render/lights/environmentlight_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_ENVIRONMENTLIGHT_P_H
+#define QT3DRENDER_RENDER_ENVIRONMENTLIGHT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/backendnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class Q_AUTOTEST_EXPORT EnvironmentLight : public BackendNode
+{
+public:
+ Qt3DCore::QNodeId shaderData() const;
+
+private:
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+
+ Qt3DCore::QNodeId m_shaderDataId;
+};
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::Render::EnvironmentLight*) // LCOV_EXCL_LINE
+
+#endif // QT3DRENDER_RENDER_ENVIRONMENTLIGHT_P_H
diff --git a/src/render/lights/lights.pri b/src/render/lights/lights.pri
index 408253d74..dbaa4352f 100644
--- a/src/render/lights/lights.pri
+++ b/src/render/lights/lights.pri
@@ -5,17 +5,22 @@ HEADERS += \
$$PWD/qabstractlight_p.h \
$$PWD/qdirectionallight.h \
$$PWD/qdirectionallight_p.h \
+ $$PWD/qenvironmentlight.h \
+ $$PWD/qenvironmentlight_p.h \
$$PWD/qpointlight.h \
$$PWD/qpointlight_p.h \
$$PWD/qspotlight.h \
$$PWD/qspotlight_p.h \
+ $$PWD/environmentlight_p.h \
$$PWD/light_p.h \
$$PWD/lightsource_p.h
SOURCES += \
$$PWD/qabstractlight.cpp \
$$PWD/qdirectionallight.cpp \
+ $$PWD/qenvironmentlight.cpp \
$$PWD/qpointlight.cpp \
$$PWD/qspotlight.cpp \
+ $$PWD/environmentlight.cpp \
$$PWD/light.cpp \
$$PWD/lightsource.cpp
diff --git a/src/render/lights/qenvironmentlight.cpp b/src/render/lights/qenvironmentlight.cpp
new file mode 100644
index 000000000..a094af7b2
--- /dev/null
+++ b/src/render/lights/qenvironmentlight.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qenvironmentlight.h"
+#include "qenvironmentlight_p.h"
+#include "qabstracttexture.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+/*!
+ * \qmltype EnvironmentLight
+ * \inqmlmodule Qt3D.Render
+ * \instantiates Qt3DRender::QEnvironmentLight
+ * \brief Encapsulate an environment light object in a Qt 3D scene.
+ * \since 5.9
+ */
+
+QEnvironmentLightPrivate::QEnvironmentLightPrivate()
+ : m_shaderData(new QShaderData)
+ , m_irradiance(nullptr)
+ , m_specular(nullptr)
+{
+}
+
+QEnvironmentLightPrivate::~QEnvironmentLightPrivate()
+{
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QEnvironmentLight::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QEnvironmentLightData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QEnvironmentLight);
+ data.shaderDataId = qIdForNode(d->m_shaderData);
+ return creationChange;
+}
+
+/*!
+ \class Qt3DRender::QEnvironmentLight
+ \inmodule Qt3DRender
+ \brief Encapsulate an environment light object in a Qt 3D scene.
+ \since 5.9
+*/
+
+QEnvironmentLight::QEnvironmentLight(Qt3DCore::QNode *parent)
+ : QComponent(*new QEnvironmentLightPrivate, parent)
+{
+ Q_D(QEnvironmentLight);
+ d->m_shaderData->setParent(this);
+}
+
+/*! \internal */
+QEnvironmentLight::QEnvironmentLight(QEnvironmentLightPrivate &dd, QNode *parent)
+ : QComponent(dd, parent)
+{
+ Q_D(QEnvironmentLight);
+ d->m_shaderData->setParent(this);
+}
+
+QEnvironmentLight::~QEnvironmentLight()
+{
+}
+
+/*!
+ \qmlproperty Texture EnvironmentLight::irradiance
+
+ Holds the current environment irradiance map texture.
+
+ By default, the environment irradiance texture is null.
+*/
+
+/*!
+ \property QEnvironmentLight::irradiance
+
+ Holds the current environment irradiance map texture.
+
+ By default, the environment irradiance texture is null.
+*/
+QAbstractTexture *QEnvironmentLight::irradiance() const
+{
+ Q_D(const QEnvironmentLight);
+ return d->m_irradiance;
+}
+
+/*!
+ \qmlproperty Texture EnvironmentLight::specular
+
+ Holds the current environment specular map texture.
+
+ By default, the environment specular texture is null.
+*/
+
+/*!
+ \property QEnvironmentLight::specular
+
+ Holds the current environment specular map texture.
+
+ By default, the environment specular texture is null.
+*/
+QAbstractTexture *QEnvironmentLight::specular() const
+{
+ Q_D(const QEnvironmentLight);
+ return d->m_specular;
+}
+
+void QEnvironmentLight::setIrradiance(QAbstractTexture *i)
+{
+ Q_D(QEnvironmentLight);
+ if (irradiance() == i)
+ return;
+
+ if (irradiance())
+ d->unregisterDestructionHelper(irradiance());
+
+ if (i && !i->parent())
+ i->setParent(this);
+
+ d->m_irradiance = i;
+ d->m_shaderData->setProperty("irradiance", QVariant::fromValue(i));
+
+ if (i)
+ d->registerDestructionHelper(i, &QEnvironmentLight::setIrradiance, i);
+
+ emit irradianceChanged(i);
+}
+
+void QEnvironmentLight::setSpecular(QAbstractTexture *s)
+{
+ Q_D(QEnvironmentLight);
+ if (specular() == s)
+ return;
+
+ if (irradiance())
+ d->unregisterDestructionHelper(specular());
+
+ if (s && !s->parent())
+ s->setParent(this);
+
+ d->m_specular = s;
+ d->m_shaderData->setProperty("specular", QVariant::fromValue(s));
+
+ if (s)
+ d->registerDestructionHelper(s, &QEnvironmentLight::setSpecular, s);
+
+ emit specularChanged(s);
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/lights/qenvironmentlight.h b/src/render/lights/qenvironmentlight.h
new file mode 100644
index 000000000..0a5087c42
--- /dev/null
+++ b/src/render/lights/qenvironmentlight.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QENVIRONMENTLIGHT_H
+#define QT3DRENDER_QENVIRONMENTLIGHT_H
+
+#include <Qt3DRender/qt3drender_global.h>
+#include <Qt3DCore/qcomponent.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAbstractTexture;
+class QEnvironmentLightPrivate;
+
+class QT3DRENDERSHARED_EXPORT QEnvironmentLight : public Qt3DCore::QComponent
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *irradiance READ irradiance WRITE setIrradiance NOTIFY irradianceChanged)
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *specular READ specular WRITE setSpecular NOTIFY specularChanged)
+
+public:
+ explicit QEnvironmentLight(Qt3DCore::QNode *parent = nullptr);
+ ~QEnvironmentLight();
+
+ Qt3DRender::QAbstractTexture *irradiance() const;
+ Qt3DRender::QAbstractTexture *specular() const;
+
+public Q_SLOTS:
+ void setIrradiance(Qt3DRender::QAbstractTexture *irradiance);
+ void setSpecular(Qt3DRender::QAbstractTexture *specular);
+
+protected:
+ explicit QEnvironmentLight(QEnvironmentLightPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+Q_SIGNALS:
+ void irradianceChanged(Qt3DRender::QAbstractTexture *environmentIrradiance);
+ void specularChanged(Qt3DRender::QAbstractTexture *environmentSpecular);
+
+private:
+ Q_DECLARE_PRIVATE(QEnvironmentLight)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QENVIRONMENTLIGHT_H
diff --git a/src/render/lights/qenvironmentlight_p.h b/src/render/lights/qenvironmentlight_p.h
new file mode 100644
index 000000000..e98da5f59
--- /dev/null
+++ b/src/render/lights/qenvironmentlight_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QENVIRONMENTLIGHT_P_H
+#define QT3DRENDER_QENVIRONMENTLIGHT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qcomponent_p.h>
+#include <qshaderdata.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAbstractTexture;
+class QEnvironmentLight;
+
+class Q_AUTOTEST_EXPORT QEnvironmentLightPrivate : public Qt3DCore::QComponentPrivate
+{
+public:
+ explicit QEnvironmentLightPrivate();
+ ~QEnvironmentLightPrivate();
+
+ Q_DECLARE_PUBLIC(QEnvironmentLight)
+ QShaderData *m_shaderData;
+ QAbstractTexture *m_irradiance;
+ QAbstractTexture *m_specular;
+};
+
+struct QEnvironmentLightData
+{
+ Qt3DCore::QNodeId shaderDataId;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QENVIRONMENTLIGHT_P_H
diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp
index 7778b5621..b611657c4 100644
--- a/src/render/materialsystem/qeffect.cpp
+++ b/src/render/materialsystem/qeffect.cpp
@@ -67,6 +67,35 @@ QEffectPrivate::QEffectPrivate()
The QEffect class combines a set of techniques and parameters used by those techniques to
produce a rendering effect for a material.
+ An QEffect instance should be shared among several QMaterial instances when possible.
+
+ \code
+ QEffect *effect = new QEffect();
+
+ // Create technique, render pass and shader
+ QTechnique *gl3Technique = new QTechnique();
+ QRenderPass *gl3Pass = new QRenderPass();
+ QShaderProgram *glShader = new QShaderProgram();
+
+ // Set the shader on the render pass
+ gl3Pass->setShaderProgram(glShader);
+
+ // Add the pass to the technique
+ gl3Technique->addRenderPass(gl3Pass);
+
+ // Set the targeted GL version for the technique
+ gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ // Add the technique to the effect
+ effect->addTechnique(gl3Technique);
+ \endcode
+
+ A QParameter defined on an Effect is overridden by a QParameter (of the same
+ name) defined in a QMaterial, QTechniqueFilter, QRenderPassFilter.
+
\sa QMaterial, QTechnique, QParameter
*/
@@ -81,6 +110,37 @@ QEffectPrivate::QEffectPrivate()
The Effect type combines a set of techniques and parameters used by those techniques to
produce a rendering effect for a material.
+ An Effect instance should be shared among several Material instances when possible.
+
+ A Parameter defined on an Effect is overridden by a QParameter (of the same
+ name) defined in a Material, TechniqueFilter, RenderPassFilter.
+
+ \code
+ Effect {
+ id: effect
+
+ technique: [
+ Technique {
+ id: gl3Technique
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 3
+ minorVersion: 1
+ }
+ renderPasses: [
+ RenderPass {
+ id: gl3Pass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ }
+ ]
+ }
+ ]
+ }
+ \endcode
+
\sa Material, Technique, Parameter
*/
diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp
index ca0f86463..c6913441e 100644
--- a/src/render/materialsystem/qmaterial.cpp
+++ b/src/render/materialsystem/qmaterial.cpp
@@ -60,7 +60,58 @@
sound should reflect off an element, the temperature of a surface,
and so on.
- \sa Effect
+ In itself, a Material doesn't do anything. It's only when it references an
+ Effect node that a Material becomes useful.
+
+ In practice, it often happens that a single Effect is being referenced by
+ several Material components. This allows to only create the effect,
+ techniques, passes and shaders once while allowing to specify the material
+ by adding Parameter instances.
+
+ A Parameter defined on a Material is overridden by a Parameter (of the same
+ name) defined in a TechniqueFilter or a RenderPassFilter.
+
+ \code
+ Effect {
+ id: effect
+
+ technique: [
+ Technique {
+ id: gl3Technique
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 3
+ minorVersion: 1
+ }
+ renderPasses: [
+ RenderPass {
+ id: gl3Pass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ }
+ ]
+ }
+ ]
+ }
+
+ Material {
+ id: material1
+ parameters: [
+ Parameter { name: "color"; value: "green" }
+ ]
+ }
+
+ Material {
+ id: material2
+ parameters: [
+ Parameter { name: "color"; value: "white" }
+ ]
+ }
+ \endcode
+
+ \sa Effect, Technique, Parameter
*/
/*!
@@ -77,7 +128,54 @@
sound should reflect off an element, the temperature of a surface,
and so on.
- \sa QEffect
+ In itself, a QMaterial doesn't do anything. It's only when it references a
+ QEffect node that a QMaterial becomes useful.
+
+ In practice, it often happens that a single QEffect is being referenced by
+ several QMaterial components. This allows to only create the effect,
+ techniques, passes and shaders once while allowing to specify the material
+ by adding QParameter instances.
+
+ A QParameter defined on a QMaterial is overridden by a QParameter (of the same
+ name) defined in a QTechniqueFilter or a QRenderPassFilter.
+
+ \code
+ QMaterial *material1 = new QMaterial();
+ QMaterial *material2 = new QMaterial();
+
+ // Create effect, technique, render pass and shader
+ QEffect *effect = new QEffect();
+ QTechnique *gl3Technique = new QTechnique();
+ QRenderPass *gl3Pass = new QRenderPass();
+ QShaderProgram *glShader = new QShaderProgram();
+
+ // Set the shader on the render pass
+ gl3Pass->setShaderProgram(glShader);
+
+ // Add the pass to the technique
+ gl3Technique->addRenderPass(gl3Pass);
+
+ // Set the targeted GL version for the technique
+ gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ // Add the technique to the effect
+ effect->addTechnique(gl3Technique);
+
+ // Set the effect on the materials
+ material1->setEffect(effect);
+ material2->setEffect(effect);
+
+ // Set different parameters on the materials
+ const QString parameterName = QStringLiteral("color");
+ material1->addParameter(new QParameter(parameterName, QColor::fromRgbF(0.0f, 1.0f, 0.0f, 1.0f);
+ material2->addParameter(new QParameter(parameterName, QColor::fromRgbF(1.0f, 1.0f, 1.0f, 1.0f);
+
+ \endcode
+
+ \sa QEffect, QTechnique, QParameter
*/
QT_BEGIN_NAMESPACE
diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp
index 8f83fd02e..2ca7d176b 100644
--- a/src/render/materialsystem/qparameter.cpp
+++ b/src/render/materialsystem/qparameter.cpp
@@ -45,18 +45,127 @@
/*!
- * \qmltype Parameter
- * \instantiates Qt3DRender::QParameter
- * \inqmlmodule Qt3D.Render
- * \brief Provides storage for a name and value pair.
+ \qmltype Parameter
+ \instantiates Qt3DRender::QParameter
+ \inqmlmodule Qt3D.Render
+ \brief Provides storage for a name and value pair. This maps to a shader uniform.
+
+ A Parameter can be referenced by a RenderPass, Technique, Effect, Material,
+ TechniqueFilter, RenderPassFilter. At runtime, depending on which shader is
+ selected for a given step of the rendering, the value contained in a
+ Parameter will be converted and uploaded if the shader contains a uniform
+ with a name matching that of the Parameter.
+
+ \code
+ Parameter {
+ name: "diffuseColor"
+ value: "blue"
+ }
+
+ // Works with the following GLSL uniform shader declarations
+ // uniform vec4 diffuseColor;
+ // uniform vec3 diffuseColor;
+ // uniform vec2 diffuseColor;
+ // uniform float diffuseColor;
+ \endcode
+
+ \note some care must be taken to ensure the value wrapped by a Parameter
+ can actually be converted to what the real uniform expect. Giving a value
+ stored as an int where the actual shader uniform is of type float could
+ result in undefined behaviors.
+
+ \note when the targeted uniform is an array, the name should be the name
+ of the uniform with [0] appended to it.
+
+ \code
+ Parameter {
+ name: "diffuseValues[0]"
+ value: [0.0, 1.0. 2.0, 3.0, 4.0, 883.0, 1340.0, 1584.0]
+ }
+
+ // Matching GLSL shader uniform declaration
+ // uniform float diffuseValues[8];
+ \endcode
+
+ When it comes to texture support, the Parameter value should be set to the
+ appropriate Texture subclass that matches the sampler type of the shader
+ uniform.
+
+ \code
+ Parameter {
+ name: "diffuseTexture"
+ value: Texture2D { ... }
+ }
+
+ // Works with the following GLSL uniform shader declaration
+ // uniform sampler2D diffuseTexture
+ \endcode
+
+ \sa Texture
*/
/*!
- * \class Qt3DRender::QParameter
- * \inheaderfile Qt3DRender/QParameter
- * \inmodule Qt3DRender
- *
- * \brief Provides storage for a name and value pair.
+ \class Qt3DRender::QParameter
+ \inheaderfile Qt3DRender/QParameter
+ \inmodule Qt3DRender
+ \brief Provides storage for a name and value pair. This maps to a shader uniform.
+
+ A QParameter can be referenced by a QRenderPass, QTechnique, QEffect, QMaterial,
+ QTechniqueFilter, QRenderPassFilter. At runtime, depending on which shader is
+ selected for a given step of the rendering, the value contained in a
+ QParameter will be converted and uploaded if the shader contains a uniform
+ with a name matching that of the QParameter.
+
+ \code
+ QParameter *param = new QParameter();
+ param->setName(QStringLiteral("diffuseColor"));
+ param->setValue(QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Alternatively you can create and set a QParameter this way
+ QParameter *param2 = new QParameter(QStringLiteral("diffuseColor"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Such QParameters will work with the following GLSL uniform shader declarations
+ // uniform vec4 diffuseColor;
+ // uniform vec3 diffuseColor;
+ // uniform vec2 diffuseColor;
+ // uniform float diffuseColor;
+ \endcode
+
+ \note some care must be taken to ensure the value wrapped by a QParameter
+ can actually be converted to what the real uniform expect. Giving a value
+ stored as an int where the actual shader uniform is of type float could
+ result in undefined behaviors.
+
+ \note when the targeted uniform is an array, the name should be the name
+ of the uniform with [0] appended to it.
+
+ \code
+ QParameter *param = new QParameter();
+ QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
+
+ param->setName(QStringLiteral("diffuseValues[0]"));
+ param->setValue(values);
+
+ // Matching GLSL shader uniform declaration
+ // uniform float diffuseValues[8];
+ \endcode
+
+ When it comes to texture support, the QParameter value should be set to the
+ appropriate QAbstractTexture subclass that matches the sampler type of the shader
+ uniform.
+
+ \code
+ QTexture2D *texture = new QTexture2D();
+ ...
+ QParameter *param = new QParameter();
+ param->setName(QStringLiteral("diffuseTexture"));
+ param->setValue(QVariant::fromValue(texture));
+
+ // Works with the following GLSL uniform shader declaration
+ // uniform sampler2D diffuseTexture
+ \endcode
+
+ \sa QAbstractTexture
*/
QT_BEGIN_NAMESPACE
diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp
index dd6363816..61f844be3 100644
--- a/src/render/materialsystem/qrenderpass.cpp
+++ b/src/render/materialsystem/qrenderpass.cpp
@@ -72,9 +72,40 @@ QRenderPassPrivate::QRenderPassPrivate()
a list of FilterKey objects, a list of RenderState objects and a list
of \l Parameter objects.
- RenderPass executes the ShaderProgram using the given render states and parameters
- when its filter keys match the filter keys in RenderPassFilter or when no filter
- keys are specified and no RenderPassFilter is present in the FrameGraph.
+ RenderPass executes the ShaderProgram using the given RenderState and
+ Parameter nodes when at least one of FilterKey nodes being referenced
+ matches any of the FilterKey nodes in RenderPassFilter or when no FilterKey
+ nodes are specified and no RenderPassFilter is present in the FrameGraph.
+
+ If the RenderPass defines a Parameter, it will be overridden by a Parameter
+ with the same name if it exists in any of the Technique, Effect, Material,
+ TechniqueFilter, RenderPassFilter associated with the pass at runtime. This
+ still can be useful to define sane default values.
+
+ At render time, for each leaf node of the FrameGraph a base render state is
+ recorded by accumulating states defined by all RenderStateSet nodes in the
+ FrameGraph branch. Each RenderPass can overload this base render state by
+ specifying its own RenderState nodes.
+
+ \code
+ RenderPass {
+ id: pass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ parameters: [
+ Parameters { name: "color"; value: "red" }
+ ]
+ filterKeys: [
+ FilterKey { name: "name"; value: "zFillPass" }
+ ]
+ renderStates: [
+ DepthTest { }
+ ]
+ }
+ \endcode
+
+ \sa RenderPassFilter, FilterKey, Parameter, RenderState, Effect, Technique
*/
/*!
@@ -88,10 +119,54 @@ QRenderPassPrivate::QRenderPassPrivate()
of a Qt3DRender::QShaderProgram and a list of Qt3DRender::QFilterKey objects,
a list of Qt3DRender::QRenderState objects and a list of Qt3DRender::QParameter objects.
- QRenderPass executes the QShaderProgram using the given render states and parameters
- when its filter keys match the filter keys in Qt3DRender::QRenderPassFilter or
- when no filter keys are specified and no QRenderPassFilter is present
- in the FrameGraph.
+ QRenderPass executes the QShaderProgram using the given QRenderState and
+ QParameter nodes when at least one of QFilterKey nodes being referenced
+ matches any of the QFilterKey nodes in QRenderPassFilter or when no
+ QFilterKey nodes are specified and no QRenderPassFilter is present in the
+ FrameGraph.
+
+ If the QRenderPass defines a QParameter, it will be overridden by a
+ QParameter with the same name if it exists in any of the QTechnique,
+ QEffect, QMaterial, QTechniqueFilter, QRenderPassFilter associated with the
+ pass at runtime. This still can be useful to define sane default values.
+
+ At render time, for each leaf node of the FrameGraph a base render state is
+ recorded by accumulating states defined by all QRenderStateSet nodes in the
+ FrameGraph branch. Each QRenderPass can overload this base render state by
+ specifying its own QRenderState nodes.
+
+ \code
+ // Create the render passes
+ QRenderPass *pass = new QRenderPass();
+
+ // Create shader program
+ QShaderProgram *glShader = new QShaderProgram();
+
+ // Set the shader on the render pass
+ pass->setShaderProgram(glShader);
+
+ // Create a FilterKey
+ QFilterKey *filterKey = new QFilterKey();
+ filterKey->setName(QStringLiteral("name"));
+ fitlerKey->setValue(QStringLiteral("zFillPass"));
+
+ // Add the FilterKey to the pass
+ pass->addFilterKey(filterKey);
+
+ // Create a QParameter
+ QParameter *colorParameter = new QParameter(QStringLiteral("color"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Add parameter to pass
+ pass->addParameter(colorParameter);
+
+ // Create a QRenderState
+ QDepthTest *depthTest = new QDepthTest();
+
+ // Add the render state to the pass
+ pass->addRenderState(depthTest);
+ \endcode
+
+ \sa QRenderPassFilter, QFilterKey, QParameter, QRenderState, QEffect, QTechnique
*/
/*!
\typedef ParameterList
@@ -236,7 +311,7 @@ QVector<QFilterKey *> QRenderPass::filterKeys() const
/*!
Adds a render \a state to the rendering pass. That implies that
when the pass is executed at render time, the globally set render state will
- be modifed by the states defined locally by the Qt3DRender::QRenderPass.
+ be modified by the states defined locally by the Qt3DRender::QRenderPass.
\note not defining any Qt3DRender::QRenderState in a pass will result in the pass using
the globally set render state for a given FrameGraph branch execution path.
diff --git a/src/render/materialsystem/qshaderdata_p.h b/src/render/materialsystem/qshaderdata_p.h
index bfa139890..17faee9ed 100644
--- a/src/render/materialsystem/qshaderdata_p.h
+++ b/src/render/materialsystem/qshaderdata_p.h
@@ -62,7 +62,6 @@ namespace Qt3DRender {
namespace {
const int qVectorShaderDataTypeId = qMetaTypeId<QVector<QShaderData*> >();
-const int qShaderDataTypeId = qMetaTypeId<QShaderData*>();
}
@@ -70,10 +69,10 @@ class QShaderDataPropertyReader: public PropertyReaderInterface
{
QVariant readProperty(const QVariant &v) Q_DECL_OVERRIDE
{
- QShaderData *shaderData = nullptr;
+ const auto node = v.value<Qt3DCore::QNode *>();
- if (v.userType() == qShaderDataTypeId && (shaderData = v.value<QShaderData *>()) != nullptr) {
- return QVariant::fromValue(shaderData->id());
+ if (node) {
+ return QVariant::fromValue(node->id());
} else if (v.userType() == qVectorShaderDataTypeId) {
QVariantList vlist;
const auto data_ = v.value<QVector<QShaderData *> >();
diff --git a/src/render/materialsystem/qshaderprogram.cpp b/src/render/materialsystem/qshaderprogram.cpp
index 522f021aa..2a65d257c 100644
--- a/src/render/materialsystem/qshaderprogram.cpp
+++ b/src/render/materialsystem/qshaderprogram.cpp
@@ -80,15 +80,48 @@
\value Compute Compute shader
*/
+/*!
+ \enum QShaderProgram::ShaderStatus
+
+ This enum identifies the status of shader used.
+
+ \value NotReady The shader hasn't been compiled and linked yet
+ \value Ready The shader was successfully compiled
+ \value Error An error occurred while compiling the shader
+*/
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
QShaderProgramPrivate::QShaderProgramPrivate()
: QNodePrivate()
+ , m_status(QShaderProgram::NotReady)
{
}
+void QShaderProgramPrivate::setLog(const QString &log)
+{
+ Q_Q(QShaderProgram);
+ if (log != m_log) {
+ m_log = log;
+ const bool blocked = q->blockNotifications(true);
+ emit q->logChanged(m_log);
+ q->blockNotifications(blocked);
+ }
+}
+
+void QShaderProgramPrivate::setStatus(QShaderProgram::Status status)
+{
+ Q_Q(QShaderProgram);
+ if (status != m_status) {
+ m_status = status;
+ const bool blocked = q->blockNotifications(true);
+ emit q->statusChanged(m_status);
+ q->blockNotifications(blocked);
+ }
+}
+
QShaderProgram::QShaderProgram(QNode *parent)
: QNode(*new QShaderProgramPrivate, parent)
{
@@ -104,6 +137,18 @@ QShaderProgram::QShaderProgram(QShaderProgramPrivate &dd, QNode *parent)
{
}
+void QShaderProgram::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+{
+ Q_D(QShaderProgram);
+ if (change->type() == Qt3DCore::PropertyUpdated) {
+ const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (e->propertyName() == QByteArrayLiteral("log"))
+ d->setLog(e->value().toString());
+ else if (e->propertyName() == QByteArrayLiteral("status"))
+ d->setStatus(static_cast<QShaderProgram::Status>(e->value().toInt()));
+ }
+}
+
/*!
\qmlproperty string ShaderProgram::vertexShaderCode
@@ -308,6 +353,40 @@ QByteArray QShaderProgram::shaderCode(ShaderType type) const
}
}
+/*!
+ \qmlproperty string ShaderProgram::log
+
+ Holds the log of the current shader program. This is useful to diagnose a
+ compilation failure of the shader program.
+*/
+/*!
+ \property QShaderProgram::log
+
+ Holds the log of the current shader program. This is useful to diagnose a
+ compilation failure of the shader program.
+*/
+QString QShaderProgram::log() const
+{
+ Q_D(const QShaderProgram);
+ return d->m_log;
+}
+
+/*!
+ \qmlproperty string ShaderProgram::status
+
+ Holds the status of the current shader program.
+*/
+/*!
+ \property QShaderProgram::status
+
+ Holds the status of the current shader program.
+*/
+QShaderProgram::Status QShaderProgram::status() const
+{
+ Q_D(const QShaderProgram);
+ return d->m_status;
+}
+
static QByteArray deincludify(const QString &filePath)
{
QFile f(filePath);
diff --git a/src/render/materialsystem/qshaderprogram.h b/src/render/materialsystem/qshaderprogram.h
index 442a25b2e..8c3da1a4a 100644
--- a/src/render/materialsystem/qshaderprogram.h
+++ b/src/render/materialsystem/qshaderprogram.h
@@ -58,6 +58,8 @@ class QT3DRENDERSHARED_EXPORT QShaderProgram : public Qt3DCore::QNode
Q_PROPERTY(QByteArray geometryShaderCode READ geometryShaderCode WRITE setGeometryShaderCode NOTIFY geometryShaderCodeChanged)
Q_PROPERTY(QByteArray fragmentShaderCode READ fragmentShaderCode WRITE setFragmentShaderCode NOTIFY fragmentShaderCodeChanged)
Q_PROPERTY(QByteArray computeShaderCode READ computeShaderCode WRITE setComputeShaderCode NOTIFY computeShaderCodeChanged)
+ Q_PROPERTY(QString log READ log NOTIFY logChanged REVISION 9)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION 9)
public:
explicit QShaderProgram(Qt3DCore::QNode *parent = nullptr);
@@ -73,6 +75,13 @@ public:
};
Q_ENUM(ShaderType) // LCOV_EXCL_LINE
+ enum Status {
+ NotReady = 0,
+ Ready,
+ Error
+ };
+ Q_ENUM(Status) // LCOV_EXCL_LINE
+
// Source code in-line
QByteArray vertexShaderCode() const;
QByteArray tessellationControlShaderCode() const;
@@ -84,6 +93,9 @@ public:
void setShaderCode(ShaderType type, const QByteArray &shaderCode);
QByteArray shaderCode(ShaderType type) const;
+ QString log() const;
+ Status status() const;
+
Q_INVOKABLE static QByteArray loadSource(const QUrl &sourceUrl);
public Q_SLOTS:
@@ -101,9 +113,12 @@ Q_SIGNALS:
void geometryShaderCodeChanged(const QByteArray &geometryShaderCode);
void fragmentShaderCodeChanged(const QByteArray &fragmentShaderCode);
void computeShaderCodeChanged(const QByteArray &computeShaderCode);
+ void logChanged(const QString &log);
+ void statusChanged(Status status);
protected:
explicit QShaderProgram(QShaderProgramPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
private:
Q_DECLARE_PRIVATE(QShaderProgram)
diff --git a/src/render/materialsystem/qshaderprogram_p.h b/src/render/materialsystem/qshaderprogram_p.h
index 5f695a279..6bdde68f1 100644
--- a/src/render/materialsystem/qshaderprogram_p.h
+++ b/src/render/materialsystem/qshaderprogram_p.h
@@ -52,13 +52,12 @@
//
#include <private/qnode_p.h>
+#include <Qt3DRender/qshaderprogram.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QShaderProgram;
-
class QShaderProgramPrivate : public Qt3DCore::QNodePrivate
{
public:
@@ -77,6 +76,11 @@ public:
QByteArray m_geometryShaderCode;
QByteArray m_fragmentShaderCode;
QByteArray m_computeShaderCode;
+ QString m_log;
+ QShaderProgram::Status m_status;
+
+ void setLog(const QString &log);
+ void setStatus(QShaderProgram::Status status);
};
struct QShaderProgramData
diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp
index 74505bfbd..df142cdee 100644
--- a/src/render/materialsystem/qtechnique.cpp
+++ b/src/render/materialsystem/qtechnique.cpp
@@ -68,14 +68,61 @@ QTechniquePrivate::~QTechniquePrivate()
\since 5.7
\brief Encapsulates a Technique.
- A Technique specifies a set of RenderPass objects, FilterKey objects, Parameter objects
- and a GraphicsApiFilter, which together define a rendering technique the given
- graphics API can render. The filter keys are used by TechniqueFilter
- to select specific techinques at specific parts of the FrameGraph.
- If the same parameter is specified both in Technique and RenderPass, the one
- in Technique overrides the one used in the RenderPass.
-
- \sa Qt3D.Render::Effect
+ A Technique specifies a set of RenderPass objects, FilterKey objects,
+ Parameter objects and a GraphicsApiFilter, which together define a
+ rendering technique the given graphics API can render. The filter keys are
+ used by TechniqueFilter to select specific techniques at specific parts of
+ the FrameGraph. If two Parameter instances with the same name are specified
+ in a Technique and a RenderPass, the one in Technique overrides the one
+ used in the RenderPass.
+
+ When creating an Effect that targets several versions of a graphics API, it
+ is useful to create several Technique nodes each with a graphicsApiFilter
+ set to match one of the targeted versions. At runtime, the Qt3D renderer
+ will select the most appropriate Technique based on which graphics API
+ versions are supported and (if specified) the FilterKey nodes that satisfy
+ a given TechniqueFilter in the FrameGraph.
+
+ \note When using OpenGL as the graphics API for rendering, Qt3D relies on
+ the QSurfaceFormat returned by QSurfaceFormat::defaultFormat() at runtime
+ to decide what is the most appropriate GL version available. If you need to
+ customize the QSurfaceFormat, do not forget to apply it with
+ QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
+ will likely have no effect on Qt3D related rendering.
+
+ \code
+ Technique {
+ id: gl3Technique
+ parameters: [
+ Parameter { name: "color"; value: "orange" }
+ ]
+ filterKeys: [
+ FilterKey { name: "name"; value: "zFillTechnique" }
+ ]
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 3
+ minorVersion: 1
+ }
+ renderPasses: [
+ RenderPass {
+ id: firstPass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ },
+ RenderPass {
+ id: secondPass
+ shaderProgram: ShaderProgram {
+ ...
+ }
+ }
+ ]
+ }
+ \endcode
+
+ \sa Effect, RenderPass, TechniqueFilter
*/
/*!
@@ -85,15 +132,62 @@ QTechniquePrivate::~QTechniquePrivate()
\since 5.7
\brief Encapsulates a Technique.
- A Qt3DRender::QTechnique specifies a set of Qt3DRender::QRenderPass objects,
- Qt3DRender::QFilterKey objects, Qt3DRender::QParameter objects and
- a Qt3DRender::QGraphicsApiFilter, which together define a rendering technique the given
- graphics API can render. The filter keys are used by Qt3DRender::QTechniqueFilter
- to select specific techinques at specific parts of the FrameGraph.
- If the same parameter is specified both in QTechnique and QRenderPass, the one
- in QTechnique overrides the one used in the QRenderPass.
-
- \sa Qt3DRender::QEffect
+ A Qt3DRender::QTechnique specifies a set of Qt3DRender::QRenderPass
+ objects, Qt3DRender::QFilterKey objects, Qt3DRender::QParameter objects and
+ a Qt3DRender::QGraphicsApiFilter, which together define a rendering
+ technique the given graphics API can render. The filter keys are used by
+ Qt3DRender::QTechniqueFilter to select specific techniques at specific
+ parts of the FrameGraph. If two QParameter instances with the same name are
+ specified in a QTechnique and a QRenderPass, the one in Technique overrides
+ the one used in the QRenderPass.
+
+ When creating an QEffect that targets several versions of a graphics API,
+ it is useful to create several QTechnique nodes each with a
+ graphicsApiFilter set to match one of the targeted GL versions. At runtime,
+ the Qt3D renderer will select the most appropriate QTechnique based on
+ which graphics API versions are supported and (if specified) the QFilterKey
+ nodes that satisfy a given QTechniqueFilter in the FrameGraph.
+
+ \note When using OpenGL as the graphics API for rendering, Qt3D relies on
+ the QSurfaceFormat returned by QSurfaceFormat::defaultFormat() at runtime
+ to decide what is the most appropriate GL version available. If you need to
+ customize the QSurfaceFormat, do not forget to apply it with
+ QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
+ will likely have no effect on Qt3D related rendering.
+
+ \code
+ QTechnique *gl3Technique = new QTechnique();
+
+ // Create the render passes
+ QRenderPass *firstPass = new QRenderPass();
+ QRenderPass *secondPass = new QRenderPass();
+
+ // Add the passes to the technique
+ gl3Technique->addRenderPass(firstPass);
+ gl3Technique->addRenderPass(secondPass);
+
+ // Set the targeted GL version for the technique
+ gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ // Create a FilterKey
+ QFilterKey *filterKey = new QFilterKey();
+ filterKey->setName(QStringLiteral("name"));
+ fitlerKey->setValue(QStringLiteral("zFillPass"));
+
+ // Add the FilterKey to the Technique
+ gl3Technique->addFilterKey(filterKey);
+
+ // Create a QParameter
+ QParameter *colorParameter = new QParameter(QStringLiteral("color"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Add parameter to technique
+ gl3Technique->addParameter(colorParameter);
+ \endcode
+
+ \sa QEffect, QRenderPass, QTechniqueFilter
*/
/*!
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index bd0af0bed..915ca1d54 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -59,10 +59,11 @@ namespace Qt3DRender {
namespace Render {
Shader::Shader()
- : BackendNode()
+ : BackendNode(ReadWrite)
, m_isLoaded(false)
, m_dna(0)
, m_graphicsContext(nullptr)
+ , m_status(QShaderProgram::NotReady)
{
m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
}
@@ -71,8 +72,8 @@ Shader::~Shader()
{
// TO DO: ShaderProgram is leaked as of now
// Fix that taking care that they may be shared given a same dna
-
- QObject::disconnect(m_contextConnection);
+ if (m_graphicsContext)
+ QObject::disconnect(m_contextConnection);
}
void Shader::cleanup()
@@ -84,6 +85,7 @@ void Shader::cleanup()
if (m_graphicsContext)
m_graphicsContext->removeShaderProgramReference(this);
m_graphicsContext = nullptr;
+ QObject::disconnect(m_contextConnection);
}
QBackendNode::setEnabled(false);
@@ -96,6 +98,7 @@ void Shader::cleanup()
m_uniforms.clear();
m_attributes.clear();
m_uniformBlocks.clear();
+ m_status = QShaderProgram::NotReady;
}
void Shader::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
@@ -183,8 +186,10 @@ void Shader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_shaderCode[QShaderProgram::Compute] = propertyValue.toByteArray();
m_isLoaded = false;
}
- if (!m_isLoaded)
+ if (!m_isLoaded) {
+ setStatus(QShaderProgram::NotReady);
updateDNA();
+ }
markDirty(AbstractRenderer::AllDirty);
}
@@ -253,6 +258,14 @@ ShaderStorageBlock Shader::storageBlockForBlockName(const QString &blockName)
return ShaderStorageBlock();
}
+// To be called from a worker thread
+void Shader::submitPendingNotifications()
+{
+ const QVector<Qt3DCore::QPropertyUpdatedChangePtr> notifications = std::move(m_pendingNotifications);
+ for (const Qt3DCore::QPropertyUpdatedChangePtr &notification : notifications)
+ notifyObservers(notification);
+}
+
void Shader::prepareUniforms(ShaderParameterPack &pack)
{
const PackUniformHash &values = pack.uniforms();
@@ -261,7 +274,7 @@ void Shader::prepareUniforms(ShaderParameterPack &pack)
const auto end = values.cend();
while (it != end) {
// Find if there's a uniform with the same name id
- for (const ShaderUniform &uniform : m_uniforms) {
+ for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
if (uniform.m_nameId == it.key()) {
pack.setSubmissionUniform(uniform);
break;
@@ -298,8 +311,8 @@ void Shader::updateDNA()
QMutexLocker locker(&m_mutex);
uint attachmentHash = 0;
- QHash<QString, int>::const_iterator it = m_fragOutputs.begin();
- QHash<QString, int>::const_iterator end = m_fragOutputs.end();
+ QHash<QString, int>::const_iterator it = m_fragOutputs.cbegin();
+ QHash<QString, int>::const_iterator end = m_fragOutputs.cend();
while (it != end) {
attachmentHash += ::qHash(it.value()) + ::qHash(it.key());
++it;
@@ -360,11 +373,11 @@ void Shader::initializeUniformBlocks(const QVector<ShaderUniformBlock> &uniformB
qCDebug(Shaders) << "Initializing Uniform Block {" << m_uniformBlockNames[i] << "}";
// Find all active uniforms for the shader block
- QVector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.begin();
- const QVector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.end();
+ QVector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.cbegin();
+ const QVector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.cend();
- QVector<QString>::const_iterator uniformNamesIt = m_uniformsNames.begin();
- const QVector<QString>::const_iterator uniformNamesEnd = m_attributesNames.end();
+ QVector<QString>::const_iterator uniformNamesIt = m_uniformsNames.cbegin();
+ const QVector<QString>::const_iterator uniformNamesEnd = m_attributesNames.cend();
QHash<QString, ShaderUniform> activeUniformsInBlock;
@@ -402,7 +415,7 @@ void Shader::initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> &sh
Initializes this Shader's state relating to attributes, global block uniforms and
and named uniform blocks by copying these details from \a other.
*/
-void Shader::initialize(const Shader &other)
+void Shader::initializeFromReference(const Shader &other)
{
Q_ASSERT(m_dna == other.m_dna);
m_uniformsNamesIds = other.m_uniformsNamesIds;
@@ -420,6 +433,32 @@ void Shader::initialize(const Shader &other)
m_shaderStorageBlockNames = other.m_shaderStorageBlockNames;
m_shaderStorageBlocks = other.m_shaderStorageBlocks;
m_isLoaded = other.m_isLoaded;
+ setStatus(other.status());
+ setLog(other.log());
+}
+
+void Shader::setLog(const QString &log)
+{
+ if (log != m_log) {
+ m_log = log;
+ Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("log");
+ e->setValue(QVariant::fromValue(m_log));
+ m_pendingNotifications.push_back(e);
+ }
+}
+
+void Shader::setStatus(QShaderProgram::Status status)
+{
+ if (status != m_status) {
+ m_status = status;
+ Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("status");
+ e->setValue(QVariant::fromValue(m_status));
+ m_pendingNotifications.push_back(e);
+ }
}
} // namespace Render
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index ad68a3bd6..b5127f5ec 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -54,6 +54,8 @@
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/shaderparameterpack_p.h>
#include <Qt3DRender/private/shadervariables_p.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QMutex>
#include <QVector>
@@ -63,8 +65,6 @@ class QOpenGLShaderProgram;
namespace Qt3DRender {
-class QShaderProgram;
-
namespace Render {
class ShaderManager;
@@ -118,6 +118,12 @@ public:
ShaderStorageBlock storageBlockForBlockNameId(int blockNameId);
ShaderStorageBlock storageBlockForBlockName(const QString &blockName);
+ inline QString log() const { return m_log; }
+ inline QShaderProgram::Status status() const { return m_status; }
+
+ void submitPendingNotifications();
+ inline bool hasPendingNotifications() const { return !m_pendingNotifications.empty(); }
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
@@ -148,6 +154,10 @@ private:
mutable QMutex m_mutex;
GraphicsContext *m_graphicsContext;
QMetaObject::Connection m_contextConnection;
+ QString m_log;
+ QShaderProgram::Status m_status;
+
+ QVector<Qt3DCore::QPropertyUpdatedChangePtr> m_pendingNotifications;
void updateDNA();
@@ -157,7 +167,9 @@ private:
void initializeUniformBlocks(const QVector<ShaderUniformBlock> &uniformBlockDescription);
void initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> &shaderStorageBlockDescription);
- void initialize(const Shader &other);
+ void initializeFromReference(const Shader &other);
+ void setLog(const QString &log);
+ void setStatus(QShaderProgram::Status status);
friend class GraphicsContext;
};
diff --git a/src/render/materialsystem/shadercache.cpp b/src/render/materialsystem/shadercache.cpp
index de3842386..4ddf26799 100644
--- a/src/render/materialsystem/shadercache.cpp
+++ b/src/render/materialsystem/shadercache.cpp
@@ -151,6 +151,11 @@ QOpenGLShaderProgram *ShaderCache::getShaderProgramForDNA(ProgramDNA dna) const
return m_programHash.value(dna, nullptr);
}
+QVector<Qt3DCore::QNodeId> ShaderCache::shaderIdsForProgram(ProgramDNA dna) const
+{
+ return m_programRefs.value(dna);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/materialsystem/shadercache_p.h b/src/render/materialsystem/shadercache_p.h
index 3cbc6bd0c..24a55876e 100644
--- a/src/render/materialsystem/shadercache_p.h
+++ b/src/render/materialsystem/shadercache_p.h
@@ -79,6 +79,7 @@ public:
// Only ever used from the OpenGL submission thread
QOpenGLShaderProgram *getShaderProgramForDNA(ProgramDNA dna) const;
+ QVector<Qt3DCore::QNodeId> shaderIdsForProgram(ProgramDNA dna) const;
private:
// Only ever used from the OpenGL submission thread
diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp
index 453bd5dc1..13d6d505c 100644
--- a/src/render/picking/objectpicker.cpp
+++ b/src/render/picking/objectpicker.cpp
@@ -44,7 +44,6 @@
#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -93,17 +92,11 @@ void ObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == Qt3DCore::PropertyUpdated) {
const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- bool notifyPickJob = false;
if (propertyChange->propertyName() == QByteArrayLiteral("hoverEnabled")) {
m_hoverEnabled = propertyChange->value().toBool();
- notifyPickJob = true;
} else if (propertyChange->propertyName() == QByteArrayLiteral("dragEnabled")) {
m_dragEnabled = propertyChange->value().toBool();
- notifyPickJob = true;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
- notifyPickJob = true;
- // actual value change handled in BackendNode::sceneChangeEvent
}
markDirty(AbstractRenderer::AllDirty);
@@ -134,7 +127,6 @@ void ObjectPicker::onClicked(QPickEventPtr event)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("clicked");
e->setValue(QVariant::fromValue(event));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -144,7 +136,6 @@ void ObjectPicker::onMoved(QPickEventPtr event)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("moved");
e->setValue(QVariant::fromValue(event));
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -155,7 +146,6 @@ void ObjectPicker::onPressed(QPickEventPtr event)
e->setPropertyName("pressed");
e->setValue(QVariant::fromValue(event));
m_isPressed = true;
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -166,7 +156,6 @@ void ObjectPicker::onReleased(QPickEventPtr event)
e->setPropertyName("released");
e->setValue(QVariant::fromValue(event));
m_isPressed = false;
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -175,7 +164,6 @@ void ObjectPicker::onEntered()
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("entered");
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -184,7 +172,6 @@ void ObjectPicker::onExited()
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("exited");
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
diff --git a/src/render/picking/pickeventfilter.cpp b/src/render/picking/pickeventfilter.cpp
index a1ae52068..19d3b6b6e 100644
--- a/src/render/picking/pickeventfilter.cpp
+++ b/src/render/picking/pickeventfilter.cpp
@@ -61,11 +61,19 @@ PickEventFilter::~PickEventFilter()
Called from a worker thread in the thread pool so be sure to
mutex protect the data.
*/
-QList<QMouseEvent> PickEventFilter::pendingEvents()
+QList<QMouseEvent> PickEventFilter::pendingMouseEvents()
{
QMutexLocker locker(&m_mutex);
- QList<QMouseEvent> pendingEvents(m_pendingEvents);
- m_pendingEvents.clear();
+ QList<QMouseEvent> pendingEvents(m_pendingMouseEvents);
+ m_pendingMouseEvents.clear();
+ return pendingEvents;
+}
+
+QList<QKeyEvent> PickEventFilter::pendingKeyEvents()
+{
+ QMutexLocker locker(&m_mutex);
+ QList<QKeyEvent> pendingEvents(m_pendingKeyEvents);
+ m_pendingKeyEvents.clear();
return pendingEvents;
}
@@ -82,7 +90,12 @@ bool PickEventFilter::eventFilter(QObject *obj, QEvent *e)
case QEvent::MouseMove:
case QEvent::HoverMove: {
QMutexLocker locker(&m_mutex);
- m_pendingEvents.push_back(QMouseEvent(*static_cast<QMouseEvent *>(e)));
+ m_pendingMouseEvents.push_back(QMouseEvent(*static_cast<QMouseEvent *>(e)));
+ } break;
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: {
+ QMutexLocker locker(&m_mutex);
+ m_pendingKeyEvents.push_back(QKeyEvent(*static_cast<QKeyEvent *>(e)));
}
default:
break;
diff --git a/src/render/picking/pickeventfilter_p.h b/src/render/picking/pickeventfilter_p.h
index df94a3085..fc4b00ddc 100644
--- a/src/render/picking/pickeventfilter_p.h
+++ b/src/render/picking/pickeventfilter_p.h
@@ -53,6 +53,7 @@
#include <QObject>
#include <QMouseEvent>
+#include <QKeyEvent>
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -68,13 +69,15 @@ public:
explicit PickEventFilter(QObject *parent = nullptr);
~PickEventFilter();
- QList<QMouseEvent> pendingEvents();
+ QList<QMouseEvent> pendingMouseEvents();
+ QList<QKeyEvent> pendingKeyEvents();
protected:
bool eventFilter(QObject *obj, QEvent *e) Q_DECL_FINAL;
private:
- QList<QMouseEvent> m_pendingEvents;
+ QList<QMouseEvent> m_pendingMouseEvents;
+ QList<QKeyEvent> m_pendingKeyEvents;
QMutex m_mutex;
};
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index 1842b7fee..49f608a67 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -55,14 +55,25 @@ namespace Qt3DRender {
\brief The QObjectPicker class instantiates a component that can
be used to interact with a QEntity by a process known as picking.
+ For every combination of viewport and camera, picking casts a ray through the scene to
+ find entities who's bounding volume intersects the ray. The bounding volume is computed using
+ the values in the attribute buffer specified by the boundingVolumePositionAttribute of the
+ geometry.
+
The signals pressed(), released(), clicked(), moved(), entered(), and exited() are
emitted when the bounding volume defined by the pickAttribute property intersects
with a ray.
+ Most signals carry a QPickEvent instance. If QPickingSettings::pickMode() is set to
+ QPickingSettings::TrianglePicking, the actual type of the pick parameter will be
+ QPickTriangleEvent.
+
Pick queries are performed on mouse press and mouse release.
If drag is enabled, queries also happen on each mouse move while any button is pressed.
If hover is enabled, queries happen on every mouse move even if no button is pressed.
- \sa QPickingSettings
+
+ \sa Qt3DRender::QPickingSettings, Qt3DRender::QGeometry, Qt3DRender::QAttribute,
+ Qt3DRender::QPickEvent, Qt3DRender::QPickTriangleEvent
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
@@ -76,28 +87,51 @@ namespace Qt3DRender {
* \inqmlmodule Qt3D.Render
* \brief The ObjectPicker class instantiates a component that can
be used to interact with an Entity by a process known as picking.
+
+ For every combination of viewport and camera, picking casts a ray through the scene to
+ find entities who's bounding volume intersects the ray. The bounding volume is computed using
+ the values in the attribute buffer specified by the boundingVolumePositionAttribute of the
+ geometry.
+
+ The signals pressed(), released(), clicked(), moved(), entered(), and exited() are
+ emitted when the bounding volume defined by the pickAttribute property intersects
+ with a ray.
+
+ Most signals carry a PickEvent instance. If PickingSettings.pickMode is set to
+ PickingSettings.TrianglePicking, the actual type of the pick parameter will be
+ PickTriangleEvent.
+
+ Pick queries are performed on mouse press and mouse release.
+ If drag is enabled, queries also happen on each mouse move while any button is pressed.
+ If hover is enabled, queries happen on every mouse move even if no button is pressed.
+
+ \sa PickingSettings, Geometry, Attribute, PickEvent, PickTriangleEvent
+
+ \note Instances of this component shouldn't be shared, not respecting that
+ condition will most likely result in undefined behavior.
+
*/
/*!
- \qmlsignal Qt3D.Render::ObjectPicker::pressed()
+ \qmlsignal Qt3D.Render::ObjectPicker::pressed(PickEvent pick)
This signal is emitted when the bounding volume defined by the pickAttribute property intersects
with a ray on a mouse press.
*/
/*!
- \qmlsignal Qt3D.Render::ObjectPicker::released()
+ \qmlsignal Qt3D.Render::ObjectPicker::released(PickEvent pick)
This signal is emitted when the bounding volume defined by the pickAttribute property intersects
with a ray on a mouse release.
*/
/*!
- \qmlsignal Qt3D.Render::ObjectPicker::clicked()
+ \qmlsignal Qt3D.Render::ObjectPicker::clicked(PickEvent pick)
This signal is emitted when the bounding volume defined by the pickAttribute property intersects
with a ray on a mouse click.
*/
/*!
- \qmlsignal Qt3D.Render::ObjectPicker::moved()
+ \qmlsignal Qt3D.Render::ObjectPicker::moved(PickEvent pick)
This signal is emitted when the bounding volume defined by the pickAttribute property intersects
with a ray on a mouse move with a button pressed.
*/
diff --git a/src/render/picking/qpickevent.cpp b/src/render/picking/qpickevent.cpp
index c7abf639c..148850baf 100644
--- a/src/render/picking/qpickevent.cpp
+++ b/src/render/picking/qpickevent.cpp
@@ -50,6 +50,10 @@ namespace Qt3DRender {
\inmodule Qt3DRender
\brief The QPickEvent class holds information when an object is picked
+
+ This is received as a parameter in most of the QObjectPicker component signals when picking
+ succeeds.
+
\sa QPickingSettings, QPickTriangleEvent, QObjectPicker
\since 5.7
@@ -61,9 +65,10 @@ namespace Qt3DRender {
* \inqmlmodule Qt3D.Render
* \sa ObjectPicker PickingSettings
* \brief PickEvent holds information when an object is picked.
+ * This is received as a parameter in most of the QObjectPicker component signals when picking
+ * succeeds.
*/
-
/*!
\fn Qt3DRender::QPickEvent::QPickEvent()
Constructs a new QPickEvent.
@@ -73,6 +78,11 @@ QPickEvent::QPickEvent()
{
}
+QPickEventPrivate *QPickEventPrivate::get(QPickEvent *object)
+{
+ return object->d_func();
+}
+
/*!
\fn Qt3DRender::QPickEvent::QPickEvent(const QPointF &position, const QVector3D &intersection, const QVector3D &localIntersection, float distance)
Constructs a new QPickEvent with the given parameters: \a position, \a intersection, \a localIntersection and \a distance
@@ -147,11 +157,11 @@ void QPickEvent::setAccepted(bool accepted)
/*!
\qmlproperty bool Qt3D.Render::PickEvent::position
- Specifies the position of the event
+ Specifies the mouse position with respect to the render area (window or quick item)
*/
/*!
\property Qt3DRender::QPickEvent::position
- Specifies the position of the event
+ Specifies the mouse position with respect to the render area (window or quick item)
*/
/*!
* \brief QPickEvent::position
@@ -165,11 +175,11 @@ QPointF QPickEvent::position() const
/*!
\qmlproperty bool Qt3D.Render::PickEvent::distance
- Specifies the distance of the event
+ Specifies the distance of the hit to the camera
*/
/*!
\property Qt3DRender::QPickEvent::distance
- Specifies the distance of the event
+ Specifies the distance of the hit to the camera
*/
/*!
* \brief QPickEvent::distance
@@ -183,15 +193,15 @@ float QPickEvent::distance() const
/*!
\qmlproperty bool Qt3D.Render::PickEvent::worldIntersection
- Specifies the world intersection of the event
+ Specifies the coordinates of the hit in world coordinate system
*/
/*!
\property Qt3DRender::QPickEvent::worldIntersection
- Specifies the world intersection of the event
+ Specifies the coordinates of the hit in world coordinate system
*/
/*!
* \brief QPickEvent::worldIntersection
- * \return world coordinate of the pick point
+ * \return coordinates of the hit in world coordinate system
*/
QVector3D QPickEvent::worldIntersection() const
{
@@ -201,15 +211,15 @@ QVector3D QPickEvent::worldIntersection() const
/*!
\qmlproperty bool Qt3D.Render::PickEvent::localIntersection
- Specifies the world local intersection of the event
+ Specifies the coordinates of the hit in the local coordinate system of the picked entity
*/
/*!
\property Qt3DRender::QPickEvent::localIntersection
- Specifies the local intersection of the event
+ Specifies the coordinates of the hit in the local coordinate system of the picked entity
*/
/*!
* \brief QPickEvent::localIntersection
- * \return local coordinate of pick point
+ * \return coordinates of the hit in the local coordinate system of the picked entity
*/
QVector3D QPickEvent::localIntersection() const
{
diff --git a/src/render/picking/qpickevent_p.h b/src/render/picking/qpickevent_p.h
index 399795619..ced36c9bb 100644
--- a/src/render/picking/qpickevent_p.h
+++ b/src/render/picking/qpickevent_p.h
@@ -48,13 +48,19 @@
// We mean it.
//
+#include <Qt3DCore/qnodeid.h>
+
#include <private/qobject_p.h>
+#include <private/qt3drender_global_p.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QPickEventPrivate : public QObjectPrivate
+class QPickEvent;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QPickEventPrivate : public QObjectPrivate
{
public:
QPickEventPrivate()
@@ -75,6 +81,9 @@ public:
QPickEvent::Buttons m_button;
int m_buttons;
int m_modifiers;
+ Qt3DCore::QNodeId m_entity;
+
+ static QPickEventPrivate *get(QPickEvent *object);
};
} // Qt3DRender
diff --git a/src/render/picking/qpicktriangleevent.cpp b/src/render/picking/qpicktriangleevent.cpp
index ae96d5d2b..2a4cdfea2 100644
--- a/src/render/picking/qpicktriangleevent.cpp
+++ b/src/render/picking/qpicktriangleevent.cpp
@@ -61,6 +61,7 @@ public:
uint m_vertex1Index;
uint m_vertex2Index;
uint m_vertex3Index;
+ QVector3D m_uvw;
};
/*!
@@ -69,7 +70,15 @@ public:
\brief The QPickTriangleEvent class holds information when a triangle is picked
- \sa QPickEvent
+ When QPickingSettings::pickMode() is set to QPickingSettings::TrianglePicking, the signals
+ on QObjectPicker will carry an instance of QPickTriangleEvent.
+
+ This contains the details of the triangle that was picked.
+
+ \note In the case of indexed rendering, the point indices are relative to the
+ array of coordinates, not the array of indices.
+
+ \sa QPickingSettings, QPickEvent, QObjectPicker, QAttribute
\since 5.7
*/
@@ -78,7 +87,16 @@ public:
* \instantiates Qt3DRender::QPickTriangleEvent
* \inqmlmodule Qt3D.Render
* \brief PickTriangleEvent holds information when a triangle is picked.
- * \sa ObjectPicker
+ *
+ * When QPickingSettings::pickMode() is set to QPickingSettings::TrianglePicking, the signals
+ * on QObjectPicker will carry an instance of QPickTriangleEvent.
+ *
+ * This contains the details of the triangle that was picked.
+ *
+ * \note In case of indexed rendering, the point indices are relative to the
+ * array of indices, not the array of coordinates.
+ *
+ * \sa PickingSettings, PickEvent, ObjectPicker, Attribute
*/
@@ -104,7 +122,8 @@ QPickTriangleEvent::QPickTriangleEvent()
*/
// NOTE: remove in Qt6
QPickTriangleEvent::QPickTriangleEvent(const QPointF &position, const QVector3D &worldIntersection, const QVector3D &localIntersection, float distance,
- uint triangleIndex, uint vertex1Index, uint vertex2Index, uint vertex3Index)
+ uint triangleIndex, uint vertex1Index, uint vertex2Index,
+ uint vertex3Index)
: QPickEvent(*new QPickTriangleEventPrivate())
{
Q_D(QPickTriangleEvent);
@@ -118,7 +137,11 @@ QPickTriangleEvent::QPickTriangleEvent(const QPointF &position, const QVector3D
d->m_vertex3Index = vertex3Index;
}
-QPickTriangleEvent::QPickTriangleEvent(const QPointF &position, const QVector3D &worldIntersection, const QVector3D &localIntersection, float distance, uint triangleIndex, uint vertex1Index, uint vertex2Index, uint vertex3Index, QPickEvent::Buttons button, int buttons, int modifiers)
+QPickTriangleEvent::QPickTriangleEvent(const QPointF &position, const QVector3D &worldIntersection,
+ const QVector3D &localIntersection, float distance,
+ uint triangleIndex, uint vertex1Index, uint vertex2Index,
+ uint vertex3Index, QPickEvent::Buttons button, int buttons,
+ int modifiers, const QVector3D &uvw)
: QPickEvent(*new QPickTriangleEventPrivate())
{
Q_D(QPickTriangleEvent);
@@ -133,6 +156,7 @@ QPickTriangleEvent::QPickTriangleEvent(const QPointF &position, const QVector3D
d->m_button = button;
d->m_buttons = buttons;
d->m_modifiers = modifiers;
+ d->m_uvw = uvw;
}
/*! \internal */
@@ -160,11 +184,11 @@ uint QPickTriangleEvent::triangleIndex() const
/*!
\qmlproperty uint Qt3D.Render::PickTriangleEvent::vertex1Index
- Specifies the vertex 1 index of the event
+ Specifies the index of the first vertex in the triangle
*/
/*!
\property Qt3DRender::QPickTriangleEvent::vertex1Index
- Specifies the vertex 1 index of the event
+ Specifies the index of the first vertex in the triangle
*/
/*!
* \brief QPickTriangleEvent::vertex1Index
@@ -178,11 +202,11 @@ uint QPickTriangleEvent::vertex1Index() const
/*!
\qmlproperty uint Qt3D.Render::PickTriangleEvent::vertex2Index
- Specifies the vertex 2 index of the event
+ Specifies the index of the second vertex in the triangle
*/
/*!
\property Qt3DRender::QPickTriangleEvent::vertex2Index
- Specifies the vertex 2 index of the event
+ Specifies the index of the second vertex in the triangle
*/
/*!
* \brief QPickTriangleEvent::vertex2Index
@@ -196,15 +220,15 @@ uint QPickTriangleEvent::vertex2Index() const
/*!
\qmlproperty uint Qt3D.Render::PickTriangleEvent::vertex3Index
- Specifies the vertex 3 index of the event
+ Specifies the index of the third vertex in the triangle
*/
/*!
\property Qt3DRender::QPickTriangleEvent::vertex3Index
- Specifies the vertex 3 index of the event
+ Specifies the index of the third vertex in the triangle
*/
/*!
* \brief QPickTriangleEvent::vertex3Index
- * \returns index of third point of picked triangle
+ * Returns index of third point of picked triangle
*/
uint QPickTriangleEvent::vertex3Index() const
{
@@ -212,6 +236,12 @@ uint QPickTriangleEvent::vertex3Index() const
return d->m_vertex3Index;
}
+QVector3D QPickTriangleEvent::uvw() const
+{
+ Q_D(const QPickTriangleEvent);
+ return d->m_uvw;
+}
+
} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/picking/qpicktriangleevent.h b/src/render/picking/qpicktriangleevent.h
index 7cafa1aeb..7655a0b94 100644
--- a/src/render/picking/qpicktriangleevent.h
+++ b/src/render/picking/qpicktriangleevent.h
@@ -54,12 +54,14 @@ class QT3DRENDERSHARED_EXPORT QPickTriangleEvent : public QPickEvent
Q_PROPERTY(uint vertex1Index READ vertex1Index CONSTANT)
Q_PROPERTY(uint vertex2Index READ vertex2Index CONSTANT)
Q_PROPERTY(uint vertex3Index READ vertex3Index CONSTANT)
+ Q_PROPERTY(QVector3D uvw READ uvw CONSTANT)
public:
QPickTriangleEvent();
QPickTriangleEvent(const QPointF &position, const QVector3D& worldIntersection, const QVector3D& localIntersection, float distance,
uint triangleIndex, uint vertex1Index, uint vertex2Index, uint vertex3Index);
QPickTriangleEvent(const QPointF &position, const QVector3D& worldIntersection, const QVector3D& localIntersection, float distance,
- uint triangleIndex, uint vertex1Index, uint vertex2Index, uint vertex3Index, Buttons button, int buttons, int modifiers);
+ uint triangleIndex, uint vertex1Index, uint vertex2Index, uint vertex3Index, Buttons button, int buttons, int modifiers,
+ const QVector3D &uvw);
~QPickTriangleEvent();
public:
@@ -67,6 +69,7 @@ public:
uint vertex1Index() const;
uint vertex2Index() const;
uint vertex3Index() const;
+ QVector3D uvw() const;
private:
Q_DECLARE_PRIVATE(QPickTriangleEvent)
diff --git a/src/render/raycasting/qabstractcollisionqueryservice.cpp b/src/render/raycasting/qabstractcollisionqueryservice.cpp
index 132af00c9..993ad840e 100644
--- a/src/render/raycasting/qabstractcollisionqueryservice.cpp
+++ b/src/render/raycasting/qabstractcollisionqueryservice.cpp
@@ -61,9 +61,11 @@ void QAbstractCollisionQueryService::setResultHandle(QCollisionQueryResult &resu
result.d_func()->setHandle(handle);
}
-void QAbstractCollisionQueryService::addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance)
+void QAbstractCollisionQueryService::addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity,
+ const QVector3D& intersection, float distance,
+ const QVector3D& uvw)
{
- result.d_func()->addEntityHit(entity, intersection, distance);
+ result.d_func()->addEntityHit(entity, intersection, distance, uvw);
}
} // RayCasting
diff --git a/src/render/raycasting/qabstractcollisionqueryservice_p.h b/src/render/raycasting/qabstractcollisionqueryservice_p.h
index e2f9fb65a..1c1261937 100644
--- a/src/render/raycasting/qabstractcollisionqueryservice_p.h
+++ b/src/render/raycasting/qabstractcollisionqueryservice_p.h
@@ -79,6 +79,7 @@ public:
class QT3DRENDERSHARED_EXPORT QAbstractCollisionQueryService : public Qt3DCore::QAbstractServiceProvider
{
+ Q_OBJECT
public:
enum QueryMode {
FirstHit,
@@ -96,7 +97,8 @@ protected:
QAbstractCollisionQueryService(QAbstractCollisionQueryServicePrivate &dd);
void setResultHandle(QCollisionQueryResult &result, const QQueryHandle &handle);
- void addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D &intersection, float distance);
+ void addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D &intersection,
+ float distance, const QVector3D &uvw);
private:
Q_DECLARE_PRIVATE(QAbstractCollisionQueryService)
diff --git a/src/render/raycasting/qboundingvolume_p.h b/src/render/raycasting/qboundingvolume_p.h
index f29d08d52..8267c2b18 100644
--- a/src/render/raycasting/qboundingvolume_p.h
+++ b/src/render/raycasting/qboundingvolume_p.h
@@ -72,7 +72,8 @@ public:
};
virtual Qt3DCore::QNodeId id() const = 0;
- virtual bool intersects(const QRay3D &ray, QVector3D *q = nullptr) const = 0;
+ virtual bool intersects(const QRay3D &ray, QVector3D *q = nullptr,
+ QVector3D *uvw = nullptr) const = 0;
virtual Type type() const = 0;
};
diff --git a/src/render/raycasting/qcollisionqueryresult.cpp b/src/render/raycasting/qcollisionqueryresult.cpp
index 4d887d287..62975200c 100644
--- a/src/render/raycasting/qcollisionqueryresult.cpp
+++ b/src/render/raycasting/qcollisionqueryresult.cpp
@@ -56,9 +56,10 @@ QCollisionQueryResultPrivate::QCollisionQueryResultPrivate(const QCollisionQuery
{
}
-void QCollisionQueryResultPrivate::addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance)
+void QCollisionQueryResultPrivate::addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection,
+ float distance, const QVector3D& uvw)
{
- m_hits.append(QCollisionQueryResult::Hit(entity, intersection, distance));
+ m_hits.append(QCollisionQueryResult::Hit(entity, intersection, distance, uvw));
}
void QCollisionQueryResultPrivate::setHandle(const QQueryHandle &handle)
diff --git a/src/render/raycasting/qcollisionqueryresult_p.h b/src/render/raycasting/qcollisionqueryresult_p.h
index 18b45370a..e13dda74a 100644
--- a/src/render/raycasting/qcollisionqueryresult_p.h
+++ b/src/render/raycasting/qcollisionqueryresult_p.h
@@ -69,13 +69,27 @@ class QT3DRENDERSHARED_EXPORT QCollisionQueryResult
{
public:
struct Hit {
- Hit() : m_distance(-1.f), m_triangleIndex(0) { m_vertexIndex[0] = m_vertexIndex[1] = m_vertexIndex[2] = 0; }
- Hit(const Qt3DCore::QNodeId &entity, const QVector3D &intersection, float distance) : m_entityId(entity), m_intersection(intersection), m_distance(distance) { }
+ Hit()
+ : m_distance(-1.f)
+ , m_triangleIndex(0)
+ {
+ m_vertexIndex[0] = m_vertexIndex[1] = m_vertexIndex[2] = 0;
+ }
+
+ Hit(Qt3DCore::QNodeId entity, const QVector3D &intersection, float distance, const QVector3D &uvw)
+ : m_entityId(entity)
+ , m_intersection(intersection)
+ , m_distance(distance)
+ , m_uvw(uvw)
+ {
+ }
+
Qt3DCore::QNodeId m_entityId;
QVector3D m_intersection;
float m_distance;
uint m_triangleIndex;
uint m_vertexIndex[3];
+ QVector3D m_uvw;
};
QCollisionQueryResult();
@@ -123,7 +137,8 @@ public:
explicit QCollisionQueryResultPrivate(const QCollisionQueryResultPrivate &copy);
void setHandle(const QQueryHandle &handle);
- void addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance);
+ void addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance,
+ const QVector3D& uvw);
QQueryHandle m_handle;
QVector<QCollisionQueryResult::Hit> m_hits;
diff --git a/src/render/raycasting/qraycastingservice.cpp b/src/render/raycasting/qraycastingservice.cpp
index e92234836..e0c7b6199 100644
--- a/src/render/raycasting/qraycastingservice.cpp
+++ b/src/render/raycasting/qraycastingservice.cpp
@@ -68,6 +68,7 @@ struct Hit
float distance;
Qt3DCore::QNodeId id;
QVector3D intersection;
+ QVector3D uvw;
};
bool compareHitsDistance(const Hit &a, const Hit &b)
@@ -78,7 +79,7 @@ bool compareHitsDistance(const Hit &a, const Hit &b)
Hit volumeRayIntersection(const QBoundingVolume *volume, const QRay3D &ray)
{
Hit hit;
- if ((hit.intersects = volume->intersects(ray, &hit.intersection))) {
+ if ((hit.intersects = volume->intersects(ray, &hit.intersection, &hit.uvw))) {
hit.distance = ray.projectedDistance(hit.intersection);
hit.id = volume->id();
}
@@ -134,12 +135,12 @@ QCollisionQueryResult QRayCastingServicePrivate::collides(const QRay3D &ray, QBo
if (mode == QAbstractCollisionQueryService::FirstHit) {
Hit firstHit = QtConcurrent::blockingMappedReduced<Hit>(volumes, gathererFunctor, reduceToFirstHit);
if (firstHit.intersects)
- q->addEntityHit(result, firstHit.id, firstHit.intersection, firstHit.distance);
+ q->addEntityHit(result, firstHit.id, firstHit.intersection, firstHit.distance, firstHit.uvw);
} else {
QVector<Hit> hits = QtConcurrent::blockingMappedReduced<QVector<Hit> >(volumes, gathererFunctor, reduceToAllHits);
std::sort(hits.begin(), hits.end(), compareHitsDistance);
for (const Hit &hit : qAsConst(hits))
- q->addEntityHit(result, hit.id, hit.intersection, hit.distance);
+ q->addEntityHit(result, hit.id, hit.intersection, hit.distance, hit.uvw);
}
return result;
@@ -154,6 +155,7 @@ QCollisionQueryResult::Hit QRayCastingServicePrivate::collides(const QRay3D &ray
result.m_distance = hit.distance;
result.m_entityId = hit.id;
result.m_intersection = hit.intersection;
+ result.m_uvw = hit.uvw;
}
return result;
}
diff --git a/src/render/render.pro b/src/render/render.pro
index 1b90af82f..c31db94b7 100644
--- a/src/render/render.pro
+++ b/src/render/render.pro
@@ -41,6 +41,7 @@ SOURCES += \
MODULE_PLUGIN_TYPES = \
sceneparsers \
- geometryloaders
+ geometryloaders \
+ renderplugins
load(qt_module)
diff --git a/src/render/renderlogging.cpp b/src/render/renderlogging.cpp
index 820392b68..b9d423163 100644
--- a/src/render/renderlogging.cpp
+++ b/src/render/renderlogging.cpp
@@ -45,17 +45,17 @@ namespace Qt3DRender {
namespace Render {
-Q_LOGGING_CATEGORY(Backend, "Qt3D.Renderer.Backend")
-Q_LOGGING_CATEGORY(Frontend, "Qt3D.Renderer.Frontend")
-Q_LOGGING_CATEGORY(Io, "Qt3D.Renderer.IO")
-Q_LOGGING_CATEGORY(Jobs, "Qt3D.Renderer.Jobs")
-Q_LOGGING_CATEGORY(Framegraph, "Qt3D.Renderer.Framegraph")
-Q_LOGGING_CATEGORY(RenderNodes, "Qt3D.Renderer.RenderNodes")
-Q_LOGGING_CATEGORY(Rendering, "Qt3D.Renderer.Rendering")
-Q_LOGGING_CATEGORY(Memory, "Qt3D.Renderer.Memory")
-Q_LOGGING_CATEGORY(Shaders, "Qt3D.Renderer.Shaders")
-Q_LOGGING_CATEGORY(RenderStates, "Qt3D.Renderer.RenderStates")
-Q_LOGGING_CATEGORY(VSyncAdvanceService, "Qt3D.Renderer.VsyncAdvanceService")
+Q_LOGGING_CATEGORY(Backend, "Qt3D.Renderer.Backend", QtWarningMsg)
+Q_LOGGING_CATEGORY(Frontend, "Qt3D.Renderer.Frontend", QtWarningMsg)
+Q_LOGGING_CATEGORY(Io, "Qt3D.Renderer.IO", QtWarningMsg)
+Q_LOGGING_CATEGORY(Jobs, "Qt3D.Renderer.Jobs", QtWarningMsg)
+Q_LOGGING_CATEGORY(Framegraph, "Qt3D.Renderer.Framegraph", QtWarningMsg)
+Q_LOGGING_CATEGORY(RenderNodes, "Qt3D.Renderer.RenderNodes", QtWarningMsg)
+Q_LOGGING_CATEGORY(Rendering, "Qt3D.Renderer.Rendering", QtWarningMsg)
+Q_LOGGING_CATEGORY(Memory, "Qt3D.Renderer.Memory", QtWarningMsg)
+Q_LOGGING_CATEGORY(Shaders, "Qt3D.Renderer.Shaders", QtWarningMsg)
+Q_LOGGING_CATEGORY(RenderStates, "Qt3D.Renderer.RenderStates", QtWarningMsg)
+Q_LOGGING_CATEGORY(VSyncAdvanceService, "Qt3D.Renderer.VsyncAdvanceService", QtWarningMsg)
} // namespace Render
diff --git a/src/render/texture/apitexturemanager_p.h b/src/render/texture/apitexturemanager_p.h
index 2fd340e7e..91747b3bc 100644
--- a/src/render/texture/apitexturemanager_p.h
+++ b/src/render/texture/apitexturemanager_p.h
@@ -237,6 +237,21 @@ public:
return true;
}
+ // Change the texture data generator for given texture, if it is a non-shared texture
+ // Return true, if it was changed successfully, false otherwise
+ bool setGenerator(APITexture *tex, const QTextureGeneratorPtr &generator)
+ {
+ Q_ASSERT(tex);
+
+ if (isShared(tex))
+ return false;
+
+ tex->setGenerator(generator);
+ m_updatedTextures.push_back(tex);
+
+ return true;
+ }
+
// Retrieves abandoned textures. This should be regularly called from the OpenGL thread
// to make sure needed GL resources are de-allocated.
QVector<APITexture*> takeAbandonedTextures()
@@ -258,7 +273,7 @@ public:
if (impl->isUnique())
return false;
- auto it = m_sharedTextures.find(impl);
+ auto it = m_sharedTextures.constFind(impl);
if (it == m_sharedTextures.cend())
return false;
diff --git a/src/render/texture/gltexture.cpp b/src/render/texture/gltexture.cpp
index 0fc37891d..854789e94 100644
--- a/src/render/texture/gltexture.cpp
+++ b/src/render/texture/gltexture.cpp
@@ -120,7 +120,7 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
if (m_properties.target != QAbstractTexture::TargetAutomatic)
qWarning() << "[Qt3DRender::GLTexture] When a texture provides a generator, it's target is expected to be TargetAutomatic";
- m_properties.target = m_textureData->target();
+ m_actualTarget = m_textureData->target();
m_properties.width = m_textureData->width();
m_properties.height = m_textureData->height();
m_properties.depth = m_textureData->depth();
@@ -188,6 +188,8 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
if (!m_gl) {
m_gl = buildGLTexture();
+ if (!m_gl)
+ return nullptr;
m_gl->allocateStorage();
if (!m_gl->isStorageAllocated()) {
qWarning() << Q_FUNC_INFO << "texture storage allocation failed";
@@ -224,6 +226,7 @@ void GLTexture::setProperties(const TextureProperties &props)
if (m_properties != props) {
m_properties = props;
QMutexLocker locker(&m_dirtyFlagMutex);
+ m_actualTarget = props.target;
m_dirty |= Properties;
}
}
@@ -278,6 +281,26 @@ void GLTexture::setImages(const QVector<Image> &images)
}
}
+void GLTexture::setGenerator(const QTextureGeneratorPtr &generator)
+{
+ // Note: we do not compare if the generator is different
+ // as in some cases we may want to reset the same generator to force a reload
+ // e.g when using remote urls for textures
+ if (m_dataFunctor)
+ m_textureDataManager->releaseData(m_dataFunctor, this);
+
+ m_textureData.reset();
+ m_dataFunctor = generator;
+
+ if (m_dataFunctor) {
+ m_textureDataManager->requestData(m_dataFunctor, this);
+ requestUpload();
+ }
+}
+
+// Return nullptr if
+// - context cannot be obtained
+// - texture hasn't yet been loaded
QOpenGLTexture *GLTexture::buildGLTexture()
{
QOpenGLContext *ctx = QOpenGLContext::currentContext();
@@ -286,12 +309,14 @@ QOpenGLTexture *GLTexture::buildGLTexture()
return nullptr;
}
- if (m_properties.target == QAbstractTexture::TargetAutomatic) {
- qWarning() << Q_FUNC_INFO << "something went wrong, target shouldn't be automatic at this point";
+ if (m_actualTarget == QAbstractTexture::TargetAutomatic) {
+ // If the target is automatic at this point, it means that the texture
+ // hasn't been loaded yet (case of remote urls) and that loading failed
+ // and that target format couldn't be deduced
return nullptr;
}
- QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(m_properties.target));
+ QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(m_actualTarget));
// m_format may not be ES2 compatible. Now it's time to convert it, if necessary.
QAbstractTexture::TextureFormat format = m_properties.format;
@@ -329,16 +354,16 @@ QOpenGLTexture *GLTexture::buildGLTexture()
static_cast<QOpenGLTexture::TextureFormat>(format));
glTex->setSize(m_properties.width, m_properties.height, m_properties.depth);
// Set layers count if texture array
- if (m_properties.target == QAbstractTexture::Target1DArray ||
- m_properties.target == QAbstractTexture::Target2DArray ||
- m_properties.target == QAbstractTexture::Target3D ||
- m_properties.target == QAbstractTexture::Target2DMultisampleArray ||
- m_properties.target == QAbstractTexture::TargetCubeMapArray) {
+ if (m_actualTarget == QAbstractTexture::Target1DArray ||
+ m_actualTarget == QAbstractTexture::Target2DArray ||
+ m_actualTarget == QAbstractTexture::Target3D ||
+ m_actualTarget == QAbstractTexture::Target2DMultisampleArray ||
+ m_actualTarget == QAbstractTexture::TargetCubeMapArray) {
glTex->setLayers(m_properties.layers);
}
- if (m_properties.target == QAbstractTexture::Target2DMultisample ||
- m_properties.target == QAbstractTexture::Target2DMultisampleArray) {
+ if (m_actualTarget == QAbstractTexture::Target2DMultisample ||
+ m_actualTarget == QAbstractTexture::Target2DMultisampleArray) {
// Set samples count if multisampled texture
// (multisampled textures don't have mipmaps)
glTex->setSamples(m_properties.samples);
@@ -384,7 +409,7 @@ void GLTexture::uploadGLTextureData()
for (int layer = 0; layer < data->layers(); layer++) {
for (int face = 0; face < data->faces(); face++) {
for (int level = 0; level < mipLevels; level++) {
- // ensure we don't accidently cause a detach / copy of the raw bytes
+ // ensure we don't accidentally cause a detach / copy of the raw bytes
const QByteArray bytes(data->data(layer, face, level));
uploadGLData(m_gl, level, layer,
static_cast<QOpenGLTexture::CubeMapFace>(QOpenGLTexture::CubeMapPositiveX + face),
@@ -399,7 +424,7 @@ void GLTexture::uploadGLTextureData()
for (int i = 0; i < m_images.size(); i++) {
const QTextureImageDataPtr &imgData = m_imageData.at(i);
- // ensure we don't accidently cause a detach / copy of the raw bytes
+ // ensure we don't accidentally cause a detach / copy of the raw bytes
const QByteArray bytes(imgData->data());
uploadGLData(m_gl, m_images[i].mipLevel, m_images[i].layer,
static_cast<QOpenGLTexture::CubeMapFace>(m_images[i].face),
@@ -410,11 +435,11 @@ void GLTexture::uploadGLTextureData()
void GLTexture::updateGLTextureParameters()
{
m_gl->setWrapMode(QOpenGLTexture::DirectionS, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeX));
- if (m_properties.target != QAbstractTexture::Target1D &&
- m_properties.target != QAbstractTexture::Target1DArray &&
- m_properties.target != QAbstractTexture::TargetBuffer)
+ if (m_actualTarget != QAbstractTexture::Target1D &&
+ m_actualTarget != QAbstractTexture::Target1DArray &&
+ m_actualTarget != QAbstractTexture::TargetBuffer)
m_gl->setWrapMode(QOpenGLTexture::DirectionT, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeY));
- if (m_properties.target == QAbstractTexture::Target3D)
+ if (m_actualTarget == QAbstractTexture::Target3D)
m_gl->setWrapMode(QOpenGLTexture::DirectionR, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeZ));
m_gl->setMinMagFilters(static_cast<QOpenGLTexture::Filter>(m_parameters.minificationFilter),
static_cast<QOpenGLTexture::Filter>(m_parameters.magnificationFilter));
diff --git a/src/render/texture/gltexture_p.h b/src/render/texture/gltexture_p.h
index 424e77854..4c0957f76 100644
--- a/src/render/texture/gltexture_p.h
+++ b/src/render/texture/gltexture_p.h
@@ -148,6 +148,16 @@ public:
m_dirty |= TextureData;
}
+ bool isDirty()
+ {
+ QMutexLocker locker(&m_dirtyFlagMutex);
+ return m_dirty == 0 ? false : true;
+ }
+
+ QMutex *textureLock()
+ {
+ return &m_dirtyFlagMutex;
+ }
protected:
template<class APITexture, class APITextureImage>
@@ -164,11 +174,12 @@ protected:
void setParameters(const TextureParameters &params);
void setProperties(const TextureProperties &props);
void setImages(const QVector<Image> &images);
+ void setGenerator(const QTextureGeneratorPtr &generator);
private:
enum DirtyFlag {
- TextureData = 0x01, // one or more generators have been executed, data needs uploading to GPU
+ TextureData = 0x01, // one or more image generators have been executed, data needs uploading to GPU
Properties = 0x02, // texture needs to be (re-)created
Parameters = 0x04 // texture parameters need to be (re-)set
@@ -188,6 +199,8 @@ private:
TextureDataManager *m_textureDataManager;
TextureImageDataManager *m_textureImageDataManager;
+ // target which is actually used for GL texture
+ QAbstractTexture::Target m_actualTarget;
TextureProperties m_properties;
TextureParameters m_parameters;
diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp
index 7703933a4..1bd002104 100644
--- a/src/render/texture/qabstracttexture.cpp
+++ b/src/render/texture/qabstracttexture.cpp
@@ -69,6 +69,11 @@ QAbstractTexturePrivate::QAbstractTexturePrivate()
{
}
+QTextureGeneratorPtr QAbstractTexturePrivate::dataFunctor() const
+{
+ return m_dataFunctor;
+}
+
void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generator)
{
if (generator != m_dataFunctor) {
diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h
index 7f5a32c94..a27ae3729 100644
--- a/src/render/texture/qabstracttexture_p.h
+++ b/src/render/texture/qabstracttexture_p.h
@@ -56,12 +56,13 @@
#include <Qt3DRender/qabstracttexture.h>
#include <Qt3DRender/qtexturewrapmode.h>
#include <Qt3DRender/qtexturegenerator.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class Q_AUTOTEST_EXPORT QAbstractTexturePrivate : public Qt3DCore::QNodePrivate
+class QT3DRENDERSHARED_PRIVATE_EXPORT QAbstractTexturePrivate : public Qt3DCore::QNodePrivate
{
public :
QAbstractTexturePrivate();
@@ -86,6 +87,7 @@ public :
int m_layers;
int m_samples;
+ QTextureGeneratorPtr dataFunctor() const;
void setDataFunctor(const QTextureGeneratorPtr &generator);
private:
diff --git a/src/render/texture/qpaintedtextureimage.cpp b/src/render/texture/qpaintedtextureimage.cpp
index 9ae43378a..4d03eb809 100644
--- a/src/render/texture/qpaintedtextureimage.cpp
+++ b/src/render/texture/qpaintedtextureimage.cpp
@@ -104,14 +104,9 @@ QPaintedTextureImage::~QPaintedTextureImage()
/*!
\property QPaintedTextureImage::width
- Holds the width of the texture image
- */
-
-/*!
- \property QPaintedTextureImage::width
-
- \return the width of the texture image.
- */
+ This property holds the width of the texture image.
+ The width must be greater than or equal to 1.
+*/
int QPaintedTextureImage::width() const
{
Q_D(const QPaintedTextureImage);
@@ -121,14 +116,9 @@ int QPaintedTextureImage::width() const
/*!
\property QPaintedTextureImage::height
- Holds the height of the texture image
- */
-
-/*!
- \property QPaintedTextureImage::height
-
- \return the height of the texture image.
- */
+ This property holds the height of the texture image.
+ The height must be greater than or equal to 1.
+*/
int QPaintedTextureImage::height() const
{
Q_D(const QPaintedTextureImage);
@@ -138,14 +128,11 @@ int QPaintedTextureImage::height() const
/*!
\property QPaintedTextureImage::size
- Holds the width and height of the texture image
- */
+ This property holds the size of the texture image.
-/*!
- \property QPaintedTextureImage::size
+ \sa height, width
- \return the size of the texture image.
- */
+*/
QSize QPaintedTextureImage::size() const
{
Q_D(const QPaintedTextureImage);
@@ -153,7 +140,7 @@ QSize QPaintedTextureImage::size() const
}
/*!
- Sets the width of the texture image. Triggers an update, if the size changes.
+ Sets the width (\a w) of the texture image. Triggers an update, if the size changes.
*/
void QPaintedTextureImage::setWidth(int w)
{
@@ -165,7 +152,7 @@ void QPaintedTextureImage::setWidth(int w)
}
/*!
- Sets the height of the texture image. Triggers an update, if the size changes.
+ Sets the height (\a h) of the texture image. Triggers an update, if the size changes.
*/
void QPaintedTextureImage::setHeight(int h)
{
@@ -177,7 +164,7 @@ void QPaintedTextureImage::setHeight(int h)
}
/*!
- Sets the width and height of the texture image. Triggers an update, if the size changes.
+ Sets the width and height of the texture image. Triggers an update, if the \a size changes.
*/
void QPaintedTextureImage::setSize(QSize size)
{
@@ -206,9 +193,10 @@ void QPaintedTextureImage::setSize(QSize size)
}
/*!
- Will trigger an update of the texture image, meaning the paint() method will
- be invoked.
- */
+ Schedules the painted texture's paint() function to be called,
+ which in turn uploads the new image to the GPU.
+ Parameter \a rect is currently unused.
+*/
void QPaintedTextureImage::update(const QRect &rect)
{
Q_UNUSED(rect)
diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp
index 7dc071833..931d66c64 100644
--- a/src/render/texture/qtexture.cpp
+++ b/src/render/texture/qtexture.cpp
@@ -44,7 +44,17 @@
#include "qtexture.h"
#include "qtexture_p.h"
#include <QFileInfo>
+#include <QMimeDatabase>
+#include <QMimeType>
#include <qendian.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/qaspectengine.h>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/texture_p.h>
+#include <Qt3DRender/private/qurlhelper_p.h>
QT_BEGIN_NAMESPACE
@@ -390,7 +400,7 @@ const struct DX10Format
{ DXGI_FORMAT_R8_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } },
{ DXGI_FORMAT_R8G8_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } },
{ DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_UNorm, QOpenGLTexture::UInt16, 2, false } },
-{ DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_UNorm, QOpenGLTexture::UInt16, 4, false } },
+{ DXGI_FORMAT_R16G16_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_UNorm, QOpenGLTexture::UInt16, 4, false } },
// depth formats
{ DXGI_FORMAT_D16_UNORM, { QOpenGLTexture::Depth, QOpenGLTexture::D16, QOpenGLTexture::NoPixelType, 2, false } },
@@ -424,9 +434,8 @@ enum CompressedFormatExtension {
PKM
};
-CompressedFormatExtension texturedCompressedFormat(const QString &source)
+CompressedFormatExtension texturedCompressedFormat(const QString &suffix)
{
- const QString suffix = QFileInfo(source).suffix();
if (suffix == QStringLiteral("pkm"))
return PKM;
if (suffix == QStringLiteral("dds"))
@@ -434,19 +443,14 @@ CompressedFormatExtension texturedCompressedFormat(const QString &source)
return None;
}
-QTextureImageDataPtr setPkmFile(const QString &source)
+QTextureImageDataPtr setPkmFile(QIODevice *source)
{
QTextureImageDataPtr imageData;
- QFile f(source);
- if (!f.open(QIODevice::ReadOnly)) {
- qWarning() << "Failed to open" << source;
- return imageData;
- }
- // ETC1 in PKM, as generated by f.ex. Android's etc1tool
+ // ETC1 in PKM, as generated by source->ex. Android's etc1tool
static const char pkmMagic[] = { 'P', 'K', 'M', ' ', '1', '0' };
const int pkmHeaderSize = 6 + 2 + 4 * 2;
- const QByteArray header = f.read(pkmHeaderSize);
+ const QByteArray header = source->read(pkmHeaderSize);
if (header.size() >= pkmHeaderSize && !qstrncmp(header.constData(), pkmMagic, 6)) {
imageData = QTextureImageDataPtr::create();
imageData->setTarget(QOpenGLTexture::Target2D);
@@ -455,7 +459,7 @@ QTextureImageDataPtr setPkmFile(const QString &source)
imageData->setWidth(qFromBigEndian(*(reinterpret_cast<const quint16 *>(header.constData() + 6 + 2))));
imageData->setHeight(qFromBigEndian(*(reinterpret_cast<const quint16 *>(header.constData() + 6 + 2 + 2))));
imageData->setDepth(1);
- const QByteArray data = f.readAll();
+ const QByteArray data = source->readAll();
if (data.size() < (imageData->width() / 4) * (imageData->height() / 4) * 8)
qWarning() << "Unexpected end of ETC1 data in" << source;
const bool isCompressed = true;
@@ -467,17 +471,12 @@ QTextureImageDataPtr setPkmFile(const QString &source)
return imageData;
}
-QTextureImageDataPtr setDdsFile(const QString &source)
+QTextureImageDataPtr setDdsFile(QIODevice *source)
{
QTextureImageDataPtr imageData;
- QFile f(source);
- if (!f.open(QIODevice::ReadOnly)) {
- qWarning() << "Failed to open" << source;
- return imageData;
- }
DdsHeader header;
- if ((f.read(reinterpret_cast<char *>(&header), sizeof header) != sizeof header)
+ if ((source->read(reinterpret_cast<char *>(&header), sizeof header) != sizeof header)
|| (qstrncmp(header.magic, "DDS ", 4) != 0))
return imageData;
@@ -490,7 +489,7 @@ QTextureImageDataPtr setDdsFile(const QString &source)
if (fourCC == DdsFourCC<'D', 'X', '1', '0'>::value) {
// DX10 texture
DdsDX10Header dx10Header;
- if (f.read(reinterpret_cast<char *>(&dx10Header), sizeof dx10Header) != sizeof dx10Header)
+ if (source->read(reinterpret_cast<char *>(&dx10Header), sizeof dx10Header) != sizeof dx10Header)
return imageData;
layers = qFromLittleEndian(dx10Header.arraySize);
@@ -582,13 +581,13 @@ QTextureImageDataPtr setDdsFile(const QString &source)
// data
const int dataSize = layers * layerSize;
- const QByteArray data = f.read(dataSize);
+ const QByteArray data = source->read(dataSize);
if (data.size() < dataSize) {
qWarning() << "Unexpected end of data in" << source;
return imageData;
}
- if (!f.atEnd())
+ if (!source->atEnd())
qWarning() << "Unrecognized data in" << source;
imageData = QTextureImageDataPtr::create();
@@ -626,26 +625,39 @@ QTextureImageDataPtr TextureLoadingHelper::loadTextureData(const QUrl &url, bool
#endif
) {
const QString source = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(url);
- const CompressedFormatExtension formatExtension = texturedCompressedFormat(source);
- switch (formatExtension) {
- case DDS:
- textureData = setDdsFile(source);
- break;
- case PKM:
- textureData = setPkmFile(source);
- break;
- default:
- QImage img;
- if (img.load(source)) {
- textureData = QTextureImageDataPtr::create();
- textureData->setImage(mirrored ? img.mirrored() : img);
- }
- break;
- }
+ QFile f(source);
+ if (!f.open(QIODevice::ReadOnly))
+ qWarning() << "Failed to open" << source;
+ else
+ textureData = loadTextureData(&f, QFileInfo(source).suffix(), allow3D, mirrored);
+ }
+ return textureData;
+}
- if (!allow3D && textureData && (textureData->layers() > 1 || textureData->depth() > 1))
- qWarning() << "Texture data has a 3rd dimension which wasn't expected";
+QTextureImageDataPtr TextureLoadingHelper::loadTextureData(QIODevice *data, const QString& suffix,
+ bool allow3D, bool mirrored)
+{
+ QTextureImageDataPtr textureData;
+ const CompressedFormatExtension formatExtension = texturedCompressedFormat(suffix);
+ switch (formatExtension) {
+ case DDS:
+ textureData = setDdsFile(data);
+ break;
+ case PKM:
+ textureData = setPkmFile(data);
+ break;
+ default: {
+ QImage img;
+ if (img.load(data, suffix.toLatin1())) {
+ textureData = QTextureImageDataPtr::create();
+ textureData->setImage(mirrored ? img.mirrored() : img);
+ }
+ break;
+ }
}
+
+ if (!allow3D && textureData && (textureData->layers() > 1 || textureData->depth() > 1))
+ qWarning() << "Texture data has a 3rd dimension which wasn't expected";
return textureData;
}
@@ -653,8 +665,43 @@ QTextureDataPtr QTextureFromSourceGenerator::operator ()()
{
QTextureDataPtr generatedData = QTextureDataPtr::create();
m_status = QAbstractTexture::Loading;
+ QTextureImageDataPtr textureData;
+
+ if (!Qt3DCore::QDownloadHelperService::isLocal(m_url)) {
+ if (m_sourceData.isEmpty()) {
+ // first time around, trigger a download
+ if (m_texture) {
+ auto downloadService = Qt3DCore::QDownloadHelperService::getService(m_engine);
+ Qt3DCore::QDownloadRequestPtr request(new TextureDownloadRequest(m_texture, m_url,
+ m_engine));
+ downloadService->submitRequest(request);
+ }
+ return generatedData;
+ }
+
+ // second time around, we have the data
+ QT_PREPEND_NAMESPACE(QBuffer) buffer(&m_sourceData);
+ if (buffer.open(QIODevice::ReadOnly)) {
+ QString suffix = m_url.toString();
+ suffix = suffix.right(suffix.length() - suffix.lastIndexOf('.'));
+
+ QStringList ext(suffix);
+
+ QMimeDatabase db;
+ QMimeType mtype = db.mimeTypeForData(m_sourceData);
+ if (mtype.isValid()) {
+ ext << mtype.suffixes();
+ }
- const QTextureImageDataPtr textureData = TextureLoadingHelper::loadTextureData(m_url, true, m_mirrored);
+ for (QString s: qAsConst(ext)) {
+ textureData = TextureLoadingHelper::loadTextureData(&buffer, suffix, true, m_mirrored);
+ if (textureData && textureData->data().length() > 0)
+ break;
+ }
+ }
+ } else {
+ textureData = TextureLoadingHelper::loadTextureData(m_url, true, m_mirrored);
+ }
if (textureData && textureData->data().length() > 0) {
generatedData->setTarget(static_cast<QAbstractTexture::Target>(textureData->target()));
@@ -672,12 +719,55 @@ QTextureDataPtr QTextureFromSourceGenerator::operator ()()
return generatedData;
}
+TextureDownloadRequest::TextureDownloadRequest(Qt3DCore::QNodeId texture, const QUrl& source,
+ Qt3DCore::QAspectEngine *engine)
+ : Qt3DCore::QDownloadRequest(source)
+ , m_texture(texture)
+ , m_engine(engine)
+{
+
+}
+
+// Executed in download thread
+void TextureDownloadRequest::onCompleted()
+{
+ if (cancelled() || !succeeded())
+ return;
+
+ QRenderAspectPrivate* d_aspect = QRenderAspectPrivate::findPrivate(m_engine);
+ if (!d_aspect)
+ return;
+
+ Render::Texture *texture = d_aspect->m_nodeManagers->textureManager()->lookupResource(m_texture);
+ if (!texture)
+ return;
+
+ QSharedPointer<QTextureFromSourceGenerator> functor =
+ qSharedPointerCast<QTextureFromSourceGenerator>(texture->dataGenerator());
+ functor->m_sourceData = m_data;
+
+ // mark the component as dirty so that the functor runs again in the correct job
+ texture->addDirtyFlag(Render::Texture::DirtyDataGenerator);
+}
+
QTextureLoaderPrivate::QTextureLoaderPrivate()
: QAbstractTexturePrivate()
, m_mirrored(true)
{
}
+void QTextureLoaderPrivate::setScene(Qt3DCore::QScene *scene)
+{
+ QAbstractTexturePrivate::setScene(scene);
+ updateFunctor();
+}
+
+void QTextureLoaderPrivate::updateFunctor()
+{
+ Qt3DCore::QAspectEngine *engine = m_scene ? m_scene->engine() : nullptr;
+ setDataFunctor(QTextureFromSourceGeneratorPtr::create(m_id, m_source, m_mirrored, engine));
+}
+
/*!
\class Qt3DRender::QTexture1D
\inmodule Qt3DRender
@@ -900,10 +990,25 @@ QTextureBuffer::~QTextureBuffer()
/*!
* Constructs a new Qt3DRender::QTextureLoader instance with \a parent as parent.
+ *
+ * Note that by default, if not contradicted by the file metadata, the loaded texture
+ * will have the following properties set:
+ * - wrapMode set to Repeat
+ * - minificationFilter set to LinearMipMapLinear
+ * - magnificationFilter set to Linear
+ * - generateMipMaps set to true
+ * - maximumAnisotropy set to 16.0f
+ * - target set to TargetAutomatic
*/
QTextureLoader::QTextureLoader(QNode *parent)
: QAbstractTexture(*new QTextureLoaderPrivate, parent)
{
+ d_func()->m_wrapMode.setX(QTextureWrapMode::Repeat);
+ d_func()->m_wrapMode.setY(QTextureWrapMode::Repeat);
+ d_func()->m_minFilter = LinearMipMapLinear;
+ d_func()->m_magFilter = Linear;
+ d_func()->m_autoMipMap = true;
+ d_func()->m_maximumAnisotropy = 16.0f;
d_func()->m_target = TargetAutomatic;
}
@@ -936,7 +1041,7 @@ void QTextureLoader::setSource(const QUrl& source)
Q_D(QTextureLoader);
if (source != d->m_source) {
d->m_source = source;
- d->setDataFunctor(QTextureFromSourceGeneratorPtr::create(d->m_source, d->m_mirrored));
+ d->updateFunctor();
const bool blocked = blockNotifications(true);
emit sourceChanged(source);
blockNotifications(blocked);
@@ -984,7 +1089,7 @@ void QTextureLoader::setMirrored(bool mirrored)
Q_D(QTextureLoader);
if (mirrored != d->m_mirrored) {
d->m_mirrored = mirrored;
- d->setDataFunctor(QTextureFromSourceGeneratorPtr::create(d->m_source, d->m_mirrored));
+ d->updateFunctor();
const bool blocked = blockNotifications(true);
emit mirroredChanged(mirrored);
blockNotifications(blocked);
@@ -1000,7 +1105,8 @@ bool QTextureFromSourceGenerator::operator ==(const QTextureGenerator &other) co
const QTextureFromSourceGenerator *otherFunctor = functor_cast<QTextureFromSourceGenerator>(&other);
return (otherFunctor != nullptr &&
otherFunctor->m_url == m_url &&
- otherFunctor->m_mirrored == m_mirrored);
+ otherFunctor->m_mirrored == m_mirrored &&
+ otherFunctor->m_engine == m_engine);
}
QUrl QTextureFromSourceGenerator::url() const
@@ -1018,16 +1124,18 @@ bool QTextureFromSourceGenerator::isMirrored() const
* instance with \a url.
* \param url
*/
-QTextureFromSourceGenerator::QTextureFromSourceGenerator(const QUrl &url, bool mirrored)
+QTextureFromSourceGenerator::QTextureFromSourceGenerator(Qt3DCore::QNodeId texture,
+ const QUrl &url, bool mirrored,
+ Qt3DCore::QAspectEngine *engine)
: QTextureGenerator()
, m_url(url)
, m_status(QAbstractTexture::None)
, m_mirrored(mirrored)
+ , m_texture(texture)
+ , m_engine(engine)
{
}
} // namespace Qt3DRender
QT_END_NAMESPACE
-
-
diff --git a/src/render/texture/qtexture_p.h b/src/render/texture/qtexture_p.h
index a0ea71a58..4afb14d62 100644
--- a/src/render/texture/qtexture_p.h
+++ b/src/render/texture/qtexture_p.h
@@ -51,8 +51,11 @@
// We mean it.
//
+#include <Qt3DCore/QNodeId>
+#include <Qt3DCore/private/qdownloadhelperservice_p.h>
#include <Qt3DRender/private/qabstracttexture_p.h>
#include <Qt3DRender/qtexturegenerator.h>
+#include <Qt3DRender/qtexture.h>
QT_BEGIN_NAMESPACE
@@ -63,14 +66,30 @@ class QTextureLoaderPrivate : public QAbstractTexturePrivate
public:
QTextureLoaderPrivate();
+ void setScene(Qt3DCore::QScene *scene) override;
+ void updateFunctor();
+
QUrl m_source;
bool m_mirrored;
};
+class Q_AUTOTEST_EXPORT TextureDownloadRequest : public Qt3DCore::QDownloadRequest
+{
+public:
+ TextureDownloadRequest(Qt3DCore::QNodeId texture, const QUrl &url, Qt3DCore::QAspectEngine *engine);
+
+ void onCompleted() Q_DECL_OVERRIDE;
+
+private:
+ Qt3DCore::QNodeId m_texture;
+ Qt3DCore::QAspectEngine *m_engine;
+};
+
class Q_AUTOTEST_EXPORT QTextureFromSourceGenerator : public QTextureGenerator
{
public:
- explicit QTextureFromSourceGenerator(const QUrl &url, bool mirrored);
+ explicit QTextureFromSourceGenerator(Qt3DCore::QNodeId texture, const QUrl &url,
+ bool mirrored, Qt3DCore::QAspectEngine *engine);
QTextureDataPtr operator ()() Q_DECL_OVERRIDE;
bool operator ==(const QTextureGenerator &other) const Q_DECL_OVERRIDE;
inline QAbstractTexture::Status status() const { return m_status; }
@@ -81,9 +100,14 @@ public:
bool isMirrored() const;
private:
+ friend class TextureDownloadRequest;
+
QUrl m_url;
QAbstractTexture::Status m_status;
bool m_mirrored;
+ QByteArray m_sourceData;
+ Qt3DCore::QNodeId m_texture;
+ Qt3DCore::QAspectEngine *m_engine;
};
typedef QSharedPointer<QTextureFromSourceGenerator> QTextureFromSourceGeneratorPtr;
@@ -91,6 +115,8 @@ class Q_AUTOTEST_EXPORT TextureLoadingHelper
{
public:
static QTextureImageDataPtr loadTextureData(const QUrl &source, bool allow3D, bool mirrored);
+ static QTextureImageDataPtr loadTextureData(QIODevice *data, const QString& suffix,
+ bool allow3D, bool mirrored);
};
} // namespace Qt3DRender
diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp
index 863733523..21f29d0b6 100644
--- a/src/render/texture/texture.cpp
+++ b/src/render/texture/texture.cpp
@@ -61,7 +61,7 @@ namespace Render {
Texture::Texture()
// We need backend -> frontend notifications to update the status of the texture
: BackendNode(ReadWrite)
- , m_dirty(DirtyGenerators|DirtyProperties|DirtyParameters)
+ , m_dirty(DirtyImageGenerators|DirtyProperties|DirtyParameters|DirtyDataGenerator)
, m_textureImageManager(nullptr)
{
}
@@ -81,11 +81,19 @@ void Texture::setTextureImageManager(TextureImageManager *manager)
void Texture::addDirtyFlag(DirtyFlags flags)
{
+ QMutexLocker lock(&m_flagsMutex);
m_dirty |= flags;
}
+Texture::DirtyFlags Texture::dirtyFlags()
+{
+ QMutexLocker lock(&m_flagsMutex);
+ return m_dirty;
+}
+
void Texture::unsetDirty()
{
+ QMutexLocker lock(&m_flagsMutex);
m_dirty = Texture::NotDirty;
}
@@ -101,7 +109,7 @@ void Texture::addTextureImage(Qt3DCore::QNodeId id)
qWarning() << "[Qt3DRender::TextureNode] addTextureImage: image handle is NULL";
} else if (!m_textureImages.contains(handle)) {
m_textureImages << handle;
- addDirtyFlag(DirtyGenerators);
+ addDirtyFlag(DirtyImageGenerators);
}
}
@@ -117,7 +125,7 @@ void Texture::removeTextureImage(Qt3DCore::QNodeId id)
qWarning() << "[Qt3DRender::TextureNode] removeTextureImage: image handle is NULL";
} else {
m_textureImages.removeAll(handle);
- addDirtyFlag(DirtyGenerators);
+ addDirtyFlag(DirtyImageGenerators);
}
}
@@ -214,7 +222,7 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
dirty = DirtyProperties;
} else if (propertyChange->propertyName() == QByteArrayLiteral("generator")) {
m_dataFunctor = propertyChange->value().value<QTextureGeneratorPtr>();
- dirty = DirtyGenerators;
+ dirty = DirtyDataGenerator;
}
}
break;
@@ -246,6 +254,16 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
BackendNode::sceneChangeEvent(e);
}
+bool Texture::isValid() const
+{
+ for (const auto handle : m_textureImages) {
+ TextureImage *img = m_textureImageManager->data(handle);
+ if (img == nullptr)
+ return false;
+ }
+ return true;
+}
+
void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractTextureData>>(change);
@@ -269,7 +287,7 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan
m_parameters.comparisonMode = data.comparisonMode;
m_dataFunctor = data.dataFunctor;
- addDirtyFlag(DirtyFlags(DirtyGenerators|DirtyProperties|DirtyParameters));
+ addDirtyFlag(DirtyFlags(DirtyImageGenerators|DirtyProperties|DirtyParameters));
}
diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h
index 8f5300552..1f3ba729c 100644
--- a/src/render/texture/texture_p.h
+++ b/src/render/texture/texture_p.h
@@ -135,14 +135,15 @@ public:
NotDirty = 0,
DirtyProperties = 0x1,
DirtyParameters = 0x2,
- DirtyGenerators = 0x4
+ DirtyImageGenerators = 0x4,
+ DirtyDataGenerator = 0x8
};
Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
void setTextureImageManager(TextureImageManager *manager);
void addDirtyFlag(DirtyFlags flags);
- inline DirtyFlags dirtyFlags() const { return m_dirty; }
+ DirtyFlags dirtyFlags();
void unsetDirty();
void addTextureImage(Qt3DCore::QNodeId id);
@@ -156,6 +157,7 @@ public:
inline const QVector<HTextureImage>& textureImages() const { return m_textureImages; }
inline const QTextureGeneratorPtr& dataGenerator() const { return m_dataFunctor; }
+ bool isValid() const;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
@@ -167,6 +169,7 @@ private:
QVector<HTextureImage> m_textureImages;
TextureImageManager *m_textureImageManager;
+ QMutex m_flagsMutex;
};
class TextureFunctor : public Qt3DCore::QBackendNodeMapper
diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp
index f44a82649..b732be2d9 100644
--- a/src/render/texture/textureimage.cpp
+++ b/src/render/texture/textureimage.cpp
@@ -106,7 +106,7 @@ void TextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
// Notify the Texture that we were updated and request it to schedule an update job
Texture *txt = m_textureManager->data(m_textureProvider);
if (txt != nullptr)
- txt->addDirtyFlag(Texture::DirtyGenerators);
+ txt->addDirtyFlag(Texture::DirtyImageGenerators);
}
markDirty(AbstractRenderer::AllDirty);
diff --git a/src/src.pro b/src/src.pro
index 6bada3424..46c205849 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -23,55 +23,65 @@ src_extras.subdir = $$PWD/extras
src_extras.target = src_extras
src_extras.depends = src_render src_input src_logic
-# Quick3D libs
-src_quick3d_core.subdir = $$PWD/quick3d/quick3d
-src_quick3d_core.target = sub-quick3d-core
-src_quick3d_core.depends = src_core src_input
-
-src_quick3d_render.subdir = $$PWD/quick3d/quick3drender
-src_quick3d_render.target = sub-quick3d-render
-src_quick3d_render.depends = src_render src_quick3d_core
-
-src_quick3d_input.subdir = $$PWD/quick3d/quick3dinput
-src_quick3d_input.target = sub-quick3d-input
-src_quick3d_input.depends = src_input src_quick3d_core
-
-src_quick3d_animation.subdir = $$PWD/quick3d/quick3danimation
-src_quick3d_animation.target = sub-quick3d-animation
-src_quick3d_animation.depends = src_animation src_quick3d_core src_quick3d_render
-
-src_quick3d_extras.subdir = $$PWD/quick3d/quick3dextras
-src_quick3d_extras.target = sub-quick3d-extras
-src_quick3d_extras.depends = src_render src_logic src_input src_extras src_quick3d_core
-
-# Quick3D imports
-src_quick3d_core_imports.file = $$PWD/quick3d/imports/core/importscore.pro
-src_quick3d_core_imports.target = sub-quick3d-imports-core
-src_quick3d_core_imports.depends = src_quick3d_core
-
-src_quick3d_imports_render.file = $$PWD/quick3d/imports/render/importsrender.pro
-src_quick3d_imports_render.target = sub-quick3d-imports-render
-src_quick3d_imports_render.depends = src_quick3d_render
-
-src_quick3d_imports_scene3d.file = $$PWD/quick3d/imports/scene3d/importsscene3d.pro
-src_quick3d_imports_scene3d.target = sub-quick3d-imports-scene3d
-src_quick3d_imports_scene3d.depends = src_quick3d_render src_input
-
-src_quick3d_imports_input.file = $$PWD/quick3d/imports/input/importsinput.pro
-src_quick3d_imports_input.target = sub-quick3d-imports-input
-src_quick3d_imports_input.depends = src_input src_quick3d_input
-
-src_quick3d_imports_logic.file = $$PWD/quick3d/imports/logic/importslogic.pro
-src_quick3d_imports_logic.target = sub-quick3d-imports-logic
-src_quick3d_imports_logic.depends = src_logic
-
-src_quick3d_imports_animation.file = $$PWD/quick3d/imports/animation/importsanimation.pro
-src_quick3d_imports_animation.target = sub-quick3d-imports-animation
-src_quick3d_imports_animation.depends = src_animation src_quick3d_animation
-
-src_quick3d_imports_extras.file = $$PWD/quick3d/imports/extras/importsextras.pro
-src_quick3d_imports_extras.target = sub-quick3d-imports-extras
-src_quick3d_imports_extras.depends = src_extras src_quick3d_extras
+qtHaveModule(quick) {
+ # Quick3D libs
+ src_quick3d_core.subdir = $$PWD/quick3d/quick3d
+ src_quick3d_core.target = sub-quick3d-core
+ src_quick3d_core.depends = src_core src_input
+
+ src_quick3d_render.subdir = $$PWD/quick3d/quick3drender
+ src_quick3d_render.target = sub-quick3d-render
+ src_quick3d_render.depends = src_render src_quick3d_core
+
+ src_quick3d_input.subdir = $$PWD/quick3d/quick3dinput
+ src_quick3d_input.target = sub-quick3d-input
+ src_quick3d_input.depends = src_input src_quick3d_core
+
+ src_quick3d_animation.subdir = $$PWD/quick3d/quick3danimation
+ src_quick3d_animation.target = sub-quick3d-animation
+ src_quick3d_animation.depends = src_animation src_quick3d_core src_quick3d_render
+
+ src_quick3d_extras.subdir = $$PWD/quick3d/quick3dextras
+ src_quick3d_extras.target = sub-quick3d-extras
+ src_quick3d_extras.depends = src_render src_logic src_input src_extras src_quick3d_core
+
+ src_quick3d_scene2d.subdir = $$PWD/quick3d/quick3dscene2d
+ src_quick3d_scene2d.target = sub-quick3d-scene2d
+ src_quick3d_scene2d.depends = src_render src_logic src_input src_quick3d_core
+
+ # Quick3D imports
+ src_quick3d_core_imports.file = $$PWD/quick3d/imports/core/importscore.pro
+ src_quick3d_core_imports.target = sub-quick3d-imports-core
+ src_quick3d_core_imports.depends = src_quick3d_core
+
+ src_quick3d_imports_render.file = $$PWD/quick3d/imports/render/importsrender.pro
+ src_quick3d_imports_render.target = sub-quick3d-imports-render
+ src_quick3d_imports_render.depends = src_quick3d_render
+
+ src_quick3d_imports_scene3d.file = $$PWD/quick3d/imports/scene3d/importsscene3d.pro
+ src_quick3d_imports_scene3d.target = sub-quick3d-imports-scene3d
+ src_quick3d_imports_scene3d.depends = src_quick3d_render src_input
+
+ src_quick3d_imports_input.file = $$PWD/quick3d/imports/input/importsinput.pro
+ src_quick3d_imports_input.target = sub-quick3d-imports-input
+ src_quick3d_imports_input.depends = src_input src_quick3d_input
+
+ src_quick3d_imports_logic.file = $$PWD/quick3d/imports/logic/importslogic.pro
+ src_quick3d_imports_logic.target = sub-quick3d-imports-logic
+ src_quick3d_imports_logic.depends = src_logic
+
+ src_quick3d_imports_animation.file = $$PWD/quick3d/imports/animation/importsanimation.pro
+ src_quick3d_imports_animation.target = sub-quick3d-imports-animation
+ src_quick3d_imports_animation.depends = src_animation src_quick3d_animation
+
+ src_quick3d_imports_extras.file = $$PWD/quick3d/imports/extras/importsextras.pro
+ src_quick3d_imports_extras.target = sub-quick3d-imports-extras
+ src_quick3d_imports_extras.depends = src_extras src_quick3d_extras
+
+ src_quick3d_imports_scene2d.file = $$PWD/quick3d/imports/scene2d/importsscene2d.pro
+ src_quick3d_imports_scene2d.target = sub-quick3d-imports-scene2d
+ src_quick3d_imports_scene2d.depends = src_quick3d_scene2d
+}
# Qt3D Scene Parser plugins
src_plugins_sceneparsers.file = $$PWD/plugins/sceneparsers/sceneparsers.pro
@@ -83,6 +93,13 @@ src_plugins_geometryloaders.file = $$PWD/plugins/geometryloaders/geometryloaders
src_plugins_geometryloaders.target = sub-plugins-geometryloaders
src_plugins_geometryloaders.depends = src_render src_extras
+qtHaveModule(quick) {
+ # Qt3D Render plugins
+ src_plugins_render.file = $$PWD/plugins/renderplugins/renderplugins.pro
+ src_plugins_render.target = sub-plugins-render
+ src_plugins_render.depends = src_render src_extras src_quick3d_render src_quick3d_scene2d
+}
+
SUBDIRS += \
src_core \
src_render \
@@ -90,20 +107,25 @@ SUBDIRS += \
src_input \
src_animation \
src_extras \
- src_quick3d_core \
- src_quick3d_core_imports \
- src_quick3d_render \
- src_quick3d_input \
- src_quick3d_animation \
- src_quick3d_extras \
- src_quick3d_imports_render \
- src_quick3d_imports_scene3d \
- src_quick3d_imports_input \
- src_quick3d_imports_logic \
- src_quick3d_imports_animation \
- src_quick3d_imports_extras \
src_plugins_sceneparsers \
src_plugins_geometryloaders \
doc
-
+qtHaveModule(quick) {
+ SUBDIRS += \
+ src_quick3d_core \
+ src_quick3d_core_imports \
+ src_quick3d_render \
+ src_quick3d_input \
+ src_quick3d_animation \
+ src_quick3d_extras \
+ src_quick3d_imports_render \
+ src_quick3d_imports_scene3d \
+ src_quick3d_imports_input \
+ src_quick3d_imports_logic \
+ src_quick3d_imports_animation \
+ src_quick3d_imports_extras \
+ src_plugins_render \
+ src_quick3d_scene2d \
+ src_quick3d_imports_scene2d
+}