summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2018-04-04 09:53:27 +0100
committerMike Krus <mike.krus@kdab.com>2018-04-09 11:51:08 +0000
commit5247d7146c65672bd245ceb0dc213dfb319919c4 (patch)
tree87159d0f24af725bb7c01c7495d71b3cc4bc76c2
parentaf4972fd15e6b11a99c631ff91b3360ceb8be5cc (diff)
Update Assimp to 4.1
Fixes build with C++17 / XCode 9.3 Change-Id: Ic1c19cc4b86e54e72dd4cfe054ec6d66f64b5a07 Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r--src/3rdparty/assimp/Readme.md121
-rw-r--r--src/3rdparty/assimp/assimp.pri1001
-rw-r--r--src/3rdparty/assimp/code/3DSConverter.cpp32
-rw-r--r--src/3rdparty/assimp/code/3DSExporter.cpp26
-rw-r--r--src/3rdparty/assimp/code/3DSExporter.h23
-rw-r--r--src/3rdparty/assimp/code/3DSHelper.h75
-rw-r--r--src/3rdparty/assimp/code/3DSLoader.cpp96
-rw-r--r--src/3rdparty/assimp/code/3DSLoader.h7
-rw-r--r--src/3rdparty/assimp/code/3MFXmlTags.h89
-rw-r--r--src/3rdparty/assimp/code/ACLoader.cpp4
-rw-r--r--src/3rdparty/assimp/code/ACLoader.h3
-rw-r--r--src/3rdparty/assimp/code/AMFImporter.cpp704
-rw-r--r--src/3rdparty/assimp/code/AMFImporter.hpp563
-rw-r--r--src/3rdparty/assimp/code/AMFImporter_Geometry.cpp356
-rw-r--r--src/3rdparty/assimp/code/AMFImporter_Macro.hpp165
-rw-r--r--src/3rdparty/assimp/code/AMFImporter_Material.cpp310
-rw-r--r--src/3rdparty/assimp/code/AMFImporter_Node.hpp400
-rw-r--r--src/3rdparty/assimp/code/AMFImporter_Postprocess.cpp976
-rw-r--r--src/3rdparty/assimp/code/ASELoader.cpp15
-rw-r--r--src/3rdparty/assimp/code/ASELoader.h12
-rw-r--r--src/3rdparty/assimp/code/ASEParser.cpp79
-rw-r--r--src/3rdparty/assimp/code/ASEParser.h23
-rw-r--r--src/3rdparty/assimp/code/AssbinExporter.cpp66
-rw-r--r--src/3rdparty/assimp/code/AssbinExporter.h3
-rw-r--r--src/3rdparty/assimp/code/AssbinLoader.cpp74
-rw-r--r--src/3rdparty/assimp/code/AssbinLoader.h7
-rw-r--r--src/3rdparty/assimp/code/Assimp.cpp40
-rw-r--r--src/3rdparty/assimp/code/AssimpCExport.cpp12
-rw-r--r--src/3rdparty/assimp/code/AssxmlExporter.cpp14
-rw-r--r--src/3rdparty/assimp/code/AssxmlExporter.h3
-rw-r--r--src/3rdparty/assimp/code/B3DImporter.cpp63
-rw-r--r--src/3rdparty/assimp/code/B3DImporter.h6
-rw-r--r--src/3rdparty/assimp/code/BVHLoader.cpp8
-rw-r--r--src/3rdparty/assimp/code/BVHLoader.h3
-rw-r--r--src/3rdparty/assimp/code/BaseImporter.cpp204
-rw-r--r--src/3rdparty/assimp/code/BaseImporter.h63
-rw-r--r--src/3rdparty/assimp/code/BaseProcess.cpp3
-rw-r--r--src/3rdparty/assimp/code/BaseProcess.h5
-rw-r--r--src/3rdparty/assimp/code/Bitmap.cpp7
-rw-r--r--src/3rdparty/assimp/code/Bitmap.h143
-rw-r--r--src/3rdparty/assimp/code/BlenderBMesh.cpp8
-rw-r--r--src/3rdparty/assimp/code/BlenderDNA.cpp25
-rw-r--r--src/3rdparty/assimp/code/BlenderDNA.h89
-rw-r--r--src/3rdparty/assimp/code/BlenderDNA.inl31
-rw-r--r--src/3rdparty/assimp/code/BlenderIntermediate.h12
-rw-r--r--src/3rdparty/assimp/code/BlenderLoader.cpp79
-rw-r--r--src/3rdparty/assimp/code/BlenderLoader.h4
-rw-r--r--src/3rdparty/assimp/code/BlenderModifier.cpp18
-rw-r--r--src/3rdparty/assimp/code/BlenderModifier.h3
-rw-r--r--src/3rdparty/assimp/code/BlenderScene.cpp49
-rw-r--r--src/3rdparty/assimp/code/BlenderScene.h89
-rw-r--r--src/3rdparty/assimp/code/BlenderTessellator.cpp45
-rw-r--r--src/3rdparty/assimp/code/BlenderTessellator.h3
-rw-r--r--src/3rdparty/assimp/code/BlobIOSystem.h11
-rw-r--r--src/3rdparty/assimp/code/ByteSwapper.h3
-rw-r--r--src/3rdparty/assimp/code/C4DImporter.cpp12
-rw-r--r--src/3rdparty/assimp/code/C4DImporter.h2
-rw-r--r--src/3rdparty/assimp/code/CInterfaceIOWrapper.cpp135
-rw-r--r--src/3rdparty/assimp/code/CInterfaceIOWrapper.h102
-rw-r--r--src/3rdparty/assimp/code/CMakeLists.txt250
-rw-r--r--src/3rdparty/assimp/code/COBLoader.cpp22
-rw-r--r--src/3rdparty/assimp/code/COBLoader.h3
-rw-r--r--src/3rdparty/assimp/code/COBScene.h10
-rw-r--r--src/3rdparty/assimp/code/CSMLoader.cpp7
-rw-r--r--src/3rdparty/assimp/code/CSMLoader.h3
-rw-r--r--src/3rdparty/assimp/code/CalcTangentsProcess.cpp5
-rw-r--r--src/3rdparty/assimp/code/CalcTangentsProcess.h3
-rw-r--r--src/3rdparty/assimp/code/ColladaExporter.cpp631
-rw-r--r--src/3rdparty/assimp/code/ColladaExporter.h35
-rw-r--r--src/3rdparty/assimp/code/ColladaHelper.h101
-rw-r--r--src/3rdparty/assimp/code/ColladaLoader.cpp715
-rw-r--r--src/3rdparty/assimp/code/ColladaLoader.h247
-rw-r--r--src/3rdparty/assimp/code/ColladaParser.cpp179
-rw-r--r--src/3rdparty/assimp/code/ColladaParser.h15
-rw-r--r--src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp77
-rw-r--r--src/3rdparty/assimp/code/ComputeUVMappingProcess.h3
-rw-r--r--src/3rdparty/assimp/code/ConvertToLHProcess.cpp3
-rw-r--r--src/3rdparty/assimp/code/ConvertToLHProcess.h3
-rw-r--r--src/3rdparty/assimp/code/CreateAnimMesh.h3
-rw-r--r--src/3rdparty/assimp/code/D3MFExporter.cpp328
-rw-r--r--src/3rdparty/assimp/code/D3MFExporter.h103
-rw-r--r--src/3rdparty/assimp/code/D3MFImporter.cpp180
-rw-r--r--src/3rdparty/assimp/code/D3MFImporter.h18
-rw-r--r--src/3rdparty/assimp/code/D3MFOpcPackage.cpp251
-rw-r--r--src/3rdparty/assimp/code/D3MFOpcPackage.h23
-rw-r--r--src/3rdparty/assimp/code/DXFHelper.h3
-rw-r--r--src/3rdparty/assimp/code/DXFLoader.cpp15
-rw-r--r--src/3rdparty/assimp/code/DXFLoader.h4
-rw-r--r--src/3rdparty/assimp/code/DeboneProcess.cpp17
-rw-r--r--src/3rdparty/assimp/code/DeboneProcess.h5
-rw-r--r--src/3rdparty/assimp/code/DefaultIOStream.cpp23
-rw-r--r--src/3rdparty/assimp/code/DefaultIOSystem.cpp8
-rw-r--r--src/3rdparty/assimp/code/DefaultLogger.cpp10
-rw-r--r--src/3rdparty/assimp/code/DefaultProgressHandler.h3
-rw-r--r--src/3rdparty/assimp/code/Exceptional.h6
-rw-r--r--src/3rdparty/assimp/code/Exporter.cpp192
-rw-r--r--src/3rdparty/assimp/code/FBXAnimation.cpp32
-rw-r--r--src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp113
-rw-r--r--src/3rdparty/assimp/code/FBXCompileConfig.h7
-rw-r--r--src/3rdparty/assimp/code/FBXConverter.cpp414
-rw-r--r--src/3rdparty/assimp/code/FBXConverter.h3
-rw-r--r--src/3rdparty/assimp/code/FBXDeformer.cpp9
-rw-r--r--src/3rdparty/assimp/code/FBXDocument.cpp92
-rw-r--r--src/3rdparty/assimp/code/FBXDocument.h62
-rw-r--r--src/3rdparty/assimp/code/FBXDocumentUtil.cpp3
-rw-r--r--src/3rdparty/assimp/code/FBXImportSettings.h8
-rw-r--r--src/3rdparty/assimp/code/FBXImporter.cpp20
-rw-r--r--src/3rdparty/assimp/code/FBXImporter.h3
-rw-r--r--src/3rdparty/assimp/code/FBXMaterial.cpp61
-rw-r--r--src/3rdparty/assimp/code/FBXMeshGeometry.cpp146
-rw-r--r--src/3rdparty/assimp/code/FBXMeshGeometry.h33
-rw-r--r--src/3rdparty/assimp/code/FBXModel.cpp8
-rw-r--r--src/3rdparty/assimp/code/FBXNodeAttribute.cpp20
-rw-r--r--src/3rdparty/assimp/code/FBXParser.cpp23
-rw-r--r--src/3rdparty/assimp/code/FBXParser.h34
-rw-r--r--src/3rdparty/assimp/code/FBXProperties.cpp3
-rw-r--r--src/3rdparty/assimp/code/FBXProperties.h51
-rw-r--r--src/3rdparty/assimp/code/FBXTokenizer.cpp3
-rw-r--r--src/3rdparty/assimp/code/FBXTokenizer.h10
-rw-r--r--src/3rdparty/assimp/code/FBXUtil.cpp4
-rw-r--r--src/3rdparty/assimp/code/FBXUtil.h4
-rw-r--r--src/3rdparty/assimp/code/FIReader.cpp1833
-rw-r--r--src/3rdparty/assimp/code/FIReader.hpp185
-rw-r--r--src/3rdparty/assimp/code/FileLogStream.h43
-rw-r--r--src/3rdparty/assimp/code/FindDegenerates.cpp115
-rw-r--r--src/3rdparty/assimp/code/FindDegenerates.h62
-rw-r--r--src/3rdparty/assimp/code/FindInstancesProcess.cpp3
-rw-r--r--src/3rdparty/assimp/code/FindInstancesProcess.h3
-rw-r--r--src/3rdparty/assimp/code/FindInvalidDataProcess.cpp40
-rw-r--r--src/3rdparty/assimp/code/FindInvalidDataProcess.h5
-rw-r--r--src/3rdparty/assimp/code/FixNormalsStep.cpp9
-rw-r--r--src/3rdparty/assimp/code/FixNormalsStep.h8
-rw-r--r--src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp3
-rw-r--r--src/3rdparty/assimp/code/GenFaceNormalsProcess.h3
-rw-r--r--src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp19
-rw-r--r--src/3rdparty/assimp/code/GenVertexNormalsProcess.h8
-rw-r--r--src/3rdparty/assimp/code/GenericProperty.h5
-rw-r--r--src/3rdparty/assimp/code/HMPFileData.h3
-rw-r--r--src/3rdparty/assimp/code/HMPLoader.cpp20
-rw-r--r--src/3rdparty/assimp/code/HMPLoader.h8
-rw-r--r--src/3rdparty/assimp/code/HalfLifeFileData.h9
-rw-r--r--src/3rdparty/assimp/code/Hash.h3
-rw-r--r--src/3rdparty/assimp/code/IFCBoolean.cpp11
-rw-r--r--src/3rdparty/assimp/code/IFCCurve.cpp156
-rw-r--r--src/3rdparty/assimp/code/IFCGeometry.cpp23
-rw-r--r--src/3rdparty/assimp/code/IFCLoader.cpp97
-rw-r--r--src/3rdparty/assimp/code/IFCLoader.h7
-rw-r--r--src/3rdparty/assimp/code/IFCMaterial.cpp39
-rw-r--r--src/3rdparty/assimp/code/IFCOpenings.cpp77
-rw-r--r--src/3rdparty/assimp/code/IFCProfile.cpp13
-rw-r--r--src/3rdparty/assimp/code/IFCReaderGen1.cpp4502
-rw-r--r--src/3rdparty/assimp/code/IFCReaderGen2.cpp2088
-rw-r--r--src/3rdparty/assimp/code/IFCUtil.cpp11
-rw-r--r--src/3rdparty/assimp/code/IFCUtil.h3
-rw-r--r--src/3rdparty/assimp/code/IOStreamBuffer.h350
-rw-r--r--src/3rdparty/assimp/code/IRRLoader.cpp100
-rw-r--r--src/3rdparty/assimp/code/IRRLoader.h37
-rw-r--r--src/3rdparty/assimp/code/IRRMeshLoader.cpp66
-rw-r--r--src/3rdparty/assimp/code/IRRMeshLoader.h3
-rw-r--r--src/3rdparty/assimp/code/IRRShared.cpp3
-rw-r--r--src/3rdparty/assimp/code/Importer.cpp34
-rw-r--r--src/3rdparty/assimp/code/Importer.h46
-rw-r--r--src/3rdparty/assimp/code/ImporterRegistry.cpp32
-rw-r--r--src/3rdparty/assimp/code/ImproveCacheLocality.cpp4
-rw-r--r--src/3rdparty/assimp/code/ImproveCacheLocality.h3
-rw-r--r--src/3rdparty/assimp/code/JoinVerticesProcess.cpp3
-rw-r--r--src/3rdparty/assimp/code/JoinVerticesProcess.h4
-rw-r--r--src/3rdparty/assimp/code/LWOAnimation.cpp18
-rw-r--r--src/3rdparty/assimp/code/LWOAnimation.h10
-rw-r--r--src/3rdparty/assimp/code/LWOBLoader.cpp3
-rw-r--r--src/3rdparty/assimp/code/LWOFileData.h3
-rw-r--r--src/3rdparty/assimp/code/LWOLoader.cpp18
-rw-r--r--src/3rdparty/assimp/code/LWOLoader.h5
-rw-r--r--src/3rdparty/assimp/code/LWOMaterial.cpp45
-rw-r--r--src/3rdparty/assimp/code/LWSLoader.cpp11
-rw-r--r--src/3rdparty/assimp/code/LWSLoader.h5
-rw-r--r--src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp7
-rw-r--r--src/3rdparty/assimp/code/LimitBoneWeightsProcess.h3
-rw-r--r--src/3rdparty/assimp/code/LineSplitter.h23
-rw-r--r--src/3rdparty/assimp/code/LogAux.h16
-rw-r--r--src/3rdparty/assimp/code/MD2FileData.h5
-rw-r--r--src/3rdparty/assimp/code/MD2Loader.cpp13
-rw-r--r--src/3rdparty/assimp/code/MD2Loader.h3
-rw-r--r--src/3rdparty/assimp/code/MD2NormalTable.h3
-rw-r--r--src/3rdparty/assimp/code/MD3FileData.h61
-rw-r--r--src/3rdparty/assimp/code/MD3Loader.cpp16
-rw-r--r--src/3rdparty/assimp/code/MD3Loader.h3
-rw-r--r--src/3rdparty/assimp/code/MD5Loader.cpp20
-rw-r--r--src/3rdparty/assimp/code/MD5Loader.h3
-rw-r--r--src/3rdparty/assimp/code/MD5Parser.cpp24
-rw-r--r--src/3rdparty/assimp/code/MD5Parser.h3
-rw-r--r--src/3rdparty/assimp/code/MDCFileData.h5
-rw-r--r--src/3rdparty/assimp/code/MDCLoader.cpp6
-rw-r--r--src/3rdparty/assimp/code/MDCLoader.h3
-rw-r--r--src/3rdparty/assimp/code/MDLDefaultColorMap.h3
-rw-r--r--src/3rdparty/assimp/code/MDLFileData.h80
-rw-r--r--src/3rdparty/assimp/code/MDLLoader.cpp17
-rw-r--r--src/3rdparty/assimp/code/MDLLoader.h3
-rw-r--r--src/3rdparty/assimp/code/MDLMaterialLoader.cpp19
-rw-r--r--src/3rdparty/assimp/code/MMDCpp14.h82
-rw-r--r--src/3rdparty/assimp/code/MMDImporter.cpp370
-rw-r--r--src/3rdparty/assimp/code/MMDImporter.h96
-rw-r--r--src/3rdparty/assimp/code/MMDPmdParser.h596
-rw-r--r--src/3rdparty/assimp/code/MMDPmxParser.cpp637
-rw-r--r--src/3rdparty/assimp/code/MMDPmxParser.h780
-rw-r--r--src/3rdparty/assimp/code/MMDVmdParser.h375
-rw-r--r--src/3rdparty/assimp/code/MS3DLoader.cpp10
-rw-r--r--src/3rdparty/assimp/code/MS3DLoader.h3
-rw-r--r--src/3rdparty/assimp/code/MakeVerboseFormat.cpp13
-rw-r--r--src/3rdparty/assimp/code/MakeVerboseFormat.h3
-rw-r--r--src/3rdparty/assimp/code/MaterialSystem.cpp93
-rw-r--r--src/3rdparty/assimp/code/MaterialSystem.h3
-rw-r--r--src/3rdparty/assimp/code/MemoryIOWrapper.h3
-rw-r--r--src/3rdparty/assimp/code/NDOLoader.cpp17
-rw-r--r--src/3rdparty/assimp/code/NFFLoader.cpp27
-rw-r--r--src/3rdparty/assimp/code/NFFLoader.h3
-rw-r--r--src/3rdparty/assimp/code/OFFLoader.cpp15
-rw-r--r--src/3rdparty/assimp/code/OFFLoader.h3
-rw-r--r--src/3rdparty/assimp/code/ObjExporter.cpp185
-rw-r--r--src/3rdparty/assimp/code/ObjExporter.h97
-rw-r--r--src/3rdparty/assimp/code/ObjFileData.h120
-rw-r--r--src/3rdparty/assimp/code/ObjFileImporter.cpp133
-rw-r--r--src/3rdparty/assimp/code/ObjFileImporter.h21
-rw-r--r--src/3rdparty/assimp/code/ObjFileMtlImporter.cpp107
-rw-r--r--src/3rdparty/assimp/code/ObjFileMtlImporter.h8
-rw-r--r--src/3rdparty/assimp/code/ObjFileParser.cpp454
-rw-r--r--src/3rdparty/assimp/code/ObjFileParser.h35
-rw-r--r--src/3rdparty/assimp/code/ObjTools.h86
-rw-r--r--src/3rdparty/assimp/code/OgreBinarySerializer.cpp7
-rw-r--r--src/3rdparty/assimp/code/OgreBinarySerializer.h3
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.cpp6
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.h3
-rw-r--r--src/3rdparty/assimp/code/OgreMaterial.cpp13
-rw-r--r--src/3rdparty/assimp/code/OgreParsingUtils.h11
-rw-r--r--src/3rdparty/assimp/code/OgreStructs.cpp57
-rw-r--r--src/3rdparty/assimp/code/OgreStructs.h3
-rw-r--r--src/3rdparty/assimp/code/OgreXmlSerializer.cpp7
-rw-r--r--src/3rdparty/assimp/code/OgreXmlSerializer.h3
-rw-r--r--src/3rdparty/assimp/code/OpenGEXExporter.cpp7
-rw-r--r--src/3rdparty/assimp/code/OpenGEXExporter.h3
-rw-r--r--src/3rdparty/assimp/code/OpenGEXImporter.cpp227
-rw-r--r--src/3rdparty/assimp/code/OpenGEXImporter.h24
-rw-r--r--src/3rdparty/assimp/code/OpenGEXStructs.h6
-rw-r--r--src/3rdparty/assimp/code/OptimizeGraph.cpp19
-rw-r--r--src/3rdparty/assimp/code/OptimizeGraph.h3
-rw-r--r--src/3rdparty/assimp/code/OptimizeMeshes.cpp14
-rw-r--r--src/3rdparty/assimp/code/OptimizeMeshes.h3
-rw-r--r--src/3rdparty/assimp/code/ParsingUtils.h3
-rw-r--r--src/3rdparty/assimp/code/PlyExporter.cpp73
-rw-r--r--src/3rdparty/assimp/code/PlyExporter.h9
-rw-r--r--src/3rdparty/assimp/code/PlyLoader.cpp1736
-rw-r--r--src/3rdparty/assimp/code/PlyLoader.h68
-rw-r--r--src/3rdparty/assimp/code/PlyParser.cpp1637
-rw-r--r--src/3rdparty/assimp/code/PlyParser.h98
-rw-r--r--src/3rdparty/assimp/code/PolyTools.h3
-rw-r--r--src/3rdparty/assimp/code/PostStepRegistry.cpp3
-rw-r--r--src/3rdparty/assimp/code/PretransformVertices.cpp28
-rw-r--r--src/3rdparty/assimp/code/PretransformVertices.h3
-rw-r--r--src/3rdparty/assimp/code/ProcessHelper.cpp31
-rw-r--r--src/3rdparty/assimp/code/ProcessHelper.h11
-rw-r--r--src/3rdparty/assimp/code/Profiler.h23
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileData.h3
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileImporter.cpp33
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileImporter.h24
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileParser.cpp5
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileParser.h3
-rw-r--r--src/3rdparty/assimp/code/Q3BSPZipArchive.cpp15
-rw-r--r--src/3rdparty/assimp/code/Q3BSPZipArchive.h120
-rw-r--r--src/3rdparty/assimp/code/Q3DLoader.cpp4
-rw-r--r--src/3rdparty/assimp/code/Q3DLoader.h3
-rw-r--r--src/3rdparty/assimp/code/RawLoader.cpp7
-rw-r--r--src/3rdparty/assimp/code/RawLoader.h3
-rw-r--r--src/3rdparty/assimp/code/RemoveComments.cpp3
-rw-r--r--src/3rdparty/assimp/code/RemoveComments.h5
-rw-r--r--src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp14
-rw-r--r--src/3rdparty/assimp/code/RemoveRedundantMaterials.h3
-rw-r--r--src/3rdparty/assimp/code/RemoveVCProcess.cpp5
-rw-r--r--src/3rdparty/assimp/code/RemoveVCProcess.h7
-rw-r--r--src/3rdparty/assimp/code/SGSpatialSort.cpp11
-rw-r--r--src/3rdparty/assimp/code/SGSpatialSort.h3
-rw-r--r--src/3rdparty/assimp/code/SIBImporter.cpp191
-rw-r--r--src/3rdparty/assimp/code/SIBImporter.h9
-rw-r--r--src/3rdparty/assimp/code/SMDLoader.cpp53
-rw-r--r--src/3rdparty/assimp/code/SMDLoader.h7
-rw-r--r--src/3rdparty/assimp/code/STEPFile.h39
-rw-r--r--src/3rdparty/assimp/code/STEPFileEncoding.cpp62
-rw-r--r--src/3rdparty/assimp/code/STEPFileEncoding.h3
-rw-r--r--src/3rdparty/assimp/code/STEPFileReader.cpp3
-rw-r--r--src/3rdparty/assimp/code/STEPFileReader.h3
-rw-r--r--src/3rdparty/assimp/code/STLExporter.cpp19
-rw-r--r--src/3rdparty/assimp/code/STLExporter.h3
-rw-r--r--src/3rdparty/assimp/code/STLLoader.cpp158
-rw-r--r--src/3rdparty/assimp/code/STLLoader.h63
-rw-r--r--src/3rdparty/assimp/code/ScaleProcess.cpp105
-rw-r--r--src/3rdparty/assimp/code/ScaleProcess.h87
-rw-r--r--src/3rdparty/assimp/code/SceneCombiner.cpp245
-rw-r--r--src/3rdparty/assimp/code/ScenePreprocessor.cpp15
-rw-r--r--src/3rdparty/assimp/code/ScenePreprocessor.h3
-rw-r--r--src/3rdparty/assimp/code/ScenePrivate.h3
-rw-r--r--src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp101
-rw-r--r--src/3rdparty/assimp/code/SkeletonMeshBuilder.h3
-rw-r--r--src/3rdparty/assimp/code/SmoothingGroups.h3
-rw-r--r--src/3rdparty/assimp/code/SortByPTypeProcess.cpp3
-rw-r--r--src/3rdparty/assimp/code/SortByPTypeProcess.h3
-rw-r--r--src/3rdparty/assimp/code/SpatialSort.cpp41
-rw-r--r--src/3rdparty/assimp/code/SpatialSort.h11
-rw-r--r--src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp5
-rw-r--r--src/3rdparty/assimp/code/SplitByBoneCountProcess.h3
-rw-r--r--src/3rdparty/assimp/code/SplitLargeMeshes.cpp3
-rw-r--r--src/3rdparty/assimp/code/SplitLargeMeshes.h3
-rw-r--r--src/3rdparty/assimp/code/StandardShapes.cpp159
-rw-r--r--src/3rdparty/assimp/code/StandardShapes.h9
-rw-r--r--src/3rdparty/assimp/code/StdOStreamLogStream.h32
-rw-r--r--src/3rdparty/assimp/code/StepExporter.cpp8
-rw-r--r--src/3rdparty/assimp/code/StepExporter.h3
-rw-r--r--src/3rdparty/assimp/code/StreamReader.h47
-rw-r--r--src/3rdparty/assimp/code/StreamWriter.h3
-rw-r--r--src/3rdparty/assimp/code/StringComparison.h4
-rw-r--r--src/3rdparty/assimp/code/StringUtils.h11
-rw-r--r--src/3rdparty/assimp/code/Subdivision.cpp29
-rw-r--r--src/3rdparty/assimp/code/Subdivision.h22
-rw-r--r--src/3rdparty/assimp/code/TargetAnimation.cpp15
-rw-r--r--src/3rdparty/assimp/code/TargetAnimation.h3
-rw-r--r--src/3rdparty/assimp/code/TerragenLoader.cpp10
-rw-r--r--src/3rdparty/assimp/code/TerragenLoader.h3
-rw-r--r--src/3rdparty/assimp/code/TextureTransform.cpp5
-rw-r--r--src/3rdparty/assimp/code/TextureTransform.h3
-rw-r--r--src/3rdparty/assimp/code/TinyFormatter.h6
-rw-r--r--src/3rdparty/assimp/code/TriangulateProcess.cpp27
-rw-r--r--src/3rdparty/assimp/code/TriangulateProcess.h3
-rw-r--r--src/3rdparty/assimp/code/UnrealLoader.cpp10
-rw-r--r--src/3rdparty/assimp/code/UnrealLoader.h3
-rw-r--r--src/3rdparty/assimp/code/ValidateDataStructure.cpp26
-rw-r--r--src/3rdparty/assimp/code/ValidateDataStructure.h7
-rw-r--r--src/3rdparty/assimp/code/Version.cpp59
-rw-r--r--src/3rdparty/assimp/code/Vertex.h71
-rw-r--r--src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp3
-rw-r--r--src/3rdparty/assimp/code/VertexTriangleAdjacency.h3
-rw-r--r--src/3rdparty/assimp/code/Win32DebugLogStream.h74
-rw-r--r--src/3rdparty/assimp/code/X3DExporter.cpp735
-rw-r--r--src/3rdparty/assimp/code/X3DExporter.hpp235
-rw-r--r--src/3rdparty/assimp/code/X3DImporter.cpp1728
-rw-r--r--src/3rdparty/assimp/code/X3DImporter.hpp833
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Geometry2D.cpp521
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Geometry3D.cpp998
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Group.cpp317
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Light.cpp289
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Macro.hpp194
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Metadata.cpp276
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Networking.cpp133
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Node.hpp779
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Postprocess.cpp826
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Rendering.cpp1070
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Shape.cpp249
-rw-r--r--src/3rdparty/assimp/code/X3DImporter_Texturing.cpp196
-rw-r--r--src/3rdparty/assimp/code/X3DVocabulary.cpp1675
-rw-r--r--src/3rdparty/assimp/code/XFileExporter.cpp16
-rw-r--r--src/3rdparty/assimp/code/XFileExporter.h10
-rw-r--r--src/3rdparty/assimp/code/XFileHelper.h9
-rw-r--r--src/3rdparty/assimp/code/XFileImporter.cpp21
-rw-r--r--src/3rdparty/assimp/code/XFileImporter.h8
-rw-r--r--src/3rdparty/assimp/code/XFileParser.cpp30
-rw-r--r--src/3rdparty/assimp/code/XFileParser.h5
-rw-r--r--src/3rdparty/assimp/code/XGLLoader.cpp120
-rw-r--r--src/3rdparty/assimp/code/XGLLoader.h13
-rw-r--r--src/3rdparty/assimp/code/XMLTools.h3
-rw-r--r--src/3rdparty/assimp/code/fast_atof.h58
-rw-r--r--src/3rdparty/assimp/code/glTF2Asset.h1131
-rw-r--r--src/3rdparty/assimp/code/glTF2Asset.inl1449
-rw-r--r--src/3rdparty/assimp/code/glTF2AssetWriter.h93
-rw-r--r--src/3rdparty/assimp/code/glTF2AssetWriter.inl638
-rw-r--r--src/3rdparty/assimp/code/glTF2Exporter.cpp1080
-rw-r--r--src/3rdparty/assimp/code/glTF2Exporter.h134
-rw-r--r--src/3rdparty/assimp/code/glTF2Importer.cpp694
-rw-r--r--src/3rdparty/assimp/code/glTF2Importer.h91
-rw-r--r--src/3rdparty/assimp/code/glTFAsset.h376
-rw-r--r--src/3rdparty/assimp/code/glTFAsset.inl466
-rw-r--r--src/3rdparty/assimp/code/glTFAssetWriter.h14
-rw-r--r--src/3rdparty/assimp/code/glTFAssetWriter.inl278
-rw-r--r--src/3rdparty/assimp/code/glTFExporter.cpp731
-rw-r--r--src/3rdparty/assimp/code/glTFExporter.h24
-rw-r--r--src/3rdparty/assimp/code/glTFImporter.cpp99
-rw-r--r--src/3rdparty/assimp/code/glTFImporter.h5
-rw-r--r--src/3rdparty/assimp/code/irrXMLWrapper.h13
-rw-r--r--src/3rdparty/assimp/code/makefile.mingw105
-rw-r--r--src/3rdparty/assimp/code/qnan.h56
-rw-r--r--src/3rdparty/assimp/code/scene.cpp139
-rw-r--r--src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.c539
-rw-r--r--src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.h151
-rw-r--r--src/3rdparty/assimp/contrib/ConvertUTF/readme.txt43
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcAdjacencyInfo.h155
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.cpp865
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.h339
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcBinaryStream.h433
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcCommon.h412
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcDVEncodeParams.h62
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVector.h84
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.cpp278
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.h76
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.cpp295
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.h79
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcFIFO.h97
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.h263
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.inl47
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.h111
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl850
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncodeParams.h140
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.h116
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl927
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTimer.h134
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTools.cpp22
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.cpp475
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.h291
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.h133
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.inl364
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.h101
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.inl719
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.h184
-rw-r--r--src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.inl317
-rw-r--r--src/3rdparty/assimp/contrib/clipper/clipper.cpp5
-rw-r--r--src/3rdparty/assimp/contrib/clipper/clipper.hpp2
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt122
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/CREDITS3
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/README.md4
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp20
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp44
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp63
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp169
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLStream.cpp96
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp35
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h29
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h7
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h30
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h16
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h44
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h89
-rw-r--r--src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h10
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.cc52
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h58
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h40
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/poly2tri.h3
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.cc5
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.h4
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.cc7
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.h32
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc133
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.h47
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc53
-rw-r--r--src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.h32
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h40
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h985
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h48
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h233
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h21
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h27
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h13
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h11
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/fwd.h151
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h2
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h14
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h46
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h5
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/regex.h734
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h49
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h32
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h25
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h9
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/istreamwrapper.h115
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h2
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h16
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h8
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/ostreamwrapper.h81
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h131
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h98
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h310
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h1293
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/schema.h2016
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stream.h179
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h30
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h458
-rw-r--r--src/3rdparty/assimp/contrib/rapidjson/readme.md69
-rw-r--r--src/3rdparty/assimp/contrib/unzip/crypt.h8
-rw-r--r--src/3rdparty/assimp/contrib/unzip/ioapi.c34
-rw-r--r--src/3rdparty/assimp/contrib/unzip/ioapi.h16
-rw-r--r--src/3rdparty/assimp/contrib/unzip/unzip.c51
-rw-r--r--src/3rdparty/assimp/contrib/unzip/unzip.h66
-rw-r--r--src/3rdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes12
-rw-r--r--src/3rdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html1789
-rw-r--r--src/3rdparty/assimp/contrib/utf8cpp/source/utf8.h34
-rw-r--r--src/3rdparty/assimp/contrib/utf8cpp/source/utf8/checked.h327
-rw-r--r--src/3rdparty/assimp/contrib/utf8cpp/source/utf8/core.h329
-rw-r--r--src/3rdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h228
-rw-r--r--src/3rdparty/assimp/contrib/zip/README.md139
-rw-r--r--src/3rdparty/assimp/contrib/zip/UNLICENSE26
-rw-r--r--src/3rdparty/assimp/contrib/zip/src/miniz.h4927
-rw-r--r--src/3rdparty/assimp/contrib/zip/src/zip.c640
-rw-r--r--src/3rdparty/assimp/contrib/zip/src/zip.h193
-rw-r--r--src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h3
-rw-r--r--src/3rdparty/assimp/include/assimp/DefaultIOStream.h (renamed from src/3rdparty/assimp/code/DefaultIOStream.h)25
-rw-r--r--src/3rdparty/assimp/include/assimp/DefaultIOSystem.h (renamed from src/3rdparty/assimp/code/DefaultIOSystem.h)5
-rw-r--r--src/3rdparty/assimp/include/assimp/DefaultLogger.hpp3
-rw-r--r--src/3rdparty/assimp/include/assimp/Defines.h (renamed from src/3rdparty/assimp/code/Defines.h)0
-rw-r--r--src/3rdparty/assimp/include/assimp/Exporter.hpp85
-rw-r--r--src/3rdparty/assimp/include/assimp/IOStream.hpp4
-rw-r--r--src/3rdparty/assimp/include/assimp/IOSystem.hpp109
-rw-r--r--src/3rdparty/assimp/include/assimp/Importer.hpp42
-rw-r--r--src/3rdparty/assimp/include/assimp/LogStream.hpp24
-rw-r--r--src/3rdparty/assimp/include/assimp/Logger.hpp7
-rw-r--r--src/3rdparty/assimp/include/assimp/NullLogger.hpp7
-rw-r--r--src/3rdparty/assimp/include/assimp/ProgressHandler.hpp12
-rw-r--r--src/3rdparty/assimp/include/assimp/SceneCombiner.h (renamed from src/3rdparty/assimp/code/SceneCombiner.h)26
-rw-r--r--src/3rdparty/assimp/include/assimp/ai_assert.h13
-rw-r--r--src/3rdparty/assimp/include/assimp/anim.h187
-rw-r--r--src/3rdparty/assimp/include/assimp/camera.h4
-rw-r--r--src/3rdparty/assimp/include/assimp/cexport.h9
-rw-r--r--src/3rdparty/assimp/include/assimp/cfileio.h20
-rw-r--r--src/3rdparty/assimp/include/assimp/cimport.h11
-rw-r--r--src/3rdparty/assimp/include/assimp/color4.h16
-rw-r--r--src/3rdparty/assimp/include/assimp/color4.inl28
-rw-r--r--src/3rdparty/assimp/include/assimp/config.h95
-rw-r--r--src/3rdparty/assimp/include/assimp/defs.h34
-rw-r--r--src/3rdparty/assimp/include/assimp/importerdesc.h10
-rw-r--r--src/3rdparty/assimp/include/assimp/light.h12
-rw-r--r--src/3rdparty/assimp/include/assimp/material.h104
-rw-r--r--src/3rdparty/assimp/include/assimp/material.inl55
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix3x3.h30
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix3x3.inl42
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix4x4.h60
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix4x4.inl248
-rw-r--r--src/3rdparty/assimp/include/assimp/mesh.h32
-rw-r--r--src/3rdparty/assimp/include/assimp/metadata.h207
-rw-r--r--src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h2
-rw-r--r--src/3rdparty/assimp/include/assimp/postprocess.h16
-rw-r--r--src/3rdparty/assimp/include/assimp/quaternion.h11
-rw-r--r--src/3rdparty/assimp/include/assimp/quaternion.inl6
-rw-r--r--src/3rdparty/assimp/include/assimp/scene.h160
-rw-r--r--src/3rdparty/assimp/include/assimp/texture.h32
-rw-r--r--src/3rdparty/assimp/include/assimp/types.h51
-rw-r--r--src/3rdparty/assimp/include/assimp/vector2.h9
-rw-r--r--src/3rdparty/assimp/include/assimp/vector2.inl7
-rw-r--r--src/3rdparty/assimp/include/assimp/vector3.h29
-rw-r--r--src/3rdparty/assimp/include/assimp/vector3.inl30
-rw-r--r--src/3rdparty/assimp/include/assimp/version.h11
-rw-r--r--src/3rdparty/assimp/revision.h2
544 files changed, 65681 insertions, 14092 deletions
diff --git a/src/3rdparty/assimp/Readme.md b/src/3rdparty/assimp/Readme.md
index e4fe07b02..1f6c4118f 100644
--- a/src/3rdparty/assimp/Readme.md
+++ b/src/3rdparty/assimp/Readme.md
@@ -1,71 +1,100 @@
Open Asset Import Library (assimp)
==================================
+A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+### Current build status ###
+[![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
+[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
+<a href="https://scan.coverity.com/projects/5607">
+ <img alt="Coverity Scan Build Status"
+ src="https://scan.coverity.com/projects/5607/badge.svg"/>
+</a>
+[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
+[![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>
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.
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:
+This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
+
+Monthly donations via Patreon:
+<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
+
+<br>
+
+One-off donations via PayPal:
+<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
-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.__
+
+Please check our Wiki as well: https://github.com/assimp/assimp/wiki
#### Supported file formats ####
-A full list [is here](http://assimp.sourceforge.net/main_features_formats.html).
+A full list [is here](http://assimp.org/main_features_formats.html).
__Importers__:
-
+- 3D
- 3DS
+- 3MF
+- AC
+- AC3D
+- ACC
+- AMJ
+- ASE
+- ASK
+- B3D;
- BLEND (Blender)
+- BVH
+- COB
+- CMS
- DAE/Collada
+- DXF
+- ENFF
- FBX
+- glTF 1.0 + GLB
+- glTF 2.0
+- HMB
- IFC-STEP
-- ASE
-- DXF
-- HMP
+- IRR / IRRMESH
+- LWO
+- LWS
+- LXO
- MD2
- MD3
- MD5
- MDC
- MDL
+- MESH / MESH.XML
+- MOT
+- MS3D
+- NDO
- NFF
-- PLY
-- STL
-- X
- OBJ
-- OpenGEX
+- OFF
+- OGEX
+- PLY
+- PMX
+- PRJ
+- Q3O
+- Q3S
+- RAW
+- SCN
+- SIB
- SMD
-- LWO
-- LXO
-- LWS
+- STL
+- STP
- TER
-- AC3D
-- MS3D
-- COB
-- Q3BSP
+- UC
+- VTA
+- X
+- X3D
- XGL
-- CSM
-- BVH
-- B3D
-- NDO
-- Ogre Binary
-- Ogre XML
-- Q3D
-- ASSBIN (Assimp custom format)
-- glTF (partial)
-- 3MF
+- ZGL
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)
+- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
__Exporters__:
@@ -78,7 +107,8 @@ __Exporters__:
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN
- STEP
-- glTF (partial)
+- glTF 1.0 (partial)
+- glTF 2.0 (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.
@@ -88,6 +118,12 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak
* [Python](port/PyAssimp/README.md)
* [.NET](port/AssimpNET/Readme.md)
* [Pascal](port/AssimpPascal/Readme.md)
+* [Javascript (Alpha)](https://github.com/makc/assimp2json)
+* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
+* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (currently supported obj, ply, stl, collada, md2)
+
+### Other tools ###
+[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
#### Repository structure ####
Open Asset Import Library is implemented in C++. The directory structure is:
@@ -107,7 +143,7 @@ Open Asset Import Library is implemented in C++. The directory structure is:
### 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.
+For more information, visit [our website](http://assimp.org/). 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 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.
@@ -117,17 +153,12 @@ For development discussions, there is also a (very low-volume) mailing list, _as
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
+And we also have a Gitter-channel: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>
### 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.
diff --git a/src/3rdparty/assimp/assimp.pri b/src/3rdparty/assimp/assimp.pri
index 4c0eb40c9..1dc7849bc 100644
--- a/src/3rdparty/assimp/assimp.pri
+++ b/src/3rdparty/assimp/assimp.pri
@@ -1,7 +1,3 @@
-######################################################################
-# Automatically generated by qmake (2.01a) Sun Mar 23 23:00:48 2014
-######################################################################
-
# AssImp expects this to be defined on debug builds
CONFIG(debug, debug|release) : DEFINES+=_DEBUG
CONFIG += exceptions rtti
@@ -21,7 +17,8 @@ DEFINES += \
ASSIMP_BUILD_NO_Q3BSP_IMPORTER \
ASSIMP_BUILD_NO_C4D_IMPORTER \
ASSIMP_BUILD_NO_3MF_IMPORTER \
- OPENDDL_STATIC_LIBARY
+ OPENDDL_STATIC_LIBARY \
+ NOUNCRYPT
intel_icc: {
# warning #310: old-style parameter list (anachronism)
@@ -81,469 +78,533 @@ INCLUDEPATH += \
# 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/AssbinExporter.h \
- code/AssbinLoader.h \
- code/AssxmlExporter.h \
- code/B3DImporter.h \
- code/BaseImporter.h \
- code/BaseProcess.h \
- code/Bitmap.h \
- code/BlenderBMesh.h \
- code/BlenderDNA.h \
- code/BlenderDNA.inl \
- code/BlenderIntermediate.h \
- code/BlenderLoader.h \
- code/BlenderModifier.h \
- code/BlenderScene.h \
- code/BlenderSceneGen.h \
- code/BlenderTessellator.h \
- code/BlobIOSystem.h \
- code/BVHLoader.h \
- code/ByteSwapper.h \
- code/C4DImporter.h \
- code/CalcTangentsProcess.h \
- code/CInterfaceIOWrapper.h \
- code/COBLoader.h \
- code/COBScene.h \
- code/ColladaExporter.h \
- code/ColladaHelper.h \
- code/ColladaLoader.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 \
- code/FindInstancesProcess.h \
- code/FindInvalidDataProcess.h \
- code/FixNormalsStep.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 \
- code/HMPLoader.h \
- code/IFCLoader.h \
- code/IFCReaderGen.h \
- code/IFCUtil.h \
- code/IFF.h \
- code/Importer.h \
- code/ImproveCacheLocality.h \
- code/IRRLoader.h \
- code/IRRMeshLoader.h \
- code/IRRShared.h \
- code/irrXMLWrapper.h \
- code/JoinVerticesProcess.h \
- code/LimitBoneWeightsProcess.h \
- code/LineSplitter.h \
- code/LogAux.h \
- code/LWOAnimation.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 \
- code/MD3FileData.h \
- code/MD3Loader.h \
- code/MD4FileData.h \
- code/MD5Loader.h \
- code/MD5Parser.h \
- code/MDCFileData.h \
- code/MDCLoader.h \
- code/MDCNormalTable.h \
- code/MDLDefaultColorMap.h \
- code/MDLFileData.h \
- code/MDLLoader.h \
- code/MemoryIOWrapper.h \
- code/MS3DLoader.h \
- code/NDOLoader.h \
- code/NFFLoader.h \
- code/ObjExporter.h \
- code/ObjFileData.h \
- code/ObjFileImporter.h \
- code/ObjFileMtlImporter.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 \
- code/PlyExporter.h \
- code/PlyLoader.h \
- code/PlyParser.h \
- code/PolyTools.h \
- code/PretransformVertices.h \
- code/ProcessHelper.h \
- code/Profiler.h \
- code/Q3BSPFileData.h \
- code/Q3BSPFileImporter.h \
- code/Q3BSPFileParser.h \
- code/Q3BSPZipArchive.h \
- code/Q3DLoader.h \
- code/qnan.h \
- code/RawLoader.h \
- code/RemoveComments.h \
- code/RemoveRedundantMaterials.h \
- code/RemoveVCProcess.h \
- code/SceneCombiner.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 \
- code/TextureTransform.h \
- code/TinyFormatter.h \
- code/TriangulateProcess.h \
- code/UnrealLoader.h \
- code/ValidateDataStructure.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 \
- contrib/irrXML/CXMLReaderImpl.h \
- contrib/irrXML/heapsort.h \
- contrib/irrXML/irrArray.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 \
- include/assimp/ai_assert.h \
- include/assimp/anim.h \
- include/assimp/camera.h \
- include/assimp/cexport.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 \
- include/assimp/Exporter.hpp \
- include/assimp/Importer.hpp \
- include/assimp/importerdesc.h \
- include/assimp/IOStream.hpp \
- include/assimp/IOSystem.hpp \
- include/assimp/light.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/vector2.inl \
- include/assimp/vector3.h \
- include/assimp/vector3.inl \
- include/assimp/version.h \
- include/assimp/Compiler/poppack1.h \
- include/assimp/Compiler/pushpack1.h \
- include/assimp/Compiler/pstdint.h
+ code/3DSExporter.h \
+ code/3DSHelper.h \
+ code/3DSLoader.h \
+ code/3MFXmlTags.h \
+ code/ACLoader.h \
+ code/ASELoader.h \
+ code/ASEParser.h \
+ code/AssbinExporter.h \
+ code/AssbinLoader.h \
+ code/AssxmlExporter.h \
+ code/B3DImporter.h \
+ code/BVHLoader.h \
+ code/BaseImporter.h \
+ code/BaseProcess.h \
+ code/Bitmap.h \
+ code/BlenderBMesh.h \
+ code/BlenderDNA.h \
+ code/BlenderIntermediate.h \
+ code/BlenderLoader.h \
+ code/BlenderModifier.h \
+ code/BlenderScene.h \
+ code/BlenderSceneGen.h \
+ code/BlenderTessellator.h \
+ code/BlobIOSystem.h \
+ code/ByteSwapper.h \
+ code/C4DImporter.h \
+ code/CInterfaceIOWrapper.h \
+ code/COBLoader.h \
+ code/COBScene.h \
+ code/CSMLoader.h \
+ code/CalcTangentsProcess.h \
+ code/ColladaExporter.h \
+ code/ColladaHelper.h \
+ code/ColladaLoader.h \
+ code/ColladaParser.h \
+ code/ComputeUVMappingProcess.h \
+ code/ConvertToLHProcess.h \
+ code/CreateAnimMesh.h \
+ code/D3MFExporter.h \
+ code/D3MFImporter.h \
+ code/D3MFOpcPackage.h \
+ code/DXFHelper.h \
+ code/DXFLoader.h \
+ code/DeboneProcess.h \
+ code/DefaultProgressHandler.h \
+ code/Exceptional.h \
+ code/FBXCompileConfig.h \
+ code/FBXConverter.h \
+ code/FBXDocument.h \
+ code/FBXDocumentUtil.h \
+ code/FBXImportSettings.h \
+ code/FBXImporter.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 \
+ code/FindInstancesProcess.h \
+ code/FindInvalidDataProcess.h \
+ code/FixNormalsStep.h \
+ code/GenFaceNormalsProcess.h \
+ code/GenVertexNormalsProcess.h \
+ code/GenericProperty.h \
+ code/HMPFileData.h \
+ code/HMPLoader.h \
+ code/HalfLifeFileData.h \
+ code/Hash.h \
+ code/IFCLoader.h \
+ code/IFCReaderGen.h \
+ code/IFCUtil.h \
+ code/IFF.h \
+ code/IOStreamBuffer.h \
+ code/IRRLoader.h \
+ code/IRRMeshLoader.h \
+ code/IRRShared.h \
+ code/Importer.h \
+ code/ImproveCacheLocality.h \
+ code/JoinVerticesProcess.h \
+ code/LWOAnimation.h \
+ code/LWOFileData.h \
+ code/LWOLoader.h \
+ code/LWSLoader.h \
+ code/LimitBoneWeightsProcess.h \
+ code/LineSplitter.h \
+ code/LogAux.h \
+ code/MD2FileData.h \
+ code/MD2Loader.h \
+ code/MD2NormalTable.h \
+ code/MD3FileData.h \
+ code/MD3Loader.h \
+ code/MD4FileData.h \
+ code/MD5Loader.h \
+ code/MD5Parser.h \
+ code/MDCFileData.h \
+ code/MDCLoader.h \
+ code/MDCNormalTable.h \
+ code/MDLDefaultColorMap.h \
+ code/MDLFileData.h \
+ code/MDLLoader.h \
+ code/MMDCpp14.h \
+ code/MMDImporter.h \
+ code/MMDPmdParser.h \
+ code/MMDPmxParser.h \
+ code/MMDVmdParser.h \
+ code/MS3DLoader.h \
+ code/Macros.h \
+ code/MakeVerboseFormat.h \
+ code/MaterialSystem.h \
+ code/MathFunctions.h \
+ code/MemoryIOWrapper.h \
+ code/NDOLoader.h \
+ code/NFFLoader.h \
+ code/OFFLoader.h \
+ code/ObjExporter.h \
+ code/ObjFileData.h \
+ code/ObjFileImporter.h \
+ code/ObjFileMtlImporter.h \
+ code/ObjFileParser.h \
+ code/ObjTools.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 \
+ code/PlyExporter.h \
+ code/PlyLoader.h \
+ code/PlyParser.h \
+ code/PolyTools.h \
+ code/PretransformVertices.h \
+ code/ProcessHelper.h \
+ code/Profiler.h \
+ code/Q3BSPFileData.h \
+ code/Q3BSPFileImporter.h \
+ code/Q3BSPFileParser.h \
+ code/Q3BSPZipArchive.h \
+ code/Q3DLoader.h \
+ code/RawLoader.h \
+ code/RemoveComments.h \
+ code/RemoveRedundantMaterials.h \
+ code/RemoveVCProcess.h \
+ code/SGSpatialSort.h \
+ code/SIBImporter.h \
+ code/SMDLoader.h \
+ code/STEPFile.h \
+ code/STEPFileEncoding.h \
+ code/STEPFileReader.h \
+ code/STLExporter.h \
+ code/STLLoader.h \
+ code/ScaleProcess.h \
+ code/ScenePreprocessor.h \
+ code/ScenePrivate.h \
+ code/SkeletonMeshBuilder.h \
+ code/SmoothingGroups.h \
+ code/SortByPTypeProcess.h \
+ code/SpatialSort.h \
+ code/SplitByBoneCountProcess.h \
+ code/SplitLargeMeshes.h \
+ code/StandardShapes.h \
+ code/StdOStreamLogStream.h \
+ code/StepExporter.h \
+ code/StreamReader.h \
+ code/StreamWriter.h \
+ code/StringComparison.h \
+ code/StringUtils.h \
+ code/Subdivision.h \
+ code/TargetAnimation.h \
+ code/TerragenLoader.h \
+ code/TextureTransform.h \
+ code/TinyFormatter.h \
+ code/TriangulateProcess.h \
+ code/UnrealLoader.h \
+ code/ValidateDataStructure.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/assbin_chunks.h \
+ code/fast_atof.h \
+ code/glTF2Asset.h \
+ code/glTF2AssetWriter.h \
+ code/glTF2Exporter.h \
+ code/glTF2Importer.h \
+ code/glTFAsset.h \
+ code/glTFAssetWriter.h \
+ code/glTFExporter.h \
+ code/glTFImporter.h \
+ code/irrXMLWrapper.h \
+ code/qnan.h \
+ code/res/resource.h \
+ contrib/Open3DGC/o3dgcAdjacencyInfo.h \
+ contrib/Open3DGC/o3dgcArithmeticCodec.h \
+ contrib/Open3DGC/o3dgcBinaryStream.h \
+ contrib/Open3DGC/o3dgcCommon.h \
+ contrib/Open3DGC/o3dgcDVEncodeParams.h \
+ contrib/Open3DGC/o3dgcDynamicVector.h \
+ contrib/Open3DGC/o3dgcDynamicVectorDecoder.h \
+ contrib/Open3DGC/o3dgcDynamicVectorEncoder.h \
+ contrib/Open3DGC/o3dgcFIFO.h \
+ contrib/Open3DGC/o3dgcIndexedFaceSet.h \
+ contrib/Open3DGC/o3dgcSC3DMCDecoder.h \
+ contrib/Open3DGC/o3dgcSC3DMCEncodeParams.h \
+ contrib/Open3DGC/o3dgcSC3DMCEncoder.h \
+ contrib/Open3DGC/o3dgcTimer.h \
+ contrib/Open3DGC/o3dgcTriangleFans.h \
+ contrib/Open3DGC/o3dgcTriangleListDecoder.h \
+ contrib/Open3DGC/o3dgcTriangleListEncoder.h \
+ contrib/Open3DGC/o3dgcVector.h \
+ contrib/clipper/clipper.hpp \
+ contrib/irrXML/CXMLReaderImpl.h \
+ contrib/irrXML/heapsort.h \
+ contrib/irrXML/irrArray.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/OpenDDLStream.h \
+ contrib/openddlparser/include/openddlparser/Value.h \
+ contrib/poly2tri/poly2tri/common/shapes.h \
+ contrib/poly2tri/poly2tri/common/utils.h \
+ contrib/poly2tri/poly2tri/poly2tri.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/fwd.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/regex.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/istreamwrapper.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/ostreamwrapper.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/schema.h \
+ contrib/rapidjson/include/rapidjson/stream.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 \
+ contrib/utf8cpp/source/utf8.h \
+ contrib/utf8cpp/source/utf8/checked.h \
+ contrib/utf8cpp/source/utf8/core.h \
+ contrib/utf8cpp/source/utf8/unchecked.h \
+ include/assimp/Compiler/poppack1.h \
+ include/assimp/Compiler/pstdint.h \
+ include/assimp/Compiler/pushpack1.h \
+ include/assimp/DefaultIOStream.h \
+ include/assimp/DefaultIOSystem.h \
+ include/assimp/DefaultLogger.hpp \
+ include/assimp/Defines.h \
+ include/assimp/Exporter.hpp \
+ include/assimp/IOStream.hpp \
+ include/assimp/IOSystem.hpp \
+ include/assimp/Importer.hpp \
+ include/assimp/LogStream.hpp \
+ include/assimp/Logger.hpp \
+ include/assimp/NullLogger.hpp \
+ include/assimp/ProgressHandler.hpp \
+ include/assimp/SceneCombiner.h \
+ include/assimp/ai_assert.h \
+ include/assimp/anim.h \
+ include/assimp/camera.h \
+ include/assimp/cexport.h \
+ include/assimp/cfileio.h \
+ include/assimp/cimport.h \
+ include/assimp/color4.h \
+ include/assimp/config.h \
+ include/assimp/defs.h \
+ include/assimp/importerdesc.h \
+ include/assimp/light.h \
+ include/assimp/material.h \
+ include/assimp/matrix3x3.h \
+ include/assimp/matrix4x4.h \
+ include/assimp/mesh.h \
+ include/assimp/metadata.h \
+ include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h \
+ include/assimp/postprocess.h \
+ include/assimp/quaternion.h \
+ include/assimp/scene.h \
+ include/assimp/texture.h \
+ include/assimp/types.h \
+ include/assimp/vector2.h \
+ include/assimp/vector3.h \
+ include/assimp/version.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/AssxmlExporter.cpp \
- code/B3DImporter.cpp \
- code/BaseImporter.cpp \
- code/BaseProcess.cpp \
- code/Bitmap.cpp \
- code/BlenderBMesh.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 \
- code/ColladaLoader.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 \
- code/IFCUtil.cpp \
- code/Importer.cpp \
- code/ImporterRegistry.cpp \
- code/ImproveCacheLocality.cpp \
- code/IRRLoader.cpp \
- code/IRRMeshLoader.cpp \
- code/IRRShared.cpp \
- code/JoinVerticesProcess.cpp \
- code/LimitBoneWeightsProcess.cpp \
- code/LWOAnimation.cpp \
- code/LWOBLoader.cpp \
- code/LWOLoader.cpp \
- code/LWOMaterial.cpp \
- code/LWSLoader.cpp \
- code/MakeVerboseFormat.cpp \
- code/MaterialSystem.cpp \
- code/MD2Loader.cpp \
- code/MD3Loader.cpp \
- code/MD5Loader.cpp \
- code/MD5Parser.cpp \
- code/MDCLoader.cpp \
- code/MDLLoader.cpp \
- code/MDLMaterialLoader.cpp \
- code/MS3DLoader.cpp \
- code/NDOLoader.cpp \
- code/NFFLoader.cpp \
- code/ObjExporter.cpp \
- code/ObjFileImporter.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 \
- code/PlyLoader.cpp \
- code/PlyParser.cpp \
- code/PostStepRegistry.cpp \
- code/PretransformVertices.cpp \
- code/ProcessHelper.cpp \
- code/Q3BSPFileImporter.cpp \
- code/Q3BSPFileParser.cpp \
- code/Q3BSPZipArchive.cpp \
- code/Q3DLoader.cpp \
- code/RawLoader.cpp \
- code/RemoveComments.cpp \
- code/RemoveRedundantMaterials.cpp \
- code/RemoveVCProcess.cpp \
- code/SceneCombiner.cpp \
- code/ScenePreprocessor.cpp \
- code/SGSpatialSort.cpp \
- code/SIBImporter.cpp \
- code/SkeletonMeshBuilder.cpp \
- code/SMDLoader.cpp \
- code/SortByPTypeProcess.cpp \
- code/SpatialSort.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 \
- code/Subdivision.cpp \
- code/TargetAnimation.cpp \
- code/TerragenLoader.cpp \
- code/TextureTransform.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/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 \
- contrib/unzip/ioapi.c \
- contrib/unzip/unzip.c
+SOURCES += \
+ code/3DSConverter.cpp \
+ code/3DSExporter.cpp \
+ code/3DSLoader.cpp \
+ code/ACLoader.cpp \
+ code/AMFImporter.cpp \
+ code/AMFImporter_Geometry.cpp \
+ code/AMFImporter_Material.cpp \
+ code/AMFImporter_Postprocess.cpp \
+ code/ASELoader.cpp \
+ code/ASEParser.cpp \
+ code/AssbinExporter.cpp \
+ code/AssbinLoader.cpp \
+ code/Assimp.cpp \
+ code/AssimpCExport.cpp \
+ code/AssxmlExporter.cpp \
+ code/B3DImporter.cpp \
+ code/BVHLoader.cpp \
+ code/BaseImporter.cpp \
+ code/BaseProcess.cpp \
+ code/Bitmap.cpp \
+ code/BlenderBMesh.cpp \
+ code/BlenderDNA.cpp \
+ code/BlenderLoader.cpp \
+ code/BlenderModifier.cpp \
+ code/BlenderScene.cpp \
+ code/BlenderTessellator.cpp \
+ code/C4DImporter.cpp \
+ code/CInterfaceIOWrapper.cpp \
+ code/COBLoader.cpp \
+ code/CSMLoader.cpp \
+ code/CalcTangentsProcess.cpp \
+ code/ColladaExporter.cpp \
+ code/ColladaLoader.cpp \
+ code/ColladaParser.cpp \
+ code/ComputeUVMappingProcess.cpp \
+ code/ConvertToLHProcess.cpp \
+ code/CreateAnimMesh.cpp \
+ code/D3MFExporter.cpp \
+ code/D3MFImporter.cpp \
+ code/D3MFOpcPackage.cpp \
+ code/DXFLoader.cpp \
+ code/DeboneProcess.cpp \
+ code/DefaultIOStream.cpp \
+ code/DefaultIOSystem.cpp \
+ code/DefaultLogger.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/FIReader.cpp \
+ code/FindDegenerates.cpp \
+ code/FindInstancesProcess.cpp \
+ code/FindInvalidDataProcess.cpp \
+ code/FixNormalsStep.cpp \
+ code/GenFaceNormalsProcess.cpp \
+ code/GenVertexNormalsProcess.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 \
+ code/IFCUtil.cpp \
+ code/IRRLoader.cpp \
+ code/IRRMeshLoader.cpp \
+ code/IRRShared.cpp \
+ code/Importer.cpp \
+ code/ImporterRegistry.cpp \
+ code/ImproveCacheLocality.cpp \
+ code/JoinVerticesProcess.cpp \
+ code/LWOAnimation.cpp \
+ code/LWOBLoader.cpp \
+ code/LWOLoader.cpp \
+ code/LWOMaterial.cpp \
+ code/LWSLoader.cpp \
+ code/LimitBoneWeightsProcess.cpp \
+ code/MD2Loader.cpp \
+ code/MD3Loader.cpp \
+ code/MD5Loader.cpp \
+ code/MD5Parser.cpp \
+ code/MDCLoader.cpp \
+ code/MDLLoader.cpp \
+ code/MDLMaterialLoader.cpp \
+ code/MMDImporter.cpp \
+ code/MMDPmxParser.cpp \
+ code/MS3DLoader.cpp \
+ code/MakeVerboseFormat.cpp \
+ code/MaterialSystem.cpp \
+ code/NDOLoader.cpp \
+ code/NFFLoader.cpp \
+ code/OFFLoader.cpp \
+ code/ObjExporter.cpp \
+ code/ObjFileImporter.cpp \
+ code/ObjFileMtlImporter.cpp \
+ code/ObjFileParser.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 \
+ code/PlyLoader.cpp \
+ code/PlyParser.cpp \
+ code/PostStepRegistry.cpp \
+ code/PretransformVertices.cpp \
+ code/ProcessHelper.cpp \
+ code/Q3BSPFileImporter.cpp \
+ code/Q3BSPFileParser.cpp \
+ code/Q3BSPZipArchive.cpp \
+ code/Q3DLoader.cpp \
+ code/RawLoader.cpp \
+ code/RemoveComments.cpp \
+ code/RemoveRedundantMaterials.cpp \
+ code/RemoveVCProcess.cpp \
+ code/SGSpatialSort.cpp \
+ code/SIBImporter.cpp \
+ code/SMDLoader.cpp \
+ code/STEPFileEncoding.cpp \
+ code/STEPFileReader.cpp \
+ code/STLExporter.cpp \
+ code/STLLoader.cpp \
+ code/ScaleProcess.cpp \
+ code/SceneCombiner.cpp \
+ code/ScenePreprocessor.cpp \
+ code/SkeletonMeshBuilder.cpp \
+ code/SortByPTypeProcess.cpp \
+ code/SpatialSort.cpp \
+ code/SplitByBoneCountProcess.cpp \
+ code/SplitLargeMeshes.cpp \
+ code/StandardShapes.cpp \
+ code/StepExporter.cpp \
+ code/Subdivision.cpp \
+ code/TargetAnimation.cpp \
+ code/TerragenLoader.cpp \
+ code/TextureTransform.cpp \
+ code/TriangulateProcess.cpp \
+ code/UnrealLoader.cpp \
+ code/ValidateDataStructure.cpp \
+ code/Version.cpp \
+ code/VertexTriangleAdjacency.cpp \
+ code/X3DExporter.cpp \
+ code/X3DImporter.cpp \
+ code/X3DImporter_Geometry2D.cpp \
+ code/X3DImporter_Geometry3D.cpp \
+ code/X3DImporter_Group.cpp \
+ code/X3DImporter_Light.cpp \
+ code/X3DImporter_Metadata.cpp \
+ code/X3DImporter_Networking.cpp \
+ code/X3DImporter_Postprocess.cpp \
+ code/X3DImporter_Rendering.cpp \
+ code/X3DImporter_Shape.cpp \
+ code/X3DImporter_Texturing.cpp \
+ code/X3DVocabulary.cpp \
+ code/XFileExporter.cpp \
+ code/XFileImporter.cpp \
+ code/XFileParser.cpp \
+ code/XGLLoader.cpp \
+ code/glTF2Exporter.cpp \
+ code/glTF2Importer.cpp \
+ code/glTFExporter.cpp \
+ code/glTFImporter.cpp \
+ code/scene.cpp \
+ contrib/Open3DGC/o3dgcArithmeticCodec.cpp \
+ contrib/Open3DGC/o3dgcDynamicVectorDecoder.cpp \
+ contrib/Open3DGC/o3dgcDynamicVectorEncoder.cpp \
+ contrib/Open3DGC/o3dgcTools.cpp \
+ contrib/Open3DGC/o3dgcTriangleFans.cpp \
+ contrib/clipper/clipper.cpp \
+ contrib/irrXML/irrXML.cpp \
+ contrib/openddlparser/code/DDLNode.cpp \
+ contrib/openddlparser/code/OpenDDLCommon.cpp \
+ contrib/openddlparser/code/OpenDDLExport.cpp \
+ contrib/openddlparser/code/OpenDDLParser.cpp \
+ contrib/openddlparser/code/OpenDDLStream.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 \
+ contrib/unzip/ioapi.c \
+ contrib/unzip/unzip.c \
+ contrib/zip/src/zip.c
diff --git a/src/3rdparty/assimp/code/3DSConverter.cpp b/src/3rdparty/assimp/code/3DSConverter.cpp
index cb6fd9077..820c28f90 100644
--- a/src/3rdparty/assimp/code/3DSConverter.cpp
+++ b/src/3rdparty/assimp/code/3DSConverter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -55,18 +56,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
+static const unsigned int NotSet = 0xcdcdcdcd;
+
// ------------------------------------------------------------------------------------------------
// 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;
+ unsigned int idx( NotSet );
for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
{
std::string s = mScene->mMaterials[i].mName;
@@ -92,7 +94,9 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
}
idx = i;
}
- if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size();
+ if ( NotSet == 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
@@ -197,7 +201,7 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
// Setup the texture blend factor
if (is_not_qnan(texture.mTextureBlend))
- mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
+ mat.AddProperty<ai_real>( &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));
@@ -207,14 +211,14 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
// 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;
+ texture.mScaleU *= 2.0;
+ texture.mScaleV *= 2.0;
+ texture.mOffsetU /= 2.0;
+ texture.mOffsetV /= 2.0;
}
// Setup texture UV transformations
- mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
+ mat.AddProperty<ai_real>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
}
// ------------------------------------------------------------------------------------------------
@@ -265,10 +269,10 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
}
// Opacity
- mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
+ mat.AddProperty<ai_real>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
// Bump height scaling
- mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
+ mat.AddProperty<ai_real>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
// Two sided rendering?
if (oldMat.mTwoSided)
@@ -690,7 +694,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
// Recursively process all children
- const unsigned int size = pcIn->mChildren.size();
+ const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
for (unsigned int i = 0; i < size;++i)
{
pcOut->mChildren[i] = new aiNode();
@@ -742,7 +746,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
- mScene->mCameras.size() + mScene->mLights.size();
+ static_cast<unsigned int>(mScene->mCameras.size() + mScene->mLights.size());
pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ];
pcOut->mRootNode->mName.Set("<3DSDummyRoot>");
diff --git a/src/3rdparty/assimp/code/3DSExporter.cpp b/src/3rdparty/assimp/code/3DSExporter.cpp
index 5bb79408f..2f561fcd6 100644
--- a/src/3rdparty/assimp/code/3DSExporter.cpp
+++ b/src/3rdparty/assimp/code/3DSExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -38,13 +39,13 @@ 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 "3DSHelper.h"
+#include <assimp/SceneCombiner.h>
#include "SplitLargeMeshes.h"
#include "StringComparison.h"
#include <assimp/IOSystem.hpp>
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
namespace Assimp {
+using namespace D3DS;
namespace {
@@ -85,7 +87,7 @@ namespace {
const std::size_t chunk_size = head_pos - chunk_start_pos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
- writer.PutU4(chunk_size);
+ writer.PutU4(static_cast<uint32_t>(chunk_size));
writer.SetCurrentPos(head_pos);
}
@@ -148,7 +150,7 @@ namespace {
// ------------------------------------------------------------------------------------------------
// 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)
+void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
std::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
if(!outfile) {
@@ -208,6 +210,12 @@ Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> outfile, con
}
// ------------------------------------------------------------------------------------------------
+Discreet3DSExporter::~Discreet3DSExporter() {
+ // empty
+}
+
+
+// ------------------------------------------------------------------------------------------------
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
@@ -365,7 +373,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
aiTextureMapMode map_mode[2] = {
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
};
- float blend = 1.0f;
+ ai_real blend = 1.0;
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
return;
}
@@ -560,6 +568,12 @@ void Discreet3DSExporter::WritePercentChunk(float f) {
writer.PutF4(f);
}
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WritePercentChunk(double f) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTD);
+ writer.PutF8(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
index 321539cff..fc02e2390 100644
--- a/src/3rdparty/assimp/code/3DSExporter.h
+++ b/src/3rdparty/assimp/code/3DSExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include "StreamWriter.h"
-#include "./../include/assimp/material.h"
+#include <assimp/material.h>
struct aiScene;
struct aiNode;
@@ -59,30 +60,28 @@ namespace Assimp
{
// ------------------------------------------------------------------------------------------------
-/** Helper class to export a given scene to a 3DS file. */
+/**
+ * @brief Helper class to export a given scene to a 3DS file.
+ */
// ------------------------------------------------------------------------------------------------
-class Discreet3DSExporter
-{
+class Discreet3DSExporter {
public:
Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* pScene);
+ ~Discreet3DSExporter();
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);
+ void WritePercentChunk(double f);
private:
-
const aiScene* const scene;
StreamWriterLE writer;
@@ -93,6 +92,6 @@ private:
};
-}
+} // Namespace Assimp
-#endif
+#endif // AI_3DSEXPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/3DSHelper.h b/src/3rdparty/assimp/code/3DSHelper.h
index 5911b9d47..9e701c3dd 100644
--- a/src/3rdparty/assimp/code/3DSHelper.h
+++ b/src/3rdparty/assimp/code/3DSHelper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,15 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_3DSFILEHELPER_H_INC
#define AI_3DSFILEHELPER_H_INC
-
#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 <assimp/material.h>
+#include <assimp/camera.h>
+#include <assimp/light.h>
+#include <assimp/anim.h>
#include <stdio.h> //sprintf
namespace Assimp {
@@ -63,16 +63,19 @@ namespace D3DS {
/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
* and data structures.
*/
-class Discreet3DS
-{
+class Discreet3DS {
private:
- inline Discreet3DS() {}
+ Discreet3DS() {
+ // empty
+ }
-public:
+ ~Discreet3DS() {
+ // empty
+ }
+public:
//! data structure for a single chunk in a .3ds file
- struct Chunk
- {
+ struct Chunk {
uint16_t Flag;
uint32_t Size;
} PACK_STRUCT;
@@ -129,6 +132,7 @@ public:
CHUNK_PERCENTW = 0x0030, // int2 percentage
CHUNK_PERCENTF = 0x0031, // float4 percentage
+ CHUNK_PERCENTD = 0x0032, // float8 percentage
// ********************************************************************
// Prj master chunk
@@ -327,11 +331,11 @@ struct Texture
{
//! Default constructor
Texture()
- : mOffsetU (0.0f)
- , mOffsetV (0.0f)
- , mScaleU (1.0f)
- , mScaleV (1.0f)
- , mRotation (0.0f)
+ : mOffsetU (0.0)
+ , mOffsetV (0.0)
+ , mScaleU (1.0)
+ , mScaleV (1.0)
+ , mRotation (0.0)
, mMapMode (aiTextureMapMode_Wrap)
, bPrivate()
, iUVSrc (0)
@@ -340,17 +344,17 @@ struct Texture
}
//! Specifies the blend factor for the texture
- float mTextureBlend;
+ ai_real 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;
+ ai_real mOffsetU;
+ ai_real mOffsetV;
+ ai_real mScaleU;
+ ai_real mScaleV;
+ ai_real mRotation;
//! Specifies the mapping mode to be used for the texture
aiTextureMapMode mMapMode;
@@ -368,14 +372,13 @@ 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)
+ : mDiffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
+ , mSpecularExponent ( ai_real( 0.0 ) )
+ , mShininessStrength ( ai_real( 1.0 ) )
+ , mShading(Discreet3DS::Gouraud)
+ , mTransparency ( ai_real( 1.0 ) )
+ , mBumpHeight ( ai_real( 1.0 ) )
+ , mTwoSided (false)
{
static int iCnt = 0;
@@ -389,9 +392,9 @@ struct Material
//! Diffuse color of the material
aiColor3D mDiffuse;
//! Specular exponent
- float mSpecularExponent;
+ ai_real mSpecularExponent;
//! Shininess strength, in percent
- float mShininessStrength;
+ ai_real mShininessStrength;
//! Specular color of the material
aiColor3D mSpecular;
//! Ambient color of the material
@@ -399,7 +402,7 @@ struct Material
//! Shading type to be used
Discreet3DS::shadetype3ds mShading;
//! Opacity of the material
- float mTransparency;
+ ai_real mTransparency;
//! Diffuse texture channel
Texture sTexDiffuse;
//! Opacity texture channel
@@ -415,7 +418,7 @@ struct Material
//! Shininess texture channel
Texture sTexShininess;
//! Scaling factor for the bump values
- float mBumpHeight;
+ ai_real mBumpHeight;
//! Emissive color
aiColor3D mEmissive;
//! Ambient texture channel
@@ -459,7 +462,7 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
struct aiFloatKey
{
double mTime; ///< The time of this key
- float mValue; ///< The value of this key
+ ai_real mValue; ///< The value of this key
#ifdef __cplusplus
diff --git a/src/3rdparty/assimp/code/3DSLoader.cpp b/src/3rdparty/assimp/code/3DSLoader.cpp
index a2b73b2cb..704884a57 100644
--- a/src/3rdparty/assimp/code/3DSLoader.cpp
+++ b/src/3rdparty/assimp/code/3DSLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
#include "StringComparison.h"
using namespace Assimp;
@@ -182,7 +184,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
ParseMainChunk();
// Process all meshes in the file. First check whether all
- // face indices haev valid values. The generate our
+ // face indices have valid values. The generate our
// internal verbose representation. Finally compute normal
// vectors from the smoothing groups we read from the
// file.
@@ -458,20 +460,20 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
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) {
+ ai_real len = camera->mLookAt.Length();
+ if (len < 1e-5) {
// 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);
+ camera->mLookAt = aiVector3D(0.0,1.0,0.0);
}
else camera->mLookAt /= len;
// And finally - the camera rotation angle, in counter clockwise direction
- const float angle = AI_DEG_TO_RAD( stream->GetF4() );
+ const ai_real angle = AI_DEG_TO_RAD( stream->GetF4() );
aiQuaternion quat(camera->mLookAt,angle);
- camera->mUp = quat.GetMatrix() * aiVector3D(0.f,1.f,0.f);
+ camera->mUp = quat.GetMatrix() * aiVector3D(0.0,1.0,0.0);
// Read the lense angle
camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() );
@@ -679,7 +681,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
if ( pcNode)
{
- // if the source is not a CHUNK_TRACKINFO block it wont be an object instance
+ // if the source is not a CHUNK_TRACKINFO block it won't be an object instance
if (parent != Discreet3DS::CHUNK_TRACKINFO)
{
mCurrentNode = pcNode;
@@ -1166,14 +1168,15 @@ void Discreet3DSImporter::ParseMaterialChunk()
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;
+ // This is the material's transparency
+ ai_real* pcf = &mScene->mMaterials.back().mTransparency;
+ *pcf = ParsePercentageChunk();
+
+ // NOTE: transparency, not opacity
+ if (is_qnan(*pcf))
+ *pcf = ai_real( 1.0 );
+ else
+ *pcf = ai_real( 1.0 ) - *pcf * (ai_real)0xFFFF / ai_real( 100.0 );
}
break;
@@ -1189,31 +1192,33 @@ void Discreet3DSImporter::ParseMaterialChunk()
case Discreet3DS::CHUNK_MAT_SHININESS:
{ // This is the shininess of the material
- float* pcf = &mScene->mMaterials.back().mSpecularExponent;
+ ai_real* pcf = &mScene->mMaterials.back().mSpecularExponent;
*pcf = ParsePercentageChunk();
if (is_qnan(*pcf))
- *pcf = 0.0f;
- else *pcf *= (float)0xFFFF;
+ *pcf = 0.0;
+ else *pcf *= (ai_real)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;
+ ai_real* pcf = &mScene->mMaterials.back().mShininessStrength;
+ *pcf = ParsePercentageChunk();
+ if (is_qnan(*pcf))
+ *pcf = ai_real( 0.0 );
+ else
+ *pcf *= (ai_real)0xffff / ai_real( 100.0 );
}
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);
+ ai_real f = ParsePercentageChunk();
+ if (is_qnan(f))
+ f = ai_real( 0.0 );
+ else
+ f *= (ai_real)0xFFFF / ai_real( 100.0 );
+ mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f);
}
break;
@@ -1270,6 +1275,11 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
break;
+ case Discreet3DS::CHUNK_PERCENTD:
+ // Manually parse the blend factor
+ pcOut->mTextureBlend = ai_real( stream->GetF8() );
+ break;
+
case Discreet3DS::CHUNK_PERCENTF:
// Manually parse the blend factor
pcOut->mTextureBlend = stream->GetF4();
@@ -1277,7 +1287,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
case Discreet3DS::CHUNK_PERCENTW:
// Manually parse the blend factor
- pcOut->mTextureBlend = (float)((uint16_t)stream->GetI2()) / 100.0f;
+ pcOut->mTextureBlend = (ai_real)((uint16_t)stream->GetI2()) / ai_real( 100.0 );
break;
case Discreet3DS::CHUNK_MAT_MAP_USCALE:
@@ -1336,7 +1346,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
// ------------------------------------------------------------------------------------------------
// Read a percentage chunk
-float Discreet3DSImporter::ParsePercentageChunk()
+ai_real Discreet3DSImporter::ParsePercentageChunk()
{
Discreet3DS::Chunk chunk;
ReadChunk(&chunk);
@@ -1344,19 +1354,18 @@ float Discreet3DSImporter::ParsePercentageChunk()
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 (ai_real)((uint16_t)stream->GetI2()) / (ai_real)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)
+void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent )
{
ai_assert(out != NULL);
// error return value
- const float qnan = get_qnan();
+ const ai_real qnan = get_qnan();
static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan);
Discreet3DS::Chunk chunk;
@@ -1384,13 +1393,16 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
case Discreet3DS::CHUNK_LINRGBB:
bGamma = true;
case Discreet3DS::CHUNK_RGBB:
- if (sizeof(char) * 3 > diff) {
- *out = clrError;
- return;
+ {
+ if ( sizeof( char ) * 3 > diff ) {
+ *out = clrError;
+ return;
+ }
+ const ai_real invVal = ai_real( 1.0 ) / ai_real( 255.0 );
+ out->r = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal;
+ out->g = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal;
+ out->b = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal;
}
- 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.
@@ -1404,7 +1416,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
case Discreet3DS::CHUNK_PERCENTW:
if (acceptPercent && 1 <= diff) {
- out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
+ out->g = out->b = out->r = (ai_real)(uint8_t)stream->GetI1() / ai_real( 255.0 );
break;
}
*out = clrError;
diff --git a/src/3rdparty/assimp/code/3DSLoader.h b/src/3rdparty/assimp/code/3DSLoader.h
index 437ec94b4..0e377180b 100644
--- a/src/3rdparty/assimp/code/3DSLoader.h
+++ b/src/3rdparty/assimp/code/3DSLoader.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -119,7 +120,7 @@ protected:
* chunk behind afterwards. If no percentage chunk is found
* QNAN is returned.
*/
- float ParsePercentageChunk();
+ ai_real ParsePercentageChunk();
// -------------------------------------------------------------------
/** Parse a color chunk. mCurrent will point to the next
@@ -265,7 +266,7 @@ protected:
aiColor3D mClrAmbient;
/** Master scaling factor of the scene */
- float mMasterScale;
+ ai_real mMasterScale;
/** Path to the background image of the scene */
std::string mBackgroundImage;
diff --git a/src/3rdparty/assimp/code/3MFXmlTags.h b/src/3rdparty/assimp/code/3MFXmlTags.h
new file mode 100644
index 000000000..7e47422f1
--- /dev/null
+++ b/src/3rdparty/assimp/code/3MFXmlTags.h
@@ -0,0 +1,89 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+namespace Assimp {
+namespace D3MF {
+
+namespace XmlTag {
+ static const std::string model = "model";
+ static const std::string model_unit = "unit";
+ static const std::string metadata = "metadata";
+ static const std::string resources = "resources";
+ static const std::string object = "object";
+ static const std::string mesh = "mesh";
+ static const std::string vertices = "vertices";
+ static const std::string vertex = "vertex";
+ static const std::string triangles = "triangles";
+ static const std::string triangle = "triangle";
+ static const std::string x = "x";
+ static const std::string y = "y";
+ static const std::string z = "z";
+ static const std::string v1 = "v1";
+ static const std::string v2 = "v2";
+ static const std::string v3 = "v3";
+ static const std::string id = "id";
+ static const std::string name = "name";
+ static const std::string type = "type";
+ static const std::string build = "build";
+ static const std::string item = "item";
+ static const std::string objectid = "objectid";
+ static const std::string transform = "transform";
+
+ static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
+ static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
+ static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
+ static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
+ static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
+ static const std::string RELS_RELATIONSHIP_NODE = "Relationship";
+ static const std::string RELS_ATTRIB_TARGET = "Target";
+ static const std::string RELS_ATTRIB_TYPE = "Type";
+ static const std::string RELS_ATTRIB_ID = "Id";
+ static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+ static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
+ static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
+ static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+ static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
+
+}
+
+} // Namespace D3MF
+} // Namespace Assimp
diff --git a/src/3rdparty/assimp/code/ACLoader.cpp b/src/3rdparty/assimp/code/ACLoader.cpp
index c040d6bbd..a30baa75a 100644
--- a/src/3rdparty/assimp/code/ACLoader.cpp
+++ b/src/3rdparty/assimp/code/ACLoader.cpp
@@ -4,7 +4,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -60,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/config.h>
#include <assimp/IOSystem.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
using namespace Assimp;
diff --git a/src/3rdparty/assimp/code/ACLoader.h b/src/3rdparty/assimp/code/ACLoader.h
index 52563adad..4b202b77a 100644
--- a/src/3rdparty/assimp/code/ACLoader.h
+++ b/src/3rdparty/assimp/code/ACLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/AMFImporter.cpp b/src/3rdparty/assimp/code/AMFImporter.cpp
new file mode 100644
index 000000000..e9211fe53
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter.cpp
@@ -0,0 +1,704 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter.cpp
+/// \brief AMF-format files importer for Assimp: main algorithm implementation.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+
+// Header files, Assimp.
+#include "AMFImporter.hpp"
+#include "AMFImporter_Macro.hpp"
+
+#include "fast_atof.h"
+#include <assimp/DefaultIOSystem.h>
+
+// Header files, stdlib.
+#include <memory>
+
+namespace Assimp
+{
+
+/// \var aiImporterDesc AMFImporter::Description
+/// Conastant which hold importer description
+const aiImporterDesc AMFImporter::Description = {
+ "Additive manufacturing file format(AMF) Importer",
+ "smalcom",
+ "",
+ "See documentation in source code. Chapter: Limitations.",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+ 0,
+ 0,
+ 0,
+ 0,
+ "amf"
+};
+
+void AMFImporter::Clear()
+{
+ mNodeElement_Cur = nullptr;
+ mUnit.clear();
+ mMaterial_Converted.clear();
+ mTexture_Converted.clear();
+ // Delete all elements
+ if(mNodeElement_List.size())
+ {
+ for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
+
+ mNodeElement_List.clear();
+ }
+}
+
+AMFImporter::~AMFImporter()
+{
+ if(mReader != nullptr) delete mReader;
+ // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
+ Clear();
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: find set ************************************************************/
+/*********************************************************************************************************************************************/
+
+bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const
+{
+ for(CAMFImporter_NodeElement* ne: mNodeElement_List)
+ {
+ if((ne->ID == pID) && (ne->Type == pType))
+ {
+ if(pNodeElement != nullptr) *pNodeElement = ne;
+
+ return true;
+ }
+ }// for(CAMFImporter_NodeElement* ne: mNodeElement_List)
+
+ return false;
+}
+
+bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
+{
+aiString node_name(pID.c_str());
+
+ for(aiNode* node: pNodeList)
+ {
+ if(node->mName == node_name)
+ {
+ if(pNode != nullptr) *pNode = node;
+
+ return true;
+ }
+ }// for(aiNode* node: pNodeList)
+
+ return false;
+}
+
+bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
+{
+ for(const SPP_Material& mat: mMaterial_Converted)
+ {
+ if(mat.ID == pID)
+ {
+ if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
+
+ return true;
+ }
+ }// for(const SPP_Material& mat: mMaterial_Converted)
+
+ return false;
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: throw set ***********************************************************/
+/*********************************************************************************************************************************************/
+
+void AMFImporter::Throw_CloseNotFound(const std::string& pNode)
+{
+ throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
+}
+
+void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName)
+{
+ throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
+}
+
+void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
+{
+ throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
+}
+
+void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
+{
+ throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
+}
+
+void AMFImporter::Throw_ID_NotFound(const std::string& pID) const
+{
+ throw DeadlyImportError("Not found node with name \"" + pID + "\".");
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************* Functions: XML set ************************************************************/
+/*********************************************************************************************************************************************/
+
+void AMFImporter::XML_CheckNode_MustHaveChildren()
+{
+ if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
+}
+
+void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
+{
+ static const size_t Uns_Skip_Len = 3;
+ const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
+
+ static bool skipped_before[Uns_Skip_Len] = { false, false, false };
+
+ std::string nn(mReader->getNodeName());
+ bool found = false;
+ bool close_found = false;
+ size_t sk_idx;
+
+ for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
+ {
+ if(nn != Uns_Skip[sk_idx]) continue;
+
+ found = true;
+ if(mReader->isEmptyElement())
+ {
+ close_found = true;
+
+ goto casu_cres;
+ }
+
+ while(mReader->read())
+ {
+ if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName()))
+ {
+ close_found = true;
+
+ goto casu_cres;
+ }
+ }
+ }// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
+
+casu_cres:
+
+ if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
+ if(!close_found) Throw_CloseNotFound(nn);
+
+ if(!skipped_before[sk_idx])
+ {
+ skipped_before[sk_idx] = true;
+ LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
+ }
+}
+
+bool AMFImporter::XML_SearchNode(const std::string& pNodeName)
+{
+ while(mReader->read())
+ {
+ if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
+ }
+
+ return false;
+}
+
+bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
+{
+ std::string val(mReader->getAttributeValue(pAttrIdx));
+
+ if((val == "false") || (val == "0"))
+ return false;
+ else if((val == "true") || (val == "1"))
+ return true;
+ else
+ throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
+}
+
+float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
+{
+ std::string val;
+ float tvalf;
+
+ ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
+ fast_atoreal_move(val.c_str(), tvalf, false);
+
+ return tvalf;
+}
+
+uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
+{
+ return strtoul10(mReader->getAttributeValue(pAttrIdx));
+}
+
+float AMFImporter::XML_ReadNode_GetVal_AsFloat()
+{
+ std::string val;
+ float tvalf;
+
+ if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
+ if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
+
+ ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
+ fast_atoreal_move(val.c_str(), tvalf, false);
+
+ return tvalf;
+}
+
+uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32()
+{
+ if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
+ if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
+
+ return strtoul10(mReader->getNodeData());
+}
+
+void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue)
+{
+ if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
+ if(mReader->getNodeType() != irr::io::EXN_TEXT)
+ throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
+
+ pValue = mReader->getNodeData();
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: parse set ***********************************************************/
+/*********************************************************************************************************************************************/
+
+void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
+{
+ mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list.
+ mNodeElement_Cur = pNode;// switch current element to new one.
+}
+
+void AMFImporter::ParseHelper_Node_Exit()
+{
+ // check if we can walk up.
+ if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
+}
+
+void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
+{
+ size_t instr_len;
+
+ pOutString.clear();
+ instr_len = strlen(pInStr);
+ if(!instr_len) return;
+
+ pOutString.reserve(instr_len * 3 / 2);
+ // check and correct floats in format ".x". Must be "x.y".
+ if(pInStr[0] == '.') pOutString.push_back('0');
+
+ pOutString.push_back(pInStr[0]);
+ for(size_t ci = 1; ci < instr_len; ci++)
+ {
+ if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t')))
+ {
+ pOutString.push_back('0');
+ pOutString.push_back('.');
+ }
+ else
+ {
+ pOutString.push_back(pInStr[ci]);
+ }
+ }
+}
+
+static bool ParseHelper_Decode_Base64_IsBase64(const char pChar)
+{
+ return (isalnum(pChar) || (pChar == '+') || (pChar == '/'));
+}
+
+void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
+{
+ // With help from
+ // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
+ const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ uint8_t tidx = 0;
+ uint8_t arr4[4], arr3[3];
+
+ // check input data
+ if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
+ // prepare output place
+ pOutputData.clear();
+ pOutputData.reserve(pInputBase64.size() / 4 * 3);
+
+ for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--)
+ {
+ if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
+ {
+ arr4[tidx++] = pInputBase64[in_idx++];
+ if(tidx == 4)
+ {
+ for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]);
+
+ arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
+ arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
+ arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
+ for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]);
+
+ tidx = 0;
+ }// if(tidx == 4)
+ }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
+ else
+ {
+ in_idx++;
+ }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else
+ }
+
+ if(tidx)
+ {
+ for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0;
+ for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i]));
+
+ arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
+ arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
+ arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
+ for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]);
+ }
+}
+
+void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
+{
+ irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
+ 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 AMF 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) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
+ //
+ // start reading
+ // search for root tag <amf>
+ if(XML_SearchNode("amf"))
+ ParseNode_Root();
+ else
+ throw DeadlyImportError("Root node \"amf\" not found.");
+
+ delete mReader;
+ // restore old XMLreader
+ mReader = OldReader;
+}
+
+// <amf
+// unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
+// version="" - Version of file format.
+// >
+// </amf>
+// Root XML element.
+// Multi elements - No.
+void AMFImporter::ParseNode_Root()
+{
+ std::string unit, version;
+ CAMFImporter_NodeElement *ne( nullptr );
+
+ // Read attributes for node <amf>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND_WSKIP;
+
+ // Check attributes
+ if(!mUnit.empty())
+ {
+ if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit");
+ }
+
+ // create root node element.
+ ne = new CAMFImporter_NodeElement_Root(nullptr);
+ mNodeElement_Cur = ne;// set first "current" element
+ // and assign attribute's values
+ ((CAMFImporter_NodeElement_Root*)ne)->Unit = unit;
+ ((CAMFImporter_NodeElement_Root*)ne)->Version = version;
+
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ MACRO_NODECHECK_LOOPBEGIN("amf");
+ if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; }
+ if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; }
+ if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; }
+ if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; }
+ if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+ MACRO_NODECHECK_LOOPEND("amf");
+ mNodeElement_Cur = ne;// force restore "current" element
+ }// if(!mReader->isEmptyElement())
+
+ mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
+}
+
+// <constellation
+// id="" - The Object ID of the new constellation being defined.
+// >
+// </constellation>
+// A collection of objects or constellations with specific relative locations.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Constellation()
+{
+ std::string id;
+ CAMFImporter_NodeElement* ne( nullptr );
+
+ // Read attributes for node <constellation>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create and if needed - define new grouping object.
+ ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience
+
+ if(!id.empty()) als.ID = id;
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("constellation");
+ if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; }
+ if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+ MACRO_NODECHECK_LOOPEND("constellation");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <instance
+// objectid="" - The Object ID of the new constellation being defined.
+// >
+// </instance>
+// A collection of objects or constellations with specific relative locations.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Instance()
+{
+ std::string objectid;
+ CAMFImporter_NodeElement* ne( nullptr );
+
+ // Read attributes for node <constellation>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // used object id must be defined, check that.
+ if(objectid.empty()) throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
+ // create and define new grouping object.
+ ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience
+
+ als.ObjectID = objectid;
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool read_flag[6] = { false, false, false, false, false, false };
+
+ als.Delta.Set(0, 0, 0);
+ als.Rotation.Set(0, 0, 0);
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("instance");
+ MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
+ MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
+ MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
+ MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
+ MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
+ MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
+ MACRO_NODECHECK_LOOPEND("instance");
+ ParseHelper_Node_Exit();
+ // also convert degrees to radians.
+ als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
+ als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
+ als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <object
+// id="" - A unique ObjectID for the new object being defined.
+// >
+// </object>
+// An object definition.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Object()
+{
+ std::string id;
+ CAMFImporter_NodeElement* ne( nullptr );
+
+ // Read attributes for node <object>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create and if needed - define new geometry object.
+ ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience
+
+ if(!id.empty()) als.ID = id;
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool col_read = false;
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("object");
+ if(XML_CheckNode_NameEqual("color"))
+ {
+ // Check if color already defined for object.
+ if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <object>.");
+ // read data and set flag about it
+ ParseNode_Color();
+ col_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; }
+ if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+ MACRO_NODECHECK_LOOPEND("object");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <metadata
+// type="" - The type of the attribute.
+// >
+// </metadata>
+// Specify additional information about an entity.
+// Multi elements - Yes.
+// Parent element - <amf>, <object>, <volume>, <material>, <vertex>.
+//
+// Reserved types are:
+// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user.
+// "Description" - A description of the content of the entity
+// "URL" - A link to an external resource relating to the entity
+// "Author" - Specifies the name(s) of the author(s) of the entity
+// "Company" - Specifying the company generating the entity
+// "CAD" - specifies the name of the originating CAD software and version
+// "Revision" - specifies the revision of the entity
+// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system
+// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only)
+void AMFImporter::ParseNode_Metadata()
+{
+ std::string type, value;
+ CAMFImporter_NodeElement* ne( nullptr );
+
+ // read attribute
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+ // and value of node.
+ value = mReader->getNodeData();
+ // Create node element and assign read data.
+ ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur);
+ ((CAMFImporter_NodeElement_Metadata*)ne)->Type = type;
+ ((CAMFImporter_NodeElement_Metadata*)ne)->Value = value;
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+/*********************************************************************************************************************************************/
+/******************************************************** Functions: BaseImporter set ********************************************************/
+/*********************************************************************************************************************************************/
+
+bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const
+{
+ const std::string extension = GetExtension(pFile);
+
+ if ( extension == "amf" ) {
+ return true;
+ }
+
+ if(!extension.length() || pCheckSig)
+ {
+ const char* tokens[] = { "<amf" };
+
+ return SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 );
+ }
+
+ return false;
+}
+
+void AMFImporter::GetExtensionList(std::set<std::string>& pExtensionList)
+{
+ pExtensionList.insert("amf");
+}
+
+const aiImporterDesc* AMFImporter::GetInfo () const
+{
+ return &Description;
+}
+
+void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+ Clear();// delete old graph.
+ ParseFile(pFile, pIOHandler);
+ Postprocess_BuildScene(pScene);
+ // scene graph is ready, exit.
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
diff --git a/src/3rdparty/assimp/code/AMFImporter.hpp b/src/3rdparty/assimp/code/AMFImporter.hpp
new file mode 100644
index 000000000..47ddc073b
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter.hpp
@@ -0,0 +1,563 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter.hpp
+/// \brief AMF-format files importer for Assimp.
+/// \date 2016
+/// \author smal.root@gmail.com
+// Thanks to acorn89 for support.
+
+#pragma once
+#ifndef INCLUDED_AI_AMF_IMPORTER_H
+#define INCLUDED_AI_AMF_IMPORTER_H
+
+#include "AMFImporter_Node.hpp"
+
+// Header files, Assimp.
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
+#include "assimp/types.h"
+#include "BaseImporter.h"
+#include "irrXMLWrapper.h"
+
+// Header files, stdlib.
+#include <set>
+
+namespace Assimp
+{
+/// \class AMFImporter
+/// Class that holding scene graph which include: geometry, metadata, materials etc.
+///
+/// Implementing features.
+///
+/// Limitations.
+///
+/// 1. When for texture mapping used set of source textures (r, g, b, a) not only one then attribute "tiled" for all set will be true if it true in any of
+/// source textures.
+/// Example. Triangle use for texture mapping three textures. Two of them has "tiled" set to false and one - set to true. In scene all three textures
+/// will be tiled.
+///
+/// Unsupported features:
+/// 1. Node <composite>, formulas in <composite> and <color>. For implementing this feature can be used expression parser "muParser" like in project
+/// "amf_tools".
+/// 2. Attribute "profile" in node <color>.
+/// 3. Curved geometry: <edge>, <normal> and children nodes of them.
+/// 4. Attributes: "unit" and "version" in <amf> read but do nothing.
+/// 5. <metadata> stored only for root node <amf>.
+/// 6. Color averaging of vertices for which <triangle>'s set different colors.
+///
+/// Supported nodes:
+/// General:
+/// <amf>; <constellation>; <instance> and children <deltax>, <deltay>, <deltaz>, <rx>, <ry>, <rz>; <metadata>;
+///
+/// Geometry:
+/// <object>; <mesh>; <vertices>; <vertex>; <coordinates> and children <x>, <y>, <z>; <volume>; <triangle> and children <v1>, <v2>, <v3>;
+///
+/// Material:
+/// <color> and children <r>, <g>, <b>, <a>; <texture>; <material>;
+/// two variants of texture coordinates:
+/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
+/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
+///
+class AMFImporter : public BaseImporter
+{
+ /***********************************************/
+ /******************** Types ********************/
+ /***********************************************/
+
+private:
+
+ struct SPP_Material;// forward declaration
+
+ /// \struct SPP_Composite
+ /// Data type for postprocessing step. More suitable container for part of material's composition.
+ struct SPP_Composite
+ {
+ SPP_Material* Material;///< Pointer to material - part of composition.
+ std::string Formula;///< Formula for calculating ratio of \ref Material.
+ };
+
+ /// \struct SPP_Material
+ /// Data type for postprocessing step. More suitable container for material.
+ struct SPP_Material
+ {
+ std::string ID;///< Material ID.
+ std::list<CAMFImporter_NodeElement_Metadata*> Metadata;///< Metadata of material.
+ CAMFImporter_NodeElement_Color* Color;///< Color of material.
+ std::list<SPP_Composite> Composition;///< List of child materials if current material is composition of few another.
+
+ /// \fn aiColor4D GetColor(const float pX, const float pY, const float pZ) const
+ /// Return color calculated for specified coordinate.
+ /// \param [in] pX - "x" coordinate.
+ /// \param [in] pY - "y" coordinate.
+ /// \param [in] pZ - "z" coordinate.
+ /// \return calculated color.
+ aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
+ };
+
+ /// \struct SPP_Texture
+ /// Data type for post-processing step. More suitable container for texture.
+ struct SPP_Texture
+ {
+ std::string ID;
+ size_t Width, Height, Depth;
+ bool Tiled;
+ char FormatHint[ 9 ];// 8 for string + 1 for terminator.
+ uint8_t *Data;
+ };
+
+ /// \struct SComplexFace
+ /// Data type for post-processing step. Contain face data.
+ struct SComplexFace
+ {
+ aiFace Face;///< Face vertices.
+ const CAMFImporter_NodeElement_Color* Color;///< Face color. Equal to nullptr if color is not set for the face.
+ const CAMFImporter_NodeElement_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
+ };
+
+
+
+ /***********************************************/
+ /****************** Constants ******************/
+ /***********************************************/
+
+private:
+
+ static const aiImporterDesc Description;
+
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+private:
+
+ CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
+ std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
+ irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
+ std::string mUnit;
+ std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.
+ std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn AMFImporter(const AMFImporter& pScene)
+ /// Disabled copy constructor.
+ AMFImporter(const AMFImporter& pScene);
+
+ /// \fn AMFImporter& operator=(const AMFImporter& pScene)
+ /// Disabled assign operator.
+ AMFImporter& operator=(const AMFImporter& pScene);
+
+ /// \fn void Clear()
+ /// Clear all temporary data.
+ void Clear();
+
+ /***********************************************/
+ /************* Functions: find set *************/
+ /***********************************************/
+
+ /// \fn bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, aiNode** pNode) const
+ /// Find specified node element in node elements list ( \ref mNodeElement_List).
+ /// \param [in] pID - ID(name) of requested node element.
+ /// \param [in] pType - type of node element.
+ /// \param [out] pNode - pointer to pointer to item found.
+ /// \return true - if the node element is found, else - false.
+ bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const;
+
+ /// \fn bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
+ /// Find requested aiNode in node list.
+ /// \param [in] pID - ID(name) of requested node.
+ /// \param [in] pNodeList - list of nodes where to find the node.
+ /// \param [out] pNode - pointer to pointer to item found.
+ /// \return true - if the node is found, else - false.
+ bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const;
+
+ /// \fn bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
+ /// Find material in list for converted materials. Use at postprocessing step.
+ /// \param [in] pID - material ID.
+ /// \param [out] pConvertedMaterial - pointer to found converted material (\ref SPP_Material).
+ /// \return true - if the material is found, else - false.
+ bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const;
+
+ /// \fn bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A, uint32_t* pConvertedTextureIndex = nullptr) const
+ /// Find texture in list of converted textures. Use at postprocessing step,
+ /// \param [in] pID_R - ID of source "red" texture.
+ /// \param [in] pID_G - ID of source "green" texture.
+ /// \param [in] pID_B - ID of source "blue" texture.
+ /// \param [in] pID_A - ID of source "alpha" texture. Use empty string to find RGB-texture.
+ /// \param [out] pConvertedTextureIndex - pointer where index in list of found texture will be written. If equivalent to nullptr then nothing will be
+ /// written.
+ /// \return true - if the texture is found, else - false.
+ bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A,
+ uint32_t* pConvertedTextureIndex = nullptr) const;
+
+ /***********************************************/
+ /********* Functions: postprocess set **********/
+ /***********************************************/
+
+ /// \fn void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray, std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const
+ /// Get data stored in <vertices> and place it to arrays.
+ /// \param [in] pNodeElement - reference to node element which kept <object> data.
+ /// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in <vertices>.
+ /// \param [in] pVertexColorArray - reference to vertices colors for all <vertex's. If color for vertex is not set then corresponding member of array
+ /// contain nullptr.
+ void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
+ std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const;
+
+ /// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A)
+ /// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
+ /// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
+ /// to converted textures list.
+ /// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified.
+ /// \param [in] pID_R - ID of source "red" texture.
+ /// \param [in] pID_G - ID of source "green" texture.
+ /// \param [in] pID_B - ID of source "blue" texture.
+ /// \param [in] pID_A - ID of source "alpha" texture.
+ /// \return index of the texture in array of the converted textures.
+ size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A);
+
+ /// \fn void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> > pOutputList_Separated)
+ /// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc).
+ /// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after
+ /// processing.
+ /// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing.
+ void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated);
+
+ /// \fn void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const
+ /// Check if child elements of node element is metadata and add it to scene node.
+ /// \param [in] pMetadataList - reference to list with collected metadata.
+ /// \param [out] pSceneNode - scene node in which metadata will be added.
+ void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const;
+
+ /// \fn void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)
+ /// To create aiMesh and aiNode for it from <object>.
+ /// \param [in] pNodeElement - reference to node element which kept <object> data.
+ /// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
+ /// \param [out] pSceneNode - pointer to place where new aiNode will be created.
+ void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode);
+
+ /// \fn void Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray, const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor, std::list<aiMesh*>& pMeshList, aiNode& pSceneNode)
+ /// Create mesh for every <volume> in <mesh>.
+ /// \param [in] pNodeElement - reference to node element which kept <mesh> data.
+ /// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all <volume>'s.
+ /// \param [in] pVertexColorArray - reference to vertices colors for all <volume>'s. If color for vertex is not set then corresponding member of array
+ /// contain nullptr.
+ /// \param [in] pObjectColor - pointer to colors for <object>. If color is not set then argument contain nullptr.
+ /// \param [in] pMaterialList - reference to a list with defined materials.
+ /// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
+ /// \param [out] pSceneNode - reference to aiNode which will own new aiMesh's.
+ void Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray,
+ const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor,
+ std::list<aiMesh*>& pMeshList, aiNode& pSceneNode);
+
+ /// \fn void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial)
+ /// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material.
+ /// \param [in] pMaterial - source CAMFImporter_NodeElement_Material.
+ void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial);
+
+ /// \fn void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const
+ /// Create and add to aiNode's list new part of scene graph defined by <constellation>.
+ /// \param [in] pConstellation - reference to <constellation> node.
+ /// \param [out] pNodeList - reference to aiNode's list.
+ void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const;
+
+ /// \fn void Postprocess_BuildScene()
+ /// Build Assimp scene graph in aiScene from collected data.
+ /// \param [out] pScene - pointer to aiScene where tree will be built.
+ void Postprocess_BuildScene(aiScene* pScene);
+
+ /***********************************************/
+ /************* Functions: throw set ************/
+ /***********************************************/
+
+ /// \fn void Throw_CloseNotFound(const std::string& pNode)
+ /// Call that function when close tag of node not found and exception must be raised.
+ /// E.g.:
+ /// <amf>
+ /// <object>
+ /// </amf> <!--- object not closed --->
+ /// \throw DeadlyImportError.
+ /// \param [in] pNode - node name in which exception happened.
+ void Throw_CloseNotFound(const std::string& pNode);
+
+ /// \fn void Throw_IncorrectAttr(const std::string& pAttrName)
+ /// Call that function when attribute name is incorrect and exception must be raised.
+ /// \param [in] pAttrName - attribute name.
+ /// \throw DeadlyImportError.
+ void Throw_IncorrectAttr(const std::string& pAttrName);
+
+ /// \fn void Throw_IncorrectAttrValue(const std::string& pAttrName)
+ /// Call that function when attribute value is incorrect and exception must be raised.
+ /// \param [in] pAttrName - attribute name.
+ /// \throw DeadlyImportError.
+ void Throw_IncorrectAttrValue(const std::string& pAttrName);
+
+ /// \fn void Throw_MoreThanOnceDefined(const std::string& pNode, const std::string& pDescription)
+ /// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised.
+ /// E.g.:
+ /// <object>
+ /// <color>... <!--- color defined --->
+ /// <color>... <!--- color defined again --->
+ /// </object>
+ /// \throw DeadlyImportError.
+ /// \param [in] pNodeType - type of node which defined one more time.
+ /// \param [in] pDescription - message about error. E.g. what the node defined while exception raised.
+ void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription);
+
+ /// \fn void Throw_ID_NotFound(const std::string& pID) const
+ /// Call that function when referenced element ID are not found in graph and exception must be raised.
+ /// \param [in] pID - ID of of element which not found.
+ /// \throw DeadlyImportError.
+ void Throw_ID_NotFound(const std::string& pID) const;
+
+ /***********************************************/
+ /************** Functions: LOG set *************/
+ /***********************************************/
+
+ /// \fn void LogInfo(const std::string& pMessage)
+ /// Short variant for calling \ref DefaultLogger::get()->info()
+ void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
+
+ /// \fn void LogWarning(const std::string& pMessage)
+ /// Short variant for calling \ref DefaultLogger::get()->warn()
+ void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); }
+
+ /// \fn void LogError(const std::string& pMessage)
+ /// Short variant for calling \ref DefaultLogger::get()->error()
+ void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
+
+ /***********************************************/
+ /************** Functions: XML set *************/
+ /***********************************************/
+
+ /// \fn void XML_CheckNode_MustHaveChildren()
+ /// Check if current node have children: <node>...</node>. If not then exception will throwed.
+ void XML_CheckNode_MustHaveChildren();
+
+ /// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
+ /// Check if current node name is equal to pNodeName.
+ /// \param [in] pNodeName - name for checking.
+ /// return true if current node name is equal to pNodeName, else - false.
+ bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
+
+ /// \fn void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
+ /// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
+ /// \param [in] pParentNodeName - parent node name. Used for reporting.
+ void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName);
+
+ /// \fn bool XML_SearchNode(const std::string& pNodeName)
+ /// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
+ /// \param [in] pNodeName - requested node name.
+ /// return true - if node is found, else - false.
+ bool XML_SearchNode(const std::string& pNodeName);
+
+ /// \fn bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \return read data.
+ bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
+
+ /// \fn float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \return read data.
+ float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
+
+ /// \fn uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \return read data.
+ uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx);
+
+ /// \fn float XML_ReadNode_GetVal_AsFloat()
+ /// Read node value.
+ /// \return read data.
+ float XML_ReadNode_GetVal_AsFloat();
+
+ /// \fn uint32_t XML_ReadNode_GetVal_AsU32()
+ /// Read node value.
+ /// \return read data.
+ uint32_t XML_ReadNode_GetVal_AsU32();
+
+ /// \fn void XML_ReadNode_GetVal_AsString(std::string& pValue)
+ /// Read node value.
+ /// \return read data.
+ void XML_ReadNode_GetVal_AsString(std::string& pValue);
+
+ /***********************************************/
+ /******** Functions: parse set private *********/
+ /***********************************************/
+
+ /// \fn void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
+ /// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
+ /// \param [in] pNode - new current node.
+ void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode);
+
+ /// \fn void ParseHelper_Group_End()
+ /// This function must be called when exiting from grouping node. \ref ParseHelper_Group_Begin.
+ void ParseHelper_Node_Exit();
+
+ /// \fn void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
+ /// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
+ /// must be converted to right form - "0.xxx".
+ /// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
+ /// \param [out[ pOutString - output string with right form of values.
+ void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
+
+ /// \fn void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
+ /// Decode Base64-encoded data.
+ /// \param [in] pInputBase64 - reference to input Base64-encoded string.
+ /// \param [out] pOutputData - reference to output array for decoded data.
+ void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const;
+
+ /// \fn void ParseNode_Root()
+ /// Parse <AMF> node of the file.
+ void ParseNode_Root();
+
+ /******** Functions: top nodes *********/
+
+ /// \fn void ParseNode_Constellation()
+ /// Parse <constellation> node of the file.
+ void ParseNode_Constellation();
+
+ /// \fn void ParseNode_Constellation()
+ /// Parse <instance> node of the file.
+ void ParseNode_Instance();
+
+ /// \fn void ParseNode_Material()
+ /// Parse <material> node of the file.
+ void ParseNode_Material();
+
+ /// \fn void ParseNode_Metadata()
+ /// Parse <metadata> node.
+ void ParseNode_Metadata();
+
+ /// \fn void ParseNode_Object()
+ /// Parse <object> node of the file.
+ void ParseNode_Object();
+
+ /// \fn void ParseNode_Texture()
+ /// Parse <texture> node of the file.
+ void ParseNode_Texture();
+
+ /******** Functions: geometry nodes *********/
+
+ /// \fn void ParseNode_Coordinates()
+ /// Parse <coordinates> node of the file.
+ void ParseNode_Coordinates();
+
+ /// \fn void ParseNode_Edge()
+ /// Parse <edge> node of the file.
+ void ParseNode_Edge();
+
+ /// \fn void ParseNode_Mesh()
+ /// Parse <mesh> node of the file.
+ void ParseNode_Mesh();
+
+ /// \fn void ParseNode_Triangle()
+ /// Parse <triangle> node of the file.
+ void ParseNode_Triangle();
+
+ /// \fn void ParseNode_Vertex()
+ /// Parse <vertex> node of the file.
+ void ParseNode_Vertex();
+
+ /// \fn void ParseNode_Vertices()
+ /// Parse <vertices> node of the file.
+ void ParseNode_Vertices();
+
+ /// \fn void ParseNode_Volume()
+ /// Parse <volume> node of the file.
+ void ParseNode_Volume();
+
+ /******** Functions: material nodes *********/
+
+ /// \fn void ParseNode_Color()
+ /// Parse <color> node of the file.
+ void ParseNode_Color();
+
+ /// \fn void ParseNode_TexMap(const bool pUseOldName = false)
+ /// Parse <texmap> of <map> node of the file.
+ /// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
+ void ParseNode_TexMap(const bool pUseOldName = false);
+
+public:
+
+ /// \fn AMFImporter()
+ /// Default constructor.
+ AMFImporter()
+ : mNodeElement_Cur(nullptr), mReader(nullptr)
+ {}
+
+ /// \fn ~AMFImporter()
+ /// Default destructor.
+ ~AMFImporter();
+
+ /***********************************************/
+ /******** Functions: parse set, public *********/
+ /***********************************************/
+
+ /// \fn void ParseFile(const std::string& pFile, IOSystem* pIOHandler)
+ /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
+ /// Also exception can be throwed if trouble will found.
+ /// \param [in] pFile - name of file to be parsed.
+ /// \param [in] pIOHandler - pointer to IO helper object.
+ void ParseFile(const std::string& pFile, IOSystem* pIOHandler);
+
+ /***********************************************/
+ /********* Functions: BaseImporter set *********/
+ /***********************************************/
+
+ bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const;
+ void GetExtensionList(std::set<std::string>& pExtensionList);
+ void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+ const aiImporterDesc* GetInfo ()const;
+
+};// class AMFImporter
+
+}// namespace Assimp
+
+#endif // INCLUDED_AI_AMF_IMPORTER_H
diff --git a/src/3rdparty/assimp/code/AMFImporter_Geometry.cpp b/src/3rdparty/assimp/code/AMFImporter_Geometry.cpp
new file mode 100644
index 000000000..afba3f2bc
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter_Geometry.cpp
@@ -0,0 +1,356 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter_Geometry.cpp
+/// \brief Parsing data from geometry nodes.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+
+#include "AMFImporter.hpp"
+#include "AMFImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <mesh>
+// </mesh>
+// A 3D mesh hull.
+// Multi elements - Yes.
+// Parent element - <object>.
+void AMFImporter::ParseNode_Mesh()
+{
+CAMFImporter_NodeElement* ne;
+
+ // create new mesh object.
+ ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool vert_read = false;
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("mesh");
+ if(XML_CheckNode_NameEqual("vertices"))
+ {
+ // Check if data already defined.
+ if(vert_read) Throw_MoreThanOnceDefined("vertices", "Only one vertices set can be defined for <mesh>.");
+ // read data and set flag about it
+ ParseNode_Vertices();
+ vert_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("volume")) { ParseNode_Volume(); continue; }
+ MACRO_NODECHECK_LOOPEND("mesh");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <vertices>
+// </vertices>
+// The list of vertices to be used in defining triangles.
+// Multi elements - No.
+// Parent element - <mesh>.
+void AMFImporter::ParseNode_Vertices()
+{
+CAMFImporter_NodeElement* ne;
+
+ // create new mesh object.
+ ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur);
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("vertices");
+ if(XML_CheckNode_NameEqual("vertex")) { ParseNode_Vertex(); continue; }
+ MACRO_NODECHECK_LOOPEND("vertices");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <vertex>
+// </vertex>
+// A vertex to be referenced in triangles.
+// Multi elements - Yes.
+// Parent element - <vertices>.
+void AMFImporter::ParseNode_Vertex()
+{
+CAMFImporter_NodeElement* ne;
+
+ // create new mesh object.
+ ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur);
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool col_read = false;
+ bool coord_read = false;
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("vertex");
+ if(XML_CheckNode_NameEqual("color"))
+ {
+ // Check if data already defined.
+ if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
+ // read data and set flag about it
+ ParseNode_Color();
+ col_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("coordinates"))
+ {
+ // Check if data already defined.
+ if(coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
+ // read data and set flag about it
+ ParseNode_Coordinates();
+ coord_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+ MACRO_NODECHECK_LOOPEND("vertex");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <coordinates>
+// </coordinates>
+// Specifies the 3D location of this vertex.
+// Multi elements - No.
+// Parent element - <vertex>.
+//
+// Children elements:
+// <x>, <y>, <z>
+// Multi elements - No.
+// X, Y, or Z coordinate, respectively, of a vertex position in space.
+void AMFImporter::ParseNode_Coordinates()
+{
+CAMFImporter_NodeElement* ne;
+
+ // create new color object.
+ ne = new CAMFImporter_NodeElement_Coordinates(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience
+
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool read_flag[3] = { false, false, false };
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("coordinates");
+ MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
+ MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
+ MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
+ MACRO_NODECHECK_LOOPEND("coordinates");
+ ParseHelper_Node_Exit();
+ // check that all components was defined
+ if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
+
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <volume
+// materialid="" - Which material to use.
+// type="" - What this volume describes can be “region” or “support”. If none specified, “object” is assumed. If support, then the geometric
+// requirements 1-8 listed in section 5 do not need to be maintained.
+// >
+// </volume>
+// Defines a volume from the established vertex list.
+// Multi elements - Yes.
+// Parent element - <mesh>.
+void AMFImporter::ParseNode_Volume()
+{
+std::string materialid;
+std::string type;
+CAMFImporter_NodeElement* ne;
+
+ // Read attributes for node <color>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create new object.
+ ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
+ // and assign read data
+ ((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid;
+ ((CAMFImporter_NodeElement_Volume*)ne)->Type = type;
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool col_read = false;
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("volume");
+ if(XML_CheckNode_NameEqual("color"))
+ {
+ // Check if data already defined.
+ if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
+ // read data and set flag about it
+ ParseNode_Color();
+ col_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("triangle")) { ParseNode_Triangle(); continue; }
+ if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+ MACRO_NODECHECK_LOOPEND("volume");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <triangle>
+// </triangle>
+// Defines a 3D triangle from three vertices, according to the right-hand rule (counter-clockwise when looking from the outside).
+// Multi elements - Yes.
+// Parent element - <volume>.
+//
+// Children elements:
+// <v1>, <v2>, <v3>
+// Multi elements - No.
+// Index of the desired vertices in a triangle or edge.
+void AMFImporter::ParseNode_Triangle()
+{
+CAMFImporter_NodeElement* ne;
+
+ // create new color object.
+ ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience
+
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool col_read = false, tex_read = false;
+ bool read_flag[3] = { false, false, false };
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("triangle");
+ if(XML_CheckNode_NameEqual("color"))
+ {
+ // Check if data already defined.
+ if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
+ // read data and set flag about it
+ ParseNode_Color();
+ col_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("texmap"))// new name of node: "texmap".
+ {
+ // Check if data already defined.
+ if(tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
+ // read data and set flag about it
+ ParseNode_TexMap();
+ tex_read = true;
+
+ continue;
+ }
+ else if(XML_CheckNode_NameEqual("map"))// old name of node: "map".
+ {
+ // Check if data already defined.
+ if(tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
+ // read data and set flag about it
+ ParseNode_TexMap(true);
+ tex_read = true;
+
+ continue;
+ }
+
+ MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
+ MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
+ MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
+ MACRO_NODECHECK_LOOPEND("triangle");
+ ParseHelper_Node_Exit();
+ // check that all components was defined
+ if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
+
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
diff --git a/src/3rdparty/assimp/code/AMFImporter_Macro.hpp b/src/3rdparty/assimp/code/AMFImporter_Macro.hpp
new file mode 100644
index 000000000..b7c0f9863
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter_Macro.hpp
@@ -0,0 +1,165 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter_Macro.hpp
+/// \brief Useful macrodefines.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#pragma once
+#ifndef AMFIMPORTER_MACRO_HPP_INCLUDED
+#define AMFIMPORTER_MACRO_HPP_INCLUDED
+
+/// \def MACRO_ATTRREAD_LOOPBEG
+/// Begin of loop that read attributes values.
+#define MACRO_ATTRREAD_LOOPBEG \
+ for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
+ { \
+ std::string an(mReader->getAttributeName(idx));
+
+/// \def MACRO_ATTRREAD_LOOPEND
+/// End of loop that read attributes values.
+#define MACRO_ATTRREAD_LOOPEND \
+ Throw_IncorrectAttr(an); \
+ }
+
+/// \def MACRO_ATTRREAD_LOOPEND_WSKIP
+/// End of loop that read attributes values. Difference from \ref MACRO_ATTRREAD_LOOPEND in that: current macro skip unknown attributes, but
+/// \ref MACRO_ATTRREAD_LOOPEND throw an exception.
+#define MACRO_ATTRREAD_LOOPEND_WSKIP \
+ continue; \
+ }
+
+/// \def MACRO_ATTRREAD_CHECK_REF
+/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
+/// "continue" will called.
+/// \param [in] pAttrName - attribute name.
+/// \param [out] pVarName - output variable name.
+/// \param [in] pFunction - function which read attribute value and write it to pVarName.
+#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
+ if(an == pAttrName) \
+ { \
+ pFunction(idx, pVarName); \
+ continue; \
+ }
+
+/// \def MACRO_ATTRREAD_CHECK_RET
+/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
+/// If result was read then "continue" will called.
+/// \param [in] pAttrName - attribute name.
+/// \param [out] pVarName - output variable name.
+/// \param [in] pFunction - function which read attribute value and write it to pVarName.
+#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
+ if(an == pAttrName) \
+ { \
+ pVarName = pFunction(idx); \
+ continue; \
+ }
+
+/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
+/// Begin of loop of parsing child nodes. Do not add ';' at end.
+/// \param [in] pNodeName - current node name.
+#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
+ do { \
+ bool close_found = false; \
+ \
+ while(mReader->read()) \
+ { \
+ if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
+ {
+
+/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
+/// End of loop of parsing child nodes.
+/// \param [in] pNodeName - current node name.
+#define MACRO_NODECHECK_LOOPEND(pNodeName) \
+ XML_CheckNode_SkipUnsupported(pNodeName); \
+ }/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
+ else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
+ { \
+ if(XML_CheckNode_NameEqual(pNodeName)) \
+ { \
+ close_found = true; \
+ \
+ break; \
+ } \
+ }/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
+ }/* while(mReader->read()) */ \
+ \
+ if(!close_found) Throw_CloseNotFound(pNodeName); \
+ \
+ } while(false)
+
+/// \def MACRO_NODECHECK_READCOMP_F
+/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float".
+/// If result was read then "continue" will called. Also check if node data already read then raise exception.
+/// \param [in] pNodeName - node name.
+/// \param [in, out] pReadFlag - read flag.
+/// \param [out] pVarName - output variable name.
+#define MACRO_NODECHECK_READCOMP_F(pNodeName, pReadFlag, pVarName) \
+ if(XML_CheckNode_NameEqual(pNodeName)) \
+ { \
+ /* Check if field already read before. */ \
+ if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
+ /* Read color component and assign it to object. */ \
+ pVarName = XML_ReadNode_GetVal_AsFloat(); \
+ pReadFlag = true; \
+ continue; \
+ }
+
+/// \def MACRO_NODECHECK_READCOMP_U32
+/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
+/// If result was read then "continue" will called. Also check if node data already read then raise exception.
+/// \param [in] pNodeName - node name.
+/// \param [in, out] pReadFlag - read flag.
+/// \param [out] pVarName - output variable name.
+#define MACRO_NODECHECK_READCOMP_U32(pNodeName, pReadFlag, pVarName) \
+ if(XML_CheckNode_NameEqual(pNodeName)) \
+ { \
+ /* Check if field already read before. */ \
+ if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
+ /* Read color component and assign it to object. */ \
+ pVarName = XML_ReadNode_GetVal_AsU32(); \
+ pReadFlag = true; \
+ continue; \
+ }
+
+#endif // AMFIMPORTER_MACRO_HPP_INCLUDED
diff --git a/src/3rdparty/assimp/code/AMFImporter_Material.cpp b/src/3rdparty/assimp/code/AMFImporter_Material.cpp
new file mode 100644
index 000000000..d15099fac
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter_Material.cpp
@@ -0,0 +1,310 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter_Material.cpp
+/// \brief Parsing data from material nodes.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+
+#include "AMFImporter.hpp"
+#include "AMFImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <color
+// profile="" - The ICC color space used to interpret the three color channels <r>, <g> and <b>.
+// >
+// </color>
+// A color definition.
+// Multi elements - No.
+// Parent element - <material>, <object>, <volume>, <vertex>, <triangle>.
+//
+// "profile" can be one of "sRGB", "AdobeRGB", "Wide-Gamut-RGB", "CIERGB", "CIELAB", or "CIEXYZ".
+// Children elements:
+// <r>, <g>, <b>, <a>
+// Multi elements - No.
+// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
+// values can be specified as constants, or as a formula depending on the coordinates.
+void AMFImporter::ParseNode_Color()
+{
+std::string profile;
+CAMFImporter_NodeElement* ne;
+
+ // Read attributes for node <color>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("profile", profile, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create new color object.
+ ne = new CAMFImporter_NodeElement_Color(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Color& als = *((CAMFImporter_NodeElement_Color*)ne);// alias for convenience
+
+ als.Profile = profile;
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool read_flag[4] = { false, false, false, false };
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("color");
+ MACRO_NODECHECK_READCOMP_F("r", read_flag[0], als.Color.r);
+ MACRO_NODECHECK_READCOMP_F("g", read_flag[1], als.Color.g);
+ MACRO_NODECHECK_READCOMP_F("b", read_flag[2], als.Color.b);
+ MACRO_NODECHECK_READCOMP_F("a", read_flag[3], als.Color.a);
+ MACRO_NODECHECK_LOOPEND("color");
+ ParseHelper_Node_Exit();
+ // check that all components was defined
+ if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
+ // check if <a> is absent. Then manualy add "a == 1".
+ if(!read_flag[3]) als.Color.a = 1;
+
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ als.Composed = false;
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <material
+// id="" - A unique material id. material ID "0" is reserved to denote no material (void) or sacrificial material.
+// >
+// </material>
+// An available material.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Material()
+{
+std::string id;
+CAMFImporter_NodeElement* ne;
+
+ // Read attributes for node <color>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create new object.
+ ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur);
+ // and assign read data
+ ((CAMFImporter_NodeElement_Material*)ne)->ID = id;
+ // Check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ bool col_read = false;
+
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("material");
+ if(XML_CheckNode_NameEqual("color"))
+ {
+ // Check if data already defined.
+ if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <material>.");
+ // read data and set flag about it
+ ParseNode_Color();
+ col_read = true;
+
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+ MACRO_NODECHECK_LOOPEND("material");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ }// if(!mReader->isEmptyElement()) else
+
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <texture
+// id="" - Assigns a unique texture id for the new texture.
+// width="" - Width (horizontal size, x) of the texture, in pixels.
+// height="" - Height (lateral size, y) of the texture, in pixels.
+// depth="" - Depth (vertical size, z) of the texture, in pixels.
+// type="" - Encoding of the data in the texture. Currently allowed values are "grayscale" only. In grayscale mode, each pixel is represented by one byte
+// in the range of 0-255. When the texture is referenced using the tex function, these values are converted into a single floating point number in the
+// range of 0-1 (see Annex 2). A full color graphics will typically require three textures, one for each of the color channels. A graphic involving
+// transparency may require a fourth channel.
+// tiled="" - If true then texture repeated when UV-coordinates is greater than 1.
+// >
+// </triangle>
+// Specifies an texture data to be used as a map. Lists a sequence of Base64 values specifying values for pixels from left to right then top to bottom,
+// then layer by layer.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Texture()
+{
+std::string id;
+uint32_t width = 0;
+uint32_t height = 0;
+uint32_t depth = 1;
+std::string type;
+bool tiled = false;
+std::string enc64_data;
+CAMFImporter_NodeElement* ne;
+
+ // Read attributes for node <color>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("width", width, XML_ReadNode_GetAttrVal_AsU32);
+ MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsU32);
+ MACRO_ATTRREAD_CHECK_RET("depth", depth, XML_ReadNode_GetAttrVal_AsU32);
+ MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("tiled", tiled, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create new texture object.
+ ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience
+
+ // Check for child nodes
+ if(!mReader->isEmptyElement()) XML_ReadNode_GetVal_AsString(enc64_data);
+
+ // check that all components was defined
+ if(id.empty()) throw DeadlyImportError("ID for texture must be defined.");
+ if(width < 1) Throw_IncorrectAttrValue("width");
+ if(height < 1) Throw_IncorrectAttrValue("height");
+ if(depth < 1) Throw_IncorrectAttrValue("depth");
+ if(type != "grayscale") Throw_IncorrectAttrValue("type");
+ if(enc64_data.empty()) throw DeadlyImportError("Texture data not defined.");
+ // copy data
+ als.ID = id;
+ als.Width = width;
+ als.Height = height;
+ als.Depth = depth;
+ als.Tiled = tiled;
+ ParseHelper_Decode_Base64(enc64_data, als.Data);
+ // check data size
+ if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size.");
+
+ mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+ mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <texmap
+// rtexid="" - Texture ID for red color component.
+// gtexid="" - Texture ID for green color component.
+// btexid="" - Texture ID for blue color component.
+// atexid="" - Texture ID for alpha color component. Optional.
+// >
+// </texmap>, old name: <map>
+// Specifies texture coordinates for triangle.
+// Multi elements - No.
+// Parent element - <triangle>.
+// Children elements:
+// <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>. Old name: <u1>, <u2>, <u3>, <v1>, <v2>, <v3>.
+// Multi elements - No.
+// Texture coordinates for every vertex of triangle.
+void AMFImporter::ParseNode_TexMap(const bool pUseOldName)
+{
+std::string rtexid, gtexid, btexid, atexid;
+CAMFImporter_NodeElement* ne;
+
+ // Read attributes for node <color>.
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // create new texture coordinates object.
+ ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur);
+
+ CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience
+ // check data
+ if(rtexid.empty() && gtexid.empty() && btexid.empty()) throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined.");
+ // Check for children nodes
+ XML_CheckNode_MustHaveChildren();
+ // read children nodes
+ bool read_flag[6] = { false, false, false, false, false, false };
+
+ ParseHelper_Node_Enter(ne);
+ if(!pUseOldName)
+ {
+ MACRO_NODECHECK_LOOPBEGIN("texmap");
+ MACRO_NODECHECK_READCOMP_F("utex1", read_flag[0], als.TextureCoordinate[0].x);
+ MACRO_NODECHECK_READCOMP_F("utex2", read_flag[1], als.TextureCoordinate[1].x);
+ MACRO_NODECHECK_READCOMP_F("utex3", read_flag[2], als.TextureCoordinate[2].x);
+ MACRO_NODECHECK_READCOMP_F("vtex1", read_flag[3], als.TextureCoordinate[0].y);
+ MACRO_NODECHECK_READCOMP_F("vtex2", read_flag[4], als.TextureCoordinate[1].y);
+ MACRO_NODECHECK_READCOMP_F("vtex3", read_flag[5], als.TextureCoordinate[2].y);
+ MACRO_NODECHECK_LOOPEND("texmap");
+ }
+ else
+ {
+ MACRO_NODECHECK_LOOPBEGIN("map");
+ MACRO_NODECHECK_READCOMP_F("u1", read_flag[0], als.TextureCoordinate[0].x);
+ MACRO_NODECHECK_READCOMP_F("u2", read_flag[1], als.TextureCoordinate[1].x);
+ MACRO_NODECHECK_READCOMP_F("u3", read_flag[2], als.TextureCoordinate[2].x);
+ MACRO_NODECHECK_READCOMP_F("v1", read_flag[3], als.TextureCoordinate[0].y);
+ MACRO_NODECHECK_READCOMP_F("v2", read_flag[4], als.TextureCoordinate[1].y);
+ MACRO_NODECHECK_READCOMP_F("v3", read_flag[5], als.TextureCoordinate[2].y);
+ MACRO_NODECHECK_LOOPEND("map");
+ }// if(!pUseOldName) else
+
+ ParseHelper_Node_Exit();
+
+ // check that all components was defined
+ if(!(read_flag[0] && read_flag[1] && read_flag[2] && read_flag[3] && read_flag[4] && read_flag[5]))
+ throw DeadlyImportError("Not all texture coordinates are defined.");
+
+ // copy attributes data
+ als.TextureID_R = rtexid;
+ als.TextureID_G = gtexid;
+ als.TextureID_B = btexid;
+ als.TextureID_A = atexid;
+
+ mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
diff --git a/src/3rdparty/assimp/code/AMFImporter_Node.hpp b/src/3rdparty/assimp/code/AMFImporter_Node.hpp
new file mode 100644
index 000000000..522e6ccca
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter_Node.hpp
@@ -0,0 +1,400 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter_Node.hpp
+/// \brief Elements of scene graph.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#pragma once
+#ifndef INCLUDED_AI_AMF_IMPORTER_NODE_H
+#define INCLUDED_AI_AMF_IMPORTER_NODE_H
+
+// Header files, stdlib.
+#include <list>
+#include <string>
+#include <vector>
+
+// Header files, Assimp.
+#include "assimp/types.h"
+#include "assimp/scene.h"
+
+/// \class CAMFImporter_NodeElement
+/// Base class for elements of nodes.
+class CAMFImporter_NodeElement {
+
+public:
+ /// Define what data type contain node element.
+ enum EType {
+ ENET_Color, ///< Color element: <color>.
+ ENET_Constellation,///< Grouping element: <constellation>.
+ ENET_Coordinates, ///< Coordinates element: <coordinates>.
+ ENET_Edge, ///< Edge element: <edge>.
+ ENET_Instance, ///< Grouping element: <constellation>.
+ ENET_Material, ///< Material element: <material>.
+ ENET_Metadata, ///< Metadata element: <metadata>.
+ ENET_Mesh, ///< Metadata element: <mesh>.
+ ENET_Object, ///< Element which hold object: <object>.
+ ENET_Root, ///< Root element: <amf>.
+ ENET_Triangle, ///< Triangle element: <triangle>.
+ ENET_TexMap, ///< Texture coordinates element: <texmap> or <map>.
+ ENET_Texture, ///< Texture element: <texture>.
+ ENET_Vertex, ///< Vertex element: <vertex>.
+ ENET_Vertices, ///< Vertex element: <vertices>.
+ ENET_Volume, ///< Volume element: <volume>.
+
+ ENET_Invalid ///< Element has invalid type and possible contain invalid data.
+ };
+
+ const EType Type;///< Type of element.
+ std::string ID;///< ID of element.
+ CAMFImporter_NodeElement* Parent;///< Parent element. If nullptr then this node is root.
+ std::list<CAMFImporter_NodeElement*> Child;///< Child elements.
+
+public: /// Destructor, virtual..
+ virtual ~CAMFImporter_NodeElement() {
+ // empty
+ }
+
+private:
+ /// Disabled copy constructor.
+ CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement);
+
+ /// Disabled assign operator.
+ CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement);
+
+ /// Disabled default constructor.
+ CAMFImporter_NodeElement();
+
+protected:
+ /// In constructor inheritor must set element type.
+ /// \param [in] pType - element type.
+ /// \param [in] pParent - parent element.
+ CAMFImporter_NodeElement(const EType pType, CAMFImporter_NodeElement* pParent)
+ : Type(pType)
+ , ID()
+ , Parent(pParent)
+ , Child() {
+ // empty
+ }
+};// class IAMFImporter_NodeElement
+
+/// \struct CAMFImporter_NodeElement_Constellation
+/// A collection of objects or constellations with specific relative locations.
+struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Constellation, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Constellation
+
+/// \struct CAMFImporter_NodeElement_Instance
+/// Part of constellation.
+struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ std::string ObjectID;///< ID of object for instantiation.
+ /// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
+ /// create an instance of the object in the current constellation.
+ aiVector3D Delta;
+
+ /// \var Rotation - The rotation, in degrees, to rotate the referenced object about its x, y, and z axes, respectively, to create an
+ /// instance of the object in the current constellation. Rotations shall be executed in order of x first, then y, then z.
+ aiVector3D Rotation;
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Instance, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Instance
+
+/// \struct CAMFImporter_NodeElement_Metadata
+/// Structure that define metadata node.
+struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ std::string Type;///< Type of "Value".
+ std::string Value;///< Value.
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Metadata, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Metadata
+
+/// \struct CAMFImporter_NodeElement_Root
+/// Structure that define root node.
+struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ std::string Unit;///< The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
+ std::string Version;///< Version of format.
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Root, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Root
+
+/// \struct CAMFImporter_NodeElement_Color
+/// Structure that define object node.
+struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ bool Composed;///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color.
+ std::string Color_Composed[4];///< By components formulas of composed color. [0..3] => RGBA.
+ aiColor4D Color;///< Constant color.
+ std::string Profile;///< The ICC color space used to interpret the three color channels <r>, <g> and <b>..
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Color, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Color
+
+/// \struct CAMFImporter_NodeElement_Material
+/// Structure that define material node.
+struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Material, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Material
+
+/// \struct CAMFImporter_NodeElement_Object
+/// Structure that define object node.
+struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Object, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Object
+
+/// \struct CAMFImporter_NodeElement_Mesh
+/// Structure that define mesh node.
+struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Mesh, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Mesh
+
+/// \struct CAMFImporter_NodeElement_Vertex
+/// Structure that define vertex node.
+struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Vertex, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Vertex
+
+/// \struct CAMFImporter_NodeElement_Edge
+/// Structure that define edge node.
+struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Edge, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Vertex
+
+/// \struct CAMFImporter_NodeElement_Vertices
+/// Structure that define vertices node.
+struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement
+{
+ /// \fn CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Vertices, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Vertices
+
+/// \struct CAMFImporter_NodeElement_Volume
+/// Structure that define volume node.
+struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ std::string MaterialID;///< Which material to use.
+ std::string Type;///< What this volume describes can be “region” or “support”. If none specified, “object” is assumed.
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Volume, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Volume
+
+/// \struct CAMFImporter_NodeElement_Coordinates
+/// Structure that define coordinates node.
+struct CAMFImporter_NodeElement_Coordinates : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ aiVector3D Coordinate;///< Coordinate.
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Coordinates, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Coordinates
+
+/// \struct CAMFImporter_NodeElement_TexMap
+/// Structure that define texture coordinates node.
+struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ aiVector3D TextureCoordinate[3];///< Texture coordinates.
+ std::string TextureID_R;///< Texture ID for red color component.
+ std::string TextureID_G;///< Texture ID for green color component.
+ std::string TextureID_B;///< Texture ID for blue color component.
+ std::string TextureID_A;///< Texture ID for alpha color component.
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_TexMap, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_TexMap
+
+/// \struct CAMFImporter_NodeElement_Triangle
+/// Structure that define triangle node.
+struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement
+{
+ /****************** Variables ******************/
+
+ size_t V[3];///< Triangle vertices.
+
+ /****************** Functions ******************/
+
+ /// \fn CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Triangle, pParent)
+ {}
+
+};// struct CAMFImporter_NodeElement_Triangle
+
+/// Structure that define texture node.
+struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement {
+ size_t Width, Height, Depth;///< Size of the texture.
+ std::vector<uint8_t> Data;///< Data of the texture.
+ bool Tiled;
+
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ CAMFImporter_NodeElement_Texture(CAMFImporter_NodeElement* pParent)
+ : CAMFImporter_NodeElement(ENET_Texture, pParent)
+ , Width( 0 )
+ , Height( 0 )
+ , Depth( 0 )
+ , Data()
+ , Tiled( false ){
+ // empty
+ }
+};// struct CAMFImporter_NodeElement_Texture
+
+#endif // INCLUDED_AI_AMF_IMPORTER_NODE_H
diff --git a/src/3rdparty/assimp/code/AMFImporter_Postprocess.cpp b/src/3rdparty/assimp/code/AMFImporter_Postprocess.cpp
new file mode 100644
index 000000000..991eb97e7
--- /dev/null
+++ b/src/3rdparty/assimp/code/AMFImporter_Postprocess.cpp
@@ -0,0 +1,976 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+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 AMFImporter_Postprocess.cpp
+/// \brief Convert built scenegraph and objects to Assimp scenegraph.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+
+#include "AMFImporter.hpp"
+
+// Header files, Assimp.
+#include <assimp/SceneCombiner.h>
+#include "StandardShapes.h"
+#include "StringUtils.h"
+
+// Header files, stdlib.
+#include <iterator>
+
+namespace Assimp
+{
+
+aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const
+{
+ aiColor4D tcol;
+
+ // Check if stored data are supported.
+ if(Composition.size() != 0)
+ {
+ throw DeadlyImportError("IME. GetColor for composition");
+ }
+ else if(Color->Composed)
+ {
+ throw DeadlyImportError("IME. GetColor, composed color");
+ }
+ else
+ {
+ tcol = Color->Color;
+ }
+
+ // Check if default color must be used
+ if((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0))
+ {
+ tcol.r = 0.5f;
+ tcol.g = 0.5f;
+ tcol.b = 0.5f;
+ tcol.a = 1;
+ }
+
+ return tcol;
+}
+
+void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
+ std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const
+{
+ CAMFImporter_NodeElement_Vertices* vn = nullptr;
+ size_t col_idx;
+
+ // All data stored in "vertices", search for it.
+ for(CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
+ {
+ if(ne_child->Type == CAMFImporter_NodeElement::ENET_Vertices) vn = (CAMFImporter_NodeElement_Vertices*)ne_child;
+ }
+
+ // If "vertices" not found then no work for us.
+ if(vn == nullptr) return;
+
+ pVertexCoordinateArray.reserve(vn->Child.size());// all coordinates stored as child and we need to reserve space for future push_back's.
+ pVertexColorArray.resize(vn->Child.size());// colors count equal vertices count.
+ col_idx = 0;
+ // Inside vertices collect all data and place to arrays
+ for(CAMFImporter_NodeElement* vn_child: vn->Child)
+ {
+ // vertices, colors
+ if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex)
+ {
+ // by default clear color for current vertex
+ pVertexColorArray[col_idx] = nullptr;
+
+ for(CAMFImporter_NodeElement* vtx: vn_child->Child)
+ {
+ if(vtx->Type == CAMFImporter_NodeElement::ENET_Coordinates)
+ {
+ pVertexCoordinateArray.push_back(((CAMFImporter_NodeElement_Coordinates*)vtx)->Coordinate);
+
+ continue;
+ }
+
+ if(vtx->Type == CAMFImporter_NodeElement::ENET_Color)
+ {
+ pVertexColorArray[col_idx] = (CAMFImporter_NodeElement_Color*)vtx;
+
+ continue;
+ }
+ }// for(CAMFImporter_NodeElement* vtx: vn_child->Child)
+
+ col_idx++;
+ }// if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex)
+ }// for(CAMFImporter_NodeElement* vn_child: vn->Child)
+}
+
+size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B,
+ const std::string& pID_A)
+{
+ size_t TextureConverted_Index;
+ std::string TextureConverted_ID;
+
+ // check input data
+ if(pID_R.empty() && pID_G.empty() && pID_B.empty() && pID_A.empty())
+ throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. At least one texture ID must be defined.");
+
+ // Create ID
+ TextureConverted_ID = pID_R + "_" + pID_G + "_" + pID_B + "_" + pID_A;
+ // Check if texture specified by set of IDs is converted already.
+ TextureConverted_Index = 0;
+ for(const SPP_Texture& tex_convd: mTexture_Converted)
+ {
+ if(tex_convd.ID == TextureConverted_ID)
+ return TextureConverted_Index;
+ else
+ TextureConverted_Index++;
+ }
+
+ //
+ // Converted texture not found, create it.
+ //
+ CAMFImporter_NodeElement_Texture* src_texture[4]{nullptr};
+ std::vector<CAMFImporter_NodeElement_Texture*> src_texture_4check;
+ SPP_Texture converted_texture;
+
+ {// find all specified source textures
+ CAMFImporter_NodeElement* t_tex;
+
+ // R
+ if(!pID_R.empty())
+ {
+ if(!Find_NodeElement(pID_R, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_R);
+
+ src_texture[0] = (CAMFImporter_NodeElement_Texture*)t_tex;
+ src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
+ }
+ else
+ {
+ src_texture[0] = nullptr;
+ }
+
+ // G
+ if(!pID_G.empty())
+ {
+ if(!Find_NodeElement(pID_G, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_G);
+
+ src_texture[1] = (CAMFImporter_NodeElement_Texture*)t_tex;
+ src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
+ }
+ else
+ {
+ src_texture[1] = nullptr;
+ }
+
+ // B
+ if(!pID_B.empty())
+ {
+ if(!Find_NodeElement(pID_B, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_B);
+
+ src_texture[2] = (CAMFImporter_NodeElement_Texture*)t_tex;
+ src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
+ }
+ else
+ {
+ src_texture[2] = nullptr;
+ }
+
+ // A
+ if(!pID_A.empty())
+ {
+ if(!Find_NodeElement(pID_A, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_A);
+
+ src_texture[3] = (CAMFImporter_NodeElement_Texture*)t_tex;
+ src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
+ }
+ else
+ {
+ src_texture[3] = nullptr;
+ }
+ }// END: find all specified source textures
+
+ // check that all textures has same size
+ if(src_texture_4check.size() > 1)
+ {
+ for (size_t i = 0, i_e = (src_texture_4check.size() - 1); i < i_e; i++)
+ {
+ if((src_texture_4check[i]->Width != src_texture_4check[i + 1]->Width) || (src_texture_4check[i]->Height != src_texture_4check[i + 1]->Height) ||
+ (src_texture_4check[i]->Depth != src_texture_4check[i + 1]->Depth))
+ {
+ throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. Source texture must has the same size.");
+ }
+ }
+ }// if(src_texture_4check.size() > 1)
+
+ // set texture attributes
+ converted_texture.Width = src_texture_4check[0]->Width;
+ converted_texture.Height = src_texture_4check[0]->Height;
+ converted_texture.Depth = src_texture_4check[0]->Depth;
+ // if one of source texture is tiled then converted texture is tiled too.
+ converted_texture.Tiled = false;
+ for(uint8_t i = 0; i < src_texture_4check.size(); i++) converted_texture.Tiled |= src_texture_4check[i]->Tiled;
+
+ // Create format hint.
+ strcpy(converted_texture.FormatHint, "rgba0000");// copy initial string.
+ if(!pID_R.empty()) converted_texture.FormatHint[4] = '8';
+ if(!pID_G.empty()) converted_texture.FormatHint[5] = '8';
+ if(!pID_B.empty()) converted_texture.FormatHint[6] = '8';
+ if(!pID_A.empty()) converted_texture.FormatHint[7] = '8';
+
+ //
+ // Сopy data of textures.
+ //
+ size_t tex_size = 0;
+ size_t step = 0;
+ size_t off_g = 0;
+ size_t off_b = 0;
+
+ // Calculate size of the target array and rule how data will be copied.
+ if(!pID_R.empty() && nullptr != src_texture[ 0 ] ) {
+ tex_size += src_texture[0]->Data.size(); step++, off_g++, off_b++;
+ }
+ if(!pID_G.empty() && nullptr != src_texture[ 1 ] ) {
+ tex_size += src_texture[1]->Data.size(); step++, off_b++;
+ }
+ if(!pID_B.empty() && nullptr != src_texture[ 2 ] ) {
+ tex_size += src_texture[2]->Data.size(); step++;
+ }
+ if(!pID_A.empty() && nullptr != src_texture[ 3 ] ) {
+ tex_size += src_texture[3]->Data.size(); step++;
+ }
+
+ // Create target array.
+ converted_texture.Data = new uint8_t[tex_size];
+ // And copy data
+ auto CopyTextureData = [&](const std::string& pID, const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
+ {
+ if(!pID.empty())
+ {
+ for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) {
+ CAMFImporter_NodeElement_Texture* tex = src_texture[pSrcTexNum];
+ ai_assert(tex);
+ converted_texture.Data[idx_target] = tex->Data.at(idx_src);
+ }
+ }
+ };// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
+
+ CopyTextureData(pID_R, 0, step, 0);
+ CopyTextureData(pID_G, off_g, step, 1);
+ CopyTextureData(pID_B, off_b, step, 2);
+ CopyTextureData(pID_A, step - 1, step, 3);
+
+ // Store new converted texture ID
+ converted_texture.ID = TextureConverted_ID;
+ // Store new converted texture
+ mTexture_Converted.push_back(converted_texture);
+
+ return TextureConverted_Index;
+}
+
+void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated)
+{
+ auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap* pTexMap1, const CAMFImporter_NodeElement_TexMap* pTexMap2) -> bool
+ {
+ if((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true;
+ if(pTexMap1 == nullptr) return false;
+ if(pTexMap2 == nullptr) return false;
+
+ if(pTexMap1->TextureID_R != pTexMap2->TextureID_R) return false;
+ if(pTexMap1->TextureID_G != pTexMap2->TextureID_G) return false;
+ if(pTexMap1->TextureID_B != pTexMap2->TextureID_B) return false;
+ if(pTexMap1->TextureID_A != pTexMap2->TextureID_A) return false;
+
+ return true;
+ };
+
+ pOutputList_Separated.clear();
+ if(pInputList.size() == 0) return;
+
+ do
+ {
+ SComplexFace face_start = pInputList.front();
+ std::list<SComplexFace> face_list_cur;
+
+ for(std::list<SComplexFace>::iterator it = pInputList.begin(), it_end = pInputList.end(); it != it_end;)
+ {
+ if(texmap_is_equal(face_start.TexMap, it->TexMap))
+ {
+ auto it_old = it;
+
+ it++;
+ face_list_cur.push_back(*it_old);
+ pInputList.erase(it_old);
+ }
+ else
+ {
+ it++;
+ }
+ }
+
+ if(face_list_cur.size() > 0) pOutputList_Separated.push_back(face_list_cur);
+
+ } while(pInputList.size() > 0);
+}
+
+void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& metadataList, aiNode& sceneNode) const
+{
+ if ( !metadataList.empty() )
+ {
+ if(sceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
+
+ // copy collected metadata to output node.
+ sceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(metadataList.size()) );
+ size_t meta_idx( 0 );
+
+ for(const CAMFImporter_NodeElement_Metadata& metadata: metadataList)
+ {
+ sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, aiString(metadata.Value));
+ }
+ }// if(!metadataList.empty())
+}
+
+void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)
+{
+CAMFImporter_NodeElement_Color* object_color = nullptr;
+
+ // create new aiNode and set name as <object> has.
+ *pSceneNode = new aiNode;
+ (*pSceneNode)->mName = pNodeElement.ID;
+ // read mesh and color
+ for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
+ {
+ std::vector<aiVector3D> vertex_arr;
+ std::vector<CAMFImporter_NodeElement_Color*> color_arr;
+
+ // color for object
+ if(ne_child->Type == CAMFImporter_NodeElement::ENET_Color) object_color = (CAMFImporter_NodeElement_Color*)ne_child;
+
+ if(ne_child->Type == CAMFImporter_NodeElement::ENET_Mesh)
+ {
+ // Create arrays from children of mesh: vertices.
+ PostprocessHelper_CreateMeshDataArray(*((CAMFImporter_NodeElement_Mesh*)ne_child), vertex_arr, color_arr);
+ // Use this arrays as a source when creating every aiMesh
+ Postprocess_BuildMeshSet(*((CAMFImporter_NodeElement_Mesh*)ne_child), vertex_arr, color_arr, object_color, pMeshList, **pSceneNode);
+ }
+ }// for(const CAMFImporter_NodeElement* ne_child: pNodeElement)
+}
+
+void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray,
+ const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray,
+ const CAMFImporter_NodeElement_Color* pObjectColor, std::list<aiMesh*>& pMeshList, aiNode& pSceneNode)
+{
+std::list<unsigned int> mesh_idx;
+
+ // all data stored in "volume", search for it.
+ for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
+ {
+ const CAMFImporter_NodeElement_Color* ne_volume_color = nullptr;
+ const SPP_Material* cur_mat = nullptr;
+
+ if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume)
+ {
+ /******************* Get faces *******************/
+ const CAMFImporter_NodeElement_Volume* ne_volume = reinterpret_cast<const CAMFImporter_NodeElement_Volume*>(ne_child);
+
+ std::list<SComplexFace> complex_faces_list;// List of the faces of the volume.
+ std::list<std::list<SComplexFace> > complex_faces_toplist;// List of the face list for every mesh.
+
+ // check if volume use material
+ if(!ne_volume->MaterialID.empty())
+ {
+ if(!Find_ConvertedMaterial(ne_volume->MaterialID, &cur_mat)) Throw_ID_NotFound(ne_volume->MaterialID);
+ }
+
+ // inside "volume" collect all data and place to arrays or create new objects
+ for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child)
+ {
+ // color for volume
+ if(ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Color)
+ {
+ ne_volume_color = reinterpret_cast<const CAMFImporter_NodeElement_Color*>(ne_volume_child);
+ }
+ else if(ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Triangle)// triangles, triangles colors
+ {
+ const CAMFImporter_NodeElement_Triangle& tri_al = *reinterpret_cast<const CAMFImporter_NodeElement_Triangle*>(ne_volume_child);
+
+ SComplexFace complex_face;
+
+ // initialize pointers
+ complex_face.Color = nullptr;
+ complex_face.TexMap = nullptr;
+ // get data from triangle children: color, texture coordinates.
+ if(tri_al.Child.size())
+ {
+ for(const CAMFImporter_NodeElement* ne_triangle_child: tri_al.Child)
+ {
+ if(ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_Color)
+ complex_face.Color = reinterpret_cast<const CAMFImporter_NodeElement_Color*>(ne_triangle_child);
+ else if(ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_TexMap)
+ complex_face.TexMap = reinterpret_cast<const CAMFImporter_NodeElement_TexMap*>(ne_triangle_child);
+ }
+ }// if(tri_al.Child.size())
+
+ // create new face and store it.
+ complex_face.Face.mNumIndices = 3;
+ complex_face.Face.mIndices = new unsigned int[3];
+ complex_face.Face.mIndices[0] = static_cast<unsigned int>(tri_al.V[0]);
+ complex_face.Face.mIndices[1] = static_cast<unsigned int>(tri_al.V[1]);
+ complex_face.Face.mIndices[2] = static_cast<unsigned int>(tri_al.V[2]);
+ complex_faces_list.push_back(complex_face);
+ }
+ }// for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child)
+
+ /**** Split faces list: one list per mesh ****/
+ PostprocessHelper_SplitFacesByTextureID(complex_faces_list, complex_faces_toplist);
+
+ /***** Create mesh for every faces list ******/
+ for(std::list<SComplexFace>& face_list_cur: complex_faces_toplist)
+ {
+ auto VertexIndex_GetMinimal = [](const std::list<SComplexFace>& pFaceList, const size_t* pBiggerThan) -> size_t
+ {
+ size_t rv;
+
+ if(pBiggerThan != nullptr)
+ {
+ bool found = false;
+
+ for(const SComplexFace& face: pFaceList)
+ {
+ for(size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++)
+ {
+ if(face.Face.mIndices[idx_vert] > *pBiggerThan)
+ {
+ rv = face.Face.mIndices[idx_vert];
+ found = true;
+
+ break;
+ }
+ }
+
+ if(found) break;
+ }
+
+ if(!found) return *pBiggerThan;
+ }
+ else
+ {
+ rv = pFaceList.front().Face.mIndices[0];
+ }// if(pBiggerThan != nullptr) else
+
+ for(const SComplexFace& face: pFaceList)
+ {
+ for(size_t vi = 0; vi < face.Face.mNumIndices; vi++)
+ {
+ if(face.Face.mIndices[vi] < rv)
+ {
+ if(pBiggerThan != nullptr)
+ {
+ if(face.Face.mIndices[vi] > *pBiggerThan) rv = face.Face.mIndices[vi];
+ }
+ else
+ {
+ rv = face.Face.mIndices[vi];
+ }
+ }
+ }
+ }// for(const SComplexFace& face: pFaceList)
+
+ return rv;
+ };// auto VertexIndex_GetMinimal = [](const std::list<SComplexFace>& pFaceList, const size_t* pBiggerThan) -> size_t
+
+ auto VertexIndex_Replace = [](std::list<SComplexFace>& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void
+ {
+ for(const SComplexFace& face: pFaceList)
+ {
+ for(size_t vi = 0; vi < face.Face.mNumIndices; vi++)
+ {
+ if(face.Face.mIndices[vi] == pIdx_From) face.Face.mIndices[vi] = static_cast<unsigned int>(pIdx_To);
+ }
+ }
+ };// auto VertexIndex_Replace = [](std::list<SComplexFace>& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void
+
+ auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D
+ {
+ // Color priorities(In descending order):
+ // 1. triangle color;
+ // 2. vertex color;
+ // 3. volume color;
+ // 4. object color;
+ // 5. material;
+ // 6. default - invisible coat.
+ //
+ // Fill vertices colors in color priority list above that's points from 1 to 6.
+ if((pIdx < pVertexColorArray.size()) && (pVertexColorArray[pIdx] != nullptr))// check for vertex color
+ {
+ if(pVertexColorArray[pIdx]->Composed)
+ throw DeadlyImportError("IME: vertex color composed");
+ else
+ return pVertexColorArray[pIdx]->Color;
+ }
+ else if(ne_volume_color != nullptr)// check for volume color
+ {
+ if(ne_volume_color->Composed)
+ throw DeadlyImportError("IME: volume color composed");
+ else
+ return ne_volume_color->Color;
+ }
+ else if(pObjectColor != nullptr)// check for object color
+ {
+ if(pObjectColor->Composed)
+ throw DeadlyImportError("IME: object color composed");
+ else
+ return pObjectColor->Color;
+ }
+ else if(cur_mat != nullptr)// check for material
+ {
+ return cur_mat->GetColor(pVertexCoordinateArray.at(pIdx).x, pVertexCoordinateArray.at(pIdx).y, pVertexCoordinateArray.at(pIdx).z);
+ }
+ else// set default color.
+ {
+ return {0, 0, 0, 0};
+ }// if((vi < pVertexColorArray.size()) && (pVertexColorArray[vi] != nullptr)) else
+
+ };// auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D
+
+ aiMesh* tmesh = new aiMesh;
+
+ tmesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;// Only triangles is supported by AMF.
+ //
+ // set geometry and colors (vertices)
+ //
+ // copy faces/triangles
+ tmesh->mNumFaces = static_cast<unsigned int>(face_list_cur.size());
+ tmesh->mFaces = new aiFace[tmesh->mNumFaces];
+
+ // Create vertices list and optimize indices. Optimisation mean following.In AMF all volumes use one big list of vertices. And one volume
+ // can use only part of vertices list, for example: vertices list contain few thousands of vertices and volume use vertices 1, 3, 10.
+ // Do you need all this thousands of garbage? Of course no. So, optimisation step transformate sparse indices set to continuous.
+ size_t VertexCount_Max = tmesh->mNumFaces * 3;// 3 - triangles.
+ std::vector<aiVector3D> vert_arr, texcoord_arr;
+ std::vector<aiColor4D> col_arr;
+
+ vert_arr.reserve(VertexCount_Max * 2);// "* 2" - see below TODO.
+ col_arr.reserve(VertexCount_Max * 2);
+
+ {// fill arrays
+ size_t vert_idx_from, vert_idx_to;
+
+ // first iteration.
+ vert_idx_to = 0;
+ vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
+ vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from));
+ col_arr.push_back(Vertex_CalculateColor(vert_idx_from));
+ if(vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to);
+
+ // rest iterations
+ do
+ {
+ vert_idx_from = VertexIndex_GetMinimal(face_list_cur, &vert_idx_to);
+ if(vert_idx_from == vert_idx_to) break;// all indices are transferred,
+
+ vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from));
+ col_arr.push_back(Vertex_CalculateColor(vert_idx_from));
+ vert_idx_to++;
+ if(vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to);
+
+ } while(true);
+ }// fill arrays. END.
+
+ //
+ // check if triangle colors are used and create additional faces if needed.
+ //
+ for(const SComplexFace& face_cur: face_list_cur)
+ {
+ if(face_cur.Color != nullptr)
+ {
+ aiColor4D face_color;
+ size_t vert_idx_new = vert_arr.size();
+
+ if(face_cur.Color->Composed)
+ throw DeadlyImportError("IME: face color composed");
+ else
+ face_color = face_cur.Color->Color;
+
+ for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++)
+ {
+ vert_arr.push_back(vert_arr.at(face_cur.Face.mIndices[idx_ind]));
+ col_arr.push_back(face_color);
+ face_cur.Face.mIndices[idx_ind] = static_cast<unsigned int>(vert_idx_new++);
+ }
+ }// if(face_cur.Color != nullptr)
+ }// for(const SComplexFace& face_cur: face_list_cur)
+
+ //
+ // if texture is used then copy texture coordinates too.
+ //
+ if(face_list_cur.front().TexMap != nullptr)
+ {
+ size_t idx_vert_new = vert_arr.size();
+ ///TODO: clean unused vertices. "* 2": in certain cases - mesh full of triangle colors - vert_arr will contain duplicated vertices for
+ /// colored triangles and initial vertices (for colored vertices) which in real became unused. This part need more thinking about
+ /// optimisation.
+ bool* idx_vert_used;
+
+ idx_vert_used = new bool[VertexCount_Max * 2];
+ for(size_t i = 0, i_e = VertexCount_Max * 2; i < i_e; i++) idx_vert_used[i] = false;
+
+ // This ID's will be used when set materials ID in scene.
+ tmesh->mMaterialIndex = static_cast<unsigned int>(PostprocessHelper_GetTextureID_Or_Create(face_list_cur.front().TexMap->TextureID_R,
+ face_list_cur.front().TexMap->TextureID_G,
+ face_list_cur.front().TexMap->TextureID_B,
+ face_list_cur.front().TexMap->TextureID_A));
+ texcoord_arr.resize(VertexCount_Max * 2);
+ for(const SComplexFace& face_cur: face_list_cur)
+ {
+ for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++)
+ {
+ const size_t idx_vert = face_cur.Face.mIndices[idx_ind];
+
+ if(!idx_vert_used[idx_vert])
+ {
+ texcoord_arr.at(idx_vert) = face_cur.TexMap->TextureCoordinate[idx_ind];
+ idx_vert_used[idx_vert] = true;
+ }
+ else if(texcoord_arr.at(idx_vert) != face_cur.TexMap->TextureCoordinate[idx_ind])
+ {
+ // in that case one vertex is shared with many texture coordinates. We need to duplicate vertex with another texture
+ // coordinates.
+ vert_arr.push_back(vert_arr.at(idx_vert));
+ col_arr.push_back(col_arr.at(idx_vert));
+ texcoord_arr.at(idx_vert_new) = face_cur.TexMap->TextureCoordinate[idx_ind];
+ face_cur.Face.mIndices[idx_ind] = static_cast<unsigned int>(idx_vert_new++);
+ }
+ }// for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++)
+ }// for(const SComplexFace& face_cur: face_list_cur)
+
+ delete [] idx_vert_used;
+ // shrink array
+ texcoord_arr.resize(idx_vert_new);
+ }// if(face_list_cur.front().TexMap != nullptr)
+
+ //
+ // copy collected data to mesh
+ //
+ tmesh->mNumVertices = static_cast<unsigned int>(vert_arr.size());
+ tmesh->mVertices = new aiVector3D[tmesh->mNumVertices];
+ tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices];
+
+ memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D));
+ memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D));
+ if(texcoord_arr.size() > 0)
+ {
+ tmesh->mTextureCoords[0] = new aiVector3D[tmesh->mNumVertices];
+ memcpy(tmesh->mTextureCoords[0], texcoord_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D));
+ tmesh->mNumUVComponents[0] = 2;// U and V stored in "x", "y" of aiVector3D.
+ }
+
+ size_t idx_face = 0;
+ for(const SComplexFace& face_cur: face_list_cur) tmesh->mFaces[idx_face++] = face_cur.Face;
+
+ // store new aiMesh
+ mesh_idx.push_back(static_cast<unsigned int>(pMeshList.size()));
+ pMeshList.push_back(tmesh);
+ }// for(const std::list<SComplexFace>& face_list_cur: complex_faces_toplist)
+ }// if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume)
+ }// for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
+
+ // if meshes was created then assign new indices with current aiNode
+ if(mesh_idx.size() > 0)
+ {
+ std::list<unsigned int>::const_iterator mit = mesh_idx.begin();
+
+ pSceneNode.mNumMeshes = static_cast<unsigned int>(mesh_idx.size());
+ pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
+ for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *mit++;
+ }// if(mesh_idx.size() > 0)
+}
+
+void AMFImporter::Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial)
+{
+SPP_Material new_mat;
+
+ new_mat.ID = pMaterial.ID;
+ for(const CAMFImporter_NodeElement* mat_child: pMaterial.Child)
+ {
+ if(mat_child->Type == CAMFImporter_NodeElement::ENET_Color)
+ {
+ new_mat.Color = (CAMFImporter_NodeElement_Color*)mat_child;
+ }
+ else if(mat_child->Type == CAMFImporter_NodeElement::ENET_Metadata)
+ {
+ new_mat.Metadata.push_back((CAMFImporter_NodeElement_Metadata*)mat_child);
+ }
+ }// for(const CAMFImporter_NodeElement* mat_child; pMaterial.Child)
+
+ // place converted material to special list
+ mMaterial_Converted.push_back(new_mat);
+}
+
+void AMFImporter::Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const
+{
+aiNode* con_node;
+std::list<aiNode*> ch_node;
+
+ // We will build next hierarchy:
+ // aiNode as parent (<constellation>) for set of nodes as a children
+ // |- aiNode for transformation (<instance> -> <delta...>, <r...>) - aiNode for pointing to object ("objectid")
+ // ...
+ // \_ aiNode for transformation (<instance> -> <delta...>, <r...>) - aiNode for pointing to object ("objectid")
+ con_node = new aiNode;
+ con_node->mName = pConstellation.ID;
+ // Walk through children and search for instances of another objects, constellations.
+ for(const CAMFImporter_NodeElement* ne: pConstellation.Child)
+ {
+ aiMatrix4x4 tmat;
+ aiNode* t_node;
+ aiNode* found_node;
+
+ if(ne->Type == CAMFImporter_NodeElement::ENET_Metadata) continue;
+ if(ne->Type != CAMFImporter_NodeElement::ENET_Instance) throw DeadlyImportError("Only <instance> nodes can be in <constellation>.");
+
+ // create alias for conveniance
+ CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);
+ // find referenced object
+ if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
+
+ // create node for apllying transformation
+ t_node = new aiNode;
+ t_node->mParent = con_node;
+ // apply transformation
+ aiMatrix4x4::Translation(als.Delta, tmat), t_node->mTransformation *= tmat;
+ aiMatrix4x4::RotationX(als.Rotation.x, tmat), t_node->mTransformation *= tmat;
+ aiMatrix4x4::RotationY(als.Rotation.y, tmat), t_node->mTransformation *= tmat;
+ aiMatrix4x4::RotationZ(als.Rotation.z, tmat), t_node->mTransformation *= tmat;
+ // create array for one child node
+ t_node->mNumChildren = 1;
+ t_node->mChildren = new aiNode*[t_node->mNumChildren];
+ SceneCombiner::Copy(&t_node->mChildren[0], found_node);
+ t_node->mChildren[0]->mParent = t_node;
+ ch_node.push_back(t_node);
+ }// for(const CAMFImporter_NodeElement* ne: pConstellation.Child)
+
+ // copy found aiNode's as children
+ if(ch_node.size() == 0) throw DeadlyImportError("<constellation> must have at least one <instance>.");
+
+ size_t ch_idx = 0;
+
+ con_node->mNumChildren = static_cast<unsigned int>(ch_node.size());
+ con_node->mChildren = new aiNode*[con_node->mNumChildren];
+ for(aiNode* node: ch_node) con_node->mChildren[ch_idx++] = node;
+
+ // and place "root" of <constellation> node to node list
+ pNodeList.push_back(con_node);
+}
+
+void AMFImporter::Postprocess_BuildScene(aiScene* pScene)
+{
+std::list<aiNode*> node_list;
+std::list<aiMesh*> mesh_list;
+std::list<CAMFImporter_NodeElement_Metadata*> meta_list;
+
+ //
+ // Because for AMF "material" is just complex colors mixing so aiMaterial will not be used.
+ // For building aiScene we are must to do few steps:
+ // at first creating root node for aiScene.
+ pScene->mRootNode = new aiNode;
+ pScene->mRootNode->mParent = nullptr;
+ pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED;
+ // search for root(<amf>) element
+ CAMFImporter_NodeElement* root_el = nullptr;
+
+ for(CAMFImporter_NodeElement* ne: mNodeElement_List)
+ {
+ if(ne->Type != CAMFImporter_NodeElement::ENET_Root) continue;
+
+ root_el = ne;
+
+ break;
+ }// for(const CAMFImporter_NodeElement* ne: mNodeElement_List)
+
+ // Check if root element are found.
+ if(root_el == nullptr) throw DeadlyImportError("Root(<amf>) element not found.");
+
+ // after that walk through children of root and collect data. Five types of nodes can be placed at top level - in <amf>: <object>, <material>, <texture>,
+ // <constellation> and <metadata>. But at first we must read <material> and <texture> because they will be used in <object>. <metadata> can be read
+ // at any moment.
+ //
+ // 1. <material>
+ // 2. <texture> will be converted later when processing triangles list. \sa Postprocess_BuildMeshSet
+ for(const CAMFImporter_NodeElement* root_child: root_el->Child)
+ {
+ if(root_child->Type == CAMFImporter_NodeElement::ENET_Material) Postprocess_BuildMaterial(*((CAMFImporter_NodeElement_Material*)root_child));
+ }
+
+ // After "appearance" nodes we must read <object> because it will be used in <constellation> -> <instance>.
+ //
+ // 3. <object>
+ for(const CAMFImporter_NodeElement* root_child: root_el->Child)
+ {
+ if(root_child->Type == CAMFImporter_NodeElement::ENET_Object)
+ {
+ aiNode* tnode = nullptr;
+
+ // for <object> mesh and node must be built: object ID assigned to aiNode name and will be used in future for <instance>
+ Postprocess_BuildNodeAndObject(*((CAMFImporter_NodeElement_Object*)root_child), mesh_list, &tnode);
+ if(tnode != nullptr) node_list.push_back(tnode);
+
+ }
+ }// for(const CAMFImporter_NodeElement* root_child: root_el->Child)
+
+ // And finally read rest of nodes.
+ //
+ for(const CAMFImporter_NodeElement* root_child: root_el->Child)
+ {
+ // 4. <constellation>
+ if(root_child->Type == CAMFImporter_NodeElement::ENET_Constellation)
+ {
+ // <object> and <constellation> at top of self abstraction use aiNode. So we can use only aiNode list for creating new aiNode's.
+ Postprocess_BuildConstellation(*((CAMFImporter_NodeElement_Constellation*)root_child), node_list);
+ }
+
+ // 5, <metadata>
+ if(root_child->Type == CAMFImporter_NodeElement::ENET_Metadata) meta_list.push_back((CAMFImporter_NodeElement_Metadata*)root_child);
+ }// for(const CAMFImporter_NodeElement* root_child: root_el->Child)
+
+ // at now we can add collected metadata to root node
+ Postprocess_AddMetadata(meta_list, *pScene->mRootNode);
+ //
+ // Check constellation children
+ //
+ // As said in specification:
+ // "When multiple objects and constellations are defined in a single file, only the top level objects and constellations are available for printing."
+ // What that means? For example: if some object is used in constellation then you must show only constellation but not original object.
+ // And at this step we are checking that relations.
+nl_clean_loop:
+
+ if(node_list.size() > 1)
+ {
+ // walk through all nodes
+ for(std::list<aiNode*>::iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++)
+ {
+ // and try to find them in another top nodes.
+ std::list<aiNode*>::const_iterator next_it = nl_it;
+
+ next_it++;
+ for(; next_it != node_list.end(); next_it++)
+ {
+ if((*next_it)->FindNode((*nl_it)->mName) != nullptr)
+ {
+ // if current top node(nl_it) found in another top node then erase it from node_list and restart search loop.
+ node_list.erase(nl_it);
+
+ goto nl_clean_loop;
+ }
+ }// for(; next_it != node_list.end(); next_it++)
+ }// for(std::list<aiNode*>::const_iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++)
+ }
+
+ //
+ // move created objects to aiScene
+ //
+ //
+ // Nodes
+ if(node_list.size() > 0)
+ {
+ std::list<aiNode*>::const_iterator nl_it = node_list.begin();
+
+ pScene->mRootNode->mNumChildren = static_cast<unsigned int>(node_list.size());
+ pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
+ for(size_t i = 0; i < pScene->mRootNode->mNumChildren; i++)
+ {
+ // Objects and constellation that must be showed placed at top of hierarchy in <amf> node. So all aiNode's in node_list must have
+ // mRootNode only as parent.
+ (*nl_it)->mParent = pScene->mRootNode;
+ pScene->mRootNode->mChildren[i] = *nl_it++;
+ }
+ }// if(node_list.size() > 0)
+
+ //
+ // Meshes
+ if(mesh_list.size() > 0)
+ {
+ std::list<aiMesh*>::const_iterator ml_it = mesh_list.begin();
+
+ pScene->mNumMeshes = static_cast<unsigned int>(mesh_list.size());
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for(size_t i = 0; i < pScene->mNumMeshes; i++) pScene->mMeshes[i] = *ml_it++;
+ }// if(mesh_list.size() > 0)
+
+ //
+ // Textures
+ pScene->mNumTextures = static_cast<unsigned int>(mTexture_Converted.size());
+ if(pScene->mNumTextures > 0)
+ {
+ size_t idx;
+
+ idx = 0;
+ pScene->mTextures = new aiTexture*[pScene->mNumTextures];
+ for(const SPP_Texture& tex_convd: mTexture_Converted)
+ {
+ pScene->mTextures[idx] = new aiTexture;
+ pScene->mTextures[idx]->mWidth = static_cast<unsigned int>(tex_convd.Width);
+ pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
+ pScene->mTextures[idx]->pcData = (aiTexel*)tex_convd.Data;
+ // texture format description.
+ strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint);
+ idx++;
+ }// for(const SPP_Texture& tex_convd: mTexture_Converted)
+
+ // Create materials for embedded textures.
+ idx = 0;
+ pScene->mNumMaterials = static_cast<unsigned int>(mTexture_Converted.size());
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for(const SPP_Texture& tex_convd: mTexture_Converted)
+ {
+ const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + to_string(idx));
+ const int mode = aiTextureOp_Multiply;
+ const int repeat = tex_convd.Tiled ? 1 : 0;
+
+ pScene->mMaterials[idx] = new aiMaterial;
+ pScene->mMaterials[idx]->AddProperty(&texture_id, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ pScene->mMaterials[idx]->AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
+ pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
+ pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
+ idx++;
+ }
+ }// if(pScene->mNumTextures > 0)
+}// END: after that walk through children of root and collect data
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
diff --git a/src/3rdparty/assimp/code/ASELoader.cpp b/src/3rdparty/assimp/code/ASELoader.cpp
index 39a33e9fd..65935f48f 100644
--- a/src/3rdparty/assimp/code/ASELoader.cpp
+++ b/src/3rdparty/assimp/code/ASELoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -45,6 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+
// internal headers
#include "ASELoader.h"
#include "StringComparison.h"
@@ -54,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include <memory>
@@ -819,10 +823,10 @@ void CopyASETexture(aiMaterial& mat, ASE::Texture& texture, aiTextureType type)
// Setup the texture blend factor
if (is_not_qnan(texture.mTextureBlend))
- mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
+ mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup texture UV transformations
- mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
+ mat.AddProperty<ai_real>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
}
// ------------------------------------------------------------------------------------------------
@@ -865,7 +869,7 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
}
// opacity
- mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
+ mat.pcInstance->AddProperty<ai_real>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
// Two sided rendering?
if (mat.mTwoSided)
@@ -1017,6 +1021,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
// convert bones, if existing
if (!mesh.mBones.empty()) {
+ ai_assert(avOutputBones);
// check whether there is a vertex weight for this vertex index
if (iIndex2 < mesh.mBoneVertices.size()) {
@@ -1318,4 +1323,6 @@ bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) {
return false;
}
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
diff --git a/src/3rdparty/assimp/code/ASELoader.h b/src/3rdparty/assimp/code/ASELoader.h
index b775fc6bb..8a8d4faa4 100644
--- a/src/3rdparty/assimp/code/ASELoader.h
+++ b/src/3rdparty/assimp/code/ASELoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include <assimp/types.h>
+#include "ASEParser.h"
struct aiNode;
-#include "ASEParser.h"
namespace Assimp {
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// --------------------------------------------------------------------------------
/** Importer class for the 3DS ASE ASCII format.
@@ -62,9 +64,6 @@ public:
ASEImporter();
~ASEImporter();
-
-public:
-
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
@@ -200,6 +199,9 @@ protected:
bool noSkeletonMesh;
};
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
} // end of namespace Assimp
+
#endif // AI_3DSIMPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/ASEParser.cpp b/src/3rdparty/assimp/code/ASEParser.cpp
index 204f8bf62..7de80a2d8 100644
--- a/src/3rdparty/assimp/code/ASEParser.cpp
+++ b/src/3rdparty/assimp/code/ASEParser.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -25,8 +26,8 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 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,
@@ -45,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers
#include "TextureTransform.h"
#include "ASELoader.h"
-#include "MaterialSystem.h"
#include "fast_atof.h"
#include <assimp/DefaultLogger.hpp>
@@ -431,7 +432,7 @@ void Parser::ParseLV1SoftSkinBlock()
ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
// Find the bone in the mesh's list
- std::pair<int,float> me;
+ std::pair<int,ai_real> me;
me.first = -1;
for (unsigned int n = 0; n < curMesh->mBones.size();++n)
@@ -618,12 +619,13 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
{
ParseLV4MeshFloat(mat.mTransparency);
- mat.mTransparency = 1.0f - mat.mTransparency;continue;
+ mat.mTransparency = ai_real( 1.0 ) - mat.mTransparency;
+ continue;
}
// material self illumination
if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
{
- float f = 0.0f;
+ ai_real f = 0.0;
ParseLV4MeshFloat(f);
mat.mEmissive.r = f;
@@ -1134,7 +1136,7 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
bool b = false;
// For the moment we're just reading the three floats -
- // we ignore the �dditional information for bezier's and TCBs
+ // we ignore the additional information for bezier's and TCBs
// simple scaling keyframe
if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
@@ -1180,7 +1182,7 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
bool b = false;
// For the moment we're just reading the three floats -
- // we ignore the �dditional information for bezier's and TCBs
+ // we ignore the additional information for bezier's and TCBs
// simple scaling keyframe
if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
@@ -1226,7 +1228,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
bool b = false;
// For the moment we're just reading the floats -
- // we ignore the �dditional information for bezier's and TCBs
+ // we ignore the additional information for bezier's and TCBs
// simple scaling keyframe
if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
@@ -1251,7 +1253,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
{
anim.akeyRotations.push_back(aiQuatKey());
aiQuatKey& key = anim.akeyRotations.back();
- aiVector3D v;float f;
+ aiVector3D v;ai_real f;
ParseLV4MeshFloatTriple(&v.x,iIndex);
ParseLV4MeshFloat(f);
key.mTime = (double)iIndex;
@@ -1463,30 +1465,29 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
continue;
}
// another mesh UV channel ...
- if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
- {
-
- unsigned int iIndex = 0;
+ 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");
+ if ( 0 == iIndex ) {
+ LogWarning( "Mapping channel has an invalid index. Skipping UV channel" );
// skip it ...
SkipSection();
+ } else {
+ 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;
}
- 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))
@@ -1604,7 +1605,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh
}
// --- ignored
- float afVert[3];
+ ai_real afVert[3];
ParseLV4MeshFloatTriple(afVert);
std::pair<int,float> pairOut;
@@ -1858,7 +1859,7 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
++filePtr;
// Face entry
- if (TokenMatch(filePtr,"MESH_CFACE" ,11))
+ if (TokenMatch(filePtr,"MESH_CFACE" ,10))
{
unsigned int aiValues[3];
unsigned int iIndex = 0;
@@ -2102,7 +2103,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut
ParseLV4MeshLongTriple(apOut);
}
// ------------------------------------------------------------------------------------------------
-void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
+void Parser::ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut)
{
ai_assert(NULL != apOut);
@@ -2113,7 +2114,7 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
ParseLV4MeshFloatTriple(apOut);
}
// ------------------------------------------------------------------------------------------------
-void Parser::ParseLV4MeshFloatTriple(float* apOut)
+void Parser::ParseLV4MeshFloatTriple(ai_real* apOut)
{
ai_assert(NULL != apOut);
@@ -2121,19 +2122,19 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut)
ParseLV4MeshFloat(apOut[i]);
}
// ------------------------------------------------------------------------------------------------
-void Parser::ParseLV4MeshFloat(float& fOut)
+void Parser::ParseLV4MeshFloat(ai_real& fOut)
{
// skip spaces and tabs
if(!SkipSpaces(&filePtr))
{
// LOG
LogWarning("Unable to parse float: unexpected EOL [#1]");
- fOut = 0.0f;
+ fOut = 0.0;
++iLineNumber;
return;
}
// parse the first float
- filePtr = fast_atoreal_move<float>(filePtr,fOut);
+ filePtr = fast_atoreal_move<ai_real>(filePtr,fOut);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLong(unsigned int& iOut)
@@ -2151,4 +2152,6 @@ void Parser::ParseLV4MeshLong(unsigned int& iOut)
iOut = strtoul10(filePtr,&filePtr);
}
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
diff --git a/src/3rdparty/assimp/code/ASEParser.h b/src/3rdparty/assimp/code/ASEParser.h
index 667c7c5a0..db64f2a16 100644
--- a/src/3rdparty/assimp/code/ASEParser.h
+++ b/src/3rdparty/assimp/code/ASEParser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/mesh.h>
#include <assimp/anim.h>
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+
// for some helper routines like IsSpace()
#include "ParsingUtils.h"
#include "qnan.h"
@@ -222,7 +225,7 @@ struct BaseNode
mName = szTemp;
// Set mTargetPosition to qnan
- const float qnan = get_qnan();
+ const ai_real qnan = get_qnan();
mTargetPosition.x = qnan;
}
@@ -317,9 +320,9 @@ struct Light : public BaseNode
LightType mLightType;
aiColor3D mColor;
- float mIntensity;
- float mAngle; // in degrees
- float mFalloff;
+ ai_real mIntensity;
+ ai_real mAngle; // in degrees
+ ai_real mFalloff;
};
// ---------------------------------------------------------------------------
@@ -342,7 +345,7 @@ struct Camera : public BaseNode
{
}
- float mFOV, mNear, mFar;
+ ai_real mFOV, mNear, mFar;
CameraType mCameraType;
};
@@ -544,13 +547,13 @@ private:
//! (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);
+ void ParseLV4MeshFloatTriple(ai_real* 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);
+ void ParseLV4MeshFloatTriple(ai_real* apOut);
// -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file
@@ -568,7 +571,7 @@ private:
// -------------------------------------------------------------------
//! Parse a single float element
//! \param fOut Output float
- void ParseLV4MeshFloat(float& fOut);
+ void ParseLV4MeshFloat(ai_real& fOut);
// -------------------------------------------------------------------
//! Parse a single int element
@@ -661,4 +664,6 @@ public:
} // Namespace ASE
} // Namespace ASSIMP
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
#endif // !! include guard
diff --git a/src/3rdparty/assimp/code/AssbinExporter.cpp b/src/3rdparty/assimp/code/AssbinExporter.cpp
index 9240d3739..bcac2e08f 100644
--- a/src/3rdparty/assimp/code/AssbinExporter.cpp
+++ b/src/3rdparty/assimp/code/AssbinExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -141,6 +142,17 @@ inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
// -----------------------------------------------------------------------------------
// Serialize a color value
template <>
+inline size_t Write<aiColor3D>(IOStream * stream, const aiColor3D& v)
+{
+ size_t t = Write<float>(stream,v.r);
+ t += Write<float>(stream,v.g);
+ t += Write<float>(stream,v.b);
+ 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);
@@ -159,6 +171,7 @@ inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
t += Write<float>(stream,v.x);
t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z);
+ ai_assert(t == 16);
return 16;
}
@@ -324,10 +337,13 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
+ unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0);
+
Write<aiString>(&chunk,node->mName);
Write<aiMatrix4x4>(&chunk,node->mTransformation);
Write<unsigned int>(&chunk,node->mNumChildren);
Write<unsigned int>(&chunk,node->mNumMeshes);
+ Write<unsigned int>(&chunk,nb_metadata);
for (unsigned int i = 0; i < node->mNumMeshes;++i) {
Write<unsigned int>(&chunk,node->mMeshes[i]);
@@ -336,6 +352,44 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
for (unsigned int i = 0; i < node->mNumChildren;++i) {
WriteBinaryNode( &chunk, node->mChildren[i] );
}
+
+ for (unsigned int i = 0; i < nb_metadata; ++i) {
+ const aiString& key = node->mMetaData->mKeys[i];
+ aiMetadataType type = node->mMetaData->mValues[i].mType;
+ void* value = node->mMetaData->mValues[i].mData;
+
+ Write<aiString>(&chunk, key);
+ Write<uint16_t>(&chunk, type);
+
+ switch (type) {
+ case AI_BOOL:
+ Write<bool>(&chunk, *((bool*) value));
+ break;
+ case AI_INT32:
+ Write<int32_t>(&chunk, *((int32_t*) value));
+ break;
+ case AI_UINT64:
+ Write<uint64_t>(&chunk, *((uint64_t*) value));
+ break;
+ case AI_FLOAT:
+ Write<float>(&chunk, *((float*) value));
+ break;
+ case AI_DOUBLE:
+ Write<double>(&chunk, *((double*) value));
+ break;
+ case AI_AISTRING:
+ Write<aiString>(&chunk, *((aiString*) value));
+ break;
+ case AI_AIVECTOR3D:
+ Write<aiVector3D>(&chunk, *((aiVector3D*) value));
+ break;
+#ifdef SWIG
+ case FORCE_32BIT:
+#endif // SWIG
+ default:
+ break;
+ }
+ }
}
// -----------------------------------------------------------------------------------
@@ -597,9 +651,9 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
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);
+ Write<aiColor3D>(&chunk,l->mColorDiffuse);
+ Write<aiColor3D>(&chunk,l->mColorSpecular);
+ Write<aiColor3D>(&chunk,l->mColorAmbient);
if (l->mType == aiLightSource_SPOT) {
Write<float>(&chunk,l->mAngleInnerCone);
@@ -737,7 +791,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
AssbinChunkWriter uncompressedStream( NULL, 0 );
WriteBinaryScene( &uncompressedStream, pScene );
- uLongf uncompressedSize = uncompressedStream.Tell();
+ uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell());
uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
@@ -757,7 +811,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
}
};
-void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
AssbinExport exporter;
exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
diff --git a/src/3rdparty/assimp/code/AssbinExporter.h b/src/3rdparty/assimp/code/AssbinExporter.h
index 4a0219c04..55bb9fc82 100644
--- a/src/3rdparty/assimp/code/AssbinExporter.h
+++ b/src/3rdparty/assimp/code/AssbinExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/AssbinLoader.cpp b/src/3rdparty/assimp/code/AssbinLoader.cpp
index c4261c4cb..a7044c119 100644
--- a/src/3rdparty/assimp/code/AssbinLoader.cpp
+++ b/src/3rdparty/assimp/code/AssbinLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/mesh.h>
#include <assimp/anim.h>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
@@ -196,9 +198,9 @@ template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int
stream->Seek( sizeof(T) * n, aiOrigin_CUR );
}
-void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
-{
+void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) {
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -208,29 +210,72 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
(*node)->mTransformation = Read<aiMatrix4x4>(stream);
(*node)->mNumChildren = Read<unsigned int>(stream);
(*node)->mNumMeshes = Read<unsigned int>(stream);
+ unsigned int nb_metadata = Read<unsigned int>(stream);
- if ((*node)->mNumMeshes)
- {
+ if(parent) {
+ (*node)->mParent = parent;
+ }
+
+ 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)
- {
+ if ((*node)->mNumChildren) {
(*node)->mChildren = new aiNode*[(*node)->mNumChildren];
for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
- ReadBinaryNode( stream, &(*node)->mChildren[i] );
+ ReadBinaryNode( stream, &(*node)->mChildren[i], *node );
}
}
+ if ( nb_metadata > 0 ) {
+ (*node)->mMetaData = aiMetadata::Alloc(nb_metadata);
+ for (unsigned int i = 0; i < nb_metadata; ++i) {
+ (*node)->mMetaData->mKeys[i] = Read<aiString>(stream);
+ (*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
+ void* data( nullptr );
+
+ switch ((*node)->mMetaData->mValues[i].mType) {
+ case AI_BOOL:
+ data = new bool(Read<bool>(stream));
+ break;
+ case AI_INT32:
+ data = new int32_t(Read<int32_t>(stream));
+ break;
+ case AI_UINT64:
+ data = new uint64_t(Read<uint64_t>(stream));
+ break;
+ case AI_FLOAT:
+ data = new float(Read<float>(stream));
+ break;
+ case AI_DOUBLE:
+ data = new double(Read<double>(stream));
+ break;
+ case AI_AISTRING:
+ data = new aiString(Read<aiString>(stream));
+ break;
+ case AI_AIVECTOR3D:
+ data = new aiVector3D(Read<aiVector3D>(stream));
+ break;
+#ifndef SWIG
+ case FORCE_32BIT:
+#endif // SWIG
+ default:
+ break;
+ }
+
+ (*node)->mMetaData->mValues[i].mData = data;
+ }
+ }
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -255,6 +300,7 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -380,6 +426,7 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -397,6 +444,7 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -419,6 +467,7 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -468,6 +517,7 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -489,6 +539,7 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -513,6 +564,7 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -540,6 +592,7 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -556,6 +609,7 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
{
uint32_t chunkID = Read<uint32_t>(stream);
+ (void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
/*uint32_t size =*/ Read<uint32_t>(stream);
@@ -569,7 +623,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
// Read node graph
scene->mRootNode = new aiNode[1];
- ReadBinaryNode( stream, &scene->mRootNode );
+ ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL );
// Read all meshes
if (scene->mNumMeshes)
@@ -659,7 +713,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (compressed)
{
uLongf uncompressedSize = Read<uint32_t>(stream);
- uLongf compressedSize = stream->FileSize() - stream->Tell();
+ uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
unsigned char * compressedData = new unsigned char[ compressedSize ];
stream->Read( compressedData, 1, compressedSize );
diff --git a/src/3rdparty/assimp/code/AssbinLoader.h b/src/3rdparty/assimp/code/AssbinLoader.h
index e8c8dd0cb..2eb7a6488 100644
--- a/src/3rdparty/assimp/code/AssbinLoader.h
+++ b/src/3rdparty/assimp/code/AssbinLoader.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_ASSBINIMPORTER_H_INC
#include "BaseImporter.h"
-#include <assimp/types.h>
struct aiMesh;
struct aiNode;
@@ -71,7 +71,6 @@ class AssbinImporter : public BaseImporter
private:
bool shortened;
bool compressed;
-protected:
public:
virtual bool CanRead(
@@ -86,7 +85,7 @@ public:
IOSystem* pIOHandler
);
void ReadBinaryScene( IOStream * stream, aiScene* pScene );
- void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
+ void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );
void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
void ReadBinaryBone( IOStream * stream, aiBone* bone );
void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
diff --git a/src/3rdparty/assimp/code/Assimp.cpp b/src/3rdparty/assimp/code/Assimp.cpp
index 8507c8641..9269f905e 100644
--- a/src/3rdparty/assimp/code/Assimp.cpp
+++ b/src/3rdparty/assimp/code/Assimp.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -65,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------
using namespace Assimp;
-namespace Assimp
-{
+namespace Assimp {
// underlying structure for aiPropertyStore
typedef BatchLoader::PropertyMap PropertyMap;
@@ -109,12 +109,11 @@ static std::mutex gLogStreamMutex;
// ------------------------------------------------------------------------------------------------
// Custom LogStream implementation for the C-API
-class LogToCallbackRedirector : public LogStream
-{
+class LogToCallbackRedirector : public LogStream {
public:
explicit LogToCallbackRedirector(const aiLogStream& s)
- : stream (s) {
- ai_assert(NULL != s.callback);
+ : stream (s) {
+ ai_assert(NULL != s.callback);
}
~LogToCallbackRedirector() {
@@ -145,32 +144,27 @@ private:
};
// ------------------------------------------------------------------------------------------------
-void ReportSceneNotFoundError()
-{
+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");
- assert(false);
+ ai_assert(false);
}
// ------------------------------------------------------------------------------------------------
// Reads the given file and returns its content.
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
-{
+const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
return aiImportFileEx(pFile,pFlags,NULL);
}
// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS)
-{
+const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) {
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
}
// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
- aiFileIO* pFS,
- const aiPropertyStore* props)
-{
+const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
+ aiFileIO* pFS, const aiPropertyStore* props) {
ai_assert(NULL != pFile);
const aiScene* scene = NULL;
@@ -189,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
pimpl->mMatrixProperties = pp->matrices;
}
// setup a custom IO system if necessary
- if (pFS) {
+ if (pFS) {
imp->SetIOHandler( new CIOSystemWrapper (pFS) );
}
@@ -200,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
if( scene) {
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
priv->mOrigImporter = imp;
- }
- else {
+ } else {
// if failed, extract error code and destroy the import
gLastErrorString = imp->GetErrorString();
delete imp;
@@ -209,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
// return imported data. If the import failed the pointer is NULL anyways
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+
return scene;
}
@@ -546,11 +540,11 @@ ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szNam
// ------------------------------------------------------------------------------------------------
// Importer::SetPropertyFloat
-ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, float value)
+ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value)
{
ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
- SetGenericProperty<float>(pp->floats,szName,value);
+ SetGenericProperty<ai_real>(pp->floats,szName,value);
ASSIMP_END_EXCEPTION_REGION(void);
}
diff --git a/src/3rdparty/assimp/code/AssimpCExport.cpp b/src/3rdparty/assimp/code/AssimpCExport.cpp
index c5f26fc47..b8d3264a1 100644
--- a/src/3rdparty/assimp/code/AssimpCExport.cpp
+++ b/src/3rdparty/assimp/code/AssimpCExport.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -44,8 +45,9 @@ Assimp C export interface. See Exporter.cpp for some notes.
*/
#ifndef ASSIMP_BUILD_NO_EXPORT
+
#include "CInterfaceIOWrapper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "ScenePrivate.h"
#include <assimp/Exporter.hpp>
@@ -70,11 +72,11 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
}
aiExportFormatDesc *desc = new aiExportFormatDesc;
- desc->description = new char[ strlen( orig->description ) + 1 ];
+ 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 ];
+ 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 ];
+ desc->id = new char[ strlen( orig->id ) + 1 ]();
::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
return desc;
diff --git a/src/3rdparty/assimp/code/AssxmlExporter.cpp b/src/3rdparty/assimp/code/AssxmlExporter.cpp
index cf18837f5..90ed66701 100644
--- a/src/3rdparty/assimp/code/AssxmlExporter.cpp
+++ b/src/3rdparty/assimp/code/AssxmlExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ASSXML exporter main code
*/
#include <stdarg.h>
-#include "./../include/assimp/version.h"
+#include <assimp/version.h>
#include "ProcessHelper.h"
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
@@ -74,11 +75,10 @@ static int ioprintf( IOStream * io, const char *format, ... ) {
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 );
+ const unsigned int nSize = vsnprintf( sz, Size-1, format, va );
ai_assert( nSize < Size );
va_end( va );
@@ -300,7 +300,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
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;
+ // const unsigned int width = (unsigned int)std::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;
@@ -458,7 +458,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
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;
+ // const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1;
// mesh header
ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n",
@@ -631,7 +631,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
} // end of namespace AssxmlExport
-void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
IOStream * out = pIOSystem->Open( pFile, "wt" );
if (!out) return;
diff --git a/src/3rdparty/assimp/code/AssxmlExporter.h b/src/3rdparty/assimp/code/AssxmlExporter.h
index ba9921f70..9694f74a3 100644
--- a/src/3rdparty/assimp/code/AssxmlExporter.h
+++ b/src/3rdparty/assimp/code/AssxmlExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/B3DImporter.cpp b/src/3rdparty/assimp/code/B3DImporter.cpp
index 1b9ba1433..bc888fb66 100644
--- a/src/3rdparty/assimp/code/B3DImporter.cpp
+++ b/src/3rdparty/assimp/code/B3DImporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -56,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/anim.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
using namespace std;
@@ -81,6 +82,20 @@ static const aiImporterDesc desc = {
//#define DEBUG_B3D
+template<typename T>
+void DeleteAllBarePointers(std::vector<T>& x)
+{
+ for(auto p : x)
+ {
+ delete p;
+ }
+}
+
+B3DImporter::~B3DImporter()
+{
+ DeleteAllBarePointers(_animations);
+}
+
// ------------------------------------------------------------------------------------------------
bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
@@ -156,7 +171,8 @@ int B3DImporter::ReadByte(){
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadInt(){
if( _pos+4<=_buf.size() ){
- int n=*(int*)&_buf[_pos];
+ int n;
+ memcpy(&n, &_buf[_pos], 4);
_pos+=4;
return n;
}
@@ -167,7 +183,8 @@ int B3DImporter::ReadInt(){
// ------------------------------------------------------------------------------------------------
float B3DImporter::ReadFloat(){
if( _pos+4<=_buf.size() ){
- float n=*(float*)&_buf[_pos];
+ float n;
+ memcpy(&n, &_buf[_pos], 4);
_pos+=4;
return n;
}
@@ -331,7 +348,7 @@ void B3DImporter::ReadVRTS(){
int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
int n_verts=ChunkSize()/sz;
- int v0=_vertices.size();
+ int v0=static_cast<int>(_vertices.size());
_vertices.resize( v0+n_verts );
for( int i=0;i<n_verts;++i ){
@@ -404,7 +421,7 @@ void B3DImporter::ReadTRIS( int v0 ){
void B3DImporter::ReadMESH(){
/*int matid=*/ReadInt();
- int v0=_vertices.size();
+ int v0= static_cast<int>(_vertices.size());
while( ChunkSize() ){
string t=ReadChunk();
@@ -462,17 +479,17 @@ void B3DImporter::ReadKEYS( aiNodeAnim *nodeAnim ){
}
if( flags & 1 ){
- nodeAnim->mNumPositionKeys=trans.size();
+ nodeAnim->mNumPositionKeys=static_cast<unsigned int>(trans.size());
nodeAnim->mPositionKeys=to_array( trans );
}
if( flags & 2 ){
- nodeAnim->mNumScalingKeys=scale.size();
+ nodeAnim->mNumScalingKeys=static_cast<unsigned int>(scale.size());
nodeAnim->mScalingKeys=to_array( scale );
}
if( flags & 4 ){
- nodeAnim->mNumRotationKeys=rot.size();
+ nodeAnim->mNumRotationKeys=static_cast<unsigned int>(rot.size());
nodeAnim->mRotationKeys=to_array( rot );
}
}
@@ -506,7 +523,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
aiMatrix4x4 tform=trans * rot * scale;
- int nodeid=_nodes.size();
+ int nodeid=static_cast<int>(_nodes.size());
aiNode *node=new aiNode( name );
_nodes.push_back( node );
@@ -521,9 +538,9 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
while( ChunkSize() ){
string t=ReadChunk();
if( t=="MESH" ){
- int n=_meshes.size();
+ unsigned int n= static_cast<unsigned int>(_meshes.size());
ReadMESH();
- for( int i=n;i<(int)_meshes.size();++i ){
+ for( unsigned int i=n;i<static_cast<unsigned int>(_meshes.size());++i ){
meshes.push_back( i );
}
}else if( t=="BONE" ){
@@ -544,10 +561,10 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
ExitChunk();
}
- node->mNumMeshes=meshes.size();
+ node->mNumMeshes= static_cast<unsigned int>(meshes.size());
node->mMeshes=to_array( meshes );
- node->mNumChildren=children.size();
+ node->mNumChildren=static_cast<unsigned int>(children.size());
node->mChildren=to_array( children );
return node;
@@ -557,13 +574,19 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
void B3DImporter::ReadBB3D( aiScene *scene ){
_textures.clear();
+
_materials.clear();
_vertices.clear();
+
_meshes.clear();
+ DeleteAllBarePointers(_nodes);
_nodes.clear();
+
_nodeAnims.clear();
+
+ DeleteAllBarePointers(_animations);
_animations.clear();
string t=ReadChunk();
@@ -645,7 +668,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
aiNode *bnode=_nodes[i];
bone->mName=bnode->mName;
- bone->mNumWeights=weights.size();
+ bone->mNumWeights= static_cast<unsigned int>(weights.size());
bone->mWeights=to_array( weights );
aiMatrix4x4 mat=bnode->mTransformation;
@@ -655,7 +678,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
}
bone->mOffsetMatrix=mat.Inverse();
}
- mesh->mNumBones=bones.size();
+ mesh->mNumBones= static_cast<unsigned int>(bones.size());
mesh->mBones=to_array( bones );
}
}
@@ -667,21 +690,21 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
if( !_materials.size() ){
_materials.push_back( new aiMaterial );
}
- scene->mNumMaterials=_materials.size();
+ scene->mNumMaterials= static_cast<unsigned int>(_materials.size());
scene->mMaterials=to_array( _materials );
//meshes
- scene->mNumMeshes=_meshes.size();
+ scene->mNumMeshes= static_cast<unsigned int>(_meshes.size());
scene->mMeshes=to_array( _meshes );
//animations
if( _animations.size()==1 && _nodeAnims.size() ){
aiAnimation *anim=_animations.back();
- anim->mNumChannels=_nodeAnims.size();
+ anim->mNumChannels=static_cast<unsigned int>(_nodeAnims.size());
anim->mChannels=to_array( _nodeAnims );
- scene->mNumAnimations=_animations.size();
+ scene->mNumAnimations=static_cast<unsigned int>(_animations.size());
scene->mAnimations=to_array( _animations );
}
diff --git a/src/3rdparty/assimp/code/B3DImporter.h b/src/3rdparty/assimp/code/B3DImporter.h
index 92ddc0272..94644edd4 100644
--- a/src/3rdparty/assimp/code/B3DImporter.h
+++ b/src/3rdparty/assimp/code/B3DImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/material.h>
#include "BaseImporter.h"
-#include <string>
#include <vector>
struct aiNodeAnim;
@@ -59,6 +59,8 @@ namespace Assimp{
class B3DImporter : public BaseImporter{
public:
+ B3DImporter() = default;
+ virtual ~B3DImporter();
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
diff --git a/src/3rdparty/assimp/code/BVHLoader.cpp b/src/3rdparty/assimp/code/BVHLoader.cpp
index ca6c5d36c..c20cbec4e 100644
--- a/src/3rdparty/assimp/code/BVHLoader.cpp
+++ b/src/3rdparty/assimp/code/BVHLoader.cpp
@@ -4,7 +4,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -51,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TinyFormatter.h"
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
using namespace Assimp;
using namespace Assimp::Formatter;
@@ -237,7 +239,7 @@ aiNode* BVHLoader::ReadNode()
// add the child nodes if there are any
if( childNodes.size() > 0)
{
- node->mNumChildren = childNodes.size();
+ node->mNumChildren = static_cast<unsigned int>(childNodes.size());
node->mChildren = new aiNode*[node->mNumChildren];
std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
}
@@ -443,7 +445,7 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
anim->mDuration = double( mAnimNumFrames - 1);
// now generate the tracks for all nodes
- anim->mNumChannels = mNodes.size();
+ anim->mNumChannels = static_cast<unsigned int>(mNodes.size());
anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
// FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
diff --git a/src/3rdparty/assimp/code/BVHLoader.h b/src/3rdparty/assimp/code/BVHLoader.h
index 8a163d1e7..6a89e1aaf 100644
--- a/src/3rdparty/assimp/code/BVHLoader.h
+++ b/src/3rdparty/assimp/code/BVHLoader.h
@@ -4,7 +4,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/BaseImporter.cpp b/src/3rdparty/assimp/code/BaseImporter.cpp
index aa615e592..b9b9eeb71 100644
--- a/src/3rdparty/assimp/code/BaseImporter.cpp
+++ b/src/3rdparty/assimp/code/BaseImporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -50,13 +51,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
+#include <assimp/importerdesc.h>
#include <ios>
#include <list>
#include <memory>
#include <sstream>
#include <cctype>
-
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
@@ -88,12 +89,12 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
FileSystemFilter filter(pFile,pIOHandler);
// create a scene object to hold the data
- ScopeGuard<aiScene> sc(new aiScene());
+ std::unique_ptr<aiScene> sc(new aiScene());
// dispatch importing
try
{
- InternReadFile( pFile, sc, &filter);
+ InternReadFile( pFile, sc.get(), &filter);
} catch( const std::exception& err ) {
// extract error description
@@ -103,8 +104,7 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
}
// return what we gathered from the import.
- sc.dismiss();
- return sc;
+ return sc.release();
}
// ------------------------------------------------------------------------------------------------
@@ -137,14 +137,17 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
}
// ------------------------------------------------------------------------------------------------
-/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler,
+/*static*/ bool BaseImporter::SearchFileHeaderForToken( IOSystem* pIOHandler,
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);
+ ai_assert( NULL != tokens );
+ ai_assert( 0 != numTokens );
+ ai_assert( 0 != searchBytes);
+
if (!pIOHandler)
return false;
@@ -179,8 +182,6 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
for (unsigned int i = 0; i < numTokens;++i) {
ai_assert(NULL != tokens[i]);
-
-
const char* r = strstr(buffer,tokens[i]);
if( !r ) {
continue;
@@ -301,24 +302,13 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
return false;
}
-#include "../contrib/ConvertUTF/ConvertUTF.h"
-
-// ------------------------------------------------------------------------------------------------
-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");
- }
-}
+#include "../contrib/utf8cpp/source/utf8.h"
// ------------------------------------------------------------------------------------------------
// Convert to UTF8 data
void BaseImporter::ConvertToUTF8(std::vector<char>& data)
{
- ConversionResult result;
+ //ConversionResult result;
if(data.size() < 8) {
throw DeadlyImportError("File is too small");
}
@@ -331,7 +321,8 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
data.resize(data.size()-3);
return;
}
-
+
+
// UTF 32 BE with BOM
if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
@@ -345,21 +336,10 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
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);
+ int *ptr = (int*)&data[ 0 ];
+ int *end = ptr + ( data.size() / sizeof(int) ) +1;
+ utf8::utf32to8( ptr, end, back_inserter(output));
return;
}
@@ -376,21 +356,8 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
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);
+ std::vector<unsigned char> output;
+ utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
return;
}
}
@@ -461,41 +428,53 @@ void BaseImporter::TextFileToBuffer(IOStream* stream,
}
// ------------------------------------------------------------------------------------------------
-namespace Assimp
-{
+namespace Assimp {
// Represents an import request
- struct LoadRequest
- {
+ 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)
+ : 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) {
+ bool operator== ( const std::string& f ) const {
return file == f;
}
+
+ const std::string file;
+ unsigned int flags;
+ unsigned int refCnt;
+ aiScene *scene;
+ bool loaded;
+ BatchLoader::PropertyMap map;
+ unsigned int id;
};
}
// ------------------------------------------------------------------------------------------------
// BatchLoader::pimpl data structure
-struct Assimp::BatchData
-{
- BatchData()
- : pIOSystem()
- , pImporter()
- , next_id(0xffff)
- {}
+struct Assimp::BatchData {
+ BatchData( IOSystem* pIO, bool validate )
+ : pIOSystem( pIO )
+ , pImporter( nullptr )
+ , next_id(0xffff)
+ , validate( validate ) {
+ ai_assert( NULL != pIO );
+
+ pImporter = new Importer();
+ pImporter->SetIOHandler( pIO );
+ }
+
+ ~BatchData() {
+ pImporter->SetIOHandler( NULL ); /* get pointer back into our possession */
+ delete pImporter;
+ }
// IO system to be used for all imports
IOSystem* pIOSystem;
@@ -511,53 +490,59 @@ struct Assimp::BatchData
// Id for next item
unsigned int next_id;
+
+ // Validation enabled state
+ bool validate;
};
+typedef std::list<LoadRequest>::iterator LoadReqIt;
+
// ------------------------------------------------------------------------------------------------
-BatchLoader::BatchLoader(IOSystem* pIO)
+BatchLoader::BatchLoader(IOSystem* pIO, bool validate )
{
ai_assert(NULL != pIO);
- data = new BatchData();
- data->pIOSystem = pIO;
-
- data->pImporter = new Importer();
- data->pImporter->SetIOHandler(data->pIOSystem);
+ m_data = new BatchData( pIO, validate );
}
// ------------------------------------------------------------------------------------------------
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 all scenes what have not been polled by the user
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
delete (*it).scene;
}
- data->pImporter->SetIOHandler(NULL); /* get pointer back into our possession */
- delete data->pImporter;
- delete data;
+ delete m_data;
+}
+
+// ------------------------------------------------------------------------------------------------
+void BatchLoader::setValidation( bool enabled ) {
+ m_data->validate = enabled;
}
+// ------------------------------------------------------------------------------------------------
+bool BatchLoader::getValidation() const {
+ return m_data->validate;
+}
// ------------------------------------------------------------------------------------------------
-unsigned int BatchLoader::AddLoadRequest (const std::string& file,
+unsigned int 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) {
-
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
// Call IOSystem's path comparison function here
- if (data->pIOSystem->ComparePaths((*it).file,file)) {
-
+ if ( m_data->pIOSystem->ComparePaths((*it).file,file)) {
if (map) {
- if (!((*it).map == *map))
+ if ( !( ( *it ).map == *map ) ) {
continue;
+ }
}
- else if (!(*it).map.empty())
+ else if ( !( *it ).map.empty() ) {
continue;
+ }
(*it).refCnt++;
return (*it).id;
@@ -565,20 +550,18 @@ unsigned int BatchLoader::AddLoadRequest (const std::string& file,
}
// 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++;
+ m_data->requests.push_back(LoadRequest(file,steps,map, m_data->next_id));
+ return m_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) {
-
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
if ((*it).id == which && (*it).loaded) {
-
aiScene* sc = (*it).scene;
if (!(--(*it).refCnt)) {
- data->requests.erase(it);
+ m_data->requests.erase(it);
}
return sc;
}
@@ -590,14 +573,15 @@ aiScene* BatchLoader::GetImport (unsigned int which)
void BatchLoader::LoadAll()
{
// no threaded implementation for the moment
- for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+ for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
// force validation in debug builds
unsigned int pp = (*it).flags;
-#ifdef ASSIMP_BUILD_DEBUG
- pp |= aiProcess_ValidateDataStructure;
-#endif
+ if ( m_data->validate ) {
+ pp |= aiProcess_ValidateDataStructure;
+ }
+
// setup config properties if necessary
- ImporterPimpl* pimpl = data->pImporter->Pimpl();
+ ImporterPimpl* pimpl = m_data->pImporter->Pimpl();
pimpl->mFloatProperties = (*it).map.floats;
pimpl->mIntProperties = (*it).map.ints;
pimpl->mStringProperties = (*it).map.strings;
@@ -608,8 +592,8 @@ void BatchLoader::LoadAll()
DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
DefaultLogger::get()->info("File: " + (*it).file);
}
- data->pImporter->ReadFile((*it).file,pp);
- (*it).scene = data->pImporter->GetOrphanedScene();
+ m_data->pImporter->ReadFile((*it).file,pp);
+ (*it).scene = m_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 5c9ddfa5e..b424d2f83 100644
--- a/src/3rdparty/assimp/code/BaseImporter.h
+++ b/src/3rdparty/assimp/code/BaseImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,14 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Exceptional.h"
-#include <string>
-#include <map>
#include <vector>
#include <set>
#include <assimp/types.h>
#include <assimp/ProgressHandler.hpp>
struct aiScene;
+struct aiImporterDesc;
namespace Assimp {
@@ -61,47 +61,10 @@ 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]))
-// ---------------------------------------------------------------------------
-template <typename T>
-struct ScopeGuard
-{
- 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:
- // 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
@@ -194,14 +157,11 @@ public:
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
@@ -317,7 +277,7 @@ public: // static utilities
* @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
+ * @note For convenience, the check is also performed for the
* byte-swapped variant of all tokens (big endian). Only for
* tokens of size 2,4.
*/
@@ -347,7 +307,12 @@ public: // static utilities
static void ConvertUTF8toISO8859_1(
std::string& data);
- enum TextFileMode { ALLOW_EMPTY, FORBID_EMPTY };
+ // -------------------------------------------------------------------
+ /// @brief Enum to define, if empty files are ok or not.
+ enum TextFileMode {
+ ALLOW_EMPTY,
+ FORBID_EMPTY
+ };
// -------------------------------------------------------------------
/** Utility for text file loaders which copies the contents of the
@@ -382,14 +347,10 @@ public: // static utilities
}
}
-
-
protected:
-
- /** Error description in case there was one. */
+ /// Error description in case there was one.
std::string m_ErrorText;
-
- /** Currently set progress handler */
+ /// Currently set progress handler.
ProgressHandler* m_progress;
};
diff --git a/src/3rdparty/assimp/code/BaseProcess.cpp b/src/3rdparty/assimp/code/BaseProcess.cpp
index 580f89cdb..9e175d315 100644
--- a/src/3rdparty/assimp/code/BaseProcess.cpp
+++ b/src/3rdparty/assimp/code/BaseProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/BaseProcess.h b/src/3rdparty/assimp/code/BaseProcess.h
index 148f07284..aa873f717 100644
--- a/src/3rdparty/assimp/code/BaseProcess.h
+++ b/src/3rdparty/assimp/code/BaseProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,8 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_BASEPROCESS_H
#include <map>
-
-#include <assimp/types.h>
#include "GenericProperty.h"
struct aiScene;
diff --git a/src/3rdparty/assimp/code/Bitmap.cpp b/src/3rdparty/assimp/code/Bitmap.cpp
index ae6d62083..76994513e 100644
--- a/src/3rdparty/assimp/code/Bitmap.cpp
+++ b/src/3rdparty/assimp/code/Bitmap.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -101,7 +102,7 @@ namespace Assimp {
offset += Copy(&data[offset], header.size);
offset += Copy(&data[offset], header.reserved1);
offset += Copy(&data[offset], header.reserved2);
- offset += Copy(&data[offset], header.offset);
+ Copy(&data[offset], header.offset);
file->Write(data, Header::header_size, 1);
}
@@ -121,7 +122,7 @@ namespace Assimp {
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);
+ Copy(&data[offset], dib.nb_important_colors);
file->Write(data, DIB::dib_size, 1);
}
diff --git a/src/3rdparty/assimp/code/Bitmap.h b/src/3rdparty/assimp/code/Bitmap.h
index ad29783ce..96c994dbe 100644
--- a/src/3rdparty/assimp/code/Bitmap.h
+++ b/src/3rdparty/assimp/code/Bitmap.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -50,93 +51,71 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#include <cstddef>
+
struct aiTexture;
namespace Assimp {
class IOStream;
-class Bitmap {
-
- protected:
-
- struct Header {
-
- uint16_t type;
-
- uint32_t size;
-
- uint16_t reserved1;
-
- uint16_t reserved2;
-
- uint32_t offset;
-
- // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
- // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
- static const std::size_t header_size =
- sizeof(uint16_t) + // type
- sizeof(uint32_t) + // size
- sizeof(uint16_t) + // reserved1
- sizeof(uint16_t) + // reserved2
- sizeof(uint32_t); // offset
-
- };
-
- struct DIB {
-
- uint32_t size;
-
- int32_t width;
-
- int32_t height;
-
- uint16_t planes;
-
- uint16_t bits_per_pixel;
-
- uint32_t compression;
-
- uint32_t image_size;
-
- int32_t x_resolution;
-
- int32_t y_resolution;
-
- uint32_t nb_colors;
-
- uint32_t nb_important_colors;
-
- // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
- // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
- static const std::size_t dib_size =
- sizeof(uint32_t) + // size
- sizeof(int32_t) + // width
- sizeof(int32_t) + // height
- sizeof(uint16_t) + // planes
- sizeof(uint16_t) + // bits_per_pixel
- sizeof(uint32_t) + // compression
- sizeof(uint32_t) + // image_size
- sizeof(int32_t) + // x_resolution
- sizeof(int32_t) + // y_resolution
- sizeof(uint32_t) + // nb_colors
- sizeof(uint32_t); // nb_important_colors
-
- };
-
- static const std::size_t mBytesPerPixel = 4;
-
- public:
-
- static void Save(aiTexture* texture, IOStream* file);
-
- protected:
-
- static void WriteHeader(Header& header, IOStream* file);
-
- static void WriteDIB(DIB& dib, IOStream* file);
-
- static void WriteData(aiTexture* texture, IOStream* file);
+class Bitmap {
+protected:
+
+ struct Header {
+ uint16_t type;
+ uint32_t size;
+ uint16_t reserved1;
+ uint16_t reserved2;
+ uint32_t offset;
+
+ // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
+ // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+ static const std::size_t header_size =
+ sizeof(uint16_t) + // type
+ sizeof(uint32_t) + // size
+ sizeof(uint16_t) + // reserved1
+ sizeof(uint16_t) + // reserved2
+ sizeof(uint32_t); // offset
+ };
+
+ struct DIB {
+ uint32_t size;
+ int32_t width;
+ int32_t height;
+ uint16_t planes;
+ uint16_t bits_per_pixel;
+ uint32_t compression;
+ uint32_t image_size;
+ int32_t x_resolution;
+ int32_t y_resolution;
+ uint32_t nb_colors;
+ uint32_t nb_important_colors;
+
+ // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
+ // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+ static const std::size_t dib_size =
+ sizeof(uint32_t) + // size
+ sizeof(int32_t) + // width
+ sizeof(int32_t) + // height
+ sizeof(uint16_t) + // planes
+ sizeof(uint16_t) + // bits_per_pixel
+ sizeof(uint32_t) + // compression
+ sizeof(uint32_t) + // image_size
+ sizeof(int32_t) + // x_resolution
+ sizeof(int32_t) + // y_resolution
+ sizeof(uint32_t) + // nb_colors
+ sizeof(uint32_t); // nb_important_colors
+ };
+
+ static const std::size_t mBytesPerPixel = 4;
+
+public:
+ static void Save(aiTexture* texture, IOStream* file);
+
+protected:
+ static void WriteHeader(Header& header, IOStream* file);
+ static void WriteDIB(DIB& dib, IOStream* file);
+ static void WriteData(aiTexture* texture, IOStream* file);
};
}
diff --git a/src/3rdparty/assimp/code/BlenderBMesh.cpp b/src/3rdparty/assimp/code/BlenderBMesh.cpp
index bf27a9396..8a13819a6 100644
--- a/src/3rdparty/assimp/code/BlenderBMesh.cpp
+++ b/src/3rdparty/assimp/code/BlenderBMesh.cpp
@@ -52,7 +52,11 @@ 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 char* LogFunctions< BlenderBMeshConverter >::Prefix()
+ {
+ static auto prefix = "BLEND_BMESH: ";
+ return prefix;
+ }
}
using namespace Assimp;
@@ -180,7 +184,7 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
// TODO - Work out how materials work
face.mat_nr = 0;
triMesh->mface.push_back( face );
- triMesh->totface = triMesh->mface.size( );
+ triMesh->totface = static_cast<int>(triMesh->mface.size( ));
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/BlenderDNA.cpp b/src/3rdparty/assimp/code/BlenderDNA.cpp
index 18ec9f2b4..23ece913f 100644
--- a/src/3rdparty/assimp/code/BlenderDNA.cpp
+++ b/src/3rdparty/assimp/code/BlenderDNA.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,17 +49,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
#include "StreamReader.h"
#include "fast_atof.h"
+#include "TinyFormatter.h"
using namespace Assimp;
using namespace Assimp::Blender;
using namespace Assimp::Formatter;
-bool match4(StreamReaderAny& stream, const char* string) {
+static bool match4(StreamReaderAny& stream, const char* string) {
+ ai_assert( nullptr != string );
char tmp[] = {
- (stream).GetI1(),
- (stream).GetI1(),
- (stream).GetI1(),
- (stream).GetI1()
+ (const char)(stream).GetI1(),
+ (const char)(stream).GetI1(),
+ (const char)(stream).GetI1(),
+ (const char)(stream).GetI1()
};
return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
}
@@ -69,7 +72,7 @@ struct Type {
};
// ------------------------------------------------------------------------------------------------
-void DNAParser :: Parse ()
+void DNAParser::Parse ()
{
StreamReaderAny& stream = *db.reader.get();
DNA& dna = db.dna;
@@ -345,10 +348,10 @@ void SectionParser :: Next()
stream.SetCurrentPos(current.start + current.size);
const char tmp[] = {
- stream.GetI1(),
- stream.GetI1(),
- stream.GetI1(),
- stream.GetI1()
+ (const char)stream.GetI1(),
+ (const char)stream.GetI1(),
+ (const char)stream.GetI1(),
+ (const char)stream.GetI1()
};
current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
diff --git a/src/3rdparty/assimp/code/BlenderDNA.h b/src/3rdparty/assimp/code/BlenderDNA.h
index 801d68fce..bac8d78bc 100644
--- a/src/3rdparty/assimp/code/BlenderDNA.h
+++ b/src/3rdparty/assimp/code/BlenderDNA.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,12 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_BLEND_DNA_H
#include "BaseImporter.h"
-#include "TinyFormatter.h"
#include "StreamReader.h"
#include <assimp/DefaultLogger.hpp>
#include <stdint.h>
#include <memory>
-
+#include <map>
// enable verbose log output. really verbose, so be careful.
#ifdef ASSIMP_BUILD_DEBUG
@@ -61,15 +61,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// #define ASSIMP_BUILD_BLENDER_NO_STATS
namespace Assimp {
- template <bool,bool> class StreamReader;
- typedef StreamReader<true,true> StreamReaderAny;
- namespace Blender {
- class FileDatabase;
- struct FileBlockHead;
+template <bool,bool> class StreamReader;
+typedef StreamReader<true,true> StreamReaderAny;
+
+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
@@ -78,20 +80,27 @@ namespace Assimp {
* the loader itself, it will still be caught by Assimp due to its
* ancestry. */
// -------------------------------------------------------------------------------
-struct Error : DeadlyImportError
-{
+struct Error : DeadlyImportError {
Error (const std::string& s)
- : DeadlyImportError(s)
- {}
+ : DeadlyImportError(s) {
+ // empty
+ }
};
// -------------------------------------------------------------------------------
/** 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
-{
- virtual ~ElemBase() {}
+struct ElemBase {
+ ElemBase()
+ : dna_type(nullptr)
+ {
+ // empty
+ }
+
+ virtual ~ElemBase() {
+ // empty
+ }
/** Type name of the element. The type
* string points is the `c_str` of the `name` attribute of the
@@ -103,25 +112,28 @@ struct ElemBase
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
* they used to point to.*/
// -------------------------------------------------------------------------------
-struct Pointer
-{
- Pointer() : val() {}
+struct Pointer {
+ Pointer()
+ : val() {
+ // empty
+ }
uint64_t val;
};
// -------------------------------------------------------------------------------
/** Represents a generic offset within a BLEND file */
// -------------------------------------------------------------------------------
-struct FileOffset
-{
- FileOffset() : val() {}
+struct FileOffset {
+ FileOffset()
+ : val() {
+ // empty
+ }
uint64_t val;
};
@@ -132,8 +144,7 @@ struct FileOffset
* functions of shared_ptr */
// -------------------------------------------------------------------------------
template <typename T>
-class vector : public std::vector<T>
-{
+class vector : public std::vector<T> {
public:
using std::vector<T>::resize;
using std::vector<T>::empty;
@@ -150,8 +161,7 @@ public:
// -------------------------------------------------------------------------------
/** Mixed flags for use in #Field */
// -------------------------------------------------------------------------------
-enum FieldFlags
-{
+enum FieldFlags {
FieldFlag_Pointer = 0x1,
FieldFlag_Array = 0x2
};
@@ -159,8 +169,7 @@ enum FieldFlags
// -------------------------------------------------------------------------------
/** Represents a single member of a data structure in a BLEND file */
// -------------------------------------------------------------------------------
-struct Field
-{
+struct Field {
std::string name;
std::string type;
@@ -180,8 +189,7 @@ 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 */
@@ -202,15 +210,14 @@ 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;
public:
-
Structure()
- : cache_idx(static_cast<size_t>(-1) )
- {}
+ : cache_idx(static_cast<size_t>(-1) ){
+ // empty
+ }
public:
@@ -252,10 +259,7 @@ public:
* 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;
-
-
+ template <typename T> void Convert (T& dest, const FileDatabase& db) const;
// --------------------------------------------------------
// generic converter
@@ -709,8 +713,6 @@ class FileDatabase
template <template <typename> class TOUT> friend class ObjectCache;
public:
-
-
FileDatabase()
: _cacheArrays(*this)
, _cache(*this)
@@ -718,7 +720,6 @@ public:
{}
public:
-
// publicly accessible fields
bool i64bit;
bool little;
diff --git a/src/3rdparty/assimp/code/BlenderDNA.inl b/src/3rdparty/assimp/code/BlenderDNA.inl
index 0b3f2fd02..c65ea81bc 100644
--- a/src/3rdparty/assimp/code/BlenderDNA.inl
+++ b/src/3rdparty/assimp/code/BlenderDNA.inl
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,9 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_BLEND_DNA_INL
#include <memory>
+#include "TinyFormatter.h"
namespace Assimp {
- namespace Blender {
+namespace Blender {
//--------------------------------------------------------------------------------
const Field& Structure :: operator [] (const std::string& ss) const
@@ -532,7 +534,7 @@ template <typename T> struct signless;
template <> struct signless<char> {typedef unsigned char type;};
template <> struct signless<short> {typedef unsigned short type;};
template <> struct signless<int> {typedef unsigned int type;};
-
+template <> struct signless<unsigned char> { typedef unsigned char type; };
template <typename T>
struct static_cast_silent {
template <typename V>
@@ -583,11 +585,14 @@ template <> inline void Structure :: Convert<int> (int& dest,const FileDataba
}
// ------------------------------------------------------------------------------------------------
-template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const
+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);
+ float f = db.reader->GetF4();
+ if ( f > 1.0f )
+ f = 1.0f;
+ dest = static_cast<short>( f * 32767.f);
//db.reader->IncPtr(-4);
return;
}
@@ -615,6 +620,22 @@ template <> inline void Structure :: Convert<char> (char& dest,const FileDatab
}
// ------------------------------------------------------------------------------------------------
+template <> inline void Structure::Convert<unsigned char>(unsigned 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<unsigned char>(db.reader->GetF4() * 255.f);
+ return;
+ }
+ else if (name == "double") {
+ dest = static_cast<unsigned 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)
diff --git a/src/3rdparty/assimp/code/BlenderIntermediate.h b/src/3rdparty/assimp/code/BlenderIntermediate.h
index e9aebf4bb..c6f9cba1e 100644
--- a/src/3rdparty/assimp/code/BlenderIntermediate.h
+++ b/src/3rdparty/assimp/code/BlenderIntermediate.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,9 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderLoader.h"
#include "BlenderDNA.h"
#include "BlenderScene.h"
-#include "BlenderSceneGen.h"
#include <deque>
-#include "./../include/assimp/material.h"
+#include <assimp/material.h>
struct aiTexture;
@@ -110,7 +110,7 @@ namespace Blender {
void operator= (const TempArray&) {
}
- TempArray(const TempArray& arr) {
+ TempArray(const TempArray& /*arr*/) {
}
private:
@@ -123,7 +123,7 @@ namespace Blender {
struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const {
- return strcmp(left->id.name, right->id.name) == -1;
+ return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
}
};
@@ -144,7 +144,7 @@ namespace Blender {
struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const {
- return strcmp(left->id.name, right->id.name) == -1;
+ return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
}
};
diff --git a/src/3rdparty/assimp/code/BlenderLoader.cpp b/src/3rdparty/assimp/code/BlenderLoader.cpp
index 5bc358716..824954f56 100644
--- a/src/3rdparty/assimp/code/BlenderLoader.cpp
+++ b/src/3rdparty/assimp/code/BlenderLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -54,10 +55,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderBMesh.h"
#include "StringUtils.h"
#include <assimp/scene.h>
-#include "StringComparison.h"
+#include <assimp/importerdesc.h>
+#include "StringComparison.h"
#include "StreamReader.h"
#include "MemoryIOWrapper.h"
+
#include <cctype>
@@ -71,7 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
namespace Assimp {
- template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: ";
+ template<> const char* LogFunctions<BlenderImporter>::Prefix()
+ {
+ static auto prefix = "BLEND: ";
+ return prefix;
+ }
}
using namespace Assimp;
@@ -95,8 +102,9 @@ static const aiImporterDesc blenderDesc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
BlenderImporter::BlenderImporter()
-: modifier_cache(new BlenderModifierShowcase())
-{}
+: modifier_cache(new BlenderModifierShowcase()) {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
@@ -105,6 +113,9 @@ BlenderImporter::~BlenderImporter()
delete modifier_cache;
}
+static const char* Tokens[] = { "BLENDER" };
+static const char* TokensForSearch[] = { "blender" };
+
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
@@ -116,8 +127,7 @@ bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, b
else if ((!extension.length() || checkSig) && pIOHandler) {
// note: this won't catch compressed files
- const char* tokens[] = {"BLENDER"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ return SearchFileHeaderForToken(pIOHandler,pFile, TokensForSearch,1);
}
return false;
}
@@ -143,8 +153,7 @@ void BlenderImporter::SetupProperties(const Importer* /*pImp*/)
// nothing to be done for the moment
}
-struct free_it
-{
+struct free_it {
free_it(void* free) : free(free) {}
~free_it() {
::free(this->free);
@@ -163,6 +172,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
free_it free_it_really(dest);
#endif
+
FileDatabase file;
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
if (!stream) {
@@ -171,7 +181,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
char magic[8] = {0};
stream->Read(magic,7,1);
- if (strcmp(magic,"BLENDER")) {
+ if (strcmp(magic, Tokens[0] )) {
// 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.
@@ -346,8 +356,9 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
if (cur->object) {
if(!cur->object->parent) {
no_parents.push_back(cur->object.get());
+ } else {
+ conv.objects.insert( cur->object.get() );
}
- else conv.objects.insert(cur->object.get());
}
}
for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
@@ -404,7 +415,7 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
}
// acknowledge that the scene might come out incomplete
- // by Assimps definition of `complete`: blender scenes
+ // by Assimp's definition of `complete`: blender scenes
// can consist of thousands of cameras or lights with
// not a single mesh between them.
if (!out->mNumMeshes) {
@@ -421,7 +432,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
// 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());
+ name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture());
aiTexture* tex = conv_data.textures->back();
@@ -430,8 +441,9 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
// 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;
+ 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] );
@@ -448,8 +460,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
tex->pcData = reinterpret_cast<aiTexel*>(ch);
LogInfo("Reading embedded texture, original file was "+std::string(img->name));
- }
- else {
+ } else {
name = aiString( img->name );
}
@@ -790,7 +801,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
)
{
- // TODO: Resolve various problems with BMesh triangluation before re-enabling.
+ // TODO: Resolve various problems with BMesh triangulation before re-enabling.
// See issues #400, #373, #318 #315 and #132.
#if defined(TODO_FIX_BMESH_CONVERSION)
BlenderBMeshConverter BMeshConverter( mesh );
@@ -852,7 +863,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
//out->mNumVertices = 0
out->mFaces = new aiFace[it.second]();
- // all submeshes created from this mesh are named equally. this allows
+ // all sub-meshes 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'
@@ -1118,12 +1129,13 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
const aiFace& f = out->mFaces[out->mNumFaces++];
aiColor4D* vo = &out->mColors[0][out->mNumVertices];
+ const ai_real scaleZeroToOne = 1.f/255.f;
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;
+ vo->r = ai_real(col.r) * scaleZeroToOne;
+ vo->g = ai_real(col.g) * scaleZeroToOne;
+ vo->b = ai_real(col.b) * scaleZeroToOne;
+ vo->a = ai_real(col.a) * scaleZeroToOne;
}
}
@@ -1136,24 +1148,24 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
// ------------------------------------------------------------------------------------------------
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* cam, ConversionData& /*conv_data*/)
{
- ScopeGuard<aiCamera> out(new aiCamera());
+ std::unique_ptr<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->mHorizontalFOV = std::atan2(cam->sensor_x, 2.f * cam->lens);
}
out->mClipPlaneNear = cam->clipsta;
out->mClipPlaneFar = cam->clipend;
- return out.dismiss();
+ return out.release();
}
// ------------------------------------------------------------------------------------------------
aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
{
- ScopeGuard<aiLight> out(new aiLight());
+ std::unique_ptr<aiLight> out(new aiLight());
out->mName = obj->id.name+2;
switch (lamp->type)
@@ -1191,7 +1203,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
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();
+ return out.release();
}
// ------------------------------------------------------------------------------------------------
@@ -1209,7 +1221,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
++it;
}
- ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
+ std::unique_ptr<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
if (obj->data) {
switch (obj->type)
{
@@ -1227,7 +1239,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
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;
+ node->mMeshes[i] = static_cast<unsigned int>(i + old);
}
}}
break;
@@ -1293,15 +1305,14 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
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;
+ (*nd++)->mParent = node.get();
}
}
// apply modifiers
modifier_cache->ApplyModifiers(*node,conv_data,in,*obj);
- return node.dismiss();
+ return node.release();
}
-
-#endif
+#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
diff --git a/src/3rdparty/assimp/code/BlenderLoader.h b/src/3rdparty/assimp/code/BlenderLoader.h
index c964eee32..66fff594b 100644
--- a/src/3rdparty/assimp/code/BlenderLoader.h
+++ b/src/3rdparty/assimp/code/BlenderLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -105,7 +106,6 @@ public:
BlenderImporter();
~BlenderImporter();
-
public:
// --------------------
diff --git a/src/3rdparty/assimp/code/BlenderModifier.cpp b/src/3rdparty/assimp/code/BlenderModifier.cpp
index 24aed25d0..348df1f48 100644
--- a/src/3rdparty/assimp/code/BlenderModifier.cpp
+++ b/src/3rdparty/assimp/code/BlenderModifier.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of some blender modifiers (i.e subdivision, mirror).
*/
-
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
+
#include "BlenderModifier.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "Subdivision.h"
#include <assimp/scene.h>
#include <memory>
@@ -265,7 +266,7 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
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));
+ [&out](unsigned int n) { return out.mNumMeshes + n; });
delete[] out.mMeshes;
out.mMeshes = nind;
@@ -275,9 +276,6 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
orig_object.id.name,"`");
}
-
-
-
// ------------------------------------------------------------------------------------------------
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
{
@@ -312,7 +310,9 @@ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
ai_assert(subd);
-
+ if ( conv_data.meshes->empty() ) {
+ return;
+ }
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
@@ -323,4 +323,4 @@ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
orig_object.id.name,"`");
}
-#endif
+#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
diff --git a/src/3rdparty/assimp/code/BlenderModifier.h b/src/3rdparty/assimp/code/BlenderModifier.h
index 1d176756e..9fa8c74ee 100644
--- a/src/3rdparty/assimp/code/BlenderModifier.h
+++ b/src/3rdparty/assimp/code/BlenderModifier.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/BlenderScene.cpp b/src/3rdparty/assimp/code/BlenderScene.cpp
index f4d07662e..0e1dec7f3 100644
--- a/src/3rdparty/assimp/code/BlenderScene.cpp
+++ b/src/3rdparty/assimp/code/BlenderScene.cpp
@@ -44,9 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
-#include "BlenderDNA.h"
#include "BlenderScene.h"
#include "BlenderSceneGen.h"
+#include "BlenderDNA.h"
using namespace Assimp;
using namespace Assimp::Blender;
@@ -59,7 +59,9 @@ template <> void Structure :: Convert<Object> (
{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
- ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+ int temp = 0;
+ ReadField<ErrorPolicy_Fail>(temp,"type",db);
+ dest.type = static_cast<Assimp::Blender::Object::Type>(temp);
ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db);
ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
@@ -100,14 +102,21 @@ template <> void Structure :: Convert<MTex> (
) const
{
- ReadField<ErrorPolicy_Igno>((short&)dest.mapto,"mapto",db);
- ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
+ int temp_short = 0;
+ ReadField<ErrorPolicy_Igno>(temp_short,"mapto",db);
+ dest.mapto = static_cast<Assimp::Blender::MTex::MapType>(temp_short);
+ int temp = 0;
+ ReadField<ErrorPolicy_Igno>(temp,"blendtype",db);
+ dest.blendtype = static_cast<Assimp::Blender::MTex::BlendType>(temp);
ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db);
- ReadField<ErrorPolicy_Igno>((int&)dest.projx,"projx",db);
- ReadField<ErrorPolicy_Igno>((int&)dest.projy,"projy",db);
- ReadField<ErrorPolicy_Igno>((int&)dest.projz,"projz",db);
+ ReadField<ErrorPolicy_Igno>(temp,"projx",db);
+ dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
+ ReadField<ErrorPolicy_Igno>(temp,"projy",db);
+ dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
+ ReadField<ErrorPolicy_Igno>(temp,"projz",db);
+ dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
@@ -190,7 +199,9 @@ template <> void Structure :: Convert<Lamp> (
{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
- ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+ int temp = 0;
+ ReadField<ErrorPolicy_Fail>(temp,"type",db);
+ dest.type = static_cast<Assimp::Blender::Lamp::Type>(temp);
ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db);
@@ -204,7 +215,8 @@ template <> void Structure :: Convert<Lamp> (
ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
- ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
+ ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db);
+ dest.falloff_type = static_cast<Assimp::Blender::Lamp::FalloffType>(temp);
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);
@@ -522,7 +534,7 @@ template <> void Structure :: Convert<MVert> (
ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
- ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
+ //ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
db.reader->IncPtr(size);
@@ -693,8 +705,12 @@ template <> void Structure :: Convert<Tex> (
const FileDatabase& db
) const
{
- ReadField<ErrorPolicy_Igno>((short&)dest.imaflag,"imaflag",db);
- ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+ short temp_short = 0;
+ ReadField<ErrorPolicy_Igno>(temp_short,"imaflag",db);
+ dest.imaflag = static_cast<Assimp::Blender::Tex::ImageFlags>(temp_short);
+ int temp = 0;
+ ReadField<ErrorPolicy_Fail>(temp,"type",db);
+ dest.type = static_cast<Assimp::Blender::Tex::Type>(temp);
ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
db.reader->IncPtr(size);
@@ -708,8 +724,11 @@ template <> void Structure :: Convert<Camera> (
{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
- ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
- ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
+ int temp = 0;
+ ReadField<ErrorPolicy_Warn>(temp,"type",db);
+ dest.type = static_cast<Assimp::Blender::Camera::Type>(temp);
+ ReadField<ErrorPolicy_Warn>(temp,"flag",db);
+ dest.flag = static_cast<Assimp::Blender::Camera::Type>(temp);
ReadField<ErrorPolicy_Warn>(dest.lens,"lens",db);
ReadField<ErrorPolicy_Warn>(dest.sensor_x,"sensor_x",db);
ReadField<ErrorPolicy_Igno>(dest.clipsta,"clipsta",db);
@@ -805,5 +824,5 @@ void DNA::RegisterConverters() {
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
}
+#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
-#endif
diff --git a/src/3rdparty/assimp/code/BlenderScene.h b/src/3rdparty/assimp/code/BlenderScene.h
index 187557765..86ab1f30c 100644
--- a/src/3rdparty/assimp/code/BlenderScene.h
+++ b/src/3rdparty/assimp/code/BlenderScene.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -64,7 +65,7 @@ namespace Blender {
// * C++ style comments only
//
// * Structures may include the primitive types char, int, short,
-// float, double. Signedness specifiers are not allowed on
+// float, double. Signed specifiers are not allowed on
// integers. Enum types are allowed, but they must have been
// defined in this header.
//
@@ -85,14 +86,23 @@ namespace Blender {
// provided they are neither pointers nor arrays.
//
// * One of WARN, FAIL can be appended to the declaration (
-// prior to the semiolon to specifiy the error handling policy if
+// prior to the semicolon to specify the error handling policy if
// this field is missing in the input DNA). If none of those
// is specified the default policy is to substitute a default
// value for the field.
//
-#define WARN // warn if field is missing, substitute default value
-#define FAIL // fail the import if the field does not exist
+// warn if field is missing, substitute default value
+#ifdef WARN
+# undef WARN
+#endif
+#define WARN
+
+// fail the import if the field does not exist
+#ifdef FAIL
+# undef FAIL
+#endif
+#define FAIL
struct Object;
struct MTex;
@@ -102,16 +112,16 @@ struct Image;
#define AI_BLEND_MESH_MAX_VERTS 2000000000L
+static const size_t MaxNameLen = 1024;
+
// -------------------------------------------------------------------------------
struct ID : ElemBase {
-
- char name[1024] WARN;
+ char name[ MaxNameLen ] WARN;
short flag;
};
// -------------------------------------------------------------------------------
struct ListBase : ElemBase {
-
std::shared_ptr<ElemBase> first;
std::shared_ptr<ElemBase> last;
};
@@ -126,7 +136,6 @@ struct PackedFile : ElemBase {
// -------------------------------------------------------------------------------
struct GroupObject : ElemBase {
-
std::shared_ptr<GroupObject> prev,next FAIL;
std::shared_ptr<Object> ob;
};
@@ -142,7 +151,6 @@ struct Group : ElemBase {
// -------------------------------------------------------------------------------
struct World : ElemBase {
ID id FAIL;
-
};
// -------------------------------------------------------------------------------
@@ -175,7 +183,7 @@ struct MLoopUV : ElemBase {
// -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase {
- char r, g, b, a;
+ unsigned char r, g, b, a;
};
// -------------------------------------------------------------------------------
@@ -217,6 +225,13 @@ struct TFace : ElemBase {
// -------------------------------------------------------------------------------
struct MTFace : ElemBase {
+ MTFace()
+ : flag(0)
+ , mode(0)
+ , tile(0)
+ , unwrap(0)
+ {
+ }
float uv[4][2] FAIL;
char flag;
@@ -235,7 +250,6 @@ struct MDeformWeight : ElemBase {
// -------------------------------------------------------------------------------
struct MDeformVert : ElemBase {
-
vector<MDeformWeight> dw WARN;
int totweight;
};
@@ -264,7 +278,6 @@ struct Material : ElemBase {
float darkness;
float refrac;
-
float amb;
float ang;
float spectra;
@@ -612,6 +625,17 @@ struct Object : ElemBase {
std::shared_ptr<ElemBase> data FAIL;
ListBase modifiers;
+
+ Object()
+ : ElemBase()
+ , type( Type_EMPTY )
+ , parent( nullptr )
+ , track()
+ , proxy()
+ , proxy_from()
+ , data() {
+ // empty
+ }
};
@@ -620,6 +644,15 @@ struct Base : ElemBase {
Base* prev WARN;
std::shared_ptr<Base> next WARN;
std::shared_ptr<Object> object WARN;
+
+ Base()
+ : ElemBase()
+ , prev( nullptr )
+ , next()
+ , object() {
+ // empty
+ // empty
+ }
};
// -------------------------------------------------------------------------------
@@ -631,8 +664,15 @@ struct Scene : ElemBase {
std::shared_ptr<Base> basact WARN;
ListBase base;
-};
+ Scene()
+ : ElemBase()
+ , camera()
+ , world()
+ , basact() {
+ // empty
+ }
+};
// -------------------------------------------------------------------------------
struct Image : ElemBase {
@@ -660,6 +700,11 @@ struct Image : ElemBase {
short animspeed;
short gen_x, gen_y, gen_type;
+
+ Image()
+ : ElemBase() {
+ // empty
+ }
};
// -------------------------------------------------------------------------------
@@ -747,6 +792,14 @@ struct Tex : ElemBase {
//VoxelData *vd;
//char use_nodes;
+
+ Tex()
+ : ElemBase()
+ , imaflag( ImageFlags_INTERPOL )
+ , type( Type_CLOUDS )
+ , ima() {
+ // empty
+ }
};
// -------------------------------------------------------------------------------
@@ -835,9 +888,13 @@ struct MTex : ElemBase {
//float lifefac, sizefac, ivelfac, pvelfac;
//float shadowfac;
//float zenupfac, zendownfac, blendfac;
-};
-
+ MTex()
+ : ElemBase() {
+ // empty
}
+};
+
+}
}
#endif
diff --git a/src/3rdparty/assimp/code/BlenderTessellator.cpp b/src/3rdparty/assimp/code/BlenderTessellator.cpp
index bea00e228..9f4c51048 100644
--- a/src/3rdparty/assimp/code/BlenderTessellator.cpp
+++ b/src/3rdparty/assimp/code/BlenderTessellator.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -50,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderBMesh.h"
#include "BlenderTessellator.h"
-#include <stddef.h>
+#include <stddef.h>
static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
@@ -58,7 +59,11 @@ static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
namspace Assimp
{
- template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
+ template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
+ {
+ static auto prefix = "BLEND_TESS_GL: ";
+ return prefix;
+ }
}
using namespace Assimp;
@@ -251,7 +256,11 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
namespace Assimp
{
- template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
+ template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
+ {
+ static auto prefix = "BLEND_TESS_P2T: ";
+ return prefix;
+ }
}
using namespace Assimp;
@@ -412,9 +421,9 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
{
float result = 0.0f;
- for ( size_t x = 0; x < 3; ++x )
+ for ( unsigned int x = 0; x < 3; ++x )
{
- for ( size_t y = 0; y < 3; ++y )
+ for ( unsigned int y = 0; y < 3; ++y )
{
result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
}
@@ -429,9 +438,9 @@ aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float sc
{
aiMatrix3x3 result;
- for ( size_t x = 0; x < 3; ++x )
+ for ( unsigned int x = 0; x < 3; ++x )
{
- for ( size_t y = 0; y < 3; ++y )
+ for ( unsigned int y = 0; y < 3; ++y )
{
result[ x ][ y ] = mtx[ x ][ y ] * scale;
}
@@ -470,19 +479,19 @@ PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& po
{
PlaneP2T result;
- aiVector3D sum( 0.0f );
+ aiVector3D sum( 0.0 );
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;
+ result.centre = sum * (ai_real)( 1.0 / points.size( ) );
+
+ ai_real sumXX = 0.0;
+ ai_real sumXY = 0.0;
+ ai_real sumXZ = 0.0;
+ ai_real sumYY = 0.0;
+ ai_real sumYZ = 0.0;
+ ai_real sumZZ = 0.0;
for ( size_t i = 0; i < points.size( ); ++i )
{
aiVector3D offset = points[ i ].point3D - result.centre;
@@ -496,7 +505,7 @@ PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& po
aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
- const float det = mtx.Determinant( );
+ const ai_real det = mtx.Determinant( );
if ( det == 0.0f )
{
result.normal = aiVector3D( 0.0f );
diff --git a/src/3rdparty/assimp/code/BlenderTessellator.h b/src/3rdparty/assimp/code/BlenderTessellator.h
index 530bd2c3e..47d3a4665 100644
--- a/src/3rdparty/assimp/code/BlenderTessellator.h
+++ b/src/3rdparty/assimp/code/BlenderTessellator.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/BlobIOSystem.h b/src/3rdparty/assimp/code/BlobIOSystem.h
index 6cd014254..f406ea0fe 100644
--- a/src/3rdparty/assimp/code/BlobIOSystem.h
+++ b/src/3rdparty/assimp/code/BlobIOSystem.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -45,10 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BLOBIOSYSTEM_H_INCLUDED
#define AI_BLOBIOSYSTEM_H_INCLUDED
-#include "./../include/assimp/IOStream.hpp"
-#include "./../include/assimp/cexport.h"
-#include "./../include/assimp/IOSystem.hpp"
-#include "./../include/assimp/DefaultLogger.hpp"
+#include <assimp/IOStream.hpp>
+#include <assimp/cexport.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
#include <stdint.h>
#include <set>
#include <vector>
diff --git a/src/3rdparty/assimp/code/ByteSwapper.h b/src/3rdparty/assimp/code/ByteSwapper.h
index 37538e7cb..e5c7569f1 100644
--- a/src/3rdparty/assimp/code/ByteSwapper.h
+++ b/src/3rdparty/assimp/code/ByteSwapper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/C4DImporter.cpp b/src/3rdparty/assimp/code/C4DImporter.cpp
index 252766ca6..1344f32fb 100644
--- a/src/3rdparty/assimp/code/C4DImporter.cpp
+++ b/src/3rdparty/assimp/code/C4DImporter.cpp
@@ -185,11 +185,11 @@ void C4DImporter::InternReadFile( const std::string& pFile,
if(mesh->mMaterialIndex >= mat_count) {
++mat_count;
- ScopeGuard<aiMaterial> def_material(new aiMaterial());
+ std::unique_ptr<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());
+ materials.push_back(def_material.release());
break;
}
}
@@ -393,7 +393,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
// ------------------------------------------------------------------------------------------------
aiMesh* C4DImporter::ReadMesh(BaseObject* object)
{
- assert(object != NULL && object->GetType() == Opolygon);
+ ai_assert(object != NULL && object->GetType() == Opolygon);
// based on Melange sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
@@ -412,7 +412,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
const CPolygon* polys = polyObject->GetPolygonR();
ai_assert(polys != NULL);
- ScopeGuard<aiMesh> mesh(new aiMesh());
+ std::unique_ptr<aiMesh> mesh(new aiMesh());
mesh->mNumFaces = static_cast<unsigned int>(polyCount);
aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces]();
@@ -616,7 +616,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
}
mesh->mMaterialIndex = ResolveMaterial(polyObject);
- return mesh.dismiss();
+ return mesh.release();
}
@@ -635,7 +635,7 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
BaseMaterial* const mat = ttag.GetMaterial();
- assert(mat != NULL);
+ ai_assert(mat != NULL);
const MaterialMap::const_iterator it = material_mapping.find(mat);
if(it == material_mapping.end()) {
diff --git a/src/3rdparty/assimp/code/C4DImporter.h b/src/3rdparty/assimp/code/C4DImporter.h
index 3ba2a17c6..4dea82161 100644
--- a/src/3rdparty/assimp/code/C4DImporter.h
+++ b/src/3rdparty/assimp/code/C4DImporter.h
@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "LogAux.h"
-#include <set>
+#include <map>
struct aiNode;
struct aiMesh;
struct aiMaterial;
diff --git a/src/3rdparty/assimp/code/CInterfaceIOWrapper.cpp b/src/3rdparty/assimp/code/CInterfaceIOWrapper.cpp
new file mode 100644
index 000000000..9de75b683
--- /dev/null
+++ b/src/3rdparty/assimp/code/CInterfaceIOWrapper.cpp
@@ -0,0 +1,135 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file aiFileIO -> IOSystem wrapper*/
+
+#include "CInterfaceIOWrapper.h"
+
+namespace Assimp {
+
+CIOStreamWrapper::~CIOStreamWrapper(void)
+{
+ /* Various places depend on this destructor to close the file */
+ if (mFile) {
+ mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
+ mFile = nullptr;
+ }
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount
+){
+ // need to typecast here as C has no void*
+ return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount
+){
+ // need to typecast here as C has no void*
+ return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
+}
+
+// ...................................................................
+aiReturn CIOStreamWrapper::Seek(size_t pOffset,
+ aiOrigin pOrigin
+){
+ return mFile->SeekProc(mFile,pOffset,pOrigin);
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::Tell(void) const {
+ return mFile->TellProc(mFile);
+}
+
+// ...................................................................
+size_t CIOStreamWrapper::FileSize() const {
+ return mFile->FileSizeProc(mFile);
+}
+
+// ...................................................................
+void CIOStreamWrapper::Flush () {
+ return mFile->FlushProc(mFile);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Custom IOStream implementation for the C-API
+bool CIOSystemWrapper::Exists( const char* pFile) const {
+ aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
+ if (p){
+ mFileSystem->CloseProc(mFileSystem,p);
+ return true;
+ }
+ return false;
+}
+
+// ...................................................................
+char CIOSystemWrapper::getOsSeparator() const {
+#ifndef _WIN32
+ return '/';
+#else
+ return '\\';
+#endif
+}
+
+// ...................................................................
+IOStream* CIOSystemWrapper::Open(const char* pFile,const char* pMode) {
+ aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
+ if (!p) {
+ return NULL;
+ }
+ return new CIOStreamWrapper(p, this);
+}
+
+// ...................................................................
+void CIOSystemWrapper::Close( IOStream* pFile) {
+ if (!pFile) {
+ return;
+ }
+ delete pFile;
+}
+
+}
diff --git a/src/3rdparty/assimp/code/CInterfaceIOWrapper.h b/src/3rdparty/assimp/code/CInterfaceIOWrapper.h
index beffd8678..78cac0cf9 100644
--- a/src/3rdparty/assimp/code/CInterfaceIOWrapper.h
+++ b/src/3rdparty/assimp/code/CInterfaceIOWrapper.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -50,106 +51,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
+class CIOSystemWrapper;
+
// ------------------------------------------------------------------------------------------------
// Custom IOStream implementation for the C-API
class CIOStreamWrapper : public IOStream
{
- friend class CIOSystemWrapper;
public:
-
- explicit CIOStreamWrapper(aiFile* pFile)
- : mFile(pFile)
+ explicit CIOStreamWrapper(aiFile* pFile, CIOSystemWrapper* io)
+ : mFile(pFile),
+ mIO(io)
{}
+ ~CIOStreamWrapper(void);
- // ...................................................................
- 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);
- }
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount);
+ size_t Write(const void* pvBuffer, size_t pSize, size_t pCount);
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin);
+ size_t Tell(void) const;
+ size_t FileSize() const;
+ void Flush();
private:
aiFile* mFile;
+ CIOSystemWrapper* mIO;
};
-// ------------------------------------------------------------------------------------------------
-// Custom IOStream implementation for the C-API
class CIOSystemWrapper : public IOSystem
{
+ friend class CIOStreamWrapper;
public:
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 '/';
-#else
- 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;
- }
+ bool Exists( const char* pFile) const;
+ char getOsSeparator() const;
+ IOStream* Open(const char* pFile,const char* pMode = "rb");
+ void Close( IOStream* pFile);
private:
aiFileIO* mFileSystem;
};
diff --git a/src/3rdparty/assimp/code/CMakeLists.txt b/src/3rdparty/assimp/code/CMakeLists.txt
index 35ecf5020..4d02240da 100644
--- a/src/3rdparty/assimp/code/CMakeLists.txt
+++ b/src/3rdparty/assimp/code/CMakeLists.txt
@@ -1,7 +1,8 @@
# Open Asset Import Library (assimp)
# ----------------------------------------------------------------------
#
-# Copyright (c) 2006-2016, assimp team
+# Copyright (c) 2006-2017, assimp team
+
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -58,8 +59,9 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/camera.h
${HEADER_PATH}/color4.h
${HEADER_PATH}/color4.inl
- ${HEADER_PATH}/config.h
+ ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h
${HEADER_PATH}/defs.h
+ ${HEADER_PATH}/Defines.h
${HEADER_PATH}/cfileio.h
${HEADER_PATH}/light.h
${HEADER_PATH}/material.h
@@ -93,6 +95,9 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/NullLogger.hpp
${HEADER_PATH}/cexport.h
${HEADER_PATH}/Exporter.hpp
+ ${HEADER_PATH}/DefaultIOStream.h
+ ${HEADER_PATH}/DefaultIOSystem.h
+ ${HEADER_PATH}/SceneCombiner.h
)
SET( Core_SRCS
@@ -125,9 +130,8 @@ SET( Common_SRCS
ByteSwapper.h
DefaultProgressHandler.h
DefaultIOStream.cpp
- DefaultIOStream.h
DefaultIOSystem.cpp
- DefaultIOSystem.h
+ CInterfaceIOWrapper.cpp
CInterfaceIOWrapper.h
Hash.h
Importer.cpp
@@ -146,13 +150,14 @@ SET( Common_SRCS
SpatialSort.cpp
SpatialSort.h
SceneCombiner.cpp
- SceneCombiner.h
ScenePreprocessor.cpp
ScenePreprocessor.h
SkeletonMeshBuilder.cpp
SkeletonMeshBuilder.h
SplitByBoneCountProcess.cpp
SplitByBoneCountProcess.h
+ ScaleProcess.cpp
+ ScaleProcess.h
SmoothingGroups.h
StandardShapes.cpp
StandardShapes.h
@@ -162,6 +167,7 @@ SET( Common_SRCS
RemoveComments.h
Subdivision.cpp
Subdivision.h
+ scene.cpp
Vertex.h
LineSplitter.h
TinyFormatter.h
@@ -171,6 +177,9 @@ SET( Common_SRCS
Bitmap.h
XMLTools.h
Version.cpp
+ IOStreamBuffer.h
+ CreateAnimMesh.h
+ CreateAnimMesh.cpp
)
SOURCE_GROUP(Common FILES ${Common_SRCS})
@@ -182,10 +191,16 @@ IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
SOURCE_GROUP( C4D FILES ${C4D_SRCS})
ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
+# if this variable is set to TRUE, the user can manually disable importers by setting
+# ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer
+# if this variable is set to FALSE, the user can manually enable importers by setting
+# ASSIMP_BUILD_XXX_IMPORTER to TRUE for each importer
+OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_IMPORTER value" TRUE)
+
# 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)
+ OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
IF(ASSIMP_BUILD_${name}_IMPORTER)
LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
@@ -195,6 +210,7 @@ MACRO(ADD_ASSIMP_IMPORTER name)
SET(${name}_SRC "")
SET(ASSIMP_IMPORTERS_DISABLED "${ASSIMP_IMPORTERS_DISABLED} ${name}")
add_definitions(-DASSIMP_BUILD_NO_${name}_IMPORTER)
+ add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER)
ENDIF()
ENDMACRO()
@@ -202,6 +218,16 @@ SET(ASSIMP_LOADER_SRCS "")
SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
SET(ASSIMP_IMPORTERS_DISABLED "") # disabled list (used to print)
+ADD_ASSIMP_IMPORTER( AMF
+ AMFImporter.hpp
+ AMFImporter_Macro.hpp
+ AMFImporter_Node.hpp
+ AMFImporter.cpp
+ AMFImporter_Geometry.cpp
+ AMFImporter_Material.cpp
+ AMFImporter_Postprocess.cpp
+)
+
ADD_ASSIMP_IMPORTER( 3DS
3DSConverter.cpp
3DSHelper.h
@@ -433,7 +459,8 @@ ADD_ASSIMP_IMPORTER( BLEND
ADD_ASSIMP_IMPORTER( IFC
IFCLoader.cpp
IFCLoader.h
- IFCReaderGen.cpp
+ IFCReaderGen1.cpp
+ IFCReaderGen2.cpp
IFCReaderGen.h
IFCUtil.h
IFCUtil.cpp
@@ -449,9 +476,13 @@ ADD_ASSIMP_IMPORTER( IFC
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)
+if (ASSIMP_BUILD_IFC_IMPORTER)
+ if (MSVC)
+ set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "/bigobj")
+ elseif(CMAKE_COMPILER_IS_MINGW)
+ set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj")
+ endif()
+endif (ASSIMP_BUILD_IFC_IMPORTER)
ADD_ASSIMP_IMPORTER( XGL
XGLLoader.cpp
@@ -542,6 +573,9 @@ SET( PostProcessing_SRCS
)
SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
+SET( IrrXML_SRCS irrXMLWrapper.h )
+SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
+
ADD_ASSIMP_IMPORTER( Q3D
Q3DLoader.cpp
Q3DLoader.h
@@ -599,6 +633,28 @@ ADD_ASSIMP_IMPORTER( X
XFileExporter.cpp
)
+ADD_ASSIMP_IMPORTER(X3D
+ X3DExporter.cpp
+ X3DExporter.hpp
+ X3DImporter.cpp
+ X3DImporter.hpp
+ X3DImporter_Geometry2D.cpp
+ X3DImporter_Geometry3D.cpp
+ X3DImporter_Group.cpp
+ X3DImporter_Light.cpp
+ X3DImporter_Macro.hpp
+ X3DImporter_Metadata.cpp
+ X3DImporter_Networking.cpp
+ X3DImporter_Node.hpp
+ X3DImporter_Postprocess.cpp
+ X3DImporter_Rendering.cpp
+ X3DImporter_Shape.cpp
+ X3DImporter_Texturing.cpp
+ FIReader.hpp
+ FIReader.cpp
+ X3DVocabulary.cpp
+)
+
ADD_ASSIMP_IMPORTER( GLTF
glTFAsset.h
glTFAsset.inl
@@ -608,16 +664,35 @@ ADD_ASSIMP_IMPORTER( GLTF
glTFImporter.h
glTFExporter.h
glTFExporter.cpp
+ glTF2Asset.h
+ glTF2Asset.inl
+ glTF2AssetWriter.h
+ glTF2AssetWriter.inl
+ glTF2Importer.cpp
+ glTF2Importer.h
+ glTF2Exporter.h
+ glTF2Exporter.cpp
)
-
ADD_ASSIMP_IMPORTER( 3MF
D3MFImporter.h
D3MFImporter.cpp
+ D3MFExporter.h
+ D3MFExporter.cpp
D3MFOpcPackage.h
D3MFOpcPackage.cpp
+ 3MFXmlTags.h
)
+ADD_ASSIMP_IMPORTER( MMD
+ MMDCpp14.h
+ MMDImporter.cpp
+ MMDImporter.h
+ MMDPmdParser.h
+ MMDPmxParser.h
+ MMDPmxParser.cpp
+ MMDVmdParser.h
+)
SET( Step_SRCS
StepExporter.h
@@ -637,23 +712,6 @@ SET( Extra_SRCS
)
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
-)
-SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
-
-SET( ConvertUTF_SRCS
- ../contrib/ConvertUTF/ConvertUTF.h
- ../contrib/ConvertUTF/ConvertUTF.c
-)
-SOURCE_GROUP( ConvertUTF FILES ${ConvertUTF_SRCS})
SET( Clipper_SRCS
../contrib/clipper/clipper.hpp
@@ -661,7 +719,6 @@ SET( Clipper_SRCS
)
SOURCE_GROUP( Clipper FILES ${Clipper_SRCS})
-
SET( Poly2Tri_SRCS
../contrib/poly2tri/poly2tri/common/shapes.cc
../contrib/poly2tri/poly2tri/common/shapes.h
@@ -686,22 +743,79 @@ SET( unzip_SRCS
)
SOURCE_GROUP( unzip FILES ${unzip_SRCS})
+SET( ziplib_SRCS
+ ../contrib/zip/src/miniz.h
+ ../contrib/zip/src/zip.c
+ ../contrib/zip/src/zip.h
+)
+
+SOURCE_GROUP( ziplib FILES ${ziplib_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/code/OpenDDLStream.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/OpenDDLStream.h
../contrib/openddlparser/include/openddlparser/DDLNode.h
../contrib/openddlparser/include/openddlparser/Value.h
)
SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
+SET ( open3dgc_SRCS
+ ../contrib/Open3DGC/o3dgcAdjacencyInfo.h
+ ../contrib/Open3DGC/o3dgcArithmeticCodec.cpp
+ ../contrib/Open3DGC/o3dgcArithmeticCodec.h
+ ../contrib/Open3DGC/o3dgcBinaryStream.h
+ ../contrib/Open3DGC/o3dgcCommon.h
+ ../contrib/Open3DGC/o3dgcDVEncodeParams.h
+ ../contrib/Open3DGC/o3dgcDynamicVectorDecoder.cpp
+ ../contrib/Open3DGC/o3dgcDynamicVectorDecoder.h
+ ../contrib/Open3DGC/o3dgcDynamicVectorEncoder.cpp
+ ../contrib/Open3DGC/o3dgcDynamicVectorEncoder.h
+ ../contrib/Open3DGC/o3dgcDynamicVector.h
+ ../contrib/Open3DGC/o3dgcFIFO.h
+ ../contrib/Open3DGC/o3dgcIndexedFaceSet.h
+ ../contrib/Open3DGC/o3dgcIndexedFaceSet.inl
+ ../contrib/Open3DGC/o3dgcSC3DMCDecoder.h
+ ../contrib/Open3DGC/o3dgcSC3DMCDecoder.inl
+ ../contrib/Open3DGC/o3dgcSC3DMCEncodeParams.h
+ ../contrib/Open3DGC/o3dgcSC3DMCEncoder.h
+ ../contrib/Open3DGC/o3dgcSC3DMCEncoder.inl
+ ../contrib/Open3DGC/o3dgcTimer.h
+ ../contrib/Open3DGC/o3dgcTools.cpp
+ ../contrib/Open3DGC/o3dgcTriangleFans.cpp
+ ../contrib/Open3DGC/o3dgcTriangleFans.h
+ ../contrib/Open3DGC/o3dgcTriangleListDecoder.h
+ ../contrib/Open3DGC/o3dgcTriangleListDecoder.inl
+ ../contrib/Open3DGC/o3dgcTriangleListEncoder.h
+ ../contrib/Open3DGC/o3dgcTriangleListEncoder.inl
+ ../contrib/Open3DGC/o3dgcVector.h
+ ../contrib/Open3DGC/o3dgcVector.inl
+)
+SOURCE_GROUP( open3dgc FILES ${open3dgc_SRCS})
+
+# Check dependencies for glTF importer with Open3DGC-compression.
+# RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
+# has implementation for different platforms: WIN32, __MACH__ and other ("else" block).
+FIND_PACKAGE(RT QUIET)
+IF (RT_FOUND OR MSVC)
+ SET( ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC 1 )
+ ADD_DEFINITIONS( -DASSIMP_IMPORTER_GLTF_USE_OPEN3DGC=1 )
+ELSE ()
+ SET (open3dgc_SRCS "")
+ MESSAGE (INFO " RT-extension not found. glTF import/export will be built without Open3DGC-compression.")
+ #!TODO: off course is better to remove statistics timers from o3dgc codec. Or propose to choose what to use.
+ENDIF ()
+
INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" )
+INCLUDE_DIRECTORIES( "../contrib" )
# VC2010 fixes
if(MSVC10)
@@ -722,6 +836,7 @@ if (UNZIP_FOUND)
SET (unzip_compile_SRCS "")
else (UNZIP_FOUND)
SET (unzip_compile_SRCS ${unzip_SRCS})
+ INCLUDE_DIRECTORIES( "../contrib/unzip/" )
endif (UNZIP_FOUND)
MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}")
@@ -742,11 +857,12 @@ SET( assimp_src
# Third-party libraries
${IrrXML_SRCS}
- ${ConvertUTF_SRCS}
${unzip_compile_SRCS}
${Poly2Tri_SRCS}
${Clipper_SRCS}
${openddl_parser_SRCS}
+ ${open3dgc_SRCS}
+ ${ziplib_SRCS}
# Necessary to show the headers in the project when using the VC++ generator:
${PUBLIC_HEADERS}
@@ -756,7 +872,8 @@ SET( assimp_src
ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD )
INCLUDE_DIRECTORIES(
- ../contrib/openddlparser/include
+ ${IRRXML_INCLUDE_DIR}
+ ../contrib/openddlparser/include
)
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
@@ -766,7 +883,7 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_LIBRARY( assimp ${assimp_src} )
-TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
+TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} )
if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
@@ -809,8 +926,27 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES
)
if (APPLE)
- SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}")
-endif()
+ SET_TARGET_PROPERTIES( assimp PROPERTIES
+ INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}"
+ )
+
+ if (BUILD_FRAMEWORK)
+ SET_TARGET_PROPERTIES( assimp PROPERTIES
+ FRAMEWORK TRUE
+ FRAMEWORK_VERSION C
+ MACOSX_FRAMEWORK_IDENTIFIER net.sf.assimp
+ PUBLIC_HEADER "${PUBLIC_HEADERS}"
+ )
+
+ # PUBLIC_HEADER option does not support directory structure creation
+ # add ./Compiler/*.h to assimp.framework via copy command
+ ADD_CUSTOM_COMMAND(TARGET assimp POST_BUILD
+ COMMAND "${CMAKE_COMMAND}" -E copy_directory
+ "../${HEADER_PATH}/Compiler"
+ assimp.framework/Headers/Compiler
+ COMMENT "Copying public ./Compiler/ header files to framework bundle's Headers/Compiler/")
+ endif(BUILD_FRAMEWORK)
+endif(APPLE)
# Build against external unzip, or add ../contrib/unzip so
# assimp can #include "unzip.h"
@@ -821,13 +957,20 @@ else (UNZIP_FOUND)
INCLUDE_DIRECTORIES("../")
endif (UNZIP_FOUND)
+# Add RT-extension library for glTF importer with Open3DGC-compression.
+IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
+ TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY})
+ENDIF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
+
INSTALL( TARGETS assimp
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
+ FRAMEWORK DESTINATION ${ASSIMP_LIB_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}
@@ -835,12 +978,35 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM)
endif(ASSIMP_ANDROID_JNIIOSYSTEM)
if(MSVC AND ASSIMP_INSTALL_PDB)
- 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
- )
+ IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
+ 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${LIBRARY_SUFFIX}.pdb
+ DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ CONFIGURATIONS RelWithDebInfo
+ )
+ ELSE()
+ install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
+ DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ CONFIGURATIONS Debug
+ )
+ install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}.pdb
+ DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ CONFIGURATIONS RelWithDebInfo
+ )
+ ENDIF()
endif ()
+
+if (ASSIMP_COVERALLS)
+ include(Coveralls)
+
+ set(COVERAGE_SRCS ${assimp_src} ${TEST_SRCS} )
+
+ # Create the coveralls target.
+ coveralls_setup(
+ "${COVERAGE_SRCS}" # The source files.
+ ON # If we should upload.
+ "${PROJECT_SOURCE_DIR}/cmake-modules/") # (Optional) Alternate project cmake module path.
+endif()
diff --git a/src/3rdparty/assimp/code/COBLoader.cpp b/src/3rdparty/assimp/code/COBLoader.cpp
index 4f0ad3980..a92e231a5 100644
--- a/src/3rdparty/assimp/code/COBLoader.cpp
+++ b/src/3rdparty/assimp/code/COBLoader.cpp
@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
using namespace Assimp::COB;
@@ -181,7 +181,7 @@ void COBImporter::InternReadFile( const std::string& pFile,
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->mNumMeshes += static_cast<unsigned int>(mesh.temp_map.size());
}
}
}
@@ -941,20 +941,22 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn
// ------------------------------------------------------------------------------------------------
// tiny utility guard to aid me at staying within chunk boundaries.
class chunk_guard {
-
public:
-
chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader)
- : nfo(nfo)
- , reader(reader)
- , cur(reader.GetCurrentPos())
- {
+ : 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);
+ try {
+ reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur );
+ } catch ( DeadlyImportError e ) {
+ // out of limit so correct the value
+ reader.IncPtr( reader.GetReadLimit() );
+ }
}
}
diff --git a/src/3rdparty/assimp/code/COBLoader.h b/src/3rdparty/assimp/code/COBLoader.h
index efccc448d..46dc86f62 100644
--- a/src/3rdparty/assimp/code/COBLoader.h
+++ b/src/3rdparty/assimp/code/COBLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/COBScene.h b/src/3rdparty/assimp/code/COBScene.h
index 0e27d1461..a1d6ebc27 100644
--- a/src/3rdparty/assimp/code/COBScene.h
+++ b/src/3rdparty/assimp/code/COBScene.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <deque>
+#include <map>
#include "BaseImporter.h"
-#include "./../include/assimp/material.h"
+#include <assimp/material.h>
-namespace Assimp {
- namespace COB {
+namespace Assimp {
+namespace COB {
// ------------------
/** Represents a single vertex index in a face */
diff --git a/src/3rdparty/assimp/code/CSMLoader.cpp b/src/3rdparty/assimp/code/CSMLoader.cpp
index 925abf4bd..eeb6986b0 100644
--- a/src/3rdparty/assimp/code/CSMLoader.cpp
+++ b/src/3rdparty/assimp/code/CSMLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -57,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/anim.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
@@ -179,7 +180,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
}
- anim->mNumChannels = anims_temp.size();
+ anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());
if (!anim->mNumChannels)
throw DeadlyImportError("CSM: Empty $order section");
diff --git a/src/3rdparty/assimp/code/CSMLoader.h b/src/3rdparty/assimp/code/CSMLoader.h
index 71abb7e91..55a632dc6 100644
--- a/src/3rdparty/assimp/code/CSMLoader.h
+++ b/src/3rdparty/assimp/code/CSMLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/CalcTangentsProcess.cpp b/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
index dbba1bed3..2af16fcc0 100644
--- a/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
+++ b/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -256,7 +257,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
}
std::vector<unsigned int> verticesFound;
- const float fLimit = cosf(configMaxAngle);
+ const float fLimit = std::cos(configMaxAngle);
std::vector<unsigned int> closeVertices;
// in the second pass we now smooth out all tangents and bitangents at the same local position
diff --git a/src/3rdparty/assimp/code/CalcTangentsProcess.h b/src/3rdparty/assimp/code/CalcTangentsProcess.h
index 4a6122668..a22785639 100644
--- a/src/3rdparty/assimp/code/CalcTangentsProcess.h
+++ b/src/3rdparty/assimp/code/CalcTangentsProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ColladaExporter.cpp b/src/3rdparty/assimp/code/ColladaExporter.cpp
index 14534ad72..4a10d5845 100644
--- a/src/3rdparty/assimp/code/ColladaExporter.cpp
+++ b/src/3rdparty/assimp/code/ColladaExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -38,17 +39,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-
-
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
-#include "ColladaExporter.h"
+#include "ColladaExporter.h"
#include "Bitmap.h"
#include "fast_atof.h"
-#include "SceneCombiner.h"
-#include "DefaultIOSystem.h"
+#include <assimp/SceneCombiner.h>
+#include "StringUtils.h"
#include "XMLTools.h"
+#include <assimp/DefaultIOSystem.h>
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/scene.h>
@@ -58,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <ctime>
#include <set>
+#include <vector>
+#include <iostream>
using namespace Assimp;
@@ -66,13 +68,17 @@ 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, const ExportProperties* pProperties)
+void ExportSceneCollada(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));
// invoke the exporter
ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file);
+
+ if (iDoTheExportThing.mOutput.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+ }
// we're still here - export successfully completed. Write result to the given IOSYstem
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
@@ -102,7 +108,7 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co
// set up strings
endstr = "\n";
- // start writing
+ // start writing the file
WriteFile();
}
@@ -132,8 +138,12 @@ void ColladaExporter::WriteFile()
WriteLightsLibrary();
WriteMaterials();
WriteGeometryLibrary();
+ WriteControllerLibrary();
WriteSceneLibrary();
+
+ // customized, Writes the animation library
+ WriteAnimationsLibrary();
// useless Collada fu at the end, just in case we haven't had enough indirections, yet.
mOutput << startstr << "<scene>" << endstr;
@@ -149,7 +159,7 @@ void ColladaExporter::WriteFile()
// Writes the asset header
void ColladaExporter::WriteHeader()
{
- static const float epsilon = 0.00001f;
+ static const ai_real epsilon = ai_real( 0.00001 );
static const aiQuaternion x_rot(aiMatrix3x3(
0, -1, 0,
1, 0, 0,
@@ -176,9 +186,9 @@ void ColladaExporter::WriteHeader()
bool add_root_node = false;
- float scale = 1.0;
+ ai_real 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);
+ scale = (ai_real) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0);
} else {
add_root_node = true;
}
@@ -451,7 +461,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light){
srcLight->mFalloffAngle);
*/
- const float fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone);
+ const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone);
mOutput << startstr <<"<falloff_angle sid=\"fall_off_angle\">"
<< fallOffAngle
<<"</falloff_angle>" << endstr;
@@ -524,7 +534,7 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
} else
{
if( pKey )
- poSurface.exist = pSrcMat->Get( pKey, pType, pIndex, poSurface.color) == aiReturn_SUCCESS;
+ poSurface.exist = pSrcMat->Get( pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
}
}
@@ -549,7 +559,7 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin
std::stringstream imageUrlEncoded;
for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
{
- if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
+ if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' )
imageUrlEncoded << *it;
else
imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
@@ -636,9 +646,24 @@ void ColladaExporter::WriteMaterials()
const aiMaterial* mat = mScene->mMaterials[a];
aiString name;
- if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
+ if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) {
name = "mat";
- materials[a].name = std::string( "m") + std::to_string(a) + name.C_Str();
+ materials[a].name = std::string( "m") + to_string(a) + name.C_Str();
+ } else {
+ // try to use the material's name if no other material has already taken it, else append #
+ std::string testName = name.C_Str();
+ size_t materialCountWithThisName = 0;
+ for( size_t i = 0; i < a; i ++ ) {
+ if( materials[i].name == testName ) {
+ materialCountWithThisName ++;
+ }
+ }
+ if( materialCountWithThisName == 0 ) {
+ materials[a].name = name.C_Str();
+ } else {
+ materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName);
+ }
+ }
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
if( !isalnum_C( *it ) ) {
*it = '_';
@@ -676,7 +701,6 @@ void ColladaExporter::WriteMaterials()
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;
}
@@ -772,6 +796,177 @@ void ColladaExporter::WriteMaterials()
}
// ------------------------------------------------------------------------------------------------
+// Writes the controller library
+void ColladaExporter::WriteControllerLibrary()
+{
+ mOutput << startstr << "<library_controllers>" << endstr;
+ PushTag();
+
+ for( size_t a = 0; a < mScene->mNumMeshes; ++a)
+ WriteController( a);
+
+ PopTag();
+ mOutput << startstr << "</library_controllers>" << endstr;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Writes a skin controller of the given mesh
+void ColladaExporter::WriteController( size_t 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;
+
+ if ( mesh->mNumBones == 0 )
+ return;
+
+ mOutput << startstr << "<controller id=\"" << idstrEscaped << "-skin\" ";
+ mOutput << "name=\"skinCluster" << pIndex << "\">"<< endstr;
+ PushTag();
+
+ mOutput << startstr << "<skin source=\"#" << idstrEscaped << "\">" << endstr;
+ PushTag();
+
+ // bind pose matrix
+ mOutput << startstr << "<bind_shape_matrix>" << endstr;
+ PushTag();
+
+ // I think it is identity in general cases.
+ aiMatrix4x4 mat;
+ mOutput << startstr << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << endstr;
+ mOutput << startstr << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << endstr;
+ mOutput << startstr << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << endstr;
+ mOutput << startstr << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4 << endstr;
+
+ PopTag();
+ mOutput << startstr << "</bind_shape_matrix>" << endstr;
+
+ mOutput << startstr << "<source id=\"" << idstrEscaped << "-skin-joints\" name=\"" << idstrEscaped << "-skin-joints\">" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<Name_array id=\"" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">";
+
+ for( size_t i = 0; i < mesh->mNumBones; ++i )
+ mOutput << XMLEscape(mesh->mBones[i]->mName.C_Str()) << " ";
+
+ mOutput << "</Name_array>" << endstr;
+
+ mOutput << startstr << "<technique_common>" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<accessor source=\"#" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\" stride=\"" << 1 << "\">" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<param name=\"JOINT\" type=\"Name\"></param>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</accessor>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</technique_common>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</source>" << endstr;
+
+ std::vector<ai_real> bind_poses;
+ bind_poses.reserve(mesh->mNumBones * 16);
+ for(unsigned int i = 0; i < mesh->mNumBones; ++i)
+ for( unsigned int j = 0; j < 4; ++j)
+ bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4);
+
+ WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16);
+
+ bind_poses.clear();
+
+ std::vector<ai_real> skin_weights;
+ skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones);
+ for( size_t i = 0; i < mesh->mNumBones; ++i)
+ for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
+ skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight);
+
+ WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size());
+
+ skin_weights.clear();
+
+ mOutput << startstr << "<joints>" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\"></input>" << endstr;
+ mOutput << startstr << "<input semantic=\"INV_BIND_MATRIX\" source=\"#" << idstrEscaped << "-skin-bind_poses\"></input>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</joints>" << endstr;
+
+ mOutput << startstr << "<vertex_weights count=\"" << mesh->mNumVertices << "\">" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\" offset=\"0\"></input>" << endstr;
+ mOutput << startstr << "<input semantic=\"WEIGHT\" source=\"#" << idstrEscaped << "-skin-weights\" offset=\"1\"></input>" << endstr;
+
+ mOutput << startstr << "<vcount>";
+
+ std::vector<ai_uint> num_influences(mesh->mNumVertices, (ai_uint)0);
+ for( size_t i = 0; i < mesh->mNumBones; ++i)
+ for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
+ ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId];
+
+ for( size_t i = 0; i < mesh->mNumVertices; ++i)
+ mOutput << num_influences[i] << " ";
+
+ mOutput << "</vcount>" << endstr;
+
+ mOutput << startstr << "<v>";
+
+ ai_uint joint_weight_indices_length = 0;
+ std::vector<ai_uint> accum_influences;
+ accum_influences.reserve(num_influences.size());
+ for( size_t i = 0; i < num_influences.size(); ++i)
+ {
+ accum_influences.push_back(joint_weight_indices_length);
+ joint_weight_indices_length += num_influences[i];
+ }
+
+ ai_uint weight_index = 0;
+ std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1);
+ for( unsigned int i = 0; i < mesh->mNumBones; ++i)
+ for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
+ {
+ unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId;
+ for( ai_uint k = 0; k < num_influences[vId]; ++k)
+ {
+ if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1)
+ {
+ joint_weight_indices[2 * (accum_influences[vId] + k)] = i;
+ joint_weight_indices[2 * (accum_influences[vId] + k) + 1] = weight_index;
+ break;
+ }
+ }
+ ++weight_index;
+ }
+
+ for( size_t i = 0; i < joint_weight_indices.size(); ++i)
+ mOutput << joint_weight_indices[i] << " ";
+
+ num_influences.clear();
+ accum_influences.clear();
+ joint_weight_indices.clear();
+
+ mOutput << "</v>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</vertex_weights>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</skin>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</controller>" << endstr;
+}
+
+// ------------------------------------------------------------------------------------------------
// Writes the geometry library
void ColladaExporter::WriteGeometryLibrary()
{
@@ -793,8 +988,8 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
const std::string idstr = GetMeshId( pIndex);
const std::string idstrEscaped = XMLEscape(idstr);
- if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
- return;
+ if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
+ return;
// opening tag
mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
@@ -804,45 +999,33 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
PushTag();
// Positions
- WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices);
+ WriteFloatArray( idstr + "-positions", FloatType_Vector, (ai_real*) mesh->mVertices, mesh->mNumVertices);
// Normals, if any
if( mesh->HasNormals() )
- WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices);
+ WriteFloatArray( idstr + "-normals", FloatType_Vector, (ai_real*) mesh->mNormals, mesh->mNumVertices);
// texture coords
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
{
- if( mesh->HasTextureCoords( a) )
+ if( mesh->HasTextureCoords(static_cast<unsigned int>(a)) )
{
- WriteFloatArray( idstr + "-tex" + std::to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
- (float*) mesh->mTextureCoords[a], mesh->mNumVertices);
+ WriteFloatArray( idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
+ (ai_real*) 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);
+ if( mesh->HasVertexColors(static_cast<unsigned int>(a)) )
+ WriteFloatArray( idstr + "-color" + to_string(a), FloatType_Color, (ai_real*) mesh->mColors[a], mesh->mNumVertices);
}
// assemble vertex structure
+ // Only write input for POSITION since we will write other as shared inputs in polygon definition
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;
@@ -861,6 +1044,19 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << 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(static_cast<unsigned int>(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(static_cast<unsigned int>(a) ) )
+ mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " << "set=\"" << a << "\"" << " />" << endstr;
+ }
+
mOutput << startstr << "<p>";
for( size_t a = 0; a < mesh->mNumFaces; ++a )
{
@@ -882,10 +1078,17 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+ if( mesh->HasNormals() )
+ mOutput << startstr << "<input offset=\"0\" 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 offset=\"0\" semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" set=\"" << a << "\" />" << endstr;
+ if( mesh->HasTextureCoords(static_cast<unsigned int>(a)) )
+ mOutput << startstr << "<input offset=\"0\" 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(static_cast<unsigned int>(a) ) )
+ mOutput << startstr << "<input offset=\"0\" semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " << "set=\"" << a << "\"" << " />" << endstr;
}
mOutput << startstr << "<vcount>";
@@ -918,7 +1121,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
// ------------------------------------------------------------------------------------------------
// Writes a float array of the given type
-void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount)
+void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount)
{
size_t floatsPerElement = 0;
switch( pType )
@@ -927,6 +1130,9 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
case FloatType_TexCoord2: floatsPerElement = 2; break;
case FloatType_TexCoord3: floatsPerElement = 3; break;
case FloatType_Color: floatsPerElement = 3; break;
+ case FloatType_Mat4x4: floatsPerElement = 16; break;
+ case FloatType_Weight: floatsPerElement = 1; break;
+ case FloatType_Time: floatsPerElement = 1; break;
default:
return;
}
@@ -995,7 +1201,21 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
mOutput << startstr << "<param name=\"G\" type=\"float\" />" << endstr;
mOutput << startstr << "<param name=\"B\" type=\"float\" />" << endstr;
break;
- }
+
+ case FloatType_Mat4x4:
+ mOutput << startstr << "<param name=\"TRANSFORM\" type=\"float4x4\" />" << endstr;
+ break;
+
+ case FloatType_Weight:
+ mOutput << startstr << "<param name=\"WEIGHT\" type=\"float\" />" << endstr;
+ break;
+
+ // customized, add animation related
+ case FloatType_Time:
+ mOutput << startstr << "<param name=\"TIME\" type=\"float\" />" << endstr;
+ break;
+
+ }
PopTag();
mOutput << startstr << "</accessor>" << endstr;
@@ -1025,7 +1245,172 @@ void ColladaExporter::WriteSceneLibrary()
PopTag();
mOutput << startstr << "</library_visual_scenes>" << endstr;
}
-
+// ------------------------------------------------------------------------------------------------
+void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
+{
+ const aiAnimation * anim = mScene->mAnimations[pIndex];
+
+ if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 )
+ return;
+
+ const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() );
+ std::string idstr = anim->mName.C_Str();
+ std::string ending = std::string( "AnimId" ) + to_string(pIndex);
+ if (idstr.length() >= ending.length()) {
+ if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) {
+ idstr = idstr + ending;
+ }
+ } else {
+ idstr = idstr + ending;
+ }
+
+ const std::string idstrEscaped = XMLEscape(idstr);
+
+ mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
+ PushTag();
+
+ for (size_t a = 0; a < anim->mNumChannels; ++a) {
+ const aiNodeAnim * nodeAnim = anim->mChannels[a];
+
+ // sanity check
+ if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
+
+ {
+ const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input");
+
+ std::vector<ai_real> frames;
+ for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
+ frames.push_back(static_cast<ai_real>(nodeAnim->mPositionKeys[i].mTime));
+ }
+
+ WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size());
+ frames.clear();
+ }
+
+ {
+ const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output");
+
+ std::vector<ai_real> keyframes;
+ keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
+ for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
+
+ aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
+ aiMatrix4x4 ScalingM; // identity
+ ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
+
+ aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue;
+ aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() );
+ aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1);
+
+ aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue;
+ aiMatrix4x4 TranslationM; // identity
+ TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z;
+
+ // Combine the above transformations
+ aiMatrix4x4 mat = TranslationM * RotationM * ScalingM;
+
+ for( unsigned int j = 0; j < 4; ++j) {
+ keyframes.insert(keyframes.end(), mat[j], mat[j] + 4);
+ }
+ }
+
+ WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16);
+ }
+
+ {
+ std::vector<std::string> names;
+ for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
+ if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT
+ || nodeAnim->mPreState == aiAnimBehaviour_LINEAR
+ || nodeAnim->mPreState == aiAnimBehaviour_REPEAT
+ ) {
+ names.push_back( "LINEAR" );
+ } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) {
+ names.push_back( "STEP" );
+ }
+ }
+
+ const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
+ std::string arrayId = node_idstr + "-array";
+
+ mOutput << startstr << "<source id=\"" << XMLEscape(node_idstr) << "\">" << endstr;
+ PushTag();
+
+ // source array
+ mOutput << startstr << "<Name_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << names.size() << "\"> ";
+ for( size_t a = 0; a < names.size(); ++a ) {
+ mOutput << names[a] << " ";
+ }
+ mOutput << "</Name_array>" << endstr;
+
+ mOutput << startstr << "<technique_common>" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<accessor source=\"#" << XMLEscape(arrayId) << "\" count=\"" << names.size() << "\" stride=\"" << 1 << "\">" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<param name=\"INTERPOLATION\" type=\"name\"></param>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</accessor>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</technique_common>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</source>" << endstr;
+ }
+
+ }
+
+ for (size_t a = 0; a < anim->mNumChannels; ++a) {
+ const aiNodeAnim * nodeAnim = anim->mChannels[a];
+
+ {
+ // samplers
+ const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler");
+ mOutput << startstr << "<sampler id=\"" << XMLEscape(node_idstr) << "\">" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<input semantic=\"INPUT\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr;
+ mOutput << startstr << "<input semantic=\"OUTPUT\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr;
+ mOutput << startstr << "<input semantic=\"INTERPOLATION\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</sampler>" << endstr;
+ }
+ }
+
+ for (size_t a = 0; a < anim->mNumChannels; ++a) {
+ const aiNodeAnim * nodeAnim = anim->mChannels[a];
+
+ {
+ // channels
+ mOutput << startstr << "<channel source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLEscape(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr;
+ }
+ }
+
+ PopTag();
+ mOutput << startstr << "</animation>" << endstr;
+
+}
+// ------------------------------------------------------------------------------------------------
+void ColladaExporter::WriteAnimationsLibrary()
+{
+ const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
+
+ if ( mScene->mNumAnimations > 0 ) {
+ mOutput << startstr << "<library_animations>" << endstr;
+ PushTag();
+
+ // start recursive write at the root node
+ for( size_t a = 0; a < mScene->mNumAnimations; ++a)
+ WriteAnimationLibrary( a );
+
+ PopTag();
+ mOutput << startstr << "</library_animations>" << endstr;
+ }
+}
// ------------------------------------------------------------------------------------------------
// Helper to find a bone by name in the scene
aiBone* findBone( const aiScene* scene, const char * name) {
@@ -1042,6 +1427,59 @@ aiBone* findBone( const aiScene* scene, const char * name) {
}
// ------------------------------------------------------------------------------------------------
+const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone)
+{
+ if ( aNode && bone && aNode->mName == bone->mName ) {
+ return aNode;
+ }
+
+ if ( aNode && bone ) {
+ for (unsigned int i=0; i < aNode->mNumChildren; ++i) {
+ aiNode * aChild = aNode->mChildren[i];
+ const aiNode * foundFromChild = 0;
+ if ( aChild ) {
+ foundFromChild = findBoneNode( aChild, bone );
+ if ( foundFromChild ) return foundFromChild;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh)
+{
+ std::set<const aiNode*> topParentBoneNodes;
+ if ( mesh && mesh->mNumBones > 0 ) {
+ for (unsigned int i=0; i < mesh->mNumBones; ++i) {
+ aiBone * bone = mesh->mBones[i];
+
+ const aiNode * node = findBoneNode( scene->mRootNode, bone);
+ if ( node ) {
+ while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) {
+ node = node->mParent;
+ }
+ topParentBoneNodes.insert( node );
+ }
+ }
+ }
+
+ if ( !topParentBoneNodes.empty() ) {
+ const aiNode * parentBoneNode = *topParentBoneNodes.begin();
+ if ( topParentBoneNodes.size() == 1 ) {
+ return parentBoneNode;
+ } else {
+ for (auto it : topParentBoneNodes) {
+ if ( it->mParent ) return it->mParent;
+ }
+ return parentBoneNode;
+ }
+ }
+
+ return NULL;
+}
+
+// ------------------------------------------------------------------------------------------------
// Recursively writes the given node
void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
{
@@ -1056,16 +1494,34 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
// 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;
+ bool is_joint, is_skeleton_root = false;
if (NULL == findBone(pScene, pNode->mName.C_Str())) {
node_type = "NODE";
+ is_joint = false;
} else {
node_type = "JOINT";
+ is_joint = true;
+ if(!pNode->mParent || NULL == findBone(pScene, pNode->mParent->mName.C_Str()))
+ is_skeleton_root = true;
}
const std::string node_name_escaped = XMLEscape(pNode->mName.data);
+ /* // customized, Note! the id field is crucial for inter-xml look up, it cannot be replaced with sid ?!
mOutput << startstr
- << "<node id=\"" << node_name_escaped
- << "\" name=\"" << node_name_escaped
+ << "<node ";
+ if(is_skeleton_root)
+ mOutput << "id=\"" << "skeleton_root" << "\" "; // For now, only support one skeleton in a scene.
+ mOutput << (is_joint ? "s" : "") << "id=\"" << node_name_escaped;
+ */
+ mOutput << startstr << "<node ";
+ if(is_skeleton_root) {
+ mOutput << "id=\"" << node_name_escaped << "\" " << (is_joint ? "sid=\"" + node_name_escaped +"\"" : "") ; // For now, only support one skeleton in a scene.
+ mFoundSkeletonRootNodeID = node_name_escaped;
+ } else {
+ mOutput << "id=\"" << node_name_escaped << "\" " << (is_joint ? "sid=\"" + node_name_escaped +"\"": "") ;
+ }
+
+ mOutput << " name=\"" << node_name_escaped
<< "\" type=\"" << node_type
<< "\">" << endstr;
PushTag();
@@ -1073,7 +1529,11 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
// 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>";
+
+ // customized, sid should be 'matrix' to match with loader code.
+ //mOutput << startstr << "<matrix sid=\"transform\">";
+ mOutput << startstr << "<matrix sid=\"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 << " ";
@@ -1101,33 +1561,56 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
for( size_t a = 0; a < pNode->mNumMeshes; ++a )
{
const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]];
- // do not instanciate mesh if empty. I wonder how this could happen
- if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
- continue;
- 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;
+ // do not instantiate mesh if empty. I wonder how this could happen
+ if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
+ continue;
+
+ if( mesh->mNumBones == 0 )
+ {
+ mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
+ PushTag();
+ }
+ else
+ {
+ mOutput << startstr
+ << "<instance_controller url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "-skin\">"
+ << endstr;
+ PushTag();
+
+ // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node.
+ // use the first bone to find skeleton root
+ const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh );
+ if ( skeletonRootBoneNode ) {
+ mFoundSkeletonRootNodeID = XMLEscape( skeletonRootBoneNode->mName.C_Str() );
+ }
+ mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr;
+ }
+ 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( static_cast<unsigned int>(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();
+ if( mesh->mNumBones == 0)
+ mOutput << startstr << "</instance_geometry>" << endstr;
+ else
+ mOutput << startstr << "</instance_controller>" << endstr;
}
// recurse into subnodes
diff --git a/src/3rdparty/assimp/code/ColladaExporter.h b/src/3rdparty/assimp/code/ColladaExporter.h
index 5e73628eb..e7a4a9b5d 100644
--- a/src/3rdparty/assimp/code/ColladaExporter.h
+++ b/src/3rdparty/assimp/code/ColladaExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <map>
+#include "StringUtils.h"
+
struct aiScene;
struct aiNode;
@@ -99,30 +102,48 @@ protected:
void WriteSpotLight(const aiLight *const light);
void WriteAmbienttLight(const aiLight *const light);
+ /// Writes the controller library
+ void WriteControllerLibrary();
+
+ /// Writes a skin controller of the given mesh
+ void WriteController( size_t pIndex);
+
/// Writes the geometry library
void WriteGeometryLibrary();
/// Writes the given mesh
void WriteGeometry( size_t pIndex);
- enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
+ //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
+ // customized to add animation related type
+ enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time };
/// Writes a float array of the given type
- void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount);
+ void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount);
/// Writes the scene library
void WriteSceneLibrary();
+ // customized, Writes the animation library
+ void WriteAnimationsLibrary();
+ void WriteAnimationLibrary( size_t pIndex);
+ std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call.
+
/// 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); }
+ 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); }
+ std::string GetMeshId( size_t pIndex) const {
+ return std::string( "meshId" ) + to_string(pIndex);
+ }
public:
/// Stringstream to write all output into
@@ -160,10 +181,10 @@ protected:
struct Property
{
bool exist;
- float value;
+ ai_real value;
Property()
: exist(false)
- , value(0.0f)
+ , value(0.0)
{}
};
diff --git a/src/3rdparty/assimp/code/ColladaHelper.h b/src/3rdparty/assimp/code/ColladaHelper.h
index 130363186..e691a6062 100644
--- a/src/3rdparty/assimp/code/ColladaHelper.h
+++ b/src/3rdparty/assimp/code/ColladaHelper.h
@@ -4,7 +4,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_COLLADAHELPER_H_INC
#define AI_COLLADAHELPER_H_INC
-#include <string>
#include <map>
#include <vector>
#include <stdint.h>
@@ -103,12 +103,13 @@ enum MorphMethod
Relative
};
+
/** 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
+ ai_real f[16]; ///< Interpretation of data depends on the type of the transformation
};
/** A collada camera. */
@@ -130,16 +131,16 @@ struct Camera
bool mOrtho;
//! Horizontal field of view in degrees
- float mHorFov;
+ ai_real mHorFov;
//! Vertical field of view in degrees
- float mVerFov;
+ ai_real mVerFov;
//! Screen aspect
- float mAspect;
+ ai_real mAspect;
//! Near& far z
- float mZNear, mZFar;
+ ai_real mZNear, mZFar;
};
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
@@ -166,21 +167,21 @@ struct Light
aiColor3D mColor;
//! Light attenuation
- float mAttConstant,mAttLinear,mAttQuadratic;
+ ai_real mAttConstant,mAttLinear,mAttQuadratic;
//! Spot light falloff
- float mFalloffAngle;
- float mFalloffExponent;
+ ai_real mFalloffAngle;
+ ai_real mFalloffExponent;
// -----------------------------------------------------
// FCOLLADA extension from here
//! ... related stuff from maja and max extensions
- float mPenumbraAngle;
- float mOuterAngle;
+ ai_real mPenumbraAngle;
+ ai_real mOuterAngle;
//! Common light intensity
- float mIntensity;
+ ai_real mIntensity;
};
/** Short vertex index description */
@@ -289,7 +290,7 @@ struct Node
struct Data
{
bool mIsStringArray;
- std::vector<float> mValues;
+ std::vector<ai_real> mValues;
std::vector<std::string> mStrings;
};
@@ -301,7 +302,7 @@ struct Accessor
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.
+ size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's 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
@@ -391,7 +392,7 @@ enum PrimitiveType
Prim_Polygon
};
-/** A skeleton or morph controller to deform a mesh with the use of joints or morph targets */
+/** A skeleton controller to deform a mesh with the use of joints */
struct Controller
{
// controller type
@@ -400,14 +401,14 @@ struct Controller
// Morphing method if type is Morph
MorphMethod mMethod;
- // the URL of the mesh deformed by the controller.
- std::string mMeshId;
+ // the URL of the mesh deformed by the controller.
+ std::string mMeshId;
// 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];
+ ai_real mBindShapeMatrix[16];
// accessor URL of the joint inverse bind matrices
std::string mJointOffsetMatrixSource;
@@ -420,8 +421,8 @@ struct Controller
// 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;
+ // JointIndex-WeightIndex pairs for all vertices
+ std::vector< std::pair<size_t, size_t> > mWeights;
std::string mMorphTarget;
std::string mMorphWeight;
@@ -513,11 +514,11 @@ struct Sampler
/** Weighting factor
*/
- float mWeighting;
+ ai_real mWeighting;
/** Mixing factor from OKINO
*/
- float mMixWithPrevious;
+ ai_real mMixWithPrevious;
};
/** A collada effect. Can contain about anything according to the Collada spec,
@@ -536,8 +537,8 @@ struct Effect
mTexTransparent, mTexBump, mTexReflective;
// Scalar factory
- float mShininess, mRefractIndex, mReflectivity;
- float mTransparency;
+ ai_real mShininess, mRefractIndex, mReflectivity;
+ ai_real mTransparency;
bool mHasTransparency;
bool mRGBTransparency;
bool mInvertTransparency;
@@ -591,21 +592,21 @@ struct Image
/** An animation channel. */
struct AnimationChannel
{
- /** URL of the data to animate. Could be about anything, but we support only the
- * "NodeID/TransformID.SubElement" notation
- */
- std::string mTarget;
+ /** URL of the data to animate. Could be about anything, but we support only the
+ * "NodeID/TransformID.SubElement" notation
+ */
+ std::string mTarget;
- /** Source URL of the time values. Collada calls them "input". Meh. */
- 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 time values. Collada calls them "input". Meh. */
+ 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;
};
/** An animation. Container for 0-x animation channels or 0-x animations */
@@ -679,13 +680,21 @@ struct ChannelEntry
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
- const Collada::Data* mTimeData; ///> Source data array for the time values
- const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values
- const Collada::Data* mValueData; ///> Source datat array for the key value values
-
- ChannelEntry() { mChannel = NULL; mSubElement = 0; }
+ // resolved data references
+ const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values
+ const Collada::Data* mTimeData; ///> Source data array for the time values
+ const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values
+ const Collada::Data* mValueData; ///> Source datat array for the key value values
+
+ ChannelEntry()
+ : mChannel()
+ , mTransformIndex()
+ , mSubElement()
+ , mTimeAccessor()
+ , mTimeData()
+ , mValueAccessor()
+ , mValueData()
+ {}
};
} // end of namespace Collada
diff --git a/src/3rdparty/assimp/code/ColladaLoader.cpp b/src/3rdparty/assimp/code/ColladaLoader.cpp
index 50d5116a6..d2141c374 100644
--- a/src/3rdparty/assimp/code/ColladaLoader.cpp
+++ b/src/3rdparty/assimp/code/ColladaLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -49,8 +50,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
-#include "ColladaParser.h"
+#include <assimp/importerdesc.h>
+#include "ColladaParser.h"
#include "fast_atof.h"
#include "ParsingUtils.h"
#include "SkeletonMeshBuilder.h"
@@ -58,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "time.h"
#include "math.h"
+#include <algorithm>
#include <numeric>
-#include "Defines.h"
-
+#include <assimp/Defines.h>
using namespace Assimp;
using namespace Assimp::Formatter;
@@ -82,15 +84,15 @@ static const aiImporterDesc desc = {
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader()
: mFileName()
- , mMeshIndexByID()
- , mMaterialIndexByName()
- , mMeshes()
- , newMats()
- , mCameras()
- , mLights()
- , mTextures()
- , mAnims()
- , noSkeletonMesh( false )
+ , mMeshIndexByID()
+ , mMaterialIndexByName()
+ , mMeshes()
+ , newMats()
+ , mCameras()
+ , mLights()
+ , mTextures()
+ , mAnims()
+ , noSkeletonMesh( false )
, ignoreUpDirection(false)
, mNodeNameCounter( 0 )
{}
@@ -117,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
* might be NULL and it's our duty to return true here.
*/
if (!pIOHandler)return true;
- const char* tokens[] = {"collada"};
+ const char* tokens[] = {"<collada"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
@@ -130,7 +132,6 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
}
-
// ------------------------------------------------------------------------------------------------
// Get file extension list
const aiImporterDesc* ColladaLoader::GetInfo () const
@@ -241,7 +242,7 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
ResolveNodeInstances(pParser,pNode,instances);
// add children. first the *real* ones
- node->mNumChildren = pNode->mChildren.size()+instances.size();
+ node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size()+instances.size());
node->mChildren = new aiNode*[node->mNumChildren];
for( size_t a = 0; a < pNode->mChildren.size(); a++)
@@ -421,13 +422,13 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
out->mHorizontalFOV = 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));
+ out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
+ std::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 *
- tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
+ out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect *
+ std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
}
// Collada uses degrees, we use radians
@@ -507,7 +508,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
unsigned int matIdx;
if( matIt != mMaterialIndexByName.end())
- matIdx = matIt->second;
+ matIdx = static_cast<unsigned int>(matIt->second);
else
matIdx = 0;
@@ -554,11 +555,19 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
}
// now place all mesh references we gathered in the target node
- pTarget->mNumMeshes = newMeshRefs.size();
+ pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
if( newMeshRefs.size())
{
+ struct UIntTypeConverter
+ {
+ unsigned int operator()(const size_t& v) const
+ {
+ return static_cast<unsigned int>(v);
+ }
+ };
+
pTarget->mMeshes = new unsigned int[pTarget->mNumMeshes];
- std::copy( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes);
+ std::transform( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes, UIntTypeConverter());
}
}
@@ -586,86 +595,86 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
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);
-
- // copy positions
- dstMesh->mNumVertices = numVertices;
- dstMesh->mVertices = new aiVector3D[numVertices];
- 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
- // 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);
- }
-
- // 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);
- }
-
- // 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);
- }
-
- // same for texturecoords, as many as we have
- // empty slots are not allowed, need to pack and adjust UV indexes accordingly
- for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
- {
- if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices)
- {
- 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;
- }
- }
-
- // same for vertex colors, as many as we have. again the same packing to avoid empty slots
- for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
- {
- if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices)
- {
- dstMesh->mColors[real] = new aiColor4D[numVertices];
- std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
- ++real;
- }
- }
-
- // create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex
- size_t vertex = 0;
- dstMesh->mNumFaces = pSubMesh.mNumFaces;
- dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
- for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
- {
- size_t s = pSrcMesh->mFaceSize[ pStartFace + a];
- aiFace& face = dstMesh->mFaces[a];
- face.mNumIndices = s;
- face.mIndices = new unsigned int[s];
- for( size_t b = 0; b < s; ++b)
- face.mIndices[b] = vertex++;
- }
+ // count the vertices addressed by its faces
+ const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
+ pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0));
+
+ // copy positions
+ dstMesh->mNumVertices = static_cast<unsigned int>(numVertices);
+ dstMesh->mVertices = new aiVector3D[numVertices];
+ 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
+ // 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);
+ }
+
+ // 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);
+ }
+
+ // 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);
+ }
+
+ // same for texturecoords, as many as we have
+ // empty slots are not allowed, need to pack and adjust UV indexes accordingly
+ for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
+ {
+ if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices)
+ {
+ 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;
+ }
+ }
+
+ // same for vertex colors, as many as we have. again the same packing to avoid empty slots
+ for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
+ {
+ if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices)
+ {
+ dstMesh->mColors[real] = new aiColor4D[numVertices];
+ std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
+ ++real;
+ }
+ }
+
+ // create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex
+ size_t vertex = 0;
+ dstMesh->mNumFaces = static_cast<unsigned int>(pSubMesh.mNumFaces);
+ dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
+ for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
+ {
+ size_t s = pSrcMesh->mFaceSize[ pStartFace + a];
+ aiFace& face = dstMesh->mFaces[a];
+ face.mNumIndices = static_cast<unsigned int>(s);
+ face.mIndices = new unsigned int[s];
+ for( size_t b = 0; b < s; ++b)
+ face.mIndices[b] = static_cast<unsigned int>(vertex++);
+ }
// create morph target meshes if any
std::vector<aiMesh*> targetMeshes;
std::vector<float> targetWeights;
- Collada::MorphMethod method;
+ Collada::MorphMethod method = Collada::Normalized;
for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); it++)
@@ -719,7 +728,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
? aiMorphingMethod_MORPH_RELATIVE
: aiMorphingMethod_MORPH_NORMALIZED;
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
- dstMesh->mNumAnimMeshes = animMeshes.size();
+ dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
for (unsigned int i = 0; i < animMeshes.size(); i++)
dstMesh->mAnimMeshes[i] = animMeshes.at(i);
}
@@ -728,8 +737,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
if( pSrcController && pSrcController->mType == Collada::Skin)
{
// 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");
+// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
+// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
// resolve references - joint names
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
@@ -782,13 +791,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
size_t jointIndex = iit->first;
size_t vertexIndex = iit->second;
- float weight = ReadFloat( weightsAcc, weights, vertexIndex, 0);
+ ai_real weight = ReadFloat( weightsAcc, weights, vertexIndex, 0);
// one day I gonna kill that XSI Collada exporter
if( weight > 0.0f)
{
aiVertexWeight w;
- w.mVertexId = a - pStartVertex;
+ w.mVertexId = static_cast<unsigned int>(a - pStartVertex);
w.mWeight = weight;
dstBones[jointIndex].push_back( w);
}
@@ -802,7 +811,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
numRemainingBones++;
// create bone array and copy bone weights one by one
- dstMesh->mNumBones = numRemainingBones;
+ dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones);
dstMesh->mBones = new aiBone*[numRemainingBones];
size_t boneCount = 0;
for( size_t a = 0; a < numBones; ++a)
@@ -826,7 +835,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
bone->mOffsetMatrix.c2 = ReadFloat( jointMatrixAcc, jointMatrices, a, 9);
bone->mOffsetMatrix.c3 = ReadFloat( jointMatrixAcc, jointMatrices, a, 10);
bone->mOffsetMatrix.c4 = ReadFloat( jointMatrixAcc, jointMatrices, a, 11);
- bone->mNumWeights = dstBones[a].size();
+ bone->mNumWeights = static_cast<unsigned int>(dstBones[a].size());
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
std::copy( dstBones[a].begin(), dstBones[a].end(), bone->mWeights);
@@ -876,7 +885,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// Stores all meshes in the given scene
void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
{
- pScene->mNumMeshes = mMeshes.size();
+ pScene->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
if( mMeshes.size() > 0)
{
pScene->mMeshes = new aiMesh*[mMeshes.size()];
@@ -889,7 +898,7 @@ void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
// Stores all cameras in the given scene
void ColladaLoader::StoreSceneCameras( aiScene* pScene)
{
- pScene->mNumCameras = mCameras.size();
+ pScene->mNumCameras = static_cast<unsigned int>(mCameras.size());
if( mCameras.size() > 0)
{
pScene->mCameras = new aiCamera*[mCameras.size()];
@@ -902,7 +911,7 @@ void ColladaLoader::StoreSceneCameras( aiScene* pScene)
// Stores all lights in the given scene
void ColladaLoader::StoreSceneLights( aiScene* pScene)
{
- pScene->mNumLights = mLights.size();
+ pScene->mNumLights = static_cast<unsigned int>(mLights.size());
if( mLights.size() > 0)
{
pScene->mLights = new aiLight*[mLights.size()];
@@ -915,7 +924,7 @@ void ColladaLoader::StoreSceneLights( aiScene* pScene)
// Stores all textures in the given scene
void ColladaLoader::StoreSceneTextures( aiScene* pScene)
{
- pScene->mNumTextures = mTextures.size();
+ pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
if( mTextures.size() > 0)
{
pScene->mTextures = new aiTexture*[mTextures.size()];
@@ -928,7 +937,7 @@ void ColladaLoader::StoreSceneTextures( aiScene* pScene)
// Stores all materials in the given scene
void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
{
- pScene->mNumMaterials = newMats.size();
+ pScene->mNumMaterials = static_cast<unsigned int>(newMats.size());
if (newMats.size() > 0) {
pScene->mMaterials = new aiMaterial*[newMats.size()];
@@ -969,7 +978,7 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
combinedAnim->mName = aiString( std::string( "combinedAnim_") + char( '0' + a));
combinedAnim->mDuration = templateAnim->mDuration;
combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
- combinedAnim->mNumChannels = collectedAnimIndices.size() + 1;
+ combinedAnim->mNumChannels = static_cast<unsigned int>(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];
@@ -1001,7 +1010,7 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
// now store all anims in the scene
if( !mAnims.empty())
{
- pScene->mNumAnimations = mAnims.size();
+ pScene->mNumAnimations = static_cast<unsigned int>(mAnims.size());
pScene->mAnimations = new aiAnimation*[mAnims.size()];
std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
}
@@ -1097,32 +1106,33 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
std::vector<aiNodeAnim*> anims;
std::vector<aiMeshMorphAnim*> morphAnims;
- for( std::vector<const aiNode*>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit)
- {
- // find all the collada anim channels which refer to the current node
- std::vector<Collada::ChannelEntry> entries;
- std::string nodeName = (*nit)->mName.data;
-
- // find the collada node corresponding to the aiNode
- const Collada::Node* srcNode = FindNode( pParser.mRootNode, nodeName);
-// ai_assert( srcNode != NULL);
- if( !srcNode)
- continue;
-
- // 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)
- {
- const Collada::AnimationChannel& srcChannel = *cit;
- Collada::ChannelEntry entry;
-
- // 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;
+ for( std::vector<const aiNode*>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit)
+ {
+ // find all the collada anim channels which refer to the current node
+ std::vector<Collada::ChannelEntry> entries;
+ std::string nodeName = (*nit)->mName.data;
+
+ // find the collada node corresponding to the aiNode
+ const Collada::Node* srcNode = FindNode( pParser.mRootNode, nodeName);
+// ai_assert( srcNode != NULL);
+ if( !srcNode)
+ continue;
+
+ // 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)
+ {
+ const Collada::AnimationChannel& srcChannel = *cit;
+ Collada::ChannelEntry entry;
+
+ // 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;
// not node transform, but something else. store as unknown animation channel for now
entry.mChannel = &(*cit);
@@ -1139,37 +1149,78 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
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( '.');
- if( dotPos != std::string::npos)
- {
- if( srcChannel.mTarget.find( '.', dotPos+1) != std::string::npos)
- continue;
-
- entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
-
- std::string subElement = srcChannel.mTarget.substr( dotPos+1);
- if( subElement == "ANGLE")
- entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
- else if( subElement == "X")
- entry.mSubElement = 0;
- else if( subElement == "Y")
- entry.mSubElement = 1;
- else if( subElement == "Z")
- entry.mSubElement = 2;
- else
- DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" );
- } else
- {
- // no subelement following, transformId is remaining string
- entry.mTransformId = srcChannel.mTarget.substr( slashPos+1);
- }
-
- // determine which transform step is affected by this channel
- entry.mTransformIndex = SIZE_MAX;
- for( size_t a = 0; a < srcNode->mTransforms.size(); ++a)
- if( srcNode->mTransforms[a].mID == entry.mTransformId)
- entry.mTransformIndex = a;
+ // find the dot that separates the transformID - there should be only one or zero
+ std::string::size_type dotPos = srcChannel.mTarget.find( '.');
+ if( dotPos != std::string::npos)
+ {
+ if( srcChannel.mTarget.find( '.', dotPos+1) != std::string::npos)
+ continue;
+
+ entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
+
+ std::string subElement = srcChannel.mTarget.substr( dotPos+1);
+ if( subElement == "ANGLE")
+ entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
+ else if( subElement == "X")
+ entry.mSubElement = 0;
+ else if( subElement == "Y")
+ entry.mSubElement = 1;
+ else if( subElement == "Z")
+ entry.mSubElement = 2;
+ else
+ DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" );
+ } else
+ {
+ // no subelement following, transformId is remaining string
+ entry.mTransformId = srcChannel.mTarget.substr( slashPos+1);
+ }
+
+ std::string::size_type bracketPos = srcChannel.mTarget.find('(');
+ if (bracketPos != std::string::npos)
+ {
+ entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
+ std::string subElement = srcChannel.mTarget.substr(bracketPos);
+
+ if (subElement == "(0)(0)")
+ entry.mSubElement = 0;
+ else if (subElement == "(1)(0)")
+ entry.mSubElement = 1;
+ else if (subElement == "(2)(0)")
+ entry.mSubElement = 2;
+ else if (subElement == "(3)(0)")
+ entry.mSubElement = 3;
+ else if (subElement == "(0)(1)")
+ entry.mSubElement = 4;
+ else if (subElement == "(1)(1)")
+ entry.mSubElement = 5;
+ else if (subElement == "(2)(1)")
+ entry.mSubElement = 6;
+ else if (subElement == "(3)(1)")
+ entry.mSubElement = 7;
+ else if (subElement == "(0)(2)")
+ entry.mSubElement = 8;
+ else if (subElement == "(1)(2)")
+ entry.mSubElement = 9;
+ else if (subElement == "(2)(2)")
+ entry.mSubElement = 10;
+ else if (subElement == "(3)(2)")
+ entry.mSubElement = 11;
+ else if (subElement == "(0)(3)")
+ entry.mSubElement = 12;
+ else if (subElement == "(1)(3)")
+ entry.mSubElement = 13;
+ else if (subElement == "(2)(3)")
+ entry.mSubElement = 14;
+ else if (subElement == "(3)(3)")
+ entry.mSubElement = 15;
+
+ }
+
+ // determine which transform step is affected by this channel
+ entry.mTransformIndex = SIZE_MAX;
+ for( size_t a = 0; a < srcNode->mTransforms.size(); ++a)
+ if( srcNode->mTransforms[a].mID == entry.mTransformId)
+ entry.mTransformIndex = a;
if( entry.mTransformIndex == SIZE_MAX)
{
@@ -1181,127 +1232,142 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
continue;
}
- entry.mChannel = &(*cit);
- entries.push_back( entry);
- }
-
- // if there's no channel affecting the current node, we skip it
- if( entries.empty())
- continue;
-
- // resolve the data pointers for all anim channels. Find the minimum time while we're at it
- float startTime = 1e20f, endTime = -1e20f;
- for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
- {
- Collada::ChannelEntry& e = *it;
- e.mTimeAccessor = &pParser.ResolveLibraryReference( pParser.mAccessorLibrary, e.mChannel->mSourceTimes);
- e.mTimeData = &pParser.ResolveLibraryReference( pParser.mDataLibrary, e.mTimeAccessor->mSource);
- e.mValueAccessor = &pParser.ResolveLibraryReference( pParser.mAccessorLibrary, e.mChannel->mSourceValues);
- e.mValueData = &pParser.ResolveLibraryReference( pParser.mDataLibrary, e.mValueAccessor->mSource);
-
- // time count and value count must match
- if( e.mTimeAccessor->mCount != e.mValueAccessor->mCount)
- throw DeadlyImportError( format() << "Time count / value count mismatch in animation channel \"" << e.mChannel->mTarget << "\"." );
-
- if( e.mTimeAccessor->mCount > 0 )
- {
- // find bounding times
- startTime = std::min( startTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, 0, 0));
- endTime = std::max( endTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, e.mTimeAccessor->mCount-1, 0));
- }
+ entry.mChannel = &(*cit);
+ entries.push_back( entry);
}
- std::vector<aiMatrix4x4> resultTrafos;
- if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
+ // if there's no channel affecting the current node, we skip it
+ if( entries.empty())
+ continue;
+
+ // resolve the data pointers for all anim channels. Find the minimum time while we're at it
+ ai_real startTime = ai_real( 1e20 ), endTime = ai_real( -1e20 );
+ for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
{
- // create a local transformation chain of the node's transforms
- std::vector<Collada::Transform> transforms = srcNode->mTransforms;
+ Collada::ChannelEntry& e = *it;
+ e.mTimeAccessor = &pParser.ResolveLibraryReference( pParser.mAccessorLibrary, e.mChannel->mSourceTimes);
+ e.mTimeData = &pParser.ResolveLibraryReference( pParser.mDataLibrary, e.mTimeAccessor->mSource);
+ e.mValueAccessor = &pParser.ResolveLibraryReference( pParser.mAccessorLibrary, e.mChannel->mSourceValues);
+ e.mValueData = &pParser.ResolveLibraryReference( pParser.mDataLibrary, e.mValueAccessor->mSource);
+
+ // time count and value count must match
+ if( e.mTimeAccessor->mCount != e.mValueAccessor->mCount)
+ throw DeadlyImportError( format() << "Time count / value count mismatch in animation channel \"" << e.mChannel->mTarget << "\"." );
+
+ if( e.mTimeAccessor->mCount > 0 )
+ {
+ // find bounding times
+ startTime = std::min( startTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, 0, 0));
+ endTime = std::max( endTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, e.mTimeAccessor->mCount-1, 0));
+ }
+ }
- // now for every unique point in time, find or interpolate the key values for that time
- // and apply them to the transform chain. Then the node's present transformation can be calculated.
- float time = startTime;
- while( 1)
+ std::vector<aiMatrix4x4> resultTrafos;
+ if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
+ {
+ // create a local transformation chain of the node's transforms
+ std::vector<Collada::Transform> transforms = srcNode->mTransforms;
+
+ // now for every unique point in time, find or interpolate the key values for that time
+ // and apply them to the transform chain. Then the node's present transformation can be calculated.
+ ai_real time = startTime;
+ while( 1)
+ {
+ for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
{
- for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
+ Collada::ChannelEntry& e = *it;
+
+ // find the keyframe behind the current point in time
+ size_t pos = 0;
+ ai_real postTime = 0.0;
+ while( 1)
{
- Collada::ChannelEntry& e = *it;
+ if( pos >= e.mTimeAccessor->mCount)
+ break;
+ postTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
+ if( postTime >= time)
+ break;
+ ++pos;
+ }
- // skip non-transform types
- if (e.mTransformId.empty())
- continue;
+ pos = std::min( pos, e.mTimeAccessor->mCount-1);
- // find the keyframe behind the current point in time
- size_t pos = 0;
- float postTime = 0.f;
- while( 1)
- {
- if( pos >= e.mTimeAccessor->mCount)
- break;
- postTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
- if( postTime >= time)
- break;
- ++pos;
- }
+ // read values from there
+ ai_real temp[16];
+ for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
+ temp[c] = ReadFloat( *e.mValueAccessor, *e.mValueData, pos, c);
- pos = std::min( pos, e.mTimeAccessor->mCount-1);
+ // if not exactly at the key time, interpolate with previous value set
+ if( postTime > time && pos > 0)
+ {
+ ai_real preTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos-1, 0);
+ ai_real factor = (time - postTime) / (preTime - postTime);
- // read values from there
- float temp[16];
for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
- temp[c] = ReadFloat( *e.mValueAccessor, *e.mValueData, pos, c);
-
- // if not exactly at the key time, interpolate with previous value set
- if( postTime > time && pos > 0)
{
- float preTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos-1, 0);
- float factor = (time - postTime) / (preTime - postTime);
-
- for( size_t c = 0; c < e.mValueAccessor->mSize; ++c)
- {
- float v = ReadFloat( *e.mValueAccessor, *e.mValueData, pos-1, c);
- temp[c] += (v - temp[c]) * factor;
- }
+ ai_real v = ReadFloat( *e.mValueAccessor, *e.mValueData, pos-1, c);
+ temp[c] += (v - temp[c]) * factor;
}
-
- // Apply values to current transformation
- std::copy( temp, temp + e.mValueAccessor->mSize, transforms[e.mTransformIndex].f + e.mSubElement);
}
- // Calculate resulting transformation
- aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms);
+ // Apply values to current transformation
+ std::copy( temp, temp + e.mValueAccessor->mSize, transforms[e.mTransformIndex].f + e.mSubElement);
+ }
- // out of laziness: we store the time in matrix.d4
- mat.d4 = time;
- resultTrafos.push_back( mat);
+ // Calculate resulting transformation
+ aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms);
- // find next point in time to evaluate. That's the closest frame larger than the current in any channel
- float nextTime = 1e20f;
- for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
- {
- Collada::ChannelEntry& e = *it;
+ // out of laziness: we store the time in matrix.d4
+ mat.d4 = time;
+ resultTrafos.push_back( mat);
+
+ // find next point in time to evaluate. That's the closest frame larger than the current in any channel
+ ai_real nextTime = ai_real( 1e20 );
+ for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
+ {
+ Collada::ChannelEntry& channelElement = *it;
- // find the next time value larger than the current
- size_t pos = 0;
- while( pos < e.mTimeAccessor->mCount)
+ // find the next time value larger than the current
+ size_t pos = 0;
+ while( pos < channelElement.mTimeAccessor->mCount)
+ {
+ const ai_real t = ReadFloat( *channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0);
+ if( t > time)
{
- float t = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0);
- if( t > time)
- {
- nextTime = std::min( nextTime, t);
- break;
- }
- ++pos;
+ nextTime = std::min( nextTime, t);
+ break;
}
+ ++pos;
}
- // no more keys on any channel after the current time -> we're done
- if( nextTime > 1e19)
- break;
-
- // else construct next keyframe at this following time point
- time = nextTime;
+ // https://github.com/assimp/assimp/issues/458
+ // Sub-sample axis-angle channels if the delta between two consecutive
+ // key-frame angles is >= 180 degrees.
+ if (transforms[channelElement.mTransformIndex].mType == Collada::TF_ROTATE && channelElement.mSubElement == 3 && pos > 0 && pos < channelElement.mTimeAccessor->mCount) {
+ const ai_real cur_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos, 0);
+ const ai_real last_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos - 1, 0);
+ const ai_real cur_key_time = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0);
+ const ai_real last_key_time = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos - 1, 0);
+ const ai_real last_eval_angle = last_key_angle + (cur_key_angle - last_key_angle) * (time - last_key_time) / (cur_key_time - last_key_time);
+ const ai_real delta = std::abs(cur_key_angle - last_eval_angle);
+ if (delta >= 180.0) {
+ const int subSampleCount = static_cast<int>(std::floor(delta / 90.0));
+ if (cur_key_time != time) {
+ const ai_real nextSampleTime = time + (cur_key_time - time) / subSampleCount;
+ nextTime = std::min(nextTime, nextSampleTime);
+ }
+ }
+ }
}
- }
+
+ // no more keys on any channel after the current time -> we're done
+ if( nextTime > 1e19)
+ break;
+
+ // else construct next keyframe at this following time point
+ time = nextTime;
+ }
+ }
// there should be some keyframes, but we aren't that fixated on valid input data
// ai_assert( resultTrafos.size() > 0);
@@ -1311,9 +1377,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
{
aiNodeAnim* dstAnim = new aiNodeAnim;
dstAnim->mNodeName = nodeName;
- dstAnim->mNumPositionKeys = resultTrafos.size();
- dstAnim->mNumRotationKeys= resultTrafos.size();
- dstAnim->mNumScalingKeys = resultTrafos.size();
+ dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
+ dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
+ dstAnim->mNumScalingKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
@@ -1379,11 +1445,11 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
++morphAnimChannelIndex;
}
- morphAnim->mNumKeys = morphTimeValues.size();
+ morphAnim->mNumKeys = static_cast<unsigned int>(morphTimeValues.size());
morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys];
for (unsigned int key = 0; key < morphAnim->mNumKeys; key++)
{
- morphAnim->mKeys[key].mNumValuesAndWeights = morphChannels.size();
+ morphAnim->mKeys[key].mNumValuesAndWeights = static_cast<unsigned int>(morphChannels.size());
morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()];
morphAnim->mKeys[key].mWeights = new double [morphChannels.size()];
@@ -1400,36 +1466,36 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
}
}
- 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);
- }
- anim->mDuration = 0.0f;
- for( size_t a = 0; a < anims.size(); ++a)
- {
- anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime);
- 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);
- }
- anim->mTicksPerSecond = 1;
- mAnims.push_back( anim);
- }
+ if( !anims.empty() || !morphAnims.empty())
+ {
+ aiAnimation* anim = new aiAnimation;
+ anim->mName.Set( pName);
+ anim->mNumChannels = static_cast<unsigned int>(anims.size());
+ if (anim->mNumChannels > 0)
+ {
+ anim->mChannels = new aiNodeAnim*[anims.size()];
+ std::copy( anims.begin(), anims.end(), anim->mChannels);
+ }
+ anim->mNumMorphMeshChannels = static_cast<unsigned int>(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)
+ {
+ anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime);
+ 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);
+ }
+ anim->mTicksPerSecond = 1;
+ mAnims.push_back( anim);
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -1469,7 +1535,7 @@ void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
_AI_MATKEY_TEXBLEND_BASE, type, idx);
// Blend factor
- mat.AddProperty((float*)&sampler.mWeighting , 1,
+ mat.AddProperty((ai_real*)&sampler.mWeighting , 1,
_AI_MATKEY_TEXBLEND_BASE, type, idx);
// UV source index ... if we didn't resolve the mapping, it is actually just
@@ -1553,13 +1619,13 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
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)...
+ // specification here (1.0 transparency => completely 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)
+ // 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 +
@@ -1644,11 +1710,11 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
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);
+ aiColor4D colAmbient( 0.2, 0.2, 0.2, 1.0), colDiffuse( 0.8, 0.8, 0.8, 1.0), colSpecular( 0.5, 0.5, 0.5, 0.5);
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;
+ const ai_real specExp = 5.0;
mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
}
#endif
@@ -1659,6 +1725,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
const Collada::Effect& pEffect, const std::string& pName)
{
+ aiString result;
+
// recurse through the param references until we end up at an image
std::string name = pName;
while( 1)
@@ -1677,11 +1745,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
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 << "\"." );
- }
+ //missing texture should not stop the conversion
+ //throw DeadlyImportError( format() <<
+ // "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
- aiString result;
+ DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
+
+ //set default texture file name
+ result.Set(name + ".jpg");
+ ConvertPath(result);
+ return result;
+ }
// if this is an embedded texture image setup an aiTexture for it
if (imIt->second.mFileName.empty())
@@ -1700,13 +1774,13 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
// and copy texture data
tex->mHeight = 0;
- tex->mWidth = imIt->second.mImageData.size();
+ tex->mWidth = static_cast<unsigned int>(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());
+ result.length = 1 + ASSIMP_itoa10(result.data+1,static_cast<unsigned int>(MAXLEN-1),static_cast<int32_t>(mTextures.size()));
// and add this texture to the list
mTextures.push_back(tex);
@@ -1767,7 +1841,7 @@ 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
+ai_real 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;
@@ -1829,14 +1903,13 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
}
// ------------------------------------------------------------------------------------------------
-// Finds a proper name for a node derived from the collada-node's properties
+// Finds a proper unique name for a node derived from the collada-node's properties.
+// The name must be unique for proper node-bone association.
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())
+ // Now setup the name of the assimp node. The collada name might not be
+ // unique, so we use the collada ID.
+ if (!pNode->mID.empty())
return pNode->mID;
else if (!pNode->mSID.empty())
return pNode->mSID;
diff --git a/src/3rdparty/assimp/code/ColladaLoader.h b/src/3rdparty/assimp/code/ColladaLoader.h
index 16750906f..8388ab01e 100644
--- a/src/3rdparty/assimp/code/ColladaLoader.h
+++ b/src/3rdparty/assimp/code/ColladaLoader.h
@@ -4,7 +4,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -95,123 +96,123 @@ public:
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;
-
- 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);
-
- /** Recursively constructs a scene node for the given parser node and returns it. */
- aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
-
- /** Resolve node instances */
- void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
- 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);
-
- 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);
-
- /** Builds cameras for the given node and references them */
- 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);
-
- /** Stores all meshes in the given scene */
- void StoreSceneMeshes( aiScene* pScene);
-
- /** Stores all materials in the given scene */
- void StoreSceneMaterials( aiScene* pScene);
-
- /** Stores all lights in the given scene */
- void StoreSceneLights( aiScene* pScene);
-
- /** Stores all cameras in the given scene */
- void StoreSceneCameras( aiScene* pScene);
-
- /** Stores all textures in the given scene */
- void StoreSceneTextures( aiScene* pScene);
-
- /** Stores all animations
- * @param pScene target scene to store the anims
- */
- void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
-
- /** Stores all animations for the given source anim and its nested child animations
- * @param pScene target scene to store the anims
- * @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);
-
- /** 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);
-
- /** Fill materials from the collada material definitions */
- void FillMaterials( const ColladaParser& pParser, aiScene* pScene);
-
- /** Resolve UV channel mappings*/
- void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
- 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);
-
- /** Resolves the texture name for the given effect texture entry */
- 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);
-
- /** Reads a float value from an accessor and its data array.
- * @param pAccessor The accessor to use for reading
- * @param pData The data array to read from
- * @param pIndex The index of the element to retrieve
- * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
- * @return the specified value
- */
- float ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const;
-
- /** Reads a string value from an accessor and its data array.
- * @param pAccessor The accessor to use for reading
- * @param pData The data array to read from
- * @param pIndex The index of the element to retrieve
- * @return the specified value
- */
- const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const;
-
- /** Recursively collects all nodes into the given array */
- void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const;
-
- /** Finds a node in the collada scene by the given name */
- const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const;
- /** Finds a node in the collada scene by the given SID */
- 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);
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ 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);
+
+ /** Recursively constructs a scene node for the given parser node and returns it. */
+ aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
+
+ /** Resolve node instances */
+ void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
+ 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);
+
+ 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);
+
+ /** Builds cameras for the given node and references them */
+ 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);
+
+ /** Stores all meshes in the given scene */
+ void StoreSceneMeshes( aiScene* pScene);
+
+ /** Stores all materials in the given scene */
+ void StoreSceneMaterials( aiScene* pScene);
+
+ /** Stores all lights in the given scene */
+ void StoreSceneLights( aiScene* pScene);
+
+ /** Stores all cameras in the given scene */
+ void StoreSceneCameras( aiScene* pScene);
+
+ /** Stores all textures in the given scene */
+ void StoreSceneTextures( aiScene* pScene);
+
+ /** Stores all animations
+ * @param pScene target scene to store the anims
+ */
+ void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
+
+ /** Stores all animations for the given source anim and its nested child animations
+ * @param pScene target scene to store the anims
+ * @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);
+
+ /** 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);
+
+ /** Fill materials from the collada material definitions */
+ void FillMaterials( const ColladaParser& pParser, aiScene* pScene);
+
+ /** Resolve UV channel mappings*/
+ void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
+ 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);
+
+ /** Resolves the texture name for the given effect texture entry */
+ 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);
+
+ /** Reads a float value from an accessor and its data array.
+ * @param pAccessor The accessor to use for reading
+ * @param pData The data array to read from
+ * @param pIndex The index of the element to retrieve
+ * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
+ * @return the specified value
+ */
+ ai_real ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const;
+
+ /** Reads a string value from an accessor and its data array.
+ * @param pAccessor The accessor to use for reading
+ * @param pData The data array to read from
+ * @param pIndex The index of the element to retrieve
+ * @return the specified value
+ */
+ const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const;
+
+ /** Recursively collects all nodes into the given array */
+ void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const;
+
+ /** Finds a node in the collada scene by the given name */
+ const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const;
+ /** Finds a node in the collada scene by the given SID */
+ 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);
protected:
/** Filename, for a verbose error message */
@@ -225,12 +226,12 @@ protected:
/** 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 material list */
+ std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;
/** Temporary camera list */
std::vector<aiCamera*> mCameras;
diff --git a/src/3rdparty/assimp/code/ColladaParser.cpp b/src/3rdparty/assimp/code/ColladaParser.cpp
index aec57e684..2fe0f1e0a 100644
--- a/src/3rdparty/assimp/code/ColladaParser.cpp
+++ b/src/3rdparty/assimp/code/ColladaParser.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Collada parser helper
*/
-
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
#include <sstream>
@@ -59,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
-
using namespace Assimp;
using namespace Assimp::Collada;
using namespace Assimp::Formatter;
@@ -128,7 +127,7 @@ bool ColladaParser::ReadBoolFromTextContent()
// ------------------------------------------------------------------------------------------------
// Read float from text contents of current element
-float ColladaParser::ReadFloatFromTextContent()
+ai_real ColladaParser::ReadFloatFromTextContent()
{
const char* cur = GetTextContent();
return fast_atof(cur);
@@ -190,8 +189,8 @@ void ColladaParser::ReadStructure()
ReadAssetInfo();
else if( IsElement( "library_animations"))
ReadAnimationLibrary();
- else if (IsElement("library_animation_clips"))
- ReadAnimationClipLibrary();
+ else if (IsElement("library_animation_clips"))
+ ReadAnimationClipLibrary();
else if( IsElement( "library_controllers"))
ReadControllerLibrary();
else if( IsElement( "library_images"))
@@ -221,11 +220,11 @@ void ColladaParser::ReadStructure()
}
}
- PostProcessRootAnimations();
+ PostProcessRootAnimations();
}
// ------------------------------------------------------------------------------------------------
-// Reads asset informations such as coordinate system informations and legal blah
+// Reads asset information such as coordinate system information and legal blah
void ColladaParser::ReadAssetInfo()
{
if( mReader->isEmptyElement())
@@ -300,7 +299,7 @@ void ColladaParser::ReadAnimationClipLibrary()
else if (indexID >= 0)
animName = mReader->getAttributeValue(indexID);
else
- animName = std::string("animation_") + std::to_string(mAnimationClipLibrary.size());
+ animName = std::string("animation_") + to_string(mAnimationClipLibrary.size());
std::pair<std::string, std::vector<std::string> > clip;
@@ -450,7 +449,7 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
// optional name given as an attribute
std::string animName;
- std::string animID;
+ std::string animID;
int indexName = TestAttribute( "name");
int indexID = TestAttribute( "id");
@@ -532,12 +531,12 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
// 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>.
+ // 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)
@@ -560,8 +559,8 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
{
mAnimationLibrary[animID] = anim;
}
- }
- }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -684,39 +683,39 @@ void ColladaParser::ReadController( Collada::Controller& pController)
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);
- }
- 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");
+ const char* content = GetTextContent();
+
+ // read the 16 floats
+ for( unsigned int a = 0; a < 16; a++)
+ {
+ // read a number
+ content = fast_atoreal_move<ai_real>( 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);
+ }
+ 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");
const char *semantics = mReader->getAttributeValue(semanticsIndex);
const char *source = mReader->getAttributeValue(sourceIndex);
@@ -1221,13 +1220,13 @@ void ColladaParser::ReadLight( Collada::Light& pLight)
// text content contains 3 floats
const char* content = GetTextContent();
- content = fast_atoreal_move<float>( content, (float&)pLight.mColor.r);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pLight.mColor.r);
SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pLight.mColor.g);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pLight.mColor.g);
SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pLight.mColor.b);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pLight.mColor.b);
SkipSpacesAndLineEnd( &content);
TestClosing( "color");
@@ -1454,7 +1453,7 @@ void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect)
pEffect.mRGBTransparency = true;
}
- // In RGB_ZERO mode, the transparency is interpreted in reverse, go figure...
+ // 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;
}
@@ -1620,22 +1619,22 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
// text content contains 4 floats
const char* content = GetTextContent();
- content = fast_atoreal_move<float>( content, (float&)pColor.r);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pColor.r);
SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pColor.g);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pColor.g);
SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pColor.b);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pColor.b);
SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pColor.a);
+ content = fast_atoreal_move<ai_real>( content, (ai_real&)pColor.a);
SkipSpacesAndLineEnd( &content);
TestClosing( "color");
}
else if( IsElement( "texture"))
{
- // get name of source textur/sampler
+ // get name of source texture/sampler
int attrTex = GetAttribute( "texture");
pSampler.mName = mReader->getAttributeValue( attrTex);
@@ -1678,7 +1677,7 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
// ------------------------------------------------------------------------------------------------
// Reads an effect entry containing a float
-void ColladaParser::ReadEffectFloat( float& pFloat)
+void ColladaParser::ReadEffectFloat( ai_real& pFloat)
{
while( mReader->read())
{
@@ -1687,7 +1686,7 @@ void ColladaParser::ReadEffectFloat( float& pFloat)
{
// text content contains a single floats
const char* content = GetTextContent();
- content = fast_atoreal_move<float>( content, pFloat);
+ content = fast_atoreal_move<ai_real>( content, pFloat);
SkipSpacesAndLineEnd( &content);
TestClosing( "float");
@@ -1866,7 +1865,7 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
ReadIndexData( pMesh);
} else
{
- // ignore the rest
+ // ignore the restf
SkipElement();
}
}
@@ -1985,9 +1984,9 @@ void ColladaParser::ReadDataArray()
if( *content == 0)
ThrowException( "Expected more values while reading float_array contents.");
- float value;
+ ai_real value;
// read a number
- content = fast_atoreal_move<float>( content, value);
+ content = fast_atoreal_move<ai_real>( content, value);
data.mValues.push_back( value);
// skip whitespace after it
SkipSpacesAndLineEnd( &content);
@@ -2216,8 +2215,9 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
else if (IsElement("extra"))
{
SkipElement("extra");
- } else
- {
+ } else if ( IsElement("ph")) {
+ SkipElement("ph");
+ } else {
ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">" );
}
}
@@ -2231,7 +2231,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
}
#ifdef ASSIMP_BUILD_DEBUG
- if (primType != Prim_TriFans && primType != Prim_TriStrips &&
+ if (primType != Prim_TriFans && primType != Prim_TriStrips && primType != Prim_LineStrip &&
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);
}
@@ -2341,7 +2341,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
}
}
- // complain if the index count doesn't fit
+ // 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'
@@ -2350,13 +2350,13 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
} else
ThrowException( "Expected different index count in <p> element.");
- } else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
+ } else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
ThrowException( "Expected different index count in <p> element.");
- // find the data for all sources
- for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
+ // find the data for all sources
+ for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
{
- InputChannel& input = *it;
+ InputChannel& input = *it;
if( input.mResolved)
continue;
@@ -2368,9 +2368,9 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
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;
+ for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
+ {
+ InputChannel& input = *it;
if( input.mResolved)
continue;
@@ -2400,6 +2400,10 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
size_t numberOfVertices = indices.size() / numOffsets;
numPrimitives = numberOfVertices - 2;
}
+ if (pPrimType == Prim_LineStrip) {
+ size_t numberOfVertices = indices.size() / numOffsets;
+ numPrimitives = numberOfVertices - 1;
+ }
pMesh->mFaceSize.reserve( numPrimitives);
pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
@@ -2416,6 +2420,11 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
+ case Prim_LineStrip:
+ numPoints = 2;
+ for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
+ CopyVertex(currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ break;
case Prim_Triangles:
numPoints = 3;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
@@ -2452,13 +2461,15 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
return numPrimitives;
}
+///@note This function willn't work correctly if both PerIndex and PerVertex channels have same channels.
+///For example if TEXCOORD present in both <vertices> and <polylist> tags this function will create wrong uv coordinates.
+///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior
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;
// don't overrun the boundaries of the index list
- size_t maxIndexRequested = baseOffset + numOffsets - 1;
- ai_assert(maxIndexRequested < indices.size());
+ ai_assert((baseOffset + numOffsets - 1) < indices.size());
// extract per-vertex channels using the global per-vertex offset
for (std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
@@ -2498,11 +2509,11 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
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;
+ const ai_real* 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];
+ ai_real obj[4];
for( size_t c = 0; c < 4; ++c)
obj[c] = dataObject[acc.mSubOffset[c]];
@@ -2577,7 +2588,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
aiColor4D result(0, 0, 0, 1);
for (size_t i = 0; i < pInput.mResolved->mSize; ++i)
{
- result[i] = obj[pInput.mResolved->mSubOffset[i]];
+ result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
}
pMesh->mColors[pInput.mIndex].push_back(result);
} else
@@ -2806,7 +2817,7 @@ void ColladaParser::ReadNodeTransformation( Node* pNode, TransformType pType)
for( unsigned int a = 0; a < sNumParameters[pType]; a++)
{
// read a number
- content = fast_atoreal_move<float>( content, tf.f[a]);
+ content = fast_atoreal_move<ai_real>( content, tf.f[a]);
// skip whitespace after it
SkipSpacesAndLineEnd( &content);
}
@@ -2870,7 +2881,7 @@ void ColladaParser::ReadNodeGeometry( Node* pNode)
if( !mReader->isEmptyElement())
{
- // read material associations. Ignore additional elements inbetween
+ // read material associations. Ignore additional elements in between
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
@@ -3117,7 +3128,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
case TF_ROTATE:
{
aiMatrix4x4 rot;
- float angle = tf.f[3] * float( AI_MATH_PI) / 180.0f;
+ ai_real angle = tf.f[3] * ai_real( AI_MATH_PI) / ai_real( 180.0 );
aiVector3D axis( tf.f[0], tf.f[1], tf.f[2]);
aiMatrix4x4::Rotation( angle, axis, rot);
res *= rot;
diff --git a/src/3rdparty/assimp/code/ColladaParser.h b/src/3rdparty/assimp/code/ColladaParser.h
index 9193e2027..941ab8414 100644
--- a/src/3rdparty/assimp/code/ColladaParser.h
+++ b/src/3rdparty/assimp/code/ColladaParser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
- Copyright (c) 2006-2016, assimp team
+ Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,7 +50,6 @@
#include "ColladaHelper.h"
#include <assimp/ai_assert.h>
#include "TinyFormatter.h"
-#include <memory>
namespace Assimp
{
@@ -77,7 +77,7 @@ namespace Assimp
/** Reads the structure of the file */
void ReadStructure();
- /** Reads asset informations such as coordinate system informations and legal blah */
+ /** Reads asset information such as coordinate system information and legal blah */
void ReadAssetInfo();
/** Reads the animation library */
@@ -147,7 +147,7 @@ namespace Assimp
void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
/** Reads an effect entry containing a float */
- void ReadEffectFloat( float& pFloat);
+ void ReadEffectFloat( ai_real& pFloat);
/** Reads an effect parameter specification of any kind */
void ReadEffectParam( Collada::EffectParam& pParam);
@@ -259,7 +259,7 @@ namespace Assimp
bool ReadBoolFromTextContent();
/** Reads a single float from current text content */
- float ReadFloatFromTextContent();
+ ai_real ReadFloatFromTextContent();
/** Calculates the resulting transformation from all the given transform steps */
aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
@@ -268,8 +268,7 @@ namespace Assimp
Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
/** 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;
+ template <typename Type> const Type& ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
protected:
/** Filename, for a verbose error message */
@@ -335,7 +334,7 @@ namespace Assimp
Collada::Animation mAnims;
/** Size unit: how large compared to a meter */
- float mUnitSize;
+ ai_real mUnitSize;
/** Which is the up vector */
enum { UP_X, UP_Y, UP_Z } mUpDirection;
diff --git a/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp b/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
index 2bbb30be8..c49666de8 100644
--- a/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
+++ b/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,10 +50,10 @@ 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.0,1.0,0.0);
+ const static aiVector3D base_axis_x(1.0,0.0,0.0);
+ const static aiVector3D base_axis_z(0.0,0.0,1.0);
+ const static ai_real angle_epsilon = ai_real( 0.95 );
}
// ------------------------------------------------------------------------------------------------
@@ -81,9 +82,9 @@ bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
const aiVector3D& planeNormal, aiVector3D& pos)
{
- const float b = planeNormal * (planePos - ray.pos);
- float h = ray.dir * planeNormal;
- if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0)
+ const ai_real b = planeNormal * (planePos - ray.pos);
+ ai_real h = ray.dir * planeNormal;
+ if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
return false;
pos = ray.pos + (ray.dir * h);
@@ -109,11 +110,11 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
// 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 ai_real LOWER_LIMIT = ai_real( 0.1 );
+ const static ai_real UPPER_LIMIT = ai_real( 0.9 );
- const static float LOWER_EPSILON = 10e-3f;
- const static float UPPER_EPSILON = 1.f-10e-3f;
+ const static ai_real LOWER_EPSILON = ai_real( 10e-3 );
+ const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 );
for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
{
@@ -156,12 +157,12 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
// 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;
+ out[face.mIndices[n]].x = 0.0;
// If the u value is below the lower limit and no other u
// value of that face is 1, round it to 1
else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
- out[face.mIndices[n]].x = 1.f;
+ out[face.mIndices[n]].x = 1.0;
// The face contains both 0 and 1 as UV coords. This can occur
// for faces which have an edge that lies directly on the seam.
@@ -171,9 +172,9 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
else if (one && zero)
{
if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON)
- out[face.mIndices[n]].x = 0.f;
+ out[face.mIndices[n]].x = 0.0;
else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
- out[face.mIndices[n]].x = 1.f;
+ out[face.mIndices[n]].x = 1.0;
}
}
}
@@ -206,24 +207,24 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
// 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);
+ out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
else if (axis * base_axis_y >= angle_epsilon) {
// ... just the same again
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
- out[pnt] = aiVector3D((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);
+ out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
else if (axis * base_axis_z >= angle_epsilon) {
// ... just the same again
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
- out[pnt] = aiVector3D((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);
+ out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes
@@ -234,8 +235,8 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
// 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);
+ out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
}
}
@@ -257,7 +258,7 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
// thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
- const float diff = max.x - min.x;
+ const ai_real diff = max.x - min.x;
// If the main axis is 'z', the z coordinate of a point 'p' is mapped
// directly to the texture V axis. The other axis is derived from
@@ -268,12 +269,12 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
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;
+ uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
}
}
else if (axis * base_axis_y >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
- const float diff = max.y - min.y;
+ const ai_real diff = max.y - min.y;
// just the same ...
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
@@ -281,12 +282,12 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
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;
+ uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
}
}
else if (axis * base_axis_z >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max);
- const float diff = max.z - min.z;
+ const ai_real diff = max.z - min.z;
// just the same ...
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
@@ -294,7 +295,7 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
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;
+ uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes
@@ -302,7 +303,7 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
- const float diff = max.y - min.y;
+ const ai_real diff = max.y - min.y;
// again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
@@ -310,7 +311,7 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
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;
+ uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
}
}
@@ -323,7 +324,7 @@ void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
- float diffu,diffv;
+ ai_real diffu,diffv;
aiVector3D center, min, max;
// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
@@ -337,7 +338,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
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);
+ out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0);
}
}
else if (axis * base_axis_y >= angle_epsilon) {
@@ -347,7 +348,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
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);
+ out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
}
}
else if (axis * base_axis_z >= angle_epsilon) {
@@ -357,7 +358,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
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);
+ out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.0);
}
}
// slower code path in case the mapping axis is not one of the coordinate system axes
@@ -372,7 +373,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
// 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);
+ out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
}
}
@@ -437,7 +438,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
}
}
- unsigned int idx;
+ unsigned int idx( 99999999 );
// Check whether we have this mapping mode already
std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
diff --git a/src/3rdparty/assimp/code/ComputeUVMappingProcess.h b/src/3rdparty/assimp/code/ComputeUVMappingProcess.h
index db4287863..1de97961d 100644
--- a/src/3rdparty/assimp/code/ComputeUVMappingProcess.h
+++ b/src/3rdparty/assimp/code/ComputeUVMappingProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ConvertToLHProcess.cpp b/src/3rdparty/assimp/code/ConvertToLHProcess.cpp
index 017282796..6a43d5c2d 100644
--- a/src/3rdparty/assimp/code/ConvertToLHProcess.cpp
+++ b/src/3rdparty/assimp/code/ConvertToLHProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/ConvertToLHProcess.h b/src/3rdparty/assimp/code/ConvertToLHProcess.h
index 0c5f91c96..130fdcafd 100644
--- a/src/3rdparty/assimp/code/ConvertToLHProcess.h
+++ b/src/3rdparty/assimp/code/ConvertToLHProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/CreateAnimMesh.h b/src/3rdparty/assimp/code/CreateAnimMesh.h
index c5ceb4028..84cab8932 100644
--- a/src/3rdparty/assimp/code/CreateAnimMesh.h
+++ b/src/3rdparty/assimp/code/CreateAnimMesh.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/D3MFExporter.cpp b/src/3rdparty/assimp/code/D3MFExporter.cpp
new file mode 100644
index 000000000..162d20764
--- /dev/null
+++ b/src/3rdparty/assimp/code/D3MFExporter.cpp
@@ -0,0 +1,328 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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_3MF_EXPORTER
+
+#include "D3MFExporter.h"
+
+#include <assimp/scene.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/IOStream.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/DefaultLogger.hpp>
+
+#include "Exceptional.h"
+#include "3MFXmlTags.h"
+#include "D3MFOpcPackage.h"
+
+#include <contrib/zip/src/zip.h>
+
+namespace Assimp {
+
+void ExportScene3MF( const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/ ) {
+ if ( nullptr == pIOSystem ) {
+ throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) );
+ }
+ D3MF::D3MFExporter myExporter( pFile, pScene );
+ if ( myExporter.validate() ) {
+ if ( pIOSystem->Exists( pFile ) ) {
+ if ( !pIOSystem->DeleteFile( pFile ) ) {
+ throw DeadlyExportError( "File exists, cannot override : " + std::string( pFile ) );
+ }
+ }
+ bool ok = myExporter.exportArchive(pFile);
+ if ( !ok ) {
+ throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) );
+ }
+ }
+}
+
+namespace D3MF {
+
+D3MFExporter::D3MFExporter( const char* pFile, const aiScene* pScene )
+: mArchiveName( pFile )
+, m_zipArchive( nullptr )
+, mScene( pScene )
+, mModelOutput()
+, mRelOutput()
+, mContentOutput()
+, mBuildItems()
+, mRelations() {
+ // empty
+}
+
+D3MFExporter::~D3MFExporter() {
+ for ( size_t i = 0; i < mRelations.size(); ++i ) {
+ delete mRelations[ i ];
+ }
+ mRelations.clear();
+}
+
+bool D3MFExporter::validate() {
+ if ( mArchiveName.empty() ) {
+ return false;
+ }
+
+ if ( nullptr == mScene ) {
+ return false;
+ }
+
+ return true;
+}
+
+bool D3MFExporter::exportArchive( const char *file ) {
+ bool ok( true );
+
+ m_zipArchive = zip_open( file, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w' );
+ if ( nullptr == m_zipArchive ) {
+ return false;
+ }
+ ok |= exportContentTypes();
+ ok |= export3DModel();
+ ok |= exportRelations();
+
+ zip_close( m_zipArchive );
+ m_zipArchive = nullptr;
+
+ return ok;
+}
+
+
+bool D3MFExporter::exportContentTypes() {
+ mContentOutput.clear();
+
+ mContentOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ mContentOutput << std::endl;
+ mContentOutput << "<Types xmlns = \"http://schemas.openxmlformats.org/package/2006/content-types\">";
+ mContentOutput << std::endl;
+ mContentOutput << "<Default Extension = \"rels\" ContentType = \"application/vnd.openxmlformats-package.relationships+xml\" />";
+ mContentOutput << std::endl;
+ mContentOutput << "<Default Extension = \"model\" ContentType = \"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" />";
+ mContentOutput << std::endl;
+ mContentOutput << "</Types>";
+ mContentOutput << std::endl;
+ exportContentTyp( XmlTag::CONTENT_TYPES_ARCHIVE );
+
+ return true;
+}
+
+bool D3MFExporter::exportRelations() {
+ mRelOutput.clear();
+
+ mRelOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ mRelOutput << std::endl;
+ mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
+
+ for ( size_t i = 0; i < mRelations.size(); ++i ) {
+ mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
+ mRelOutput << "Id=\"" << mRelations[i]->id << "\" ";
+ mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />";
+ mRelOutput << std::endl;
+ }
+ mRelOutput << "</Relationships>";
+ mRelOutput << std::endl;
+
+ writeRelInfoToFile( "_rels", ".rels" );
+ mRelOutput.flush();
+
+ return true;
+}
+
+bool D3MFExporter::export3DModel() {
+ mModelOutput.clear();
+
+ writeHeader();
+ mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\""
+ << "xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">"
+ << std::endl;
+ mModelOutput << "<" << XmlTag::resources << ">";
+ mModelOutput << std::endl;
+
+ writeObjects();
+
+
+ mModelOutput << "</" << XmlTag::resources << ">";
+ mModelOutput << std::endl;
+ writeBuild();
+
+ mModelOutput << "</" << XmlTag::model << ">\n";
+
+ OpcPackageRelationship *info = new OpcPackageRelationship;
+ info->id = "rel0";
+ info->target = "/3D/3DModel.model";
+ info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
+ mRelations.push_back( info );
+
+ writeModelToArchive( "3D", "3DModel.model" );
+ mModelOutput.flush();
+
+ return true;
+}
+
+void D3MFExporter::writeHeader() {
+ mModelOutput << "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
+ mModelOutput << std::endl;
+}
+
+void D3MFExporter::writeObjects() {
+ if ( nullptr == mScene->mRootNode ) {
+ return;
+ }
+
+ aiNode *root = mScene->mRootNode;
+ for ( unsigned int i = 0; i < root->mNumChildren; ++i ) {
+ aiNode *currentNode( root->mChildren[ i ] );
+ if ( nullptr == currentNode ) {
+ continue;
+ }
+ mModelOutput << "<" << XmlTag::object << " id=\"" << currentNode->mName.C_Str() << "\" type=\"model\">";
+ mModelOutput << std::endl;
+ for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) {
+ aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ];
+ if ( nullptr == currentMesh ) {
+ continue;
+ }
+ writeMesh( currentMesh );
+ }
+ mBuildItems.push_back( i );
+
+ mModelOutput << "</" << XmlTag::object << ">";
+ mModelOutput << std::endl;
+ }
+}
+
+void D3MFExporter::writeMesh( aiMesh *mesh ) {
+ if ( nullptr == mesh ) {
+ return;
+ }
+
+ mModelOutput << "<" << XmlTag::mesh << ">" << std::endl;
+ mModelOutput << "<" << XmlTag::vertices << ">" << std::endl;
+ for ( unsigned int i = 0; i < mesh->mNumVertices; ++i ) {
+ writeVertex( mesh->mVertices[ i ] );
+ }
+ mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
+
+ writeFaces( mesh );
+
+ mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
+}
+
+void D3MFExporter::writeVertex( const aiVector3D &pos ) {
+ mModelOutput << "<" << XmlTag::vertex << " x=\"" << pos.x << "\" y=\"" << pos.y << "\" z=\"" << pos.z << "\" />";
+ mModelOutput << std::endl;
+}
+
+void D3MFExporter::writeFaces( aiMesh *mesh ) {
+ if ( nullptr == mesh ) {
+ return;
+ }
+
+ if ( !mesh->HasFaces() ) {
+ return;
+ }
+ mModelOutput << "<" << XmlTag::triangles << ">" << std::endl;
+ for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) {
+ aiFace &currentFace = mesh->mFaces[ i ];
+ mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\""
+ << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>";
+ mModelOutput << std::endl;
+ }
+ mModelOutput << "</" << XmlTag::triangles << ">";
+ mModelOutput << std::endl;
+}
+
+void D3MFExporter::writeBuild() {
+ mModelOutput << "<" << XmlTag::build << ">" << std::endl;
+
+ for ( size_t i = 0; i < mBuildItems.size(); ++i ) {
+ mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 1 << "\"/>";
+ mModelOutput << std::endl;
+ }
+ mModelOutput << "</" << XmlTag::build << ">";
+ mModelOutput << std::endl;
+}
+
+void D3MFExporter::exportContentTyp( const std::string &filename ) {
+ if ( nullptr == m_zipArchive ) {
+ throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+ }
+ const std::string entry = filename;
+ zip_entry_open( m_zipArchive, entry.c_str() );
+
+ const std::string &exportTxt( mContentOutput.str() );
+ zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+ zip_entry_close( m_zipArchive );
+}
+
+void D3MFExporter::writeModelToArchive( const std::string &folder, const std::string &modelName ) {
+ if ( nullptr == m_zipArchive ) {
+ throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+ }
+ const std::string entry = folder + "/" + modelName;
+ zip_entry_open( m_zipArchive, entry.c_str() );
+
+ const std::string &exportTxt( mModelOutput.str() );
+ zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+ zip_entry_close( m_zipArchive );
+}
+
+void D3MFExporter::writeRelInfoToFile( const std::string &folder, const std::string &relName ) {
+ if ( nullptr == m_zipArchive ) {
+ throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+ }
+ const std::string entry = folder + "/" + relName;
+ zip_entry_open( m_zipArchive, entry.c_str() );
+
+ const std::string &exportTxt( mRelOutput.str() );
+ zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+ zip_entry_close( m_zipArchive );
+}
+
+
+} // Namespace D3MF
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/D3MFExporter.h b/src/3rdparty/assimp/code/D3MFExporter.h
new file mode 100644
index 000000000..16efabf29
--- /dev/null
+++ b/src/3rdparty/assimp/code/D3MFExporter.h
@@ -0,0 +1,103 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <memory>
+#include <sstream>
+#include <vector>
+#include <assimp/vector3.h>
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+struct aiMesh;
+
+struct zip_t;
+
+namespace Assimp {
+
+class IOStream;
+
+namespace D3MF {
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO3MF_EXPORTER
+
+struct OpcPackageRelationship;
+
+class D3MFExporter {
+public:
+ D3MFExporter( const char* pFile, const aiScene* pScene );
+ ~D3MFExporter();
+ bool validate();
+ bool exportArchive( const char *file );
+ bool exportContentTypes();
+ bool exportRelations();
+ bool export3DModel();
+
+protected:
+ void writeHeader();
+ void writeObjects();
+ void writeMesh( aiMesh *mesh );
+ void writeVertex( const aiVector3D &pos );
+ void writeFaces( aiMesh *mesh );
+ void writeBuild();
+ void exportContentTyp( const std::string &filename );
+ void writeModelToArchive( const std::string &folder, const std::string &modelName );
+ void writeRelInfoToFile( const std::string &folder, const std::string &relName );
+
+private:
+ std::string mArchiveName;
+ zip_t *m_zipArchive;
+ const aiScene *mScene;
+ std::ostringstream mModelOutput;
+ std::ostringstream mRelOutput;
+ std::ostringstream mContentOutput;
+ std::vector<unsigned int> mBuildItems;
+ std::vector<OpcPackageRelationship*> mRelations;
+};
+
+#endif // ASSIMP_BUILD_NO3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
+
+} // Namespace D3MF
+} // Namespace Assimp
+
diff --git a/src/3rdparty/assimp/code/D3MFImporter.cpp b/src/3rdparty/assimp/code/D3MFImporter.cpp
index 52ebba40e..372416dbd 100644
--- a/src/3rdparty/assimp/code/D3MFImporter.cpp
+++ b/src/3rdparty/assimp/code/D3MFImporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,94 +44,52 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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 <assimp/importerdesc.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"
+#include <contrib/unzip/unzip.h>
+#include "irrXMLWrapper.h"
+#include "3MFXmlTags.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
-{
+class XmlSerializer {
public:
XmlSerializer(XmlReader* xmlReader)
- : xmlReader(xmlReader)
- {
-
+ : xmlReader(xmlReader) {
+ // empty
}
- void ImportXml(aiScene* scene)
- {
-
- scene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ ~XmlSerializer() {
+ // empty
+ }
+ void ImportXml(aiScene* scene) {
scene->mRootNode = new aiNode();
std::vector<aiNode*> children;
- while(ReadToEndElement(D3MF::XmlTag::model))
- {
-
- if(xmlReader->getNodeName() == D3MF::XmlTag::object)
- {
+ while(ReadToEndElement(D3MF::XmlTag::model)) {
+ if(xmlReader->getNodeName() == D3MF::XmlTag::object) {
children.push_back(ReadObject(scene));
- }
- else if(xmlReader->getNodeName() == D3MF::XmlTag::build)
- {
+ } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) {
}
- }
-
- if(scene->mRootNode->mName.length == 0)
- scene->mRootNode->mName.Set("3MF");
+ }
+ 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]();
@@ -141,34 +100,40 @@ public:
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::unique_ptr<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()));
+ const char *attrib( nullptr );
+ std::string name, type;
+ attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() );
+ if ( nullptr != attrib ) {
+ name = attrib;
+ }
+ attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() );
+ if ( nullptr != attrib ) {
+ type = attrib;
+ }
node->mParent = scene->mRootNode;
- node->mName.Set(name);
+ node->mName.Set(name);
- unsigned long meshIdx = meshes.size();
+ size_t 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);
+ meshIds.push_back(static_cast<unsigned long>(meshIdx));
meshIdx++;
}
@@ -180,16 +145,14 @@ private:
std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
- return node.dismiss();
+ return node.release();
}
- aiMesh* ReadMesh()
- {
+ aiMesh* ReadMesh() {
aiMesh* mesh = new aiMesh();
-
while(ReadToEndElement(D3MF::XmlTag::mesh))
- {
+ {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertices)
{
ImportVertices(mesh);
@@ -198,21 +161,19 @@ private:
{
ImportTriangles(mesh);
}
-
}
-
return mesh;
}
void ImportVertices(aiMesh* mesh)
{
- std::vector<aiVector3D> vertices;
+ std::vector<aiVector3D> vertices;
while(ReadToEndElement(D3MF::XmlTag::vertices))
- {
+ {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex)
- {
+ {
vertices.push_back(ReadVertex());
}
}
@@ -222,19 +183,21 @@ private:
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);
+ vertex.z = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr);
return vertex;
}
void ImportTriangles(aiMesh* mesh)
{
- std::vector<aiFace> faces;
+ std::vector<aiFace> faces;
while(ReadToEndElement(D3MF::XmlTag::triangles))
@@ -249,9 +212,7 @@ private:
mesh->mFaces = new aiFace[mesh->mNumFaces];
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
std::copy(faces.begin(), faces.end(), mesh->mFaces);
-
}
aiFace ReadTriangle()
@@ -268,7 +229,6 @@ private:
}
private:
-
bool ReadToStartElement(const std::string& startTag)
{
while(xmlReader->read())
@@ -308,12 +268,11 @@ private:
private:
std::vector<aiMesh*> meshes;
XmlReader* xmlReader;
-
-
};
} //namespace D3MF
+static const std::string Extension = "3mf";
static const aiImporterDesc desc = {
"3mf Importer",
@@ -325,51 +284,41 @@ static const aiImporterDesc desc = {
0,
0,
0,
- "3mf"
+ Extension.c_str()
};
D3MFImporter::D3MFImporter()
-{
-
+: BaseImporter() {
+ // empty
}
-D3MFImporter::~D3MFImporter()
-{
-
+D3MFImporter::~D3MFImporter() {
+ // empty
}
-bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const
-{
+bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
-
- if(extension == "3mf")
- {
+ if(extension == Extension ) {
return true;
- }
- else if(!extension.length() || checkSig)
- {
- if(!pIOHandler)
+ } else if ( !extension.length() || checkSig ) {
+ if (nullptr == pIOHandler ) {
return true;
+ }
}
return false;
}
-void D3MFImporter::SetupProperties(const Importer *pImp)
-{
-
+void D3MFImporter::SetupProperties(const Importer * /*pImp*/) {
+ // empty
}
-const aiImporterDesc *D3MFImporter::GetInfo() const
-{
+const aiImporterDesc *D3MFImporter::GetInfo() const {
return &desc;
}
-void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler)
-{
-
-
+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()));
@@ -377,12 +326,9 @@ void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOS
D3MF::XmlSerializer xmlSerializer(xmlReader.get());
-
xmlSerializer.ImportXml(pScene);
-
-
}
-}
+} // Namespace Assimp
#endif // ASSIMP_BUILD_NO_3MF_IMPORTER
diff --git a/src/3rdparty/assimp/code/D3MFImporter.h b/src/3rdparty/assimp/code/D3MFImporter.h
index 36c6d53e4..604d73bd5 100644
--- a/src/3rdparty/assimp/code/D3MFImporter.h
+++ b/src/3rdparty/assimp/code/D3MFImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,28 +42,23 @@ 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
-{
+class D3MFImporter : public BaseImporter {
public:
+ // BaseImporter interface
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);
-
};
-}
+
+} // Namespace Assimp
+
#endif // AI_D3MFLOADER_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/D3MFOpcPackage.cpp b/src/3rdparty/assimp/code/D3MFOpcPackage.cpp
index 9f4bdc468..49143fee7 100644
--- a/src/3rdparty/assimp/code/D3MFOpcPackage.cpp
+++ b/src/3rdparty/assimp/code/D3MFOpcPackage.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,64 +44,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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 <cstdlib>
#include <memory>
#include <vector>
#include <map>
#include <algorithm>
#include <cassert>
-#include <cstdlib>
+#include <contrib/unzip/unzip.h>
+#include "3MFXmlTags.h"
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);
+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) {
@@ -119,26 +90,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
}
}
-
return (voidpf) io_system->Open(filename, mode_fopen);
}
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
IOStream* io_stream = (IOStream*) stream;
- return io_stream->Read(buf, 1, size);
+ return static_cast<uLong>(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);
+ return static_cast<uLong>(io_stream->Write(buf, 1, size));
}
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream* io_stream = (IOStream*) stream;
- return io_stream->Tell();
+ return static_cast<long>(io_stream->Tell());
}
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
@@ -189,58 +159,51 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
return mapping;
}
-
-class ZipFile : public IOStream
-{
+class ZipFile : public IOStream {
friend class D3MFZipArchive;
public:
explicit ZipFile(size_t size);
-
- ~ZipFile();
-
+ virtual ~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;
-
+ void *m_Buffer;
size_t m_Size;
-
};
-ZipFile::ZipFile(size_t size) : m_Size(size) {
+ZipFile::ZipFile(size_t size)
+: m_Buffer( nullptr )
+, m_Size(size) {
ai_assert(m_Size != 0);
-
- m_Buffer = malloc(m_Size);
+ m_Buffer = ::malloc(m_Size);
}
ZipFile::~ZipFile() {
- free(m_Buffer);
+ ::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);
+ ai_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::Write(const void* pvBuffer, size_t size, size_t pCount ) {
+ const size_t size_to_write( size * pCount );
+ if ( 0 == size_to_write ) {
+ return 0U;
+ }
+ return 0U;
}
size_t ZipFile::FileSize() const {
@@ -259,55 +222,36 @@ void ZipFile::Flush() {
// empty
}
-
-class D3MFZipArchive : public IOSystem
-{
+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())
- {
+: 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();
}
@@ -382,6 +326,7 @@ IOStream *D3MFZipArchive::Open(const char* pFile, const char* /*pMode*/) {
// ------------------------------------------------------------------------------------------------
// Close a filestream.
void D3MFZipArchive::Close(IOStream *pFile) {
+ (void)(pFile);
ai_assert(pFile != NULL);
// We don't do anything in case the file would be opened again in the future
@@ -436,33 +381,20 @@ bool D3MFZipArchive::mapArchive() {
// ------------------------------------------------------------------------------------------------
-struct OpcPackageRelationship
-{
- std::string id;
- std::string type;
- std::string target;
-};
-
typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
-class OpcPackageRelationshipReader
-{
+class OpcPackageRelationshipReader {
public:
-
- OpcPackageRelationshipReader(XmlReader* xmlReader)
- {
-
- while(xmlReader->read())
- {
+ 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);
@@ -475,63 +407,70 @@ public:
ParseChildNode(xmlReader);
}
}
-
}
- void ParseAttributes(XmlReader*)
- {
+ void ParseAttributes(XmlReader*) {
+ // empty
+ }
+ bool validateRels( OpcPackageRelationshipPtr &relPtr ) {
+ if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) {
+ return false;
+ }
+ return true;
}
- 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());
+ void ParseChildNode(XmlReader* xmlReader) {
+ OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
- m_relationShips.push_back(relPtr);
+ relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
+ relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
+ relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
+ if ( validateRels( relPtr ) ) {
+ m_relationShips.push_back( relPtr );
+ }
}
- std::vector<OpcPackageRelationshipPtr> m_relationShips;
+ 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())
+: mRootStream(nullptr)
+, mZipArchive() {
+ mZipArchive.reset( new D3MF::D3MFZipArchive( pIOHandler, rFile ) );
+ if(!mZipArchive->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)
- {
+ mZipArchive->getFileList(fileList);
+ for (auto& file: fileList) {
+ if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) {
//PkgRelationshipReader pkgRelReader(file, archive);
- ai_assert(zipArchive->Exists(file.c_str()));
+ ai_assert(mZipArchive->Exists(file.c_str()));
- IOStream *fileStream = zipArchive->Open(file.c_str());
+ IOStream *fileStream = mZipArchive->Open(file.c_str());
ai_assert(fileStream != nullptr);
std::string rootFile = ReadPackageRootRelationship(fileStream);
- if(rootFile.size() > 0 && rootFile[0] == '/')
- rootFile = rootFile.substr(1);
+ if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
+ rootFile = rootFile.substr( 1 );
+ if ( rootFile[ 0 ] == '/' ) {
+ // deal with zipbug
+ rootFile = rootFile.substr( 1 );
+ }
+ }
DefaultLogger::get()->debug(rootFile);
- m_RootStream = zipArchive->Open(rootFile.c_str());
-
- ai_assert(m_RootStream != nullptr);
-
-
-
+ mRootStream = mZipArchive->Open(rootFile.c_str());
+ ai_assert( mRootStream != nullptr );
+ if ( nullptr == mRootStream ) {
+ throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile );
+ }
// const size_t size = zipArchive->FileSize();
// m_Data.resize( size );
@@ -542,50 +481,40 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
// m_Data.clear();
// return false;
// }
- zipArchive->Close( fileStream );
+ mZipArchive->Close( fileStream );
- }
- else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE)
- {
+ } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
}
}
}
-D3MFOpcPackage::~D3MFOpcPackage()
-{
-
+D3MFOpcPackage::~D3MFOpcPackage() {
+ // empty
}
-IOStream* D3MFOpcPackage::RootStream() const
-{
- return m_RootStream;
+IOStream* D3MFOpcPackage::RootStream() const {
+ return mRootStream;
}
-
-std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream)
-{
-
+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);
+ throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
return (*itr)->target;
}
-} //namespace D3MF
+} // Namespace D3MF
-}
+} // Namespace Assimp
#endif //ASSIMP_BUILD_NO_3MF_IMPORTER
diff --git a/src/3rdparty/assimp/code/D3MFOpcPackage.h b/src/3rdparty/assimp/code/D3MFOpcPackage.h
index dd8a40aab..818415e9f 100644
--- a/src/3rdparty/assimp/code/D3MFOpcPackage.h
+++ b/src/3rdparty/assimp/code/D3MFOpcPackage.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,33 +42,37 @@ 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;
+struct OpcPackageRelationship {
+ std::string id;
+ std::string type;
+ std::string target;
+};
+
class D3MFZipArchive;
-class D3MFOpcPackage
-{
+class D3MFOpcPackage {
public:
D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile);
~D3MFOpcPackage();
-
IOStream* RootStream() const;
-private:
+
+protected:
std::string ReadPackageRootRelationship(IOStream* stream);
+
private:
- IOStream* m_RootStream;
- std::unique_ptr<D3MFZipArchive> zipArchive;
+ IOStream* mRootStream;
+ std::unique_ptr<D3MFZipArchive> mZipArchive;
};
}
diff --git a/src/3rdparty/assimp/code/DXFHelper.h b/src/3rdparty/assimp/code/DXFHelper.h
index 1947469a8..e16b7f1aa 100644
--- a/src/3rdparty/assimp/code/DXFHelper.h
+++ b/src/3rdparty/assimp/code/DXFHelper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/DXFLoader.cpp b/src/3rdparty/assimp/code/DXFLoader.cpp
index 3e69eff1e..1e932e509 100644
--- a/src/3rdparty/assimp/code/DXFLoader.cpp
+++ b/src/3rdparty/assimp/code/DXFLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,6 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DXFHelper.h"
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
+
#include <numeric>
using namespace Assimp;
@@ -223,8 +226,8 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
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();
+ vcount += static_cast<unsigned int>(pl->positions.size());
+ icount += static_cast<unsigned int>(pl->counts.size());
}
}
@@ -296,7 +299,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
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();
+ cface += static_cast<unsigned int>(pl->counts.size());
}
aiVector3D* verts = mesh->mVertices = new aiVector3D[cvert];
@@ -705,7 +708,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
// closed polyline?
if (line.flags & DXF_POLYLINE_FLAG_CLOSED) {
- line.indices.push_back(line.positions.size()-1);
+ line.indices.push_back(static_cast<unsigned int>(line.positions.size()-1));
line.indices.push_back(0);
line.counts.push_back(2);
}
@@ -906,7 +909,7 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
line.counts.push_back(cnt);
for (unsigned int i = 0; i < cnt; ++i) {
- line.indices.push_back(line.positions.size());
+ line.indices.push_back(static_cast<unsigned int>(line.positions.size()));
line.positions.push_back(vip[i]);
line.colors.push_back(clr);
}
diff --git a/src/3rdparty/assimp/code/DXFLoader.h b/src/3rdparty/assimp/code/DXFLoader.h
index 13af4cdec..64822e9e2 100644
--- a/src/3rdparty/assimp/code/DXFLoader.h
+++ b/src/3rdparty/assimp/code/DXFLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_DXFLOADER_H_INCLUDED
#include "BaseImporter.h"
+#include <map>
namespace Assimp {
namespace DXF {
diff --git a/src/3rdparty/assimp/code/DeboneProcess.cpp b/src/3rdparty/assimp/code/DeboneProcess.cpp
index 5d688f813..b43dcad84 100644
--- a/src/3rdparty/assimp/code/DeboneProcess.cpp
+++ b/src/3rdparty/assimp/code/DeboneProcess.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -137,7 +138,7 @@ void DeboneProcess::Execute( aiScene* pScene)
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);
+ std::pair<unsigned int,aiNode*> push_pair(static_cast<unsigned int>(meshes.size()),theNode);
mSubMeshIndices[a].push_back(push_pair);
meshes.push_back(newMeshes[b].first);
@@ -156,13 +157,13 @@ void DeboneProcess::Execute( aiScene* pScene)
}
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));
+ mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(static_cast<unsigned int>(meshes.size()),(aiNode*)0));
meshes.push_back(srcMesh);
}
}
// rebuild the scene's mesh array
- pScene->mNumMeshes = meshes.size();
+ 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);
@@ -382,7 +383,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const
// this will require two passes
- unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
+ unsigned int m = static_cast<unsigned int>(pNode->mNumMeshes), n = static_cast<unsigned int>(mSubMeshIndices.size());
// first pass, look for meshes which have not moved
@@ -390,7 +391,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const
unsigned int srcIndex = pNode->mMeshes[a];
const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
- unsigned int nSubmeshes = subMeshes.size();
+ unsigned int nSubmeshes = static_cast<unsigned int>(subMeshes.size());
for(unsigned int b=0;b<nSubmeshes;b++) {
if(!subMeshes[b].second) {
@@ -404,7 +405,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const
for(unsigned int a=0;a<n;a++)
{
const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
- unsigned int nSubmeshes = subMeshes.size();
+ unsigned int nSubmeshes = static_cast<unsigned int>(subMeshes.size());
for(unsigned int b=0;b<nSubmeshes;b++) {
if(subMeshes[b].second == pNode) {
@@ -417,7 +418,7 @@ void DeboneProcess::UpdateNode(aiNode* pNode) const
delete [] pNode->mMeshes; pNode->mMeshes = NULL;
}
- pNode->mNumMeshes = newMeshList.size();
+ pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
if(pNode->mNumMeshes) {
pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
diff --git a/src/3rdparty/assimp/code/DeboneProcess.h b/src/3rdparty/assimp/code/DeboneProcess.h
index 5920473e2..8d4607bb9 100644
--- a/src/3rdparty/assimp/code/DeboneProcess.h
+++ b/src/3rdparty/assimp/code/DeboneProcess.h
@@ -1,8 +1,9 @@
- /*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/DefaultIOStream.cpp b/src/3rdparty/assimp/code/DefaultIOStream.cpp
index f1809d894..cce9af19d 100644
--- a/src/3rdparty/assimp/code/DefaultIOStream.cpp
+++ b/src/3rdparty/assimp/code/DefaultIOStream.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -44,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h>
-#include "DefaultIOStream.h"
+#include <assimp/DefaultIOStream.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -55,6 +56,7 @@ DefaultIOStream::~DefaultIOStream()
{
if (mFile) {
::fclose(mFile);
+ mFile = nullptr;
}
}
@@ -109,9 +111,9 @@ size_t DefaultIOStream::FileSize() const
return 0;
}
- if (SIZE_MAX == cachedSize) {
+ if (SIZE_MAX == mCachedSize ) {
- // Although fseek/ftell would allow us to reuse the exising file handle here,
+ // Although fseek/ftell would allow us to reuse the existing file handle here,
// it is generally unsafe because:
// - For binary streams, it is not technically well-defined
// - For text files the results are meaningless
@@ -119,21 +121,24 @@ 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__
+#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
struct __stat64 fileStat;
int err = _stat64( mFilename.c_str(), &fileStat );
if (0 != err)
return 0;
- cachedSize = (size_t) (fileStat.st_size);
-#else
+ mCachedSize = (size_t) (fileStat.st_size);
+#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
struct stat fileStat;
int err = stat(mFilename.c_str(), &fileStat );
if (0 != err)
return 0;
- cachedSize = (size_t) (fileStat.st_size);
+ const unsigned long long cachedSize = fileStat.st_size;
+ mCachedSize = static_cast< size_t >( cachedSize );
+#else
+# error "Unknown platform"
#endif
}
- return cachedSize;
+ return mCachedSize;
}
// ----------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/DefaultIOSystem.cpp b/src/3rdparty/assimp/code/DefaultIOSystem.cpp
index 8c44c8bd0..8687b0059 100644
--- a/src/3rdparty/assimp/code/DefaultIOSystem.cpp
+++ b/src/3rdparty/assimp/code/DefaultIOSystem.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -40,15 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Default implementation of IOSystem using the standard C file functions */
-#include "DefaultIOSystem.h"
-#include "DefaultIOStream.h"
#include "StringComparison.h"
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/DefaultIOStream.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/ai_assert.h>
#include <stdlib.h>
-
#ifdef __unix__
#include <sys/param.h>
#include <stdlib.h>
diff --git a/src/3rdparty/assimp/code/DefaultLogger.cpp b/src/3rdparty/assimp/code/DefaultLogger.cpp
index 5364bd8bc..b69e18ea9 100644
--- a/src/3rdparty/assimp/code/DefaultLogger.cpp
+++ b/src/3rdparty/assimp/code/DefaultLogger.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -43,13 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of DefaultLogger (and Logger)
*/
-#include "DefaultIOSystem.h"
// Default log streams
#include "Win32DebugLogStream.h"
#include "StdOStreamLogStream.h"
#include "FileLogStream.h"
#include "StringUtils.h"
+
+#include <assimp/DefaultIOSystem.h>
#include <assimp/NullLogger.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/ai_assert.h>
@@ -251,8 +253,8 @@ void DefaultLogger::kill()
// Debug message
void DefaultLogger::OnDebug( const char* message )
{
- if ( m_Severity == Logger::NORMAL )
- return;
+ if ( m_Severity == Logger::NORMAL )
+ return;
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size];
diff --git a/src/3rdparty/assimp/code/DefaultProgressHandler.h b/src/3rdparty/assimp/code/DefaultProgressHandler.h
index b729e4bfa..6cd872eaa 100644
--- a/src/3rdparty/assimp/code/DefaultProgressHandler.h
+++ b/src/3rdparty/assimp/code/DefaultProgressHandler.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/Exceptional.h b/src/3rdparty/assimp/code/Exceptional.h
index e04da757c..5109b8f07 100644
--- a/src/3rdparty/assimp/code/Exceptional.h
+++ b/src/3rdparty/assimp/code/Exceptional.h
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_EXCEPTIONAL_H
#include <stdexcept>
-#include "DefaultIOStream.h"
+#include <assimp/DefaultIOStream.h>
using std::runtime_error;
#ifdef _MSC_VER
@@ -58,8 +58,8 @@ class DeadlyImportError
{
public:
/** Constructor with arguments */
- explicit DeadlyImportError( const std::string& pErrorText)
- : runtime_error(pErrorText)
+ explicit DeadlyImportError( const std::string& errorText)
+ : runtime_error(errorText)
{
}
diff --git a/src/3rdparty/assimp/code/Exporter.cpp b/src/3rdparty/assimp/code/Exporter.cpp
index af2267a62..3fc31a722 100644
--- a/src/3rdparty/assimp/code/Exporter.cpp
+++ b/src/3rdparty/assimp/code/Exporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,9 +53,8 @@ Here we implement only the C++ interface (Assimp::Exporter).
#ifndef ASSIMP_BUILD_NO_EXPORT
-#include "DefaultIOSystem.h"
#include "BlobIOSystem.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "BaseProcess.h"
#include "Importer.h" // need this for GetPostProcessingStepInstanceList()
@@ -64,11 +64,12 @@ Here we implement only the C++ interface (Assimp::Exporter).
#include "Exceptional.h"
#include "ScenePrivate.h"
#include <memory>
+
+#include <assimp/DefaultIOSystem.h>
#include <assimp/Exporter.hpp>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
-#include <memory>
namespace Assimp {
@@ -82,6 +83,7 @@ void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportPrope
void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
@@ -89,29 +91,34 @@ void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportPr
void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
// ------------------------------------------------------------------------------------------------
// global array of all export formats which Assimp supports in its current build
Exporter::ExportFormatEntry gExporters[] =
{
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
- Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
+ Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada ),
#endif
-#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
+#ifndef ASSIMP_BUILD_NO_X_EXPORTER
Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
- aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
+ aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs ),
#endif
#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
- Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0),
+ 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 */),
+ aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ),
+ Exporter::ExportFormatEntry( "objnomtl", "Wavefront OBJ format without material file", "obj", &ExportSceneObjNoMtl,
+ aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ),
#endif
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
@@ -134,22 +141,32 @@ Exporter::ExportFormatEntry gExporters[] =
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
- aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
+ 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*/),
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
- aiProcess_JoinIdenticalVertices /*| aiProcess_SortByPType*/),
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+ Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
+ aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
#endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
- Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
+ Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0 ),
#endif
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
- Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0),
+ Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
+ Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
+#endif
+
+#ifndef ASSIMP_BUILD_NO3MF_EXPORTER
+ Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
#endif
};
@@ -158,7 +175,6 @@ Exporter::ExportFormatEntry gExporters[] =
class ExporterPimpl {
public:
-
ExporterPimpl()
: blob()
, mIOSystem(new Assimp::DefaultIOSystem())
@@ -166,9 +182,11 @@ public:
{
GetPostProcessingStepInstanceList(mPostProcessingSteps);
- // grab all builtin exporters
- mExporters.resize(ASSIMP_NUM_EXPORTERS);
- std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
+ // grab all built-in exporters
+ if ( 0 != ( ASSIMP_NUM_EXPORTERS ) ) {
+ mExporters.resize( ASSIMP_NUM_EXPORTERS );
+ std::copy( gExporters, gExporters + ASSIMP_NUM_EXPORTERS, mExporters.begin() );
+ }
}
~ExporterPimpl()
@@ -182,7 +200,6 @@ public:
}
public:
-
aiExportDataBlob* blob;
std::shared_ptr< Assimp::IOSystem > mIOSystem;
bool mIsDefaultIOHandler;
@@ -197,65 +214,48 @@ public:
std::vector<Exporter::ExportFormatEntry> mExporters;
};
-
} // end of namespace Assimp
-
-
-
-
using namespace Assimp;
-
// ------------------------------------------------------------------------------------------------
Exporter :: Exporter()
-: pimpl(new ExporterPimpl())
-{
+: pimpl(new ExporterPimpl()) {
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
-Exporter :: ~Exporter()
-{
+Exporter::~Exporter() {
FreeBlob();
delete pimpl;
}
-
// ------------------------------------------------------------------------------------------------
-void Exporter :: SetIOHandler( IOSystem* pIOHandler)
-{
+void Exporter::SetIOHandler( IOSystem* pIOHandler) {
pimpl->mIsDefaultIOHandler = !pIOHandler;
pimpl->mIOSystem.reset(pIOHandler);
}
-
// ------------------------------------------------------------------------------------------------
-IOSystem* Exporter :: GetIOHandler() const
-{
+IOSystem* Exporter::GetIOHandler() const {
return pimpl->mIOSystem.get();
}
-
// ------------------------------------------------------------------------------------------------
-bool Exporter :: IsDefaultIOHandler() const
-{
+bool Exporter::IsDefaultIOHandler() const {
return pimpl->mIsDefaultIOHandler;
}
-
// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties)
-{
+const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId,
+ unsigned int, const ExportProperties* /*pProperties*/ ) {
if (pimpl->blob) {
delete pimpl->blob;
pimpl->blob = NULL;
}
-
std::shared_ptr<IOSystem> old = pimpl->mIOSystem;
-
BlobIOSystem* blobio = new BlobIOSystem();
pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
@@ -270,10 +270,8 @@ const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const
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) {
@@ -288,10 +286,8 @@ bool IsVerboseFormat(const aiMesh* mesh)
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;
@@ -300,10 +296,8 @@ bool IsVerboseFormat(const aiScene* pScene)
return true;
}
-
// ------------------------------------------------------------------------------------------------
-aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
-{
+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
@@ -316,12 +310,10 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
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;
+ aiScene* scenecopy_tmp = NULL;
SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
std::unique_ptr<aiScene> scenecopy(scenecopy_tmp);
@@ -337,18 +329,17 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
? (priv->mPPStepsApplied & ~nonIdempotentSteps)
: 0u);
- // If no extra postprocessing was specified, and we obtained this scene from an
+ // If no extra post-processing was specified, and we obtained this scene from an
// Assimp importer, apply the reverse steps automatically.
// TODO: either drop this, or document it. Otherwise it is just a bad surprise.
//if (!pPreprocessing && priv) {
// pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
//}
- // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
+ // If the input scene is not in verbose format, but there is at least post-processing step that relies on it,
// we need to run the MakeVerboseFormat step first.
bool must_join_again = false;
if (!is_verbose_format) {
-
bool verbosify = false;
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* const p = pimpl->mPostProcessingSteps[a];
@@ -419,8 +410,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
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) {
+ } catch (DeadlyExportError& err) {
pimpl->mError = err.what();
return AI_FAILURE;
}
@@ -430,67 +420,57 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
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
-{
+const char* Exporter::GetErrorString() const {
return pimpl->mError.c_str();
}
// ------------------------------------------------------------------------------------------------
-void Exporter :: FreeBlob( )
-{
+void Exporter::FreeBlob() {
delete pimpl->blob;
pimpl->blob = NULL;
pimpl->mError = "";
}
-
// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: GetBlob() const
-{
+const aiExportDataBlob* Exporter::GetBlob() const {
return pimpl->blob;
}
-
// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
-{
+const aiExportDataBlob* Exporter::GetOrphanedBlob() const {
const aiExportDataBlob* tmp = pimpl->blob;
pimpl->blob = NULL;
return tmp;
}
-
// ------------------------------------------------------------------------------------------------
-size_t Exporter :: GetExportFormatCount() const
-{
+size_t Exporter::GetExportFormatCount() const {
return pimpl->mExporters.size();
}
// ------------------------------------------------------------------------------------------------
-const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
-{
- if (pIndex >= GetExportFormatCount()) {
+const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
+ if (index >= 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;
+ if (index < sizeof(gExporters) / sizeof(gExporters[0])) {
+ return &gExporters[index].mDescription;
}
- return &pimpl->mExporters[pIndex].mDescription;
+ return &pimpl->mExporters[index].mDescription;
}
// ------------------------------------------------------------------------------------------------
-aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
-{
+aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
for(const ExportFormatEntry& e : pimpl->mExporters) {
if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
return aiReturn_FAILURE;
@@ -501,10 +481,8 @@ aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
return aiReturn_SUCCESS;
}
-
// ------------------------------------------------------------------------------------------------
-void Exporter :: UnregisterExporter(const char* id)
-{
+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);
@@ -513,30 +491,30 @@ void Exporter :: UnregisterExporter(const char* id)
}
}
-ExportProperties :: ExportProperties() {}
+// ------------------------------------------------------------------------------------------------
+ExportProperties::ExportProperties() {
+ // empty
+}
+// ------------------------------------------------------------------------------------------------
ExportProperties::ExportProperties(const ExportProperties &other)
- : mIntProperties(other.mIntProperties),
- mFloatProperties(other.mFloatProperties),
- mStringProperties(other.mStringProperties),
- mMatrixProperties(other.mMatrixProperties)
-{
-
+: mIntProperties(other.mIntProperties)
+, mFloatProperties(other.mFloatProperties)
+, mStringProperties(other.mStringProperties)
+, mMatrixProperties(other.mMatrixProperties) {
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
// Set a configuration property
-bool ExportProperties :: SetPropertyInteger(const char* szName, int iValue)
-{
+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);
+bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
+ return SetGenericProperty<ai_real>(mFloatProperties, szName,iValue);
}
// ------------------------------------------------------------------------------------------------
@@ -563,10 +541,10 @@ int ExportProperties :: GetPropertyInteger(const char* szName,
// ------------------------------------------------------------------------------------------------
// Get a configuration property
-float ExportProperties :: GetPropertyFloat(const char* szName,
- float iErrorReturn /*= 10e10*/) const
+ai_real ExportProperties :: GetPropertyFloat(const char* szName,
+ ai_real iErrorReturn /*= 10e10*/) const
{
- return GetGenericProperty<float>(mFloatProperties,szName,iErrorReturn);
+ return GetGenericProperty<ai_real>(mFloatProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
@@ -597,28 +575,28 @@ bool ExportProperties :: HasPropertyInteger(const char* szName) const
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);
-};
+ return HasGenericProperty<ai_real>(mFloatProperties, szName);
+}
// ------------------------------------------------------------------------------------------------
// Has a configuration property
bool ExportProperties :: HasPropertyString(const char* szName) const
{
return HasGenericProperty<std::string>(mStringProperties, szName);
-};
+}
// ------------------------------------------------------------------------------------------------
// Has a configuration property
bool ExportProperties :: HasPropertyMatrix(const char* szName) const
{
return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
-};
+}
#endif // !ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/FBXAnimation.cpp b/src/3rdparty/assimp/code/FBXAnimation.cpp
index 0758d4db7..6f9613f0d 100644
--- a/src/3rdparty/assimp/code/FBXAnimation.cpp
+++ b/src/3rdparty/assimp/code/FBXAnimation.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,14 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXParser.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
-#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
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*/)
@@ -88,17 +87,16 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s
}
}
-
// ------------------------------------------------------------------------------------------------
AnimationCurve::~AnimationCurve()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
-AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
- const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/)
+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)
@@ -155,18 +153,16 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
}
-
// ------------------------------------------------------------------------------------------------
AnimationCurveNode::~AnimationCurveNode()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
const AnimationCurveMap& AnimationCurveNode::Curves() const
{
- if(curves.empty()) {
+ if ( curves.empty() ) {
// resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
@@ -196,7 +192,6 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
return curves;
}
-
// ------------------------------------------------------------------------------------------------
AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name)
@@ -208,14 +203,12 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
}
-
// ------------------------------------------------------------------------------------------------
AnimationLayer::~AnimationLayer()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
size_t whitelist_size /*= 0*/) const
@@ -299,14 +292,13 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s
}
}
-
// ------------------------------------------------------------------------------------------------
AnimationStack::~AnimationStack()
{
-
+ // empty
}
} //!FBX
} //!Assimp
-#endif
+#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
diff --git a/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp b/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp
index 551b174ed..519f2e176 100644
--- a/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp
+++ b/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -55,7 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
-
+//enum Flag
+//{
+// e_unknown_0 = 1 << 0,
+// e_unknown_1 = 1 << 1,
+// e_unknown_2 = 1 << 2,
+// e_unknown_3 = 1 << 3,
+// e_unknown_4 = 1 << 4,
+// e_unknown_5 = 1 << 5,
+// e_unknown_6 = 1 << 6,
+// e_unknown_7 = 1 << 7,
+// e_unknown_8 = 1 << 8,
+// e_unknown_9 = 1 << 9,
+// e_unknown_10 = 1 << 10,
+// e_unknown_11 = 1 << 11,
+// e_unknown_12 = 1 << 12,
+// e_unknown_13 = 1 << 13,
+// e_unknown_14 = 1 << 14,
+// e_unknown_15 = 1 << 15,
+// e_unknown_16 = 1 << 16,
+// e_unknown_17 = 1 << 17,
+// e_unknown_18 = 1 << 18,
+// e_unknown_19 = 1 << 19,
+// e_unknown_20 = 1 << 20,
+// e_unknown_21 = 1 << 21,
+// e_unknown_22 = 1 << 22,
+// e_unknown_23 = 1 << 23,
+// e_flag_field_size_64_bit = 1 << 24, // Not sure what is
+// e_unknown_25 = 1 << 25,
+// e_unknown_26 = 1 << 26,
+// e_unknown_27 = 1 << 27,
+// e_unknown_28 = 1 << 28,
+// e_unknown_29 = 1 << 29,
+// e_unknown_30 = 1 << 30,
+// e_unknown_31 = 1 << 31
+//};
+//
+//bool check_flag(uint32_t flags, Flag to_check)
+//{
+// return (flags & to_check) != 0;
+//}
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
:
@@ -106,23 +146,39 @@ void TokenizeError(const std::string& message, const char* begin, const char* cu
// ------------------------------------------------------------------------------------------------
uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
{
- if(Offset(cursor, end) < 4) {
+ const size_t k_to_read = sizeof( uint32_t );
+ if(Offset(cursor, end) < k_to_read ) {
TokenizeError("cannot ReadWord, out of bounds",input, cursor);
}
- uint32_t word = *reinterpret_cast<const uint32_t*>(cursor);
+ uint32_t word;
+ memcpy(&word, cursor, 4);
AI_SWAP4(word);
- cursor += 4;
+ cursor += k_to_read;
return word;
}
+// ------------------------------------------------------------------------------------------------
+uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) {
+ const size_t k_to_read = sizeof(uint64_t);
+ if(Offset(cursor, end) < k_to_read) {
+ TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
+ }
+
+ uint64_t dword = *reinterpret_cast<const uint64_t*>(cursor);
+ AI_SWAP8(dword);
+
+ cursor += k_to_read;
+
+ return dword;
+}
// ------------------------------------------------------------------------------------------------
uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
{
- if(Offset(cursor, end) < 1) {
+ if(Offset(cursor, end) < sizeof( uint8_t ) ) {
TokenizeError("cannot ReadByte, out of bounds",input, cursor);
}
@@ -165,8 +221,6 @@ unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const ch
return length;
}
-
-
// ------------------------------------------------------------------------------------------------
void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end)
{
@@ -287,10 +341,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
// ------------------------------------------------------------------------------------------------
-bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end)
+bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
{
// the first word contains the offset at which this block ends
- const uint32_t end_offset = ReadWord(input, cursor, end);
+ const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
// we may get 0 if reading reached the end of the file -
// fbx files have a mysterious extra footer which I don't know
@@ -308,10 +362,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
}
// the second data word contains the number of properties in the scope
- const uint32_t prop_count = ReadWord(input, cursor, end);
+ const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
// the third data word contains the length of the property list
- const uint32_t prop_length = ReadWord(input, cursor, end);
+ const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
// now comes the name of the scope/key
const char* sbeg, *send;
@@ -337,29 +391,28 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& 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
+ // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit.
+ const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1);
if (Offset(input, cursor) < end_offset) {
-
- if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) {
+ if (end_offset - Offset(input, cursor) < sentinel_block_length) {
TokenizeError("insufficient padding bytes at block end",input, cursor);
}
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
// XXX this is vulnerable to stack overflowing ..
- while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) {
- ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
+ while(Offset(input, cursor) < end_offset - sentinel_block_length) {
+ ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
}
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
- for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
+ for (unsigned int i = 0; i < sentinel_block_length; ++i) {
if(cursor[i] != '\0') {
TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
}
}
- cursor += BLOCK_SENTINEL_LENGTH;
+ cursor += sentinel_block_length;
}
if (Offset(input, cursor) != end_offset) {
@@ -369,10 +422,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
return true;
}
-
}
// ------------------------------------------------------------------------------------------------
+// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
{
ai_assert(input);
@@ -385,13 +438,17 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
TokenizeError("magic bytes not found",0);
}
-
- //uint32_t offset = 0x1b;
-
- const char* cursor = input + 0x1b;
-
- while (cursor < input + length) {
- if(!ReadScope(output_tokens, input, cursor, input + length)) {
+ const char* cursor = input + 18;
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ /*Result ignored*/ ReadByte(input, cursor, input + length);
+ const uint32_t version = ReadWord(input, cursor, input + length);
+ const bool is64bits = version >= 7500;
+ while (cursor < input + length)
+ {
+ if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
break;
}
}
diff --git a/src/3rdparty/assimp/code/FBXCompileConfig.h b/src/3rdparty/assimp/code/FBXCompileConfig.h
index 901f5b330..56aa1c787 100644
--- a/src/3rdparty/assimp/code/FBXCompileConfig.h
+++ b/src/3rdparty/assimp/code/FBXCompileConfig.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_COMPILECONFIG_H
#define INCLUDED_AI_FBX_COMPILECONFIG_H
+#include <map>
+
//
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
@@ -63,4 +66,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# endif
#endif
-#endif
+#endif // INCLUDED_AI_FBX_COMPILECONFIG_H
diff --git a/src/3rdparty/assimp/code/FBXConverter.cpp b/src/3rdparty/assimp/code/FBXConverter.cpp
index 692cda836..24bdfdd11 100644
--- a/src/3rdparty/assimp/code/FBXConverter.cpp
+++ b/src/3rdparty/assimp/code/FBXConverter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -54,11 +55,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h"
#include <assimp/scene.h>
+
#include <tuple>
#include <memory>
-
#include <iterator>
-#include <sstream>
#include <vector>
namespace Assimp {
@@ -71,7 +71,7 @@ using namespace Util;
#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 */
@@ -114,11 +114,9 @@ private:
// 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 );
@@ -189,7 +187,6 @@ private:
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
@@ -341,8 +338,6 @@ private:
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 );
@@ -441,6 +436,18 @@ private:
aiScene* const out;
const FBX::Document& doc;
+
+ bool FindTextureIndexByFilename(const Video& video, unsigned int& index) {
+ index = 0;
+ const char* videoFileName = video.FileName().c_str();
+ for (auto texture = textures_converted.begin(); texture != textures_converted.end(); ++texture) {
+ if (!strcmp(texture->first->FileName().c_str(), videoFileName)) {
+ index = texture->second;
+ return true;
+ }
+ }
+ return false;
+ }
};
Converter::Converter( aiScene* out, const Document& doc )
@@ -558,7 +565,6 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
if ( !name_carrier ) {
nodes_chain.push_back( new aiNode( original_name ) );
- name_carrier = nodes_chain.back();
}
//setup metadata on newest node
@@ -637,7 +643,6 @@ void Converter::ConvertCameras( const Model& model )
}
}
-
void Converter::ConvertLight( const Model& model, const Light& light )
{
lights.push_back( new aiLight() );
@@ -645,7 +650,7 @@ void Converter::ConvertLight( const Model& model, const Light& light )
out_light->mName.Set( FixNodeName( model.Name() ) );
- const float intensity = light.Intensity();
+ const float intensity = light.Intensity() / 100.0f;
const aiVector3D& col = light.Color();
out_light->mColorDiffuse = aiColor3D( col.x, col.y, col.z );
@@ -655,6 +660,11 @@ void Converter::ConvertLight( const Model& model, const Light& light )
out_light->mColorSpecular = out_light->mColorDiffuse;
+ //lights are defined along negative y direction
+ out_light->mPosition = aiVector3D(0.0f);
+ out_light->mDirection = aiVector3D(0.0f, -1.0f, 0.0f);
+ out_light->mUp = aiVector3D(0.0f, 0.0f, -1.0f);
+
switch ( light.LightType() )
{
case Light::Type_Point:
@@ -684,17 +694,23 @@ void Converter::ConvertLight( const Model& model, const Light& light )
ai_assert( false );
}
- // XXX: how to best convert the near and far decay ranges?
+ float decay = light.DecayStart();
switch ( light.DecayType() )
{
case Light::Decay_None:
- out_light->mAttenuationConstant = 1.0f;
+ out_light->mAttenuationConstant = decay;
+ out_light->mAttenuationLinear = 0.0f;
+ out_light->mAttenuationQuadratic = 0.0f;
break;
case Light::Decay_Linear:
- out_light->mAttenuationLinear = 1.0f;
+ out_light->mAttenuationConstant = 0.0f;
+ out_light->mAttenuationLinear = 2.0f / decay;
+ out_light->mAttenuationQuadratic = 0.0f;
break;
case Light::Decay_Quadratic:
- out_light->mAttenuationQuadratic = 1.0f;
+ out_light->mAttenuationConstant = 0.0f;
+ out_light->mAttenuationLinear = 0.0f;
+ out_light->mAttenuationQuadratic = 2.0f / (decay * decay);
break;
case Light::Decay_Cubic:
FBXImporter::LogWarn( "cannot represent cubic attenuation, set to Quadratic" );
@@ -713,10 +729,13 @@ void Converter::ConvertCamera( const Model& model, const Camera& cam )
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;
+ //cameras are defined along positive x direction
+ out_camera->mPosition = aiVector3D(0.0f);
+ out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
+ out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
out_camera->mHorizontalFOV = AI_DEG_TO_RAD( cam.FieldOfView() );
+ out_camera->mClipPlaneNear = cam.NearPlane();
+ out_camera->mClipPlaneFar = cam.FarPlane();
}
@@ -761,7 +780,6 @@ const char* Converter::NameTransformationComp( TransformationComp comp )
return NULL;
}
-
const char* Converter::NameTransformationCompProperty( TransformationComp comp )
{
switch ( comp )
@@ -899,7 +917,6 @@ void Converter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotat
}
}
-
bool Converter::NeedsComplexTransformationChain( const Model& model )
{
const PropertyTable& props = model.Props();
@@ -910,7 +927,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
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 ) {
+ comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) {
continue;
}
@@ -923,14 +940,12 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
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 )
+void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
{
const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder();
@@ -1045,6 +1060,10 @@ void Converter::GenerateTransformationNodeChain( const Model& model,
continue;
}
+ if ( comp == TransformationComp_PostRotation ) {
+ chain[ i ] = chain[ i ].Inverse();
+ }
+
aiNode* nd = new aiNode();
output_nodes.push_back( nd );
@@ -1067,18 +1086,14 @@ void Converter::GenerateTransformationNodeChain( const Model& model,
}
}
-
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 ]();
+ const std::size_t numStaticMetaData = 2;
+ aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData) );
nd.mMetaData = data;
int index = 0;
@@ -1089,22 +1104,22 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd )
// 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> >() )
+ 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> >() )
+ } 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> >() )
+ } 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> >() )
+ } 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> >() )
+ } 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> >() )
+ } else if ( const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >() ) {
data->Set( index++, prop.first, interpreted->Value() );
- else
- assert( false );
+ } else {
+ ai_assert( false );
+ }
}
}
@@ -1135,7 +1150,6 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
}
}
-
std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
const aiMatrix4x4& node_global_transform )
{
@@ -1171,7 +1185,6 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
return temp;
}
-
aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
{
aiMesh* const out_mesh = new aiMesh();
@@ -1191,7 +1204,6 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
return out_mesh;
}
-
unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
const aiMatrix4x4& node_global_transform )
{
@@ -1394,9 +1406,9 @@ unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, cons
// allocate tangents, binormals.
const std::vector<aiVector3D>& tangents = mesh.GetTangents();
const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
+ std::vector<aiVector3D> tempBinormals;
if ( tangents.size() ) {
- std::vector<aiVector3D> tempBinormals;
if ( !binormals->size() ) {
if ( normals.size() ) {
// XXX this computes the binormals for the entire mesh, not only
@@ -1514,7 +1526,6 @@ unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, cons
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,
@@ -1661,7 +1672,6 @@ void Converter::ConvertCluster( std::vector<aiBone*>& bones, const Model& /*mode
}
}
-
void Converter::ConvertMaterialForMesh( aiMesh* out, const Model& model, const MeshGeometry& geo,
MatIndexArray::value_type materialIndex )
{
@@ -1751,7 +1761,7 @@ unsigned int Converter::ConvertVideo( const Video& video )
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
+ // 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
@@ -1785,22 +1795,32 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
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 );
- }
+ if (media != 0) {
+ bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
+ unsigned int index;
+
+ VideoMap::const_iterator it = textures_converted.find(media);
+ if (it != textures_converted.end()) {
+ index = (*it).second;
+ textureReady = true;
+ }
+ else {
+ if (media->ContentLength() > 0) {
+ index = ConvertVideo(*media);
+ textures_converted[media] = index;
+ textureReady = true;
+ }
+ else if (doc.Settings().searchEmbeddedTextures) { //try to find the texture on the already-loaded textures by the filename, if the flag is on
+ textureReady = FindTextureIndexByFilename(*media, index);
+ }
+ }
+
+ // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
+ if (textureReady) {
+ path.data[0] = '*';
+ path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+ }
+ }
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
@@ -1916,57 +1936,92 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
return;
}
- const Texture* const tex = ( *it ).second->getTexture();
+ int texCount = (*it).second->textureCount();
+
+ // Set the blend mode for layered textures
+ int blendmode= (*it).second->GetBlendMode();
+ out_mat->AddProperty(&blendmode,1,_AI_MATKEY_TEXOP_BASE,target,0);
+
+ for(int texIndex = 0; texIndex < texCount; texIndex++){
+
+ const Texture* const tex = ( *it ).second->getTexture(texIndex);
+
+ aiString path;
+ path.Set( tex->RelativeFilename() );
+
+ out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
- aiString path;
- path.Set( tex->RelativeFilename() );
+ aiUVTransform uvTrafo;
+ // XXX handle all kinds of UV transformations
+ uvTrafo.mScaling = tex->UVScaling();
+ uvTrafo.mTranslation = tex->UVTranslation();
+ out_mat->AddProperty( &uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex );
- out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
+ const PropertyTable& props = tex->Props();
- 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 );
+ int uvIndex = 0;
- const PropertyTable& props = tex->Props();
+ 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.
- int uvIndex = 0;
+ // 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.
- 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 unsigned int matIndex = static_cast<unsigned int>( std::distance( materials.begin(),
+ std::find( materials.begin(), materials.end(), out_mat )
+ ) );
- const MatIndexArray& mats = mesh->GetMaterialIndices();
- if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) {
- continue;
- }
+ 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() ) {
@@ -1980,48 +2035,22 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
}
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;
+ FBXImporter::LogWarn( "failed to resolve UV channel " + uvSet + ", using first UV channel" );
+ uvIndex = 0;
}
}
-
- 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 );
+ out_mat->AddProperty( &uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex );
+ }
}
void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh )
@@ -2030,6 +2059,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& tex
TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh );
TrySetTextureProperties( out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh );
TrySetTextureProperties( out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh );
+ TrySetTextureProperties( out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
TrySetTextureProperties( out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh );
TrySetTextureProperties( out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh );
TrySetTextureProperties( out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh );
@@ -2044,6 +2074,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureM
TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh );
+ TrySetTextureProperties( out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
TrySetTextureProperties( out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh );
@@ -2125,6 +2156,16 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT
if ( ok ) {
out_mat->AddProperty( &ShininessExponent, 1, AI_MATKEY_SHININESS );
}
+
+ const float BumpFactor = PropertyGet<float>(props, "BumpFactor", ok);
+ if (ok) {
+ out_mat->AddProperty(&BumpFactor, 1, AI_MATKEY_BUMPSCALING);
+ }
+
+ const float DispFactor = PropertyGet<float>(props, "DisplacementFactor", ok);
+ if (ok) {
+ out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0);
+ }
}
@@ -2194,9 +2235,17 @@ void Converter::ConvertAnimations()
}
}
+void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) {
+ if ( node_names.find( fixed_name ) == node_names.end() ) {
+ FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing.");
+ return;
+ }
+
+ if ( node_names.find( new_name ) != node_names.end() ) {
+ FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." );
+ return;
+ }
-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() );
@@ -2326,8 +2375,13 @@ void Converter::ConvertAnimationStack( const AnimationStack& st )
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 );
+ bool has_local_startstop = start_time != 0 || stop_time != 0;
+ if ( !has_local_startstop ) {
+ // no time range given, so accept every keyframe and use the actual min/max time
+ // the numbers are INT64_MIN/MAX, the 20000 is for safety because GenerateNodeAnimations uses an epsilon of 10000
+ start_time = -9223372036854775807ll + 20000;
+ stop_time = 9223372036854775807ll - 20000;
+ }
try {
for( const NodeMap::value_type& kv : node_map ) {
@@ -2359,30 +2413,27 @@ void Converter::ConvertAnimationStack( const AnimationStack& st )
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;
- }
+ double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time;
+ double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time;
- max_time -= min_time;
+ // adjust relative timing for animation
+ for ( unsigned int c = 0; c < anim->mNumChannels; c++ ) {
+ aiNodeAnim* channel = anim->mChannels[ c ];
+ for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ )
+ channel->mPositionKeys[ i ].mTime -= start_time_fps;
+ for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ )
+ channel->mRotationKeys[ i ].mTime -= start_time_fps;
+ for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ )
+ channel->mScalingKeys[ i ].mTime -= start_time_fps;
}
// for 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->mDuration = stop_time_fps - start_time_fps;
anim->mTicksPerSecond = anim_fps;
}
+#ifdef ASSIMP_BUILD_DEBUG
// ------------------------------------------------------------------------------------------------
// sanity check whether the input is ok
static void validateAnimCurveNodes( const std::vector<const AnimationCurveNode*>& curves,
@@ -2400,6 +2451,7 @@ static void validateAnimCurveNodes( const std::vector<const AnimationCurveNode*>
}
}
}
+#endif // ASSIMP_BUILD_DEBUG
// ------------------------------------------------------------------------------------------------
void Converter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
@@ -2691,10 +2743,10 @@ aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name,
double& max_time,
double& min_time )
{
- ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() );
na->mNodeName.Set( name );
- ConvertRotationKeys( na, curves, layer_map, start, stop, max_time, min_time, target.RotationOrder() );
+ ConvertRotationKeys( na.get(), curves, layer_map, start, stop, max_time, min_time, target.RotationOrder() );
// dummy scaling key
na->mScalingKeys = new aiVectorKey[ 1 ];
@@ -2710,7 +2762,7 @@ aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name,
na->mPositionKeys[ 0 ].mTime = 0.;
na->mPositionKeys[ 0 ].mValue = aiVector3D();
- return na.dismiss();
+ return na.release();
}
aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name,
@@ -2721,10 +2773,10 @@ aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name,
double& max_time,
double& min_time )
{
- ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() );
na->mNodeName.Set( name );
- ConvertScaleKeys( na, curves, layer_map, start, stop, max_time, min_time );
+ ConvertScaleKeys( na.get(), curves, layer_map, start, stop, max_time, min_time );
// dummy rotation key
na->mRotationKeys = new aiQuatKey[ 1 ];
@@ -2740,7 +2792,7 @@ aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name,
na->mPositionKeys[ 0 ].mTime = 0.;
na->mPositionKeys[ 0 ].mValue = aiVector3D();
- return na.dismiss();
+ return na.release();
}
@@ -2753,10 +2805,10 @@ aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name,
double& min_time,
bool inverse )
{
- ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() );
na->mNodeName.Set( name );
- ConvertTranslationKeys( na, curves, layer_map, start, stop, max_time, min_time );
+ ConvertTranslationKeys( na.get(), curves, layer_map, start, stop, max_time, min_time );
if ( inverse ) {
for ( unsigned int i = 0; i < na->mNumPositionKeys; ++i ) {
@@ -2778,7 +2830,7 @@ aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name,
na->mRotationKeys[ 0 ].mTime = 0.;
na->mRotationKeys[ 0 ].mValue = aiQuaternion();
- return na.dismiss();
+ return na.release();
}
aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
@@ -2792,7 +2844,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
bool reverse_order )
{
- ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ std::unique_ptr<aiNodeAnim> na( new aiNodeAnim() );
na->mNodeName.Set( name );
const PropertyTable& props = target.Props();
@@ -2864,7 +2916,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
// which requires all of rotation, scaling and translation
// to be set.
if ( chain[ TransformationComp_Scaling ] != iter_end ) {
- ConvertScaleKeys( na, ( *chain[ TransformationComp_Scaling ] ).second,
+ ConvertScaleKeys( na.get(), ( *chain[ TransformationComp_Scaling ] ).second,
layer_map,
start, stop,
max_time,
@@ -2880,7 +2932,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
}
if ( chain[ TransformationComp_Rotation ] != iter_end ) {
- ConvertRotationKeys( na, ( *chain[ TransformationComp_Rotation ] ).second,
+ ConvertRotationKeys( na.get(), ( *chain[ TransformationComp_Rotation ] ).second,
layer_map,
start, stop,
max_time,
@@ -2898,7 +2950,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
}
if ( chain[ TransformationComp_Translation ] != iter_end ) {
- ConvertTranslationKeys( na, ( *chain[ TransformationComp_Translation ] ).second,
+ ConvertTranslationKeys( na.get(), ( *chain[ TransformationComp_Translation ] ).second,
layer_map,
start, stop,
max_time,
@@ -2914,7 +2966,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name,
}
}
- return na.dismiss();
+ return na.release();
}
Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop )
@@ -2953,10 +3005,10 @@ Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector<const
//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();
+ const size_t count = curve->GetKeys().size();
Keys->reserve( count );
Values->reserve( count );
- for ( int n = 0; n < count; n++ )
+ for (size_t n = 0; n < count; n++ )
{
int64_t k = curve->GetKeys().at( n );
if ( k >= adj_start && k <= adj_stop )
@@ -3037,7 +3089,7 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
next_pos.resize( inputs.size(), 0 );
for( KeyTimeList::value_type time : keys ) {
- float result[ 3 ] = { def_value.x, def_value.y, def_value.z };
+ ai_real result[ 3 ] = { def_value.x, def_value.y, def_value.z };
for ( size_t i = 0; i < count; ++i ) {
const KeyFrameList& kfl = inputs[ i ];
@@ -3057,10 +3109,8 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
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 );
+ const ai_real factor = timeB == timeA ? ai_real(0.) : static_cast<ai_real>( ( time - timeA ) ) / ( timeB - timeA );
+ const ai_real interpValue = static_cast<ai_real>( valueA + ( valueB - valueA ) * factor );
result[ std::get<2>(kfl) ] = interpValue;
}
@@ -3079,7 +3129,6 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
}
}
-
void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
const aiVector3D& def_value,
double& maxTime,
@@ -3100,7 +3149,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
valOut[ i ].mTime = temp[ i ].mTime;
-
GetRotationMatrix( order, temp[ i ].mValue, m );
aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) );
@@ -3119,7 +3167,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
}
}
-
void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale,
aiVectorKey* out_translation,
const KeyFrameListList& scaling,
@@ -3178,7 +3225,6 @@ void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey
}
}
-
aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order )
{
aiMatrix4x4 m;
@@ -3187,7 +3233,6 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde
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,
@@ -3208,7 +3253,6 @@ void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const Animat
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,
@@ -3227,7 +3271,6 @@ void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const
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,
@@ -3249,7 +3292,8 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const Ani
void Converter::TransferDataToScene()
{
- ai_assert( !out->mMeshes && !out->mNumMeshes );
+ ai_assert( !out->mMeshes );
+ ai_assert( !out->mNumMeshes );
// note: the trailing () ensures initialization with NULL - not
// many C++ users seem to know this, so pointing it out to avoid
diff --git a/src/3rdparty/assimp/code/FBXConverter.h b/src/3rdparty/assimp/code/FBXConverter.h
index ddbbbbf25..8a62d8811 100644
--- a/src/3rdparty/assimp/code/FBXConverter.h
+++ b/src/3rdparty/assimp/code/FBXConverter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/FBXDeformer.cpp b/src/3rdparty/assimp/code/FBXDeformer.cpp
index 47db96563..637144ab1 100644
--- a/src/3rdparty/assimp/code/FBXDeformer.cpp
+++ b/src/3rdparty/assimp/code/FBXDeformer.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,14 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXParser.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
-#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
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)
@@ -159,8 +158,6 @@ Skin::~Skin()
}
-
-
}
}
diff --git a/src/3rdparty/assimp/code/FBXDocument.cpp b/src/3rdparty/assimp/code/FBXDocument.cpp
index cf5f6da86..9592bf31f 100644
--- a/src/3rdparty/assimp/code/FBXDocument.cpp
+++ b/src/3rdparty/assimp/code/FBXDocument.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -55,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <functional>
-
+#include <map>
namespace Assimp {
namespace FBX {
@@ -69,19 +70,13 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
, id(id)
, flags()
{
-
+ // empty
}
// ------------------------------------------------------------------------------------------------
LazyObject::~LazyObject()
{
-
-}
-
-// ------------------------------------------------------------------------------------------------
-static void dumpObjectClassInfo( const char* obtype, const std::string &classtag ) {
- DefaultLogger::get()->debug( "obtype: " + std::string(obtype ));
- DefaultLogger::get()->debug( "Classtag: " + classtag );
+ // empty
}
// ------------------------------------------------------------------------------------------------
@@ -237,32 +232,29 @@ Object::Object(uint64_t id, const Element& element, const std::string& name)
, name(name)
, id(id)
{
-
+ // empty
}
// ------------------------------------------------------------------------------------------------
Object::~Object()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
: props(props)
, doc(doc)
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
FileGlobalSettings::~FileGlobalSettings()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
Document::Document(const Parser& parser, const ImportSettings& settings)
: settings(settings)
@@ -285,7 +277,6 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
ReadConnections();
}
-
// ------------------------------------------------------------------------------------------------
Document::~Document()
{
@@ -300,11 +291,10 @@ Document::~Document()
}
// ------------------------------------------------------------------------------------------------
-static const int LowerSupportedVersion = 7100;
-static const int UpperSupportedVersion = 7400;
+static const unsigned int LowerSupportedVersion = 7100;
+static const unsigned int UpperSupportedVersion = 7400;
-void Document::ReadHeader()
-{
+void Document::ReadHeader() {
// Read ID objects from "Objects" section
const Scope& sc = parser.GetRootScope();
const Element* const ehead = sc["FBXHeaderExtension"];
@@ -315,7 +305,7 @@ void Document::ReadHeader()
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
+ // While we may have some success with newer files, we don't support
// the older 6.n fbx format
if(fbxVersion < LowerSupportedVersion ) {
DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
@@ -331,7 +321,6 @@ void Document::ReadHeader()
}
}
-
const Element* const ecreator = shead["Creator"];
if(ecreator) {
creator = ParseTokenAsString(GetRequiredToken(*ecreator,0));
@@ -371,7 +360,6 @@ void Document::ReadGlobalSettings()
globals.reset(new FileGlobalSettings(*this, props));
}
-
// ------------------------------------------------------------------------------------------------
void Document::ReadObjects()
{
@@ -397,7 +385,6 @@ void Document::ReadObjects()
}
const char* err;
-
const uint64_t id = ParseTokenAsID(*tok[0], err);
if(err) {
DOMError(err,el.second);
@@ -479,8 +466,6 @@ void Document::ReadPropertyTemplates()
}
}
-
-
// ------------------------------------------------------------------------------------------------
void Document::ReadConnections()
{
@@ -492,7 +477,6 @@ void Document::ReadConnections()
}
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) {
@@ -501,7 +485,9 @@ void Document::ReadConnections()
// PP = property-property connection, ignored for now
// (tokens: "PP", ID1, "Property1", ID2, "Property2")
- if(type == "PP") continue;
+ if ( type == "PP" ) {
+ continue;
+ }
const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1));
const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2));
@@ -528,11 +514,10 @@ void Document::ReadConnections()
}
}
-
// ------------------------------------------------------------------------------------------------
const std::vector<const AnimationStack*>& Document::AnimationStacks() const
{
- if (!animationStacksResolved.empty() || !animationStacks.size()) {
+ if (!animationStacksResolved.empty() || animationStacks.empty()) {
return animationStacksResolved;
}
@@ -550,7 +535,6 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
return animationStacksResolved;
}
-
// ------------------------------------------------------------------------------------------------
LazyObject* Document::GetObject(uint64_t id) const
{
@@ -561,8 +545,7 @@ LazyObject* Document::GetObject(uint64_t id) const
#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;
@@ -574,12 +557,11 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
temp.push_back((*it).second);
}
- std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
+ std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
return temp; // NRVO should handle this
}
-
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
const ConnectionMap& conns,
@@ -588,17 +570,17 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
{
ai_assert(classnames);
- ai_assert(count != 0 && count <= MAX_CLASSNAMES);
+ ai_assert( count != 0 );
+ ai_assert( count <= 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]);
+ lenghts[ i ] = strlen(classnames[i]);
}
std::vector<const Connection*> temp;
-
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
conns.equal_range(id);
@@ -626,53 +608,44 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
temp.push_back((*it).second);
}
- std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
+ std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
return temp; // NRVO should handle this
}
-
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
{
return GetConnectionsSequenced(source, ConnectionsBySource());
}
-
-
// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t 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);
}
-
-
// ------------------------------------------------------------------------------------------------
-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);
}
-
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
- const char* classname) const
+ const char* classname) const
{
const char* arr[] = {classname};
return GetConnectionsByDestinationSequenced(dest, arr,1);
}
-
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
{
return GetConnectionsSequenced(dest, ConnectionsByDestination());
}
-
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* const* classnames, size_t count) const
@@ -681,10 +654,9 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
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)
+ const Document& doc)
: insertionOrder(insertionOrder)
, prop(prop)
@@ -697,14 +669,12 @@ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, co
ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
}
-
// ------------------------------------------------------------------------------------------------
Connection::~Connection()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazySourceObject() const
{
@@ -713,7 +683,6 @@ LazyObject& Connection::LazySourceObject() const
return *lazy;
}
-
// ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazyDestinationObject() const
{
@@ -722,7 +691,6 @@ LazyObject& Connection::LazyDestinationObject() const
return *lazy;
}
-
// ------------------------------------------------------------------------------------------------
const Object* Connection::SourceObject() const
{
@@ -731,7 +699,6 @@ const Object* Connection::SourceObject() const
return lazy->Get();
}
-
// ------------------------------------------------------------------------------------------------
const Object* Connection::DestinationObject() const
{
@@ -744,4 +711,3 @@ const Object* Connection::DestinationObject() const
} // !Assimp
#endif
-
diff --git a/src/3rdparty/assimp/code/FBXDocument.h b/src/3rdparty/assimp/code/FBXDocument.h
index 62d463bab..a4e28b2aa 100644
--- a/src/3rdparty/assimp/code/FBXDocument.h
+++ b/src/3rdparty/assimp/code/FBXDocument.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -240,6 +241,9 @@ public:
fbx_simple_property(FilmWidth, float, 1.0f)
fbx_simple_property(FilmHeight, float, 1.0f)
+ fbx_simple_property(NearPlane, float, 0.1f)
+ fbx_simple_property(FarPlane, float, 100.0f)
+
fbx_simple_property(FilmAspectRatio, float, 1.0f)
fbx_simple_property(ApertureMode, int, 0)
@@ -302,12 +306,12 @@ public:
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(Intensity, float, 100.0f)
fbx_simple_property(InnerAngle, float, 0.0f)
fbx_simple_property(OuterAngle, float, 45.0f)
fbx_simple_property(Fog, int, 50)
- fbx_simple_enum_property(DecayType, Decay, 0)
- fbx_simple_property(DecayStart, int, 0)
+ fbx_simple_enum_property(DecayType, Decay, 2)
+ fbx_simple_property(DecayStart, float, 1.0f)
fbx_simple_property(FileName, std::string, "")
fbx_simple_property(EnableNearAttenuation, bool, false)
@@ -334,12 +338,7 @@ public:
class Model : public Object
{
public:
- Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- virtual ~Model();
-
-public:
- enum RotOrder
- {
+ enum RotOrder {
RotOrder_EulerXYZ = 0,
RotOrder_EulerXZY,
RotOrder_EulerYZX,
@@ -353,8 +352,7 @@ public:
};
- enum TransformInheritance
- {
+ enum TransformInheritance {
TransformInheritance_RrSs = 0,
TransformInheritance_RSrs,
TransformInheritance_Rrs,
@@ -362,7 +360,10 @@ public:
TransformInheritance_MAX // end-of-enum sentinel
};
-public:
+ Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+
+ virtual ~Model();
+
fbx_simple_property(QuaternionInterpolate, int, 0)
fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
@@ -439,7 +440,6 @@ public:
fbx_simple_property(LODBox, bool, false)
fbx_simple_property(Freeze, bool, false)
-public:
const std::string& Shading() const {
return shading;
}
@@ -458,13 +458,11 @@ public:
return materials;
}
-
/** Get geometry links */
const std::vector<const Geometry*>& GetGeometry() const {
return geometry;
}
-
/** Get node attachments */
const std::vector<const NodeAttribute*>& GetAttributes() const {
return attributes;
@@ -473,7 +471,6 @@ public:
/** convenience method to check if the node has a Null node marker */
bool IsNull() const;
-
private:
void ResolveLinks(const Element& element, const Document& doc);
@@ -594,23 +591,24 @@ public:
BlendMode_BlendModeCount
};
- const Texture* getTexture() const
+ const Texture* getTexture(int index=0) const
{
- return texture;
- }
+ return textures[index];
- BlendMode GetBlendMode()
+ }
+ int textureCount() const {
+ return static_cast<int>(textures.size());
+ }
+ BlendMode GetBlendMode() const
{
return blendMode;
}
-
float Alpha()
{
return alpha;
}
-
private:
- const Texture* texture;
+ std::vector<const Texture*> textures;
BlendMode blendMode;
float alpha;
};
@@ -649,7 +647,7 @@ public:
return content;
}
- const uint32_t ContentLength() const {
+ uint32_t ContentLength() const {
return contentLength;
}
@@ -800,7 +798,6 @@ private:
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
-
/** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer : public Object
{
@@ -823,10 +820,8 @@ private:
const Document& doc;
};
-
typedef std::vector<const AnimationLayer*> AnimationLayerList;
-
/** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack : public Object
{
@@ -834,7 +829,6 @@ public:
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)
@@ -874,7 +868,6 @@ private:
typedef std::vector<float> WeightArray;
typedef std::vector<unsigned int> WeightIndexArray;
-
/** DOM class for skin deformer clusters (aka subdeformers) */
class Cluster : public Deformer
{
@@ -919,8 +912,6 @@ private:
const Model* node;
};
-
-
/** DOM class for skin deformers */
class Skin : public Deformer
{
@@ -1004,10 +995,8 @@ public:
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;
-
/** DOM class for global document settings, a single instance per document can
* be accessed via Document.Globals(). */
class FileGlobalSettings
@@ -1069,9 +1058,6 @@ private:
const Document& doc;
};
-
-
-
/** DOM root for a FBX file */
class Document
{
@@ -1149,8 +1135,6 @@ private:
const ConnectionMap&,
const char* const* classnames,
size_t count) const;
-
-private:
void ReadHeader();
void ReadObjects();
void ReadPropertyTemplates();
diff --git a/src/3rdparty/assimp/code/FBXDocumentUtil.cpp b/src/3rdparty/assimp/code/FBXDocumentUtil.cpp
index 442c60b5d..27921b920 100644
--- a/src/3rdparty/assimp/code/FBXDocumentUtil.cpp
+++ b/src/3rdparty/assimp/code/FBXDocumentUtil.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/FBXImportSettings.h b/src/3rdparty/assimp/code/FBXImportSettings.h
index df7cdbd37..53fa64ec6 100644
--- a/src/3rdparty/assimp/code/FBXImportSettings.h
+++ b/src/3rdparty/assimp/code/FBXImportSettings.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -62,6 +63,7 @@ struct ImportSettings
, readWeights(true)
, preservePivots(true)
, optimizeEmptyAnimationCurves(true)
+ , searchEmbeddedTextures(false)
{}
@@ -136,6 +138,10 @@ struct ImportSettings
* values matching the corresponding node transformation.
* The default value is true. */
bool optimizeEmptyAnimationCurves;
+
+ /** search for embedded loaded textures, where no embedded texture data is provided.
+ * The default value is false. */
+ bool searchEmbeddedTextures;
};
diff --git a/src/3rdparty/assimp/code/FBXImporter.cpp b/src/3rdparty/assimp/code/FBXImporter.cpp
index b319da8b6..51e41b8f4 100644
--- a/src/3rdparty/assimp/code/FBXImporter.cpp
+++ b/src/3rdparty/assimp/code/FBXImporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,9 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-#include <exception>
-#include <iterator>
-
#include "FBXImporter.h"
#include "FBXTokenizer.h"
@@ -58,9 +56,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StreamReader.h"
#include "MemoryIOWrapper.h"
#include <assimp/Importer.hpp>
+#include <assimp/importerdesc.h>
namespace Assimp {
- template<> const std::string LogFunctions<FBXImporter>::log_prefix = "FBX: ";
+ template<> const char* LogFunctions<FBXImporter>::Prefix()
+ {
+ static auto prefix = "FBX: ";
+ return prefix;
+ }
}
using namespace Assimp;
@@ -99,7 +102,7 @@ FBXImporter::~FBXImporter()
bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string& extension = GetExtension(pFile);
- if (extension == "fbx") {
+ if (extension == std::string( desc.mFileExtensions ) ) {
return true;
}
@@ -118,7 +121,6 @@ const aiImporterDesc* FBXImporter::GetInfo () const
return &desc;
}
-
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void FBXImporter::SetupProperties(const Importer* pImp)
@@ -133,9 +135,9 @@ void FBXImporter::SetupProperties(const Importer* pImp)
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.searchEmbeddedTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES, false);
}
-
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void FBXImporter::InternReadFile( const std::string& pFile,
@@ -165,7 +167,7 @@ void FBXImporter::InternReadFile( const std::string& pFile,
bool is_binary = false;
if (!strncmp(begin,"Kaydara FBX Binary",18)) {
is_binary = true;
- TokenizeBinary(tokens,begin,contents.size());
+ TokenizeBinary(tokens,begin,static_cast<unsigned int>(contents.size()));
}
else {
Tokenize(tokens,begin);
diff --git a/src/3rdparty/assimp/code/FBXImporter.h b/src/3rdparty/assimp/code/FBXImporter.h
index 350ecfb67..43be97ffa 100644
--- a/src/3rdparty/assimp/code/FBXImporter.h
+++ b/src/3rdparty/assimp/code/FBXImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/FBXMaterial.cpp b/src/3rdparty/assimp/code/FBXMaterial.cpp
index 43e501d67..a80f243ba 100644
--- a/src/3rdparty/assimp/code/FBXMaterial.cpp
+++ b/src/3rdparty/assimp/code/FBXMaterial.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -227,7 +228,6 @@ Texture::~Texture()
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)
{
@@ -249,7 +249,7 @@ LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Docume
LayeredTexture::~LayeredTexture()
{
-
+
}
void LayeredTexture::fillTexture(const Document& doc)
@@ -267,7 +267,7 @@ void LayeredTexture::fillTexture(const Document& doc)
const Texture* const tex = dynamic_cast<const Texture*>(ob);
- texture = tex;
+ textures.push_back(tex);
}
}
@@ -281,7 +281,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
const Scope& sc = GetRequiredScope(element);
const Element* const Type = sc["Type"];
- const Element* const FileName = sc["FileName"];
+ const Element* const FileName = sc.FindElementCaseInsensitive("FileName"); //some files retain the information as "Filename", others "FileName", who knows
const Element* const RelativeFilename = sc["RelativeFilename"];
const Element* const Content = sc["Content"];
@@ -291,35 +291,40 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
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);
- }
+ //this field is ommited when the embedded texture is already loaded, let's ignore if its not found
+ try {
+ 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);
+ }
+ } catch (runtime_error runtimeError) {
+ //we dont need the content data for contents that has already been loaded
+ }
}
props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
diff --git a/src/3rdparty/assimp/code/FBXMeshGeometry.cpp b/src/3rdparty/assimp/code/FBXMeshGeometry.cpp
index e9d83911b..8d43a2436 100644
--- a/src/3rdparty/assimp/code/FBXMeshGeometry.cpp
+++ b/src/3rdparty/assimp/code/FBXMeshGeometry.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -117,12 +118,12 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
return;
}
- vertices.reserve(tempFaces.size());
- faces.reserve(tempFaces.size() / 3);
+ m_vertices.reserve(tempFaces.size());
+ m_faces.reserve(tempFaces.size() / 3);
- mapping_offsets.resize(tempVerts.size());
- mapping_counts.resize(tempVerts.size(),0);
- mappings.resize(tempFaces.size());
+ m_mapping_offsets.resize(tempVerts.size());
+ m_mapping_counts.resize(tempVerts.size(),0);
+ m_mappings.resize(tempFaces.size());
const size_t vertex_count = tempVerts.size();
@@ -135,29 +136,29 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
DOMError("polygon vertex index out of range",&PolygonVertexIndex);
}
- vertices.push_back(tempVerts[absi]);
+ m_vertices.push_back(tempVerts[absi]);
++count;
- ++mapping_counts[absi];
+ ++m_mapping_counts[absi];
if (index < 0) {
- faces.push_back(count);
+ m_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];
+ m_mapping_offsets[i] = cursor;
+ cursor += m_mapping_counts[i];
- mapping_counts[i] = 0;
+ m_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++;
+ m_mappings[m_mapping_offsets[absi] + m_mapping_counts[absi]++] = cursor++;
}
// if settings.readAllLayers is true:
@@ -191,84 +192,83 @@ MeshGeometry::~MeshGeometry()
// ------------------------------------------------------------------------------------------------
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
- return vertices;
+ return m_vertices;
}
// ------------------------------------------------------------------------------------------------
const std::vector<aiVector3D>& MeshGeometry::GetNormals() const {
- return normals;
+ return m_normals;
}
// ------------------------------------------------------------------------------------------------
const std::vector<aiVector3D>& MeshGeometry::GetTangents() const {
- return tangents;
+ return m_tangents;
}
// ------------------------------------------------------------------------------------------------
const std::vector<aiVector3D>& MeshGeometry::GetBinormals() const {
- return binormals;
+ return m_binormals;
}
// ------------------------------------------------------------------------------------------------
const std::vector<unsigned int>& MeshGeometry::GetFaceIndexCounts() const {
- return faces;
+ return m_faces;
}
// ------------------------------------------------------------------------------------------------
const std::vector<aiVector2D>& MeshGeometry::GetTextureCoords( unsigned int index ) const {
static const std::vector<aiVector2D> empty;
- return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : uvs[ index ];
+ return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ];
}
std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const {
- return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : uvNames[ index ];
+ return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : m_uvNames[ index ];
}
const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index ) const {
static const std::vector<aiColor4D> empty;
- return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : colors[ index ];
+ return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ];
}
const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
- return materials;
+ return m_materials;
}
// ------------------------------------------------------------------------------------------------
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
- if ( in_index >= mapping_counts.size() ) {
+ if ( in_index >= m_mapping_counts.size() ) {
return NULL;
}
- ai_assert( mapping_counts.size() == mapping_offsets.size() );
- count = mapping_counts[ in_index ];
+ ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
+ count = m_mapping_counts[ in_index ];
- ai_assert( count != 0 );
- ai_assert( mapping_offsets[ in_index ] + count <= mappings.size() );
+ ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() );
- return &mappings[ mapping_offsets[ in_index ] ];
+ return &m_mappings[ m_mapping_offsets[ in_index ] ];
}
// ------------------------------------------------------------------------------------------------
unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
- ai_assert( in_index < vertices.size() );
+ ai_assert( in_index < m_vertices.size() );
// in the current conversion pattern this will only be needed if
// weights are present, so no need to always pre-compute this table
- if ( facesVertexStartIndices.empty() ) {
- facesVertexStartIndices.resize( faces.size() + 1, 0 );
+ if ( m_facesVertexStartIndices.empty() ) {
+ m_facesVertexStartIndices.resize( m_faces.size() + 1, 0 );
- std::partial_sum( faces.begin(), faces.end(), facesVertexStartIndices.begin() + 1 );
- facesVertexStartIndices.pop_back();
+ std::partial_sum( m_faces.begin(), m_faces.end(), m_facesVertexStartIndices.begin() + 1 );
+ m_facesVertexStartIndices.pop_back();
}
- ai_assert( facesVertexStartIndices.size() == faces.size() );
+ ai_assert( m_facesVertexStartIndices.size() == m_faces.size() );
const std::vector<unsigned int>::iterator it = std::upper_bound(
- facesVertexStartIndices.begin(),
- facesVertexStartIndices.end(),
+ m_facesVertexStartIndices.begin(),
+ m_facesVertexStartIndices.end(),
in_index
);
- return static_cast< unsigned int >( std::distance( facesVertexStartIndices.begin(), it - 1 ) );
+ return static_cast< unsigned int >( std::distance( m_facesVertexStartIndices.begin(), it - 1 ) );
}
// ------------------------------------------------------------------------------------------------
@@ -327,18 +327,18 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
}
const Element* Name = source["Name"];
- uvNames[index] = "";
+ m_uvNames[index] = "";
if(Name) {
- uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
+ m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
}
- ReadVertexDataUV(uvs[index],source,
+ ReadVertexDataUV(m_uvs[index],source,
MappingInformationType,
ReferenceInformationType
);
}
else if (type == "LayerElementMaterial") {
- if (materials.size() > 0) {
+ if (m_materials.size() > 0) {
FBXImporter::LogError("ignoring additional material layer");
return;
}
@@ -356,43 +356,43 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
// 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));
+ const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; });
if(count_neg == temp_materials.size()) {
FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
return;
}
- std::swap(temp_materials, materials);
+ std::swap(temp_materials, m_materials);
}
else if (type == "LayerElementNormal") {
- if (normals.size() > 0) {
+ if (m_normals.size() > 0) {
FBXImporter::LogError("ignoring additional normal layer");
return;
}
- ReadVertexDataNormals(normals,source,
+ ReadVertexDataNormals(m_normals,source,
MappingInformationType,
ReferenceInformationType
);
}
else if (type == "LayerElementTangent") {
- if (tangents.size() > 0) {
+ if (m_tangents.size() > 0) {
FBXImporter::LogError("ignoring additional tangent layer");
return;
}
- ReadVertexDataTangents(tangents,source,
+ ReadVertexDataTangents(m_tangents,source,
MappingInformationType,
ReferenceInformationType
);
}
else if (type == "LayerElementBinormal") {
- if (binormals.size() > 0) {
+ if (m_binormals.size() > 0) {
FBXImporter::LogError("ignoring additional binormal layer");
return;
}
- ReadVertexDataBinormals(binormals,source,
+ ReadVertexDataBinormals(m_binormals,source,
MappingInformationType,
ReferenceInformationType
);
@@ -404,7 +404,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
return;
}
- ReadVertexDataColors(colors[index],source,
+ ReadVertexDataColors(m_colors[index],source,
MappingInformationType,
ReferenceInformationType
);
@@ -515,10 +515,10 @@ void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, c
ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
"Normals",
"NormalsIndex",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
}
@@ -530,10 +530,10 @@ void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope
ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
"UV",
"UVIndex",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
}
@@ -545,10 +545,10 @@ void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, cons
ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
"Colors",
"ColorIndex",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
}
// ------------------------------------------------------------------------------------------------
@@ -564,10 +564,10 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
str,
strIdx,
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
}
// ------------------------------------------------------------------------------------------------
@@ -583,10 +583,10 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
str,
strIdx,
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ m_vertices.size(),
+ m_mapping_counts,
+ m_mapping_offsets,
+ m_mappings);
}
@@ -595,7 +595,7 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
const std::string& MappingInformationType,
const std::string& ReferenceInformationType)
{
- const size_t face_count = faces.size();
+ const size_t face_count = m_faces.size();
ai_assert(face_count);
// materials are handled separately. First of all, they are assigned per-face
@@ -614,10 +614,10 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
materials_out.clear();
}
- materials.assign(vertices.size(),materials_out[0]);
+ m_materials.assign(m_vertices.size(),materials_out[0]);
}
else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
- materials.resize(face_count);
+ m_materials.resize(face_count);
if(materials_out.size() != face_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
diff --git a/src/3rdparty/assimp/code/FBXMeshGeometry.h b/src/3rdparty/assimp/code/FBXMeshGeometry.h
index 48ac550c1..19f7b0a9c 100644
--- a/src/3rdparty/assimp/code/FBXMeshGeometry.h
+++ b/src/3rdparty/assimp/code/FBXMeshGeometry.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -156,21 +157,21 @@ private:
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;
+ MatIndexArray m_materials;
+ std::vector<aiVector3D> m_vertices;
+ std::vector<unsigned int> m_faces;
+ mutable std::vector<unsigned int> m_facesVertexStartIndices;
+ std::vector<aiVector3D> m_tangents;
+ std::vector<aiVector3D> m_binormals;
+ std::vector<aiVector3D> m_normals;
+
+ std::string m_uvNames[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ std::vector<aiVector2D> m_uvs[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ std::vector<aiColor4D> m_colors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
+
+ std::vector<unsigned int> m_mapping_counts;
+ std::vector<unsigned int> m_mapping_offsets;
+ std::vector<unsigned int> m_mappings;
};
}
diff --git a/src/3rdparty/assimp/code/FBXModel.cpp b/src/3rdparty/assimp/code/FBXModel.cpp
index bbeb14bfb..3d694d7d8 100644
--- a/src/3rdparty/assimp/code/FBXModel.cpp
+++ b/src/3rdparty/assimp/code/FBXModel.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,9 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXMeshGeometry.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
-#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
namespace Assimp {
namespace FBX {
@@ -78,14 +77,12 @@ Model::Model(uint64_t id, const Element& element, const Document& doc, const std
ResolveLinks(element,doc);
}
-
// ------------------------------------------------------------------------------------------------
Model::~Model()
{
}
-
// ------------------------------------------------------------------------------------------------
void Model::ResolveLinks(const Element& element, const Document& doc)
{
@@ -133,7 +130,6 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
}
}
-
// ------------------------------------------------------------------------------------------------
bool Model::IsNull() const
{
diff --git a/src/3rdparty/assimp/code/FBXNodeAttribute.cpp b/src/3rdparty/assimp/code/FBXNodeAttribute.cpp
index 405ce7206..545343c09 100644
--- a/src/3rdparty/assimp/code/FBXNodeAttribute.cpp
+++ b/src/3rdparty/assimp/code/FBXNodeAttribute.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,14 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXParser.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
-#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
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)
@@ -76,7 +75,7 @@ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document
// ------------------------------------------------------------------------------------------------
NodeAttribute::~NodeAttribute()
{
-
+ // empty
}
@@ -102,33 +101,30 @@ CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Docume
}
}
-
// ------------------------------------------------------------------------------------------------
CameraSwitcher::~CameraSwitcher()
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
-
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
Camera::~Camera()
{
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
-
+ // empty
}
diff --git a/src/3rdparty/assimp/code/FBXParser.cpp b/src/3rdparty/assimp/code/FBXParser.cpp
index beca20b14..d4d06567b 100644
--- a/src/3rdparty/assimp/code/FBXParser.cpp
+++ b/src/3rdparty/assimp/code/FBXParser.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -51,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# include "../contrib/zlib/zlib.h"
#endif
-
#include "FBXTokenizer.h"
#include "FBXParser.h"
#include "FBXUtil.h"
@@ -103,6 +103,7 @@ namespace {
T SafeParse(const char* data, const char* end) {
// Actual size validation happens during Tokenization so
// this is valid as an assertion.
+ (void)(end);
ai_assert(static_cast<size_t>(end - data) >= sizeof(T));
T result = static_cast<T>(0);
::memcpy(&result, data, sizeof(T));
@@ -224,41 +225,36 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
root.reset(new Scope(*this,true));
}
-
// ------------------------------------------------------------------------------------------------
Parser::~Parser()
{
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::AdvanceToNextToken()
{
last = current;
if (cursor == tokens.end()) {
current = NULL;
- }
- else {
+ } else {
current = *cursor++;
}
return current;
}
-
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::CurrentToken() const
{
return current;
}
-
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::LastToken() const
{
return last;
}
-
// ------------------------------------------------------------------------------------------------
uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
{
@@ -286,7 +282,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
ai_assert(length > 0);
- const char* out;
+ const char* out = nullptr;
const uint64_t id = strtoul10_64(t.begin(),&out,&length);
if (out > t.end()) {
err_out = "failed to parse ID (text)";
@@ -296,7 +292,6 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
return id;
}
-
// ------------------------------------------------------------------------------------------------
size_t ParseTokenAsDim(const Token& t, const char*& err_out)
{
@@ -333,7 +328,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return 0;
}
- const char* out;
+ const char* out = nullptr;
const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
if (out > t.end()) {
err_out = "failed to parse ID";
@@ -446,7 +441,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
ai_assert(length > 0);
- const char* out;
+ const char* out = nullptr;
const int64_t id = strtol10_64(t.begin(), &out, &length);
if (out > t.end()) {
err_out = "failed to parse Int64 (text)";
@@ -583,7 +578,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
zstream.next_in = reinterpret_cast<Bytef*>( const_cast<char*>(data) );
zstream.avail_in = comp_len;
- zstream.avail_out = buff.size();
+ zstream.avail_out = static_cast<uInt>(buff.size());
zstream.next_out = reinterpret_cast<Bytef*>(&*buff.begin());
const int ret = inflate(&zstream, Z_FINISH);
diff --git a/src/3rdparty/assimp/code/FBXParser.h b/src/3rdparty/assimp/code/FBXParser.h
index 6bc34272a..4d3766d70 100644
--- a/src/3rdparty/assimp/code/FBXParser.h
+++ b/src/3rdparty/assimp/code/FBXParser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include <memory>
#include "LogAux.h"
+#include "fast_atof.h"
#include "FBXCompileConfig.h"
#include "FBXTokenizer.h"
@@ -83,12 +85,9 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
class Element
{
public:
-
Element(const Token& key_token, Parser& parser);
~Element();
-public:
-
const Scope* Compound() const {
return compound.get();
}
@@ -102,14 +101,11 @@ public:
}
private:
-
const Token& key_token;
TokenList tokens;
std::unique_ptr<Scope> compound;
};
-
-
/** FBX data entity that consists of a 'scope', a collection
* of not necessarily unique #Element instances.
*
@@ -123,19 +119,26 @@ private:
* @endverbatim */
class Scope
{
-
public:
-
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* FindElementCaseInsensitive(const std::string& elementName) const {
+ const char* elementNameCStr = elementName.c_str();
+ for (auto element = elements.begin(); element != elements.end(); ++element)
+ {
+ if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
+ return element->second;
+ }
+ }
+ return NULL;
+ }
+
ElementCollection GetCollection(const std::string& index) const {
return elements.equal_range(index);
}
@@ -145,28 +148,23 @@ public:
}
private:
-
ElementMap elements;
};
-
/** FBX parsing class, takes a list of input tokens and generates a hierarchy
* of nested #Scope instances, representing the fbx DOM.*/
class Parser
{
public:
-
/** Parse given a token list. Does not take ownership of the tokens -
* the objects must persist during the entire parser lifetime */
Parser (const TokenList& tokens,bool is_binary);
~Parser();
-public:
const Scope& GetRootScope() const {
return *root.get();
}
-
bool IsBinary() const {
return is_binary;
}
@@ -220,8 +218,6 @@ 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);
-
-
// 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);
@@ -230,8 +226,6 @@ const Scope& GetRequiredScope(const Element& el);
// get token at a particular index
const Token& GetRequiredToken(const Element& el, unsigned int index);
-
-
// read a 4x4 matrix from an array of 16 floats
aiMatrix4x4 ReadMatrix(const Element& element);
diff --git a/src/3rdparty/assimp/code/FBXProperties.cpp b/src/3rdparty/assimp/code/FBXProperties.cpp
index 23d072b18..774beac3c 100644
--- a/src/3rdparty/assimp/code/FBXProperties.cpp
+++ b/src/3rdparty/assimp/code/FBXProperties.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/FBXProperties.h b/src/3rdparty/assimp/code/FBXProperties.h
index 60cdfe2c6..09b8aa94c 100644
--- a/src/3rdparty/assimp/code/FBXProperties.h
+++ b/src/3rdparty/assimp/code/FBXProperties.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,15 +45,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_PROPERTIES_H
#define INCLUDED_AI_FBX_PROPERTIES_H
-#include <map>
#include "FBXCompileConfig.h"
#include <memory>
+#include <string>
namespace Assimp {
namespace FBX {
- class Element;
-
+// Forward declarations
+class Element;
/** Represents a dynamic property. Type info added by deriving classes,
* see #TypedProperty.
@@ -60,10 +61,8 @@ namespace FBX {
@verbatim
P: "ShininessExponent", "double", "Number", "",0.5
@endvebatim
-
*/
-class Property
-{
+class Property {
protected:
Property();
@@ -77,17 +76,14 @@ public:
}
};
-
template<typename T>
-class TypedProperty : public Property
-{
+class TypedProperty : public Property {
public:
explicit TypedProperty(const T& value)
- : value(value)
- {
+ : value(value) {
+ // empty
}
-public:
const T& Value() const {
return value;
}
@@ -98,21 +94,19 @@ private:
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;
+typedef std::fbx_unordered_map<std::string,const Property*> PropertyMap;
+typedef std::fbx_unordered_map<std::string,const Element*> LazyPropertyMap;
/**
* Represents a property table as can be found in the newer FBX files (Properties60, Properties70)
*/
-class PropertyTable
-{
+class PropertyTable {
public:
// 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;
// PropertyTable's need not be coupled with FBX elements so this can be NULL
@@ -133,41 +127,37 @@ private:
const Element* const element;
};
-
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline T PropertyGet(const PropertyTable& in, const std::string& name,
- const T& defaultValue)
-{
+inline
+T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) {
const Property* const prop = in.Get(name);
- if(!prop) {
+ if( nullptr == prop) {
return defaultValue;
}
// strong typing, no need to be lenient
const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
- if(!tprop) {
+ if( nullptr == tprop) {
return defaultValue;
}
return tprop->Value();
}
-
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline T PropertyGet(const PropertyTable& in, const std::string& name,
- bool& result)
-{
+inline
+T PropertyGet(const PropertyTable& in, const std::string& name, bool& result) {
const Property* const prop = in.Get(name);
- if(!prop) {
+ if( nullptr == prop) {
result = false;
return T();
}
// strong typing, no need to be lenient
const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
- if(!tprop) {
+ if( nullptr == tprop) {
result = false;
return T();
}
@@ -176,7 +166,6 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
return tprop->Value();
}
-
} //! FBX
} //! Assimp
diff --git a/src/3rdparty/assimp/code/FBXTokenizer.cpp b/src/3rdparty/assimp/code/FBXTokenizer.cpp
index 7ede49f39..881dcf53d 100644
--- a/src/3rdparty/assimp/code/FBXTokenizer.cpp
+++ b/src/3rdparty/assimp/code/FBXTokenizer.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/FBXTokenizer.h b/src/3rdparty/assimp/code/FBXTokenizer.h
index f9f1fb871..e00ff5b79 100644
--- a/src/3rdparty/assimp/code/FBXTokenizer.h
+++ b/src/3rdparty/assimp/code/FBXTokenizer.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,7 +45,6 @@ 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 <memory>
#include "FBXCompileConfig.h"
#include <assimp/ai_assert.h>
#include <vector>
@@ -84,13 +84,10 @@ enum TokenType
* Offers iterator protocol. Tokens are immutable. */
class Token
{
-
private:
-
static const unsigned int BINARY_MARKER = static_cast<unsigned int>(-1);
public:
-
/** construct a textual token */
Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column);
@@ -100,13 +97,10 @@ public:
~Token();
public:
-
std::string StringContents() const {
return std::string(begin(),end());
}
-public:
-
bool IsBinary() const {
return column == BINARY_MARKER;
}
diff --git a/src/3rdparty/assimp/code/FBXUtil.cpp b/src/3rdparty/assimp/code/FBXUtil.cpp
index 601d5e214..4fd91e18f 100644
--- a/src/3rdparty/assimp/code/FBXUtil.cpp
+++ b/src/3rdparty/assimp/code/FBXUtil.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXTokenizer.h"
#include "TinyFormatter.h"
+#include <string>
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
diff --git a/src/3rdparty/assimp/code/FBXUtil.h b/src/3rdparty/assimp/code/FBXUtil.h
index bd41834b0..c1d9459b3 100644
--- a/src/3rdparty/assimp/code/FBXUtil.h
+++ b/src/3rdparty/assimp/code/FBXUtil.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_UTIL_H
#define INCLUDED_AI_FBX_UTIL_H
-#include <string>
#include "FBXCompileConfig.h"
#include "FBXTokenizer.h"
diff --git a/src/3rdparty/assimp/code/FIReader.cpp b/src/3rdparty/assimp/code/FIReader.cpp
new file mode 100644
index 000000000..0633ea050
--- /dev/null
+++ b/src/3rdparty/assimp/code/FIReader.cpp
@@ -0,0 +1,1833 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 FIReader.cpp
+/// \brief Reader for Fast Infoset encoded binary XML files.
+/// \date 2017
+/// \author Patrick Daehne
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "FIReader.hpp"
+#include "StringUtils.h"
+
+// Workaround for issue #1361
+// https://github.com/assimp/assimp/issues/1361
+#ifdef __ANDROID__
+# define _GLIBCXX_USE_C99 1
+#endif
+
+#include "Exceptional.h"
+#include <assimp/IOStream.hpp>
+#include <assimp/types.h>
+#include "MemoryIOWrapper.h"
+#include "irrXMLWrapper.h"
+#include "../contrib/utf8cpp/source/utf8.h"
+#include "fast_atof.h"
+#include <stack>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+namespace Assimp {
+
+static const std::string parseErrorMessage = "Fast Infoset parse error";
+
+static const char *xmlDeclarations[] = {
+ "<?xml encoding='finf'?>",
+ "<?xml encoding='finf' standalone='yes'?>",
+ "<?xml encoding='finf' standalone='no'?>",
+ "<?xml version='1.0' encoding='finf'?>",
+ "<?xml version='1.0' encoding='finf' standalone='yes'?>",
+ "<?xml version='1.0' encoding='finf' standalone='no'?>",
+ "<?xml version='1.1' encoding='finf'?>",
+ "<?xml version='1.1' encoding='finf' standalone='yes'?>",
+ "<?xml version='1.1' encoding='finf' standalone='no'?>"
+};
+
+static size_t parseMagic(const uint8_t *data, const uint8_t *dataEnd) {
+ if (dataEnd - data < 4) {
+ return 0;
+ }
+ uint32_t magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ switch (magic) {
+ case 0xe0000001:
+ return 4;
+ case 0x3c3f786d: // "<?xm"
+ {
+ size_t xmlDeclarationsLength = sizeof(xmlDeclarations) / sizeof(xmlDeclarations[0]);
+ for (size_t i = 0; i < xmlDeclarationsLength; ++i) {
+ auto xmlDeclaration = xmlDeclarations[i];
+ ptrdiff_t xmlDeclarationLength = strlen(xmlDeclaration);
+ if ((dataEnd - data >= xmlDeclarationLength) && (memcmp(xmlDeclaration, data, xmlDeclarationLength) == 0)) {
+ data += xmlDeclarationLength;
+ if (dataEnd - data < 4) {
+ return 0;
+ }
+ magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ return magic == 0xe0000001 ? xmlDeclarationLength + 4 : 0;
+ }
+ }
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+static std::string parseUTF8String(const uint8_t *data, size_t len) {
+ return std::string((char*)data, len);
+}
+
+static std::string parseUTF16String(const uint8_t *data, size_t len) {
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ size_t numShorts = len / 2;
+ std::vector<short> utf16;
+ utf16.reserve(numShorts);
+ for (size_t i = 0; i < numShorts; ++i) {
+ short v = (data[0] << 8) | data[1];
+ utf16.push_back(v);
+ data += 2;
+ }
+ std::string result;
+ utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(result));
+ return result;
+}
+
+struct FIStringValueImpl: public FIStringValue {
+ inline FIStringValueImpl(std::string &&value_) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ { return value; }
+};
+
+std::shared_ptr<FIStringValue> FIStringValue::create(std::string &&value) {
+ return std::make_shared<FIStringValueImpl>(std::move(value));
+}
+
+struct FIHexValueImpl: public FIHexValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIHexValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ os << std::hex << std::uppercase << std::setfill('0');
+ std::for_each(value.begin(), value.end(), [&](uint8_t c) { os << std::setw(2) << static_cast<int>(c); });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIHexValue> FIHexValue::create(std::vector<uint8_t> &&value) {
+ return std::make_shared<FIHexValueImpl>(std::move(value));
+}
+
+struct FIBase64ValueImpl: public FIBase64Value {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIBase64ValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ uint8_t c1 = 0, c2;
+ int imod3 = 0;
+ std::vector<uint8_t>::size_type valueSize = value.size();
+ for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
+ c2 = value[i];
+ switch (imod3) {
+ case 0:
+ os << basis_64[c2 >> 2];
+ imod3 = 1;
+ break;
+ case 1:
+ os << basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
+ imod3 = 2;
+ break;
+ case 2:
+ os << basis_64[((c1 & 0x0f) << 2) | ((c2 & 0xc0) >> 6)] << basis_64[c2 & 0x3f];
+ imod3 = 0;
+ break;
+ }
+ c1 = c2;
+ }
+ switch (imod3) {
+ case 1:
+ os << basis_64[(c1 & 0x03) << 4] << "==";
+ break;
+ case 2:
+ os << basis_64[(c1 & 0x0f) << 2] << '=';
+ break;
+ }
+ strValue = os.str();
+ }
+ return strValue;
+ };
+ static const char basis_64[];
+};
+
+const char FIBase64ValueImpl::basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::shared_ptr<FIBase64Value> FIBase64Value::create(std::vector<uint8_t> &&value) {
+ return std::make_shared<FIBase64ValueImpl>(std::move(value));
+}
+
+struct FIShortValueImpl: public FIShortValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIShortValueImpl(std::vector<int16_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](int16_t s) { if (++n > 1) os << ' '; os << s; });
+ strValue = os.str();
+ }
+ return strValue;
+ }
+};
+
+std::shared_ptr<FIShortValue> FIShortValue::create(std::vector<int16_t> &&value) {
+ return std::make_shared<FIShortValueImpl>(std::move(value));
+}
+
+struct FIIntValueImpl: public FIIntValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIIntValueImpl(std::vector<int32_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](int32_t i) { if (++n > 1) os << ' '; os << i; });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIIntValue> FIIntValue::create(std::vector<int32_t> &&value) {
+ return std::make_shared<FIIntValueImpl>(std::move(value));
+}
+
+struct FILongValueImpl: public FILongValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FILongValueImpl(std::vector<int64_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](int64_t l) { if (++n > 1) os << ' '; os << l; });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FILongValue> FILongValue::create(std::vector<int64_t> &&value) {
+ return std::make_shared<FILongValueImpl>(std::move(value));
+}
+
+struct FIBoolValueImpl: public FIBoolValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIBoolValueImpl(std::vector<bool> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ os << std::boolalpha;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](bool b) { if (++n > 1) os << ' '; os << b; });
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIBoolValue> FIBoolValue::create(std::vector<bool> &&value) {
+ return std::make_shared<FIBoolValueImpl>(std::move(value));
+}
+
+struct FIFloatValueImpl: public FIFloatValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIFloatValueImpl(std::vector<float> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](float f) { if (++n > 1) os << ' '; os << f; });
+ strValue = os.str();
+ }
+ return strValue;
+ }
+};
+
+std::shared_ptr<FIFloatValue> FIFloatValue::create(std::vector<float> &&value) {
+ return std::make_shared<FIFloatValueImpl>(std::move(value));
+}
+
+struct FIDoubleValueImpl: public FIDoubleValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIDoubleValueImpl(std::vector<double> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ int n = 0;
+ std::for_each(value.begin(), value.end(), [&](double d) { if (++n > 1) os << ' '; os << d; });
+ strValue = os.str();
+ }
+ return strValue;
+ }
+};
+
+std::shared_ptr<FIDoubleValue> FIDoubleValue::create(std::vector<double> &&value) {
+ return std::make_shared<FIDoubleValueImpl>(std::move(value));
+}
+
+struct FIUUIDValueImpl: public FIUUIDValue {
+ mutable std::string strValue;
+ mutable bool strValueValid;
+ inline FIUUIDValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ {
+ if (!strValueValid) {
+ strValueValid = true;
+ std::ostringstream os;
+ os << std::hex << std::uppercase << std::setfill('0');
+ std::vector<uint8_t>::size_type valueSize = value.size();
+ for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
+ switch (i & 15) {
+ case 0:
+ if (i > 0) {
+ os << ' ';
+ }
+ os << std::setw(2) << static_cast<int>(value[i]);
+ break;
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ os << '-';
+ // intentionally fall through!
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ os << std::setw(2) << static_cast<int>(value[i]);
+ break;
+ }
+ }
+ strValue = os.str();
+ }
+ return strValue;
+ };
+};
+
+std::shared_ptr<FIUUIDValue> FIUUIDValue::create(std::vector<uint8_t> &&value) {
+ return std::make_shared<FIUUIDValueImpl>(std::move(value));
+}
+
+struct FICDATAValueImpl: public FICDATAValue {
+ inline FICDATAValueImpl(std::string &&value_) { value = std::move(value_); }
+ virtual const std::string &toString() const /*override*/ { return value; }
+};
+
+std::shared_ptr<FICDATAValue> FICDATAValue::create(std::string &&value) {
+ return std::make_shared<FICDATAValueImpl>(std::move(value));
+}
+
+struct FIHexDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ return FIHexValue::create(std::vector<uint8_t>(data, data + len));
+ }
+};
+
+struct FIBase64Decoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ return FIBase64Value::create(std::vector<uint8_t>(data, data + len));
+ }
+};
+
+struct FIShortDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<int16_t> value;
+ size_t numShorts = len / 2;
+ value.reserve(numShorts);
+ for (size_t i = 0; i < numShorts; ++i) {
+ int16_t v = (data[0] << 8) | data[1];
+ value.push_back(v);
+ data += 2;
+ }
+ return FIShortValue::create(std::move(value));
+ }
+};
+
+struct FIIntDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 3) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<int32_t> value;
+ size_t numInts = len / 4;
+ value.reserve(numInts);
+ for (size_t i = 0; i < numInts; ++i) {
+ int32_t v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ value.push_back(v);
+ data += 4;
+ }
+ return FIIntValue::create(std::move(value));
+ }
+};
+
+struct FILongDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 7) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<int64_t> value;
+ size_t numLongs = len / 8;
+ value.reserve(numLongs);
+ for (size_t i = 0; i < numLongs; ++i) {
+ int64_t b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
+ int64_t v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ value.push_back(v);
+ data += 8;
+ }
+ return FILongValue::create(std::move(value));
+ }
+};
+
+struct FIBoolDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<bool> value;
+ uint8_t b = *data++;
+ size_t unusedBits = b >> 4;
+ size_t numBools = (len * 8) - 4 - unusedBits;
+ value.reserve(numBools);
+ uint8_t mask = 1 << 3;
+ for (size_t i = 0; i < numBools; ++i) {
+ if (!mask) {
+ mask = 1 << 7;
+ b = *data++;
+ }
+ value.push_back((b & mask) != 0);
+ }
+ return FIBoolValue::create(std::move(value));
+ }
+};
+
+struct FIFloatDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 3) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<float> value;
+ size_t numFloats = len / 4;
+ value.reserve(numFloats);
+ for (size_t i = 0; i < numFloats; ++i) {
+ int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ float f;
+ memcpy(&f, &v, 4);
+ value.push_back(f);
+ data += 4;
+ }
+ return FIFloatValue::create(std::move(value));
+ }
+};
+
+struct FIDoubleDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 7) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::vector<double> value;
+ size_t numDoubles = len / 8;
+ value.reserve(numDoubles);
+ for (size_t i = 0; i < numDoubles; ++i) {
+ long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
+ long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
+ double f;
+ memcpy(&f, &v, 8);
+ value.push_back(f);
+ data += 8;
+ }
+ return FIDoubleValue::create(std::move(value));
+ }
+};
+
+struct FIUUIDDecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ if (len & 15) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return FIUUIDValue::create(std::vector<uint8_t>(data, data + len));
+ }
+};
+
+struct FICDATADecoder: public FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
+ return FICDATAValue::create(parseUTF8String(data, len));
+ }
+};
+
+class CFIReaderImpl: public FIReader {
+public:
+
+ CFIReaderImpl(std::unique_ptr<uint8_t[]> data_, size_t size):
+ data(std::move(data_)), dataP(data.get()), dataEnd(data.get() + size), currentNodeType(irr::io::EXN_NONE),
+ emptyElement(false), headerPending(true), terminatorPending(false)
+ {}
+
+ virtual ~CFIReaderImpl() {}
+
+ virtual bool read() /*override*/ {
+ if (headerPending) {
+ headerPending = false;
+ parseHeader();
+ }
+ if (terminatorPending) {
+ terminatorPending = false;
+ if (elementStack.empty()) {
+ return false;
+ }
+ else {
+ nodeName = elementStack.top();
+ elementStack.pop();
+ currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
+ return true;
+ }
+ }
+ if (dataP >= dataEnd) {
+ return false;
+ }
+ uint8_t b = *dataP;
+ if (b < 0x80) { // Element (C.2.11.2, C.3.7.2)
+ // C.3
+ parseElement();
+ return true;
+ }
+ else if (b < 0xc0) { // Characters (C.3.7.5)
+ // C.7
+ auto chars = parseNonIdentifyingStringOrIndex3(vocabulary.charactersTable);
+ nodeName = chars->toString();
+ currentNodeType = irr::io::EXN_TEXT;
+ return true;
+ }
+ else if (b < 0xe0) {
+ if ((b & 0xfc) == 0xc4) { // DTD (C.2.11.5)
+ // C.9
+ ++dataP;
+ if (b & 0x02) {
+ /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ if (b & 0x01) {
+ /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ elementStack.push(EmptyString);
+ currentNodeType = irr::io::EXN_UNKNOWN;
+ return true;
+ }
+ else if ((b & 0xfc) == 0xc8) { // Unexpanded entity reference (C.3.7.4)
+ // C.6
+ ++dataP;
+ /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ if (b & 0x02) {
+ /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ if (b & 0x01) {
+ /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ currentNodeType = irr::io::EXN_UNKNOWN;
+ return true;
+ }
+ }
+ else if (b < 0xf0) {
+ if (b == 0xe1) { // Processing instruction (C.2.11.3, C.3.7.3)
+ // C.5
+ ++dataP;
+ /*const std::string &target =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::shared_ptr<const FIValue> data =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+ currentNodeType = irr::io::EXN_UNKNOWN;
+ return true;
+ }
+ else if (b == 0xe2) { // Comment (C.2.11.4, C.3.7.6)
+ // C.8
+ ++dataP;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::shared_ptr<const FIValue> comment = parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+ nodeName = comment->toString();
+ currentNodeType = irr::io::EXN_COMMENT;
+ return true;
+ }
+ }
+ else { // Terminator (C.2.12, C.3.8)
+ ++dataP;
+ if (b == 0xff) {
+ terminatorPending = true;
+ }
+ if (elementStack.empty()) {
+ return false;
+ }
+ else {
+ nodeName = elementStack.top();
+ elementStack.pop();
+ currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
+ return true;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
+ return currentNodeType;
+ }
+
+ virtual int getAttributeCount() const /*override*/ {
+ return static_cast<int>(attributes.size());
+ }
+
+ virtual const char* getAttributeName(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return nullptr;
+ }
+ return attributes[idx].name.c_str();
+ }
+
+ virtual const char* getAttributeValue(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return nullptr;
+ }
+ return attributes[idx].value->toString().c_str();
+ }
+
+ virtual const char* getAttributeValue(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return nullptr;
+ }
+ return attr->value->toString().c_str();
+ }
+
+ virtual const char* getAttributeValueSafe(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return EmptyString.c_str();
+ }
+ return attr->value->toString().c_str();
+ }
+
+ virtual int getAttributeValueAsInt(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return 0;
+ }
+ std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attr->value);
+ if (intValue) {
+ return intValue->value.size() == 1 ? intValue->value.front() : 0;
+ }
+ return atoi(attr->value->toString().c_str());
+ }
+
+ virtual int getAttributeValueAsInt(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return 0;
+ }
+ std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attributes[idx].value);
+ if (intValue) {
+ return intValue->value.size() == 1 ? intValue->value.front() : 0;
+ }
+ return atoi(attributes[idx].value->toString().c_str());
+ }
+
+ virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return 0;
+ }
+ std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attr->value);
+ if (floatValue) {
+ return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
+ }
+
+ return fast_atof(attr->value->toString().c_str());
+ }
+
+ virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return 0;
+ }
+ std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attributes[idx].value);
+ if (floatValue) {
+ return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
+ }
+ return fast_atof(attributes[idx].value->toString().c_str());
+ }
+
+ virtual const char* getNodeName() const /*override*/ {
+ return nodeName.c_str();
+ }
+
+ virtual const char* getNodeData() const /*override*/ {
+ return nodeName.c_str();
+ }
+
+ virtual bool isEmptyElement() const /*override*/ {
+ return emptyElement;
+ }
+
+ virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
+ return irr::io::ETF_UTF8;
+ }
+
+ virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
+ return irr::io::ETF_UTF8;
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const /*override*/ {
+ if (idx < 0 || idx >= (int)attributes.size()) {
+ return nullptr;
+ }
+ return attributes[idx].value;
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* name) const /*override*/ {
+ const Attribute* attr = getAttributeByName(name);
+ if (!attr) {
+ return nullptr;
+ }
+ return attr->value;
+ }
+
+ virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) /*override*/ {
+ decoderMap[algorithmUri] = std::move(decoder);
+ }
+
+ virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) /*override*/ {
+ vocabularyMap[vocabularyUri] = vocabulary;
+ }
+
+private:
+
+ struct QName {
+ std::string prefix;
+ std::string uri;
+ std::string name;
+ inline QName() {}
+ inline QName(const FIQName &qname): prefix(qname.prefix ? qname.prefix : ""), uri(qname.uri ? qname.uri : ""), name(qname.name) {}
+ };
+
+ struct Attribute {
+ QName qname;
+ std::string name;
+ std::shared_ptr<const FIValue> value;
+ };
+
+ struct Vocabulary {
+ std::vector<std::string> restrictedAlphabetTable;
+ std::vector<std::string> encodingAlgorithmTable;
+ std::vector<std::string> prefixTable;
+ std::vector<std::string> namespaceNameTable;
+ std::vector<std::string> localNameTable;
+ std::vector<std::string> otherNCNameTable;
+ std::vector<std::string> otherURITable;
+ std::vector<std::shared_ptr<const FIValue>> attributeValueTable;
+ std::vector<std::shared_ptr<const FIValue>> charactersTable;
+ std::vector<std::shared_ptr<const FIValue>> otherStringTable;
+ std::vector<QName> elementNameTable;
+ std::vector<QName> attributeNameTable;
+ Vocabulary() {
+ prefixTable.push_back("xml");
+ namespaceNameTable.push_back("http://www.w3.org/XML/1998/namespace");
+ }
+ };
+
+ const Attribute* getAttributeByName(const char* name) const {
+ if (!name) {
+ return 0;
+ }
+ std::string n = name;
+ for (int i=0; i<(int)attributes.size(); ++i) {
+ if (attributes[i].name == n) {
+ return &attributes[i];
+ }
+ }
+ return 0;
+ }
+
+ size_t parseInt2() { // C.25
+ uint8_t b = *dataP++;
+ if (!(b & 0x40)) { // x0...... (C.25.2)
+ return b & 0x3f;
+ }
+ else if ((b & 0x60) == 0x40) { // x10..... ........ (C.25.3)
+ if (dataEnd - dataP > 0) {
+ return (((b & 0x1f) << 8) | *dataP++) + 0x40;
+ }
+ }
+ else if ((b & 0x70) == 0x60) { // x110.... ........ ........ (C.25.4)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x2040;
+ dataP += 2;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseInt3() { // C.27
+ uint8_t b = *dataP++;
+ if (!(b & 0x20)) { // xx0..... (C.27.2)
+ return b & 0x1f;
+ }
+ else if ((b & 0x38) == 0x20) { // xx100... ........ (C.27.3)
+ if (dataEnd - dataP > 0) {
+ return (((b & 0x07) << 8) | *dataP++) + 0x20;
+ }
+ }
+ else if ((b & 0x38) == 0x28) { // xx101... ........ ........ (C.27.4)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x07) << 16) | (dataP[0] << 8) | dataP[1]) + 0x820;
+ dataP += 2;
+ return result;
+ }
+ }
+ else if ((b & 0x3f) == 0x30) { // xx110000 0000.... ........ ........ (C.27.5)
+ if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
+ size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x80820;
+ dataP += 3;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseInt4() { // C.28
+ uint8_t b = *dataP++;
+ if (!(b & 0x10)) { // xxx0.... (C.28.2)
+ return b & 0x0f;
+ }
+ else if ((b & 0x1c) == 0x10) { // xxx100.. ........ (C.28.3)
+ if (dataEnd - dataP > 0) {
+ return (((b & 0x03) << 8) | *dataP++) + 0x10;
+ }
+ }
+ else if ((b & 0x1c) == 0x14) { // xxx101.. ........ ........ (C.28.4)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x03) << 16) | (dataP[0] << 8) | dataP[1]) + 0x410;
+ dataP += 2;
+ return result;
+ }
+ }
+ else if ((b & 0x1f) == 0x18) { // xxx11000 0000.... ........ ........ (C.28.5)
+ if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
+ size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x40410;
+ dataP += 3;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseSequenceLen() { // C.21
+ if (dataEnd - dataP > 0) {
+ uint8_t b = *dataP++;
+ if (b < 0x80) { // 0....... (C.21.2)
+ return b;
+ }
+ else if ((b & 0xf0) == 0x80) { // 1000.... ........ ........ (C.21.3)
+ if (dataEnd - dataP > 1) {
+ size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x80;
+ dataP += 2;
+ return result;
+ }
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ std::string parseNonEmptyOctetString2() { // C.22
+ // Parse the length of the string
+ uint8_t b = *dataP++ & 0x7f;
+ size_t len;
+ if (!(b & 0x40)) { // x0...... (C.22.3.1)
+ len = b + 1;
+ }
+ else if (b == 0x40) { // x1000000 ........ (C.22.3.2)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ len = *dataP++ + 0x41;
+ }
+ else if (b == 0x60) { // x1100000 ........ ........ ........ ........ (C.22.3.3)
+ if (dataEnd - dataP < 4) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ len = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x141;
+ dataP += 4;
+ }
+ else {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ // Parse the string (C.22.4)
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::string s = parseUTF8String(dataP, len);
+ dataP += len;
+
+ return s;
+ }
+
+ size_t parseNonEmptyOctetString5Length() { // C.23
+ // Parse the length of the string
+ size_t b = *dataP++ & 0x0f;
+ if (!(b & 0x08)) { // xxxx0... (C.23.3.1)
+ return b + 1;
+ }
+ else if (b == 0x08) { // xxxx1000 ........ (C.23.3.2)
+ if (dataEnd - dataP > 0) {
+ return *dataP++ + 0x09;
+ }
+ }
+ else if (b == 0x0c) { // xxxx1100 ........ ........ ........ ........ (C.23.3.3)
+ if (dataEnd - dataP > 3) {
+ size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x109;
+ dataP += 4;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ size_t parseNonEmptyOctetString7Length() { // C.24
+ // Parse the length of the string
+ size_t b = *dataP++ & 0x03;
+ if (!(b & 0x02)) { // xxxxxx0. (C.24.3.1)
+ return b + 1;
+ }
+ else if (b == 0x02) { // xxxxxx10 ........ (C.24.3.2)
+ if (dataEnd - dataP > 0) {
+ return *dataP++ + 0x3;
+ }
+ }
+ else if (b == 0x03) { // xxxxxx11 ........ ........ ........ ........ (C.24.3.3)
+ if (dataEnd - dataP > 3) {
+ size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x103;
+ dataP += 4;
+ return result;
+ }
+ }
+ throw DeadlyImportError(parseErrorMessage);
+ }
+
+ std::shared_ptr<const FIValue> parseEncodedData(size_t index, size_t len) {
+ if (index < 32) {
+ FIDecoder *decoder = defaultDecoder[index];
+ if (!decoder) {
+ throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
+ }
+ return decoder->decode(dataP, len);
+ }
+ else {
+ if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
+ throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
+ }
+ std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
+ auto it = decoderMap.find(uri);
+ if (it == decoderMap.end()) {
+ throw DeadlyImportError("Unsupported encoding algorithm " + uri);
+ }
+ else {
+ return it->second->decode(dataP, len);
+ }
+ }
+ }
+
+ std::shared_ptr<const FIValue> parseRestrictedAlphabet(size_t index, size_t len) {
+ std::string alphabet;
+ if (index < 16) {
+ switch (index) {
+ case 0: // numeric
+ alphabet = "0123456789-+.e ";
+ break;
+ case 1: // date and time
+ alphabet = "0123456789-:TZ ";
+ break;
+ default:
+ throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
+ }
+ }
+ else {
+ if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
+ throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
+ }
+ alphabet = vocabulary.restrictedAlphabetTable[index - 16];
+ }
+ std::vector<uint32_t> alphabetUTF32;
+ utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
+ std::string::size_type alphabetLength = alphabetUTF32.size();
+ if (alphabetLength < 2) {
+ throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength));
+ }
+ std::string::size_type bitsPerCharacter = 1;
+ while ((1ull << bitsPerCharacter) <= alphabetLength) {
+ ++bitsPerCharacter;
+ }
+ size_t bitsAvail = 0;
+ uint8_t mask = (1 << bitsPerCharacter) - 1;
+ uint32_t bits = 0;
+ std::string s;
+ for (size_t i = 0; i < len; ++i) {
+ bits = (bits << 8) | dataP[i];
+ bitsAvail += 8;
+ while (bitsAvail >= bitsPerCharacter) {
+ bitsAvail -= bitsPerCharacter;
+ size_t charIndex = (bits >> bitsAvail) & mask;
+ if (charIndex < alphabetLength) {
+ s.push_back(alphabetUTF32[charIndex]);
+ }
+ else if (charIndex != mask) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ }
+ }
+ return FIStringValue::create(std::move(s));
+ }
+
+ std::shared_ptr<const FIValue> parseEncodedCharacterString3() { // C.19
+ std::shared_ptr<const FIValue> result;
+ size_t len;
+ uint8_t b = *dataP;
+ if (b & 0x20) {
+ ++dataP;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ size_t index = ((b & 0x0f) << 4) | ((*dataP & 0xf0) >> 4); // C.29
+ len = parseNonEmptyOctetString5Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x10) {
+ // encoding algorithm (C.19.3.4)
+ result = parseEncodedData(index, len);
+ }
+ else {
+ // Restricted alphabet (C.19.3.3)
+ result = parseRestrictedAlphabet(index, len);
+ }
+ }
+ else {
+ len = parseNonEmptyOctetString5Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x10) {
+ // UTF-16 (C.19.3.2)
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result = FIStringValue::create(parseUTF16String(dataP, len));
+ }
+ else {
+ // UTF-8 (C.19.3.1)
+ result = FIStringValue::create(parseUTF8String(dataP, len));
+ }
+ }
+ dataP += len;
+ return result;
+ }
+
+ std::shared_ptr<const FIValue> parseEncodedCharacterString5() { // C.20
+ std::shared_ptr<const FIValue> result;
+ size_t len;
+ uint8_t b = *dataP;
+ if (b & 0x08) {
+ ++dataP;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ size_t index = ((b & 0x03) << 6) | ((*dataP & 0xfc) >> 2); /* C.29 */
+ len = parseNonEmptyOctetString7Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x04) {
+ // encoding algorithm (C.20.3.4)
+ result = parseEncodedData(index, len);
+ }
+ else {
+ // Restricted alphabet (C.20.3.3)
+ result = parseRestrictedAlphabet(index, len);
+ }
+ }
+ else {
+ len = parseNonEmptyOctetString7Length();
+ if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ if (b & 0x04) {
+ // UTF-16 (C.20.3.2)
+ if (len & 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result = FIStringValue::create(parseUTF16String(dataP, len));
+ }
+ else {
+ // UTF-8 (C.20.3.1)
+ result = FIStringValue::create(parseUTF8String(dataP, len));
+ }
+ }
+ dataP += len;
+ return result;
+ }
+
+ const std::string &parseIdentifyingStringOrIndex(std::vector<std::string> &stringTable) { // C.13
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b = *dataP;
+ if (b & 0x80) {
+ // We have an index (C.13.4)
+ size_t index = parseInt2();
+ if (index >= stringTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return stringTable[index];
+ }
+ else {
+ // We have a string (C.13.3)
+ stringTable.push_back(parseNonEmptyOctetString2());
+ return stringTable.back();
+ }
+ }
+
+ QName parseNameSurrogate() { // C.16
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b = *dataP++;
+ if (b & 0xfc) { // Padding '000000' C.2.5.5
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ QName result;
+ size_t index;
+ if (b & 0x02) { // prefix (C.16.3)
+ if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ index = parseInt2();
+ if (index >= vocabulary.prefixTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result.prefix = vocabulary.prefixTable[index];
+ }
+ if (b & 0x01) { // namespace-name (C.16.4)
+ if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ index = parseInt2();
+ if (index >= vocabulary.namespaceNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result.uri = vocabulary.namespaceNameTable[index];
+ }
+ // local-name
+ if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ index = parseInt2();
+ if (index >= vocabulary.localNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ result.name = vocabulary.localNameTable[index];
+ return result;
+ }
+
+ const QName &parseQualifiedNameOrIndex2(std::vector<QName> &qNameTable) { // C.17
+ uint8_t b = *dataP;
+ if ((b & 0x7c) == 0x78) { // x11110..
+ // We have a literal (C.17.3)
+ ++dataP;
+ QName result;
+ // prefix (C.17.3.1)
+ result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+ // namespace-name (C.17.3.1)
+ result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+ // local-name
+ result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
+ qNameTable.push_back(result);
+ return qNameTable.back();
+ }
+ else {
+ // We have an index (C.17.4)
+ size_t index = parseInt2();
+ if (index >= qNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return qNameTable[index];
+ }
+ }
+
+ const QName &parseQualifiedNameOrIndex3(std::vector<QName> &qNameTable) { // C.18
+ uint8_t b = *dataP;
+ if ((b & 0x3c) == 0x3c) { // xx1111..
+ // We have a literal (C.18.3)
+ ++dataP;
+ QName result;
+ // prefix (C.18.3.1)
+ result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+ // namespace-name (C.18.3.1)
+ result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+ // local-name
+ result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
+ qNameTable.push_back(result);
+ return qNameTable.back();
+ }
+ else {
+ // We have an index (C.18.4)
+ size_t index = parseInt3();
+ if (index >= qNameTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return qNameTable[index];
+ }
+ }
+
+ std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex1(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.14
+ uint8_t b = *dataP;
+ if (b == 0xff) { // C.26.2
+ // empty string
+ ++dataP;
+ return EmptyFIString;
+ }
+ else if (b & 0x80) { // C.14.4
+ // We have an index
+ size_t index = parseInt2();
+ if (index >= valueTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return valueTable[index];
+ }
+ else { // C.14.3
+ // We have a literal
+ std::shared_ptr<const FIValue> result = parseEncodedCharacterString3();
+ if (b & 0x40) { // C.14.3.1
+ valueTable.push_back(result);
+ }
+ return result;
+ }
+ }
+
+ std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex3(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.15
+ uint8_t b = *dataP;
+ if (b & 0x20) { // C.15.4
+ // We have an index
+ size_t index = parseInt4();
+ if (index >= valueTable.size()) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ return valueTable[index];
+ }
+ else { // C.15.3
+ // We have a literal
+ std::shared_ptr<const FIValue> result = parseEncodedCharacterString5();
+ if (b & 0x10) { // C.15.3.1
+ valueTable.push_back(result);
+ }
+ return result;
+ }
+ }
+
+ void parseElement() {
+ // C.3
+
+ attributes.clear();
+
+ uint8_t b = *dataP;
+ bool hasAttributes = (b & 0x40) != 0; // C.3.3
+ if ((b & 0x3f) == 0x38) { // C.3.4.1
+ // Parse namespaces
+ ++dataP;
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ b = *dataP++;
+ if (b == 0xf0) { // C.3.4.3
+ break;
+ }
+ if ((b & 0xfc) != 0xcc) { // C.3.4.2
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ // C.12
+ Attribute attr;
+ attr.qname.prefix = "xmlns";
+ attr.qname.name = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
+ attr.qname.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
+ attr.name = attr.qname.name.empty() ? "xmlns" : "xmlns:" + attr.qname.name;
+ attr.value = FIStringValue::create(std::string(attr.qname.uri));
+ attributes.push_back(attr);
+ }
+ if ((dataEnd - dataP < 1) || (*dataP & 0xc0)) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ }
+
+ // Parse Element name (C.3.5)
+ const QName &elemName = parseQualifiedNameOrIndex3(vocabulary.elementNameTable);
+ nodeName = elemName.prefix.empty() ? elemName.name : elemName.prefix + ':' + elemName.name;
+
+ if (hasAttributes) {
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ b = *dataP;
+ if (b < 0x80) { // C.3.6.1
+ // C.4
+ Attribute attr;
+ attr.qname = parseQualifiedNameOrIndex2(vocabulary.attributeNameTable);
+ attr.name = attr.qname.prefix.empty() ? attr.qname.name : attr.qname.prefix + ':' + attr.qname.name;
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ attr.value = parseNonIdentifyingStringOrIndex1(vocabulary.attributeValueTable);
+ attributes.push_back(attr);
+ }
+ else {
+ if ((b & 0xf0) != 0xf0) { // C.3.6.2
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ emptyElement = b == 0xff; // C.3.6.2, C.3.8
+ ++dataP;
+ break;
+ }
+ }
+ }
+ else {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ b = *dataP;
+ switch (b) {
+ case 0xff:
+ terminatorPending = true;
+ // Intentionally fall through
+ case 0xf0:
+ emptyElement = true;
+ ++dataP;
+ break;
+ default:
+ emptyElement = false;
+ }
+ }
+ if (!emptyElement) {
+ elementStack.push(nodeName);
+ }
+
+ currentNodeType = irr::io::EXN_ELEMENT;
+ }
+
+ void parseHeader() {
+ // Parse header (C.1.3)
+ size_t magicSize = parseMagic(dataP, dataEnd);
+ if (!magicSize) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ dataP += magicSize;
+ // C.2.3
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b = *dataP++;
+ if (b & 0x40) {
+ // Parse additional data (C.2.4)
+ size_t len = parseSequenceLen();
+ for (size_t i = 0; i < len; ++i) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::string id =*/ parseNonEmptyOctetString2();
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::string data =*/ parseNonEmptyOctetString2();
+ }
+ }
+ if (b & 0x20) {
+ // Parse initial vocabulary (C.2.5)
+ if (dataEnd - dataP < 2) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint16_t b1 = (dataP[0] << 8) | dataP[1];
+ dataP += 2;
+ if (b1 & 0x1000) {
+ // External vocabulary (C.2.5.2)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ std::string uri = parseNonEmptyOctetString2();
+ auto it = vocabularyMap.find(uri);
+ if (it == vocabularyMap.end()) {
+ throw DeadlyImportError("Unknown vocabulary " + uri);
+ }
+ const FIVocabulary *externalVocabulary = it->second;
+ if (externalVocabulary->restrictedAlphabetTable) {
+ std::copy(externalVocabulary->restrictedAlphabetTable, externalVocabulary->restrictedAlphabetTable + externalVocabulary->restrictedAlphabetTableSize, std::back_inserter(vocabulary.restrictedAlphabetTable));
+ }
+ if (externalVocabulary->encodingAlgorithmTable) {
+ std::copy(externalVocabulary->encodingAlgorithmTable, externalVocabulary->encodingAlgorithmTable + externalVocabulary->encodingAlgorithmTableSize, std::back_inserter(vocabulary.encodingAlgorithmTable));
+ }
+ if (externalVocabulary->prefixTable) {
+ std::copy(externalVocabulary->prefixTable, externalVocabulary->prefixTable + externalVocabulary->prefixTableSize, std::back_inserter(vocabulary.prefixTable));
+ }
+ if (externalVocabulary->namespaceNameTable) {
+ std::copy(externalVocabulary->namespaceNameTable, externalVocabulary->namespaceNameTable + externalVocabulary->namespaceNameTableSize, std::back_inserter(vocabulary.namespaceNameTable));
+ }
+ if (externalVocabulary->localNameTable) {
+ std::copy(externalVocabulary->localNameTable, externalVocabulary->localNameTable + externalVocabulary->localNameTableSize, std::back_inserter(vocabulary.localNameTable));
+ }
+ if (externalVocabulary->otherNCNameTable) {
+ std::copy(externalVocabulary->otherNCNameTable, externalVocabulary->otherNCNameTable + externalVocabulary->otherNCNameTableSize, std::back_inserter(vocabulary.otherNCNameTable));
+ }
+ if (externalVocabulary->otherURITable) {
+ std::copy(externalVocabulary->otherURITable, externalVocabulary->otherURITable + externalVocabulary->otherURITableSize, std::back_inserter(vocabulary.otherURITable));
+ }
+ if (externalVocabulary->attributeValueTable) {
+ std::copy(externalVocabulary->attributeValueTable, externalVocabulary->attributeValueTable + externalVocabulary->attributeValueTableSize, std::back_inserter(vocabulary.attributeValueTable));
+ }
+ if (externalVocabulary->charactersTable) {
+ std::copy(externalVocabulary->charactersTable, externalVocabulary->charactersTable + externalVocabulary->charactersTableSize, std::back_inserter(vocabulary.charactersTable));
+ }
+ if (externalVocabulary->otherStringTable) {
+ std::copy(externalVocabulary->otherStringTable, externalVocabulary->otherStringTable + externalVocabulary->otherStringTableSize, std::back_inserter(vocabulary.otherStringTable));
+ }
+ if (externalVocabulary->elementNameTable) {
+ std::copy(externalVocabulary->elementNameTable, externalVocabulary->elementNameTable + externalVocabulary->elementNameTableSize, std::back_inserter(vocabulary.elementNameTable));
+ }
+ if (externalVocabulary->attributeNameTable) {
+ std::copy(externalVocabulary->attributeNameTable, externalVocabulary->attributeNameTable + externalVocabulary->attributeNameTableSize, std::back_inserter(vocabulary.attributeNameTable));
+ }
+ }
+ if (b1 & 0x0800) {
+ // Parse restricted alphabets (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.restrictedAlphabetTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0400) {
+ // Parse encoding algorithms (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.encodingAlgorithmTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0200) {
+ // Parse prefixes (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.prefixTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0100) {
+ // Parse namespace names (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.namespaceNameTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0080) {
+ // Parse local names (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.localNameTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0040) {
+ // Parse other ncnames (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.otherNCNameTable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0020) {
+ // Parse other uris (C.2.5.3)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.otherURITable.push_back(parseNonEmptyOctetString2());
+ }
+ }
+ if (b1 & 0x0010) {
+ // Parse attribute values (C.2.5.4)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.attributeValueTable.push_back(parseEncodedCharacterString3());
+ }
+ }
+ if (b1 & 0x0008) {
+ // Parse content character chunks (C.2.5.4)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.charactersTable.push_back(parseEncodedCharacterString3());
+ }
+ }
+ if (b1 & 0x0004) {
+ // Parse other strings (C.2.5.4)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ vocabulary.otherStringTable.push_back(parseEncodedCharacterString3());
+ }
+ }
+ if (b1 & 0x0002) {
+ // Parse element name surrogates (C.2.5.5)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ vocabulary.elementNameTable.push_back(parseNameSurrogate());
+ }
+ }
+ if (b1 & 0x0001) {
+ // Parse attribute name surrogates (C.2.5.5)
+ for (size_t len = parseSequenceLen(); len > 0; --len) {
+ vocabulary.attributeNameTable.push_back(parseNameSurrogate());
+ }
+ }
+ }
+ if (b & 0x10) {
+ // Parse notations (C.2.6)
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b1 = *dataP++;
+ if (b1 == 0xf0) {
+ break;
+ }
+ if ((b1 & 0xfc) != 0xc0) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /* C.11 */
+ /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ if (b1 & 0x02) {
+ /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ if (b1 & 0x01) {
+ /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ }
+ }
+ if (b & 0x08) {
+ // Parse unparsed entities (C.2.7)
+ for (;;) {
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b1 = *dataP++;
+ if (b1 == 0xf0) {
+ break;
+ }
+ if ((b1 & 0xfe) != 0xd0) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /* C.10 */
+ /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ if (b1 & 0x01) {
+ /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable);
+ }
+ /*const std::string &notationName =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
+ }
+ }
+ if (b & 0x04) {
+ // Parse character encoding scheme (C.2.8)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::string characterEncodingScheme =*/ parseNonEmptyOctetString2();
+ }
+ if (b & 0x02) {
+ // Parse standalone flag (C.2.9)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ uint8_t b1 = *dataP++;
+ if (b1 & 0xfe) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ //bool standalone = b1 & 0x01;
+ }
+ if (b & 0x01) {
+ // Parse version (C.2.10)
+ if (dataEnd - dataP < 1) {
+ throw DeadlyImportError(parseErrorMessage);
+ }
+ /*std::shared_ptr<const FIValue> version =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
+ }
+ }
+
+ std::unique_ptr<uint8_t[]> data;
+ uint8_t *dataP, *dataEnd;
+ irr::io::EXML_NODE currentNodeType;
+ bool emptyElement;
+ bool headerPending;
+ bool terminatorPending;
+ Vocabulary vocabulary;
+ std::vector<Attribute> attributes;
+ std::stack<std::string> elementStack;
+ std::string nodeName;
+ std::map<std::string, std::unique_ptr<FIDecoder>> decoderMap;
+ std::map<std::string, const FIVocabulary*> vocabularyMap;
+
+ static const std::string EmptyString;
+ static std::shared_ptr<const FIValue> EmptyFIString;
+
+ static FIHexDecoder hexDecoder;
+ static FIBase64Decoder base64Decoder;
+ static FIShortDecoder shortDecoder;
+ static FIIntDecoder intDecoder;
+ static FILongDecoder longDecoder;
+ static FIBoolDecoder boolDecoder;
+ static FIFloatDecoder floatDecoder;
+ static FIDoubleDecoder doubleDecoder;
+ static FIUUIDDecoder uuidDecoder;
+ static FICDATADecoder cdataDecoder;
+ static FIDecoder *defaultDecoder[32];
+};
+
+const std::string CFIReaderImpl::EmptyString;
+std::shared_ptr<const FIValue> CFIReaderImpl::EmptyFIString = FIStringValue::create(std::string());
+
+FIHexDecoder CFIReaderImpl::hexDecoder;
+FIBase64Decoder CFIReaderImpl::base64Decoder;
+FIShortDecoder CFIReaderImpl::shortDecoder;
+FIIntDecoder CFIReaderImpl::intDecoder;
+FILongDecoder CFIReaderImpl::longDecoder;
+FIBoolDecoder CFIReaderImpl::boolDecoder;
+FIFloatDecoder CFIReaderImpl::floatDecoder;
+FIDoubleDecoder CFIReaderImpl::doubleDecoder;
+FIUUIDDecoder CFIReaderImpl::uuidDecoder;
+FICDATADecoder CFIReaderImpl::cdataDecoder;
+
+FIDecoder *CFIReaderImpl::defaultDecoder[32] = {
+ &hexDecoder,
+ &base64Decoder,
+ &shortDecoder,
+ &intDecoder,
+ &longDecoder,
+ &boolDecoder,
+ &floatDecoder,
+ &doubleDecoder,
+ &uuidDecoder,
+ &cdataDecoder
+};
+
+class CXMLReaderImpl : public FIReader
+{
+public:
+
+ //! Constructor
+ CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader_)
+ : reader(std::move(reader_))
+ {}
+
+ virtual ~CXMLReaderImpl() {}
+
+ virtual bool read() /*override*/ {
+ return reader->read();
+ }
+
+ virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
+ return reader->getNodeType();
+ }
+
+ virtual int getAttributeCount() const /*override*/ {
+ return reader->getAttributeCount();
+ }
+
+ virtual const char* getAttributeName(int idx) const /*override*/ {
+ return reader->getAttributeName(idx);
+ }
+
+ virtual const char* getAttributeValue(int idx) const /*override*/ {
+ return reader->getAttributeValue(idx);
+ }
+
+ virtual const char* getAttributeValue(const char* name) const /*override*/ {
+ return reader->getAttributeValue(name);
+ }
+
+ virtual const char* getAttributeValueSafe(const char* name) const /*override*/ {
+ return reader->getAttributeValueSafe(name);
+ }
+
+ virtual int getAttributeValueAsInt(const char* name) const /*override*/ {
+ return reader->getAttributeValueAsInt(name);
+ }
+
+ virtual int getAttributeValueAsInt(int idx) const /*override*/ {
+ return reader->getAttributeValueAsInt(idx);
+ }
+
+ virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
+ return reader->getAttributeValueAsFloat(name);
+ }
+
+ virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
+ return reader->getAttributeValueAsFloat(idx);
+ }
+
+ virtual const char* getNodeName() const /*override*/ {
+ return reader->getNodeName();
+ }
+
+ virtual const char* getNodeData() const /*override*/ {
+ return reader->getNodeData();
+ }
+
+ virtual bool isEmptyElement() const /*override*/ {
+ return reader->isEmptyElement();
+ }
+
+ virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
+ return reader->getSourceFormat();
+ }
+
+ virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
+ return reader->getParserFormat();
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int /*idx*/) const /*override*/ {
+ return nullptr;
+ }
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* /*name*/) const /*override*/ {
+ return nullptr;
+ }
+
+ virtual void registerDecoder(const std::string & /*algorithmUri*/, std::unique_ptr<FIDecoder> /*decoder*/) /*override*/ {}
+
+
+ virtual void registerVocabulary(const std::string &/*vocabularyUri*/, const FIVocabulary * /*vocabulary*/) /*override*/ {}
+
+private:
+
+ std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader;
+};
+
+static std::unique_ptr<uint8_t[]> readFile(IOStream *stream, size_t &size, bool &isFI) {
+ size = stream->FileSize();
+ std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
+ if (stream->Read(data.get(), size, 1) != 1) {
+ size = 0;
+ data.reset();
+ }
+ isFI = parseMagic(data.get(), data.get() + size) > 0;
+ return data;
+}
+
+std::unique_ptr<FIReader> FIReader::create(IOStream *stream)
+{
+ size_t size;
+ bool isFI;
+ auto data = readFile(stream, size, isFI);
+ if (isFI) {
+ return std::unique_ptr<FIReader>(new CFIReaderImpl(std::move(data), size));
+ }
+ else {
+ auto memios = std::unique_ptr<MemoryIOStream>(new MemoryIOStream(data.release(), size, true));
+ auto callback = std::unique_ptr<CIrrXML_IOStreamReader>(new CIrrXML_IOStreamReader(memios.get()));
+ return std::unique_ptr<FIReader>(new CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>>(createIrrXMLReader(callback.get()))));
+ }
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/FIReader.hpp b/src/3rdparty/assimp/code/FIReader.hpp
new file mode 100644
index 000000000..5f4e5bb48
--- /dev/null
+++ b/src/3rdparty/assimp/code/FIReader.hpp
@@ -0,0 +1,185 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 FIReader.hpp
+/// \brief Reader for Fast Infoset encoded binary XML files.
+/// \date 2017
+/// \author Patrick Daehne
+
+#ifndef INCLUDED_AI_FI_READER_H
+#define INCLUDED_AI_FI_READER_H
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+//#include <wchar.h>
+#include <string>
+#include <memory>
+#include <cerrno>
+#include <cwchar>
+#include <vector>
+//#include <stdio.h>
+//#include <cstdint>
+#include <irrXML.h>
+
+namespace Assimp {
+
+struct FIValue {
+ virtual const std::string &toString() const = 0;
+};
+
+struct FIStringValue: public FIValue {
+ std::string value;
+ static std::shared_ptr<FIStringValue> create(std::string &&value);
+};
+
+struct FIByteValue: public FIValue {
+ std::vector<uint8_t> value;
+};
+
+struct FIHexValue: public FIByteValue {
+ static std::shared_ptr<FIHexValue> create(std::vector<uint8_t> &&value);
+};
+
+struct FIBase64Value: public FIByteValue {
+ static std::shared_ptr<FIBase64Value> create(std::vector<uint8_t> &&value);
+};
+
+struct FIShortValue: public FIValue {
+ std::vector<int16_t> value;
+ static std::shared_ptr<FIShortValue> create(std::vector<int16_t> &&value);
+};
+
+struct FIIntValue: public FIValue {
+ std::vector<int32_t> value;
+ static std::shared_ptr<FIIntValue> create(std::vector<int32_t> &&value);
+};
+
+struct FILongValue: public FIValue {
+ std::vector<int64_t> value;
+ static std::shared_ptr<FILongValue> create(std::vector<int64_t> &&value);
+};
+
+struct FIBoolValue: public FIValue {
+ std::vector<bool> value;
+ static std::shared_ptr<FIBoolValue> create(std::vector<bool> &&value);
+};
+
+struct FIFloatValue: public FIValue {
+ std::vector<float> value;
+ static std::shared_ptr<FIFloatValue> create(std::vector<float> &&value);
+};
+
+struct FIDoubleValue: public FIValue {
+ std::vector<double> value;
+ static std::shared_ptr<FIDoubleValue> create(std::vector<double> &&value);
+};
+
+struct FIUUIDValue: public FIByteValue {
+ static std::shared_ptr<FIUUIDValue> create(std::vector<uint8_t> &&value);
+};
+
+struct FICDATAValue: public FIStringValue {
+ static std::shared_ptr<FICDATAValue> create(std::string &&value);
+};
+
+struct FIDecoder {
+ virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) = 0;
+};
+
+struct FIQName {
+ const char *name;
+ const char *prefix;
+ const char *uri;
+};
+
+struct FIVocabulary {
+ const char **restrictedAlphabetTable;
+ size_t restrictedAlphabetTableSize;
+ const char **encodingAlgorithmTable;
+ size_t encodingAlgorithmTableSize;
+ const char **prefixTable;
+ size_t prefixTableSize;
+ const char **namespaceNameTable;
+ size_t namespaceNameTableSize;
+ const char **localNameTable;
+ size_t localNameTableSize;
+ const char **otherNCNameTable;
+ size_t otherNCNameTableSize;
+ const char **otherURITable;
+ size_t otherURITableSize;
+ const std::shared_ptr<const FIValue> *attributeValueTable;
+ size_t attributeValueTableSize;
+ const std::shared_ptr<const FIValue> *charactersTable;
+ size_t charactersTableSize;
+ const std::shared_ptr<const FIValue> *otherStringTable;
+ size_t otherStringTableSize;
+ const FIQName *elementNameTable;
+ size_t elementNameTableSize;
+ const FIQName *attributeNameTable;
+ size_t attributeNameTableSize;
+};
+
+class IOStream;
+
+class FIReader: public irr::io::IIrrXMLReader<char, irr::io::IXMLBase> {
+public:
+ virtual ~FIReader();
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const = 0;
+
+ virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char *name) const = 0;
+
+ virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) = 0;
+
+ virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) = 0;
+
+ static std::unique_ptr<FIReader> create(IOStream *stream);
+
+};// class IFIReader
+
+inline
+FIReader::~FIReader() {
+ // empty
+}
+
+}// namespace Assimp
+
+#endif // #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#endif // INCLUDED_AI_FI_READER_H
diff --git a/src/3rdparty/assimp/code/FileLogStream.h b/src/3rdparty/assimp/code/FileLogStream.h
index 574a63ed6..e935624a1 100644
--- a/src/3rdparty/assimp/code/FileLogStream.h
+++ b/src/3rdparty/assimp/code/FileLogStream.h
@@ -1,9 +1,50 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/** @file FileLofStream.h
+*/
#ifndef ASSIMP_FILELOGSTREAM_H_INC
#define ASSIMP_FILELOGSTREAM_H_INC
#include <assimp/LogStream.hpp>
#include <assimp/IOStream.hpp>
-#include "DefaultIOSystem.h"
+#include <assimp/DefaultIOSystem.h>
namespace Assimp {
diff --git a/src/3rdparty/assimp/code/FindDegenerates.cpp b/src/3rdparty/assimp/code/FindDegenerates.cpp
index 62750bfad..f9c04133a 100644
--- a/src/3rdparty/assimp/code/FindDegenerates.cpp
+++ b/src/3rdparty/assimp/code/FindDegenerates.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -55,98 +56,138 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindDegeneratesProcess::FindDegeneratesProcess()
-: configRemoveDegenerates (false)
-{}
+: mConfigRemoveDegenerates( false )
+, mConfigCheckAreaOfTriangle( false ){
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-FindDegeneratesProcess::~FindDegeneratesProcess()
-{
+FindDegeneratesProcess::~FindDegeneratesProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
-bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const
-{
+bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const {
return 0 != (pFlags & aiProcess_FindDegenerates);
}
// ------------------------------------------------------------------------------------------------
// Setup import configuration
-void FindDegeneratesProcess::SetupProperties(const Importer* pImp)
-{
+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));
+ mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
+ mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) );
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
-void FindDegeneratesProcess::Execute( aiScene* pScene)
-{
+void FindDegeneratesProcess::Execute( aiScene* pScene) {
DefaultLogger::get()->debug("FindDegeneratesProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
- ExecuteOnMesh( pScene->mMeshes[i]);
+ ExecuteOnMesh( pScene->mMeshes[ i ] );
}
DefaultLogger::get()->debug("FindDegeneratesProcess finished");
}
+static ai_real heron( ai_real a, ai_real b, ai_real c ) {
+ ai_real s = (a + b + c) / 2;
+ ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
+ return area;
+}
+
+static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB ) {
+ const ai_real lx = ( vB.x - vA.x );
+ const ai_real ly = ( vB.y - vA.y );
+ const ai_real lz = ( vB.z - vA.z );
+ ai_real a = lx*lx + ly*ly + lz*lz;
+ ai_real d = pow( a, (ai_real)0.5 );
+
+ return d;
+}
+
+static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
+ ai_real area = 0;
+
+ aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
+ aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
+ aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
+
+ ai_real a( distance3D( vA, vB ) );
+ ai_real b( distance3D( vB, vC ) );
+ ai_real c( distance3D( vC, vA ) );
+ area = heron( a, b, c );
+
+ return area;
+}
+
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported mesh
-void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
-{
+void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
mesh->mPrimitiveTypes = 0;
std::vector<bool> remove_me;
- if (configRemoveDegenerates)
- remove_me.resize(mesh->mNumFaces,false);
+ if (mConfigRemoveDegenerates) {
+ remove_me.resize( mesh->mNumFaces, false );
+ }
unsigned int deg = 0, limit;
- for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
- {
+ 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)
- {
+ 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);
+ 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]])
- {
+ 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];
+ --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;
+ face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
- if(first)
- {
+ if(first) {
++deg;
first = false;
}
- if (configRemoveDegenerates) {
- remove_me[a] = true;
+ if ( mConfigRemoveDegenerates ) {
+ remove_me[ a ] = true;
goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
}
}
}
+
+ if ( mConfigCheckAreaOfTriangle ) {
+ if ( face.mNumIndices == 3 ) {
+ ai_real area = calculateAreaOfTriangle( face, mesh );
+ if ( area < 1e-6 ) {
+ if ( mConfigRemoveDegenerates ) {
+ remove_me[ a ] = true;
+ goto evil_jump_outside;
+ }
+
+ // todo: check for index which is corrupt.
+ }
+ }
+ }
}
// We need to update the primitive flags array of the mesh.
@@ -170,7 +211,7 @@ evil_jump_outside:
}
// If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
- if (configRemoveDegenerates && deg) {
+ if (mConfigRemoveDegenerates && deg) {
unsigned int n = 0;
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
{
diff --git a/src/3rdparty/assimp/code/FindDegenerates.h b/src/3rdparty/assimp/code/FindDegenerates.h
index 7b945ea3a..cf03a24bc 100644
--- a/src/3rdparty/assimp/code/FindDegenerates.h
+++ b/src/3rdparty/assimp/code/FindDegenerates.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,15 +54,11 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** FindDegeneratesProcess: Searches a mesh for degenerated triangles.
*/
-class ASSIMP_API FindDegeneratesProcess : public BaseProcess
-{
+class ASSIMP_API FindDegeneratesProcess : public BaseProcess {
public:
-
FindDegeneratesProcess();
~FindDegeneratesProcess();
-public:
-
// -------------------------------------------------------------------
// Check whether step is active
bool IsActive( unsigned int pFlags) const;
@@ -78,28 +75,53 @@ public:
// Execute step on a given mesh
void ExecuteOnMesh( aiMesh* mesh);
+ // -------------------------------------------------------------------
+ /// @brief Enable the instant removal of degenerated primitives
+ /// @param enabled true for enabled.
+ void EnableInstantRemoval(bool enabled);
// -------------------------------------------------------------------
- /** @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 The instant removal state.
+ bool IsInstantRemoval() const;
// -------------------------------------------------------------------
- /** @brief Check whether instant removal is currently enabled
- * @return ...
- */
- bool IsInstantRemoval() const {
- return configRemoveDegenerates;
- }
+ /// @brief Enable the area check for triangles.
+ /// @param enabled true for enabled.
+ void EnableAreaCheck( bool enabled );
-private:
+ // -------------------------------------------------------------------
+ /// @brief Check whether the area check is enabled.
+ /// @return The area check state.
+ bool isAreaCheckEnabled() const;
+private:
//! Configuration option: remove degenerates faces immediately
- bool configRemoveDegenerates;
+ bool mConfigRemoveDegenerates;
+ //! Configuration option: check for area
+ bool mConfigCheckAreaOfTriangle;
};
+
+inline
+void FindDegeneratesProcess::EnableInstantRemoval(bool enabled) {
+ mConfigRemoveDegenerates = enabled;
+}
+
+inline
+bool FindDegeneratesProcess::IsInstantRemoval() const {
+ return mConfigRemoveDegenerates;
+}
+
+inline
+void FindDegeneratesProcess::EnableAreaCheck( bool enabled ) {
+ mConfigCheckAreaOfTriangle = enabled;
+}
+
+inline
+bool FindDegeneratesProcess::isAreaCheckEnabled() const {
+ return mConfigCheckAreaOfTriangle;
}
+} // Namespace Assimp
+
#endif // !! AI_FINDDEGENERATESPROCESS_H_INC
diff --git a/src/3rdparty/assimp/code/FindInstancesProcess.cpp b/src/3rdparty/assimp/code/FindInstancesProcess.cpp
index 479f6561e..ab2d2257b 100644
--- a/src/3rdparty/assimp/code/FindInstancesProcess.cpp
+++ b/src/3rdparty/assimp/code/FindInstancesProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/FindInstancesProcess.h b/src/3rdparty/assimp/code/FindInstancesProcess.h
index 14876045c..dc4396566 100644
--- a/src/3rdparty/assimp/code/FindInstancesProcess.h
+++ b/src/3rdparty/assimp/code/FindInstancesProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
index bb87f8dd8..c37d8956c 100644
--- a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
+++ b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -58,7 +59,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindInvalidDataProcess::FindInvalidDataProcess()
- : configEpsilon(0.0f)
+ : configEpsilon(0.0)
{
// nothing to do here
}
@@ -168,8 +169,8 @@ void FindInvalidDataProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline const char* ValidateArrayContents(const T* arr, unsigned int size,
- const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
+inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/,
+ const std::vector<bool>& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/)
{
return NULL;
}
@@ -221,16 +222,16 @@ inline bool ProcessArray(T*& in, unsigned int num,const char* name,
// ------------------------------------------------------------------------------------------------
template <typename T>
-AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, float epsilon);
+AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, ai_real epsilon);
// ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) {
+AI_FORCE_INLINE bool EpsilonCompare(ai_real n, ai_real s, ai_real epsilon) {
return std::fabs(n-s)>epsilon;
}
// ------------------------------------------------------------------------------------------------
template <>
-bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, float epsilon) {
+bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, ai_real epsilon) {
return
EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
@@ -239,7 +240,7 @@ bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, flo
// ------------------------------------------------------------------------------------------------
template <>
-bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, float epsilon) {
+bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, ai_real epsilon) {
return
EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
@@ -249,7 +250,7 @@ bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, float eps
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline bool AllIdentical(T* in, unsigned int num, float epsilon)
+inline bool AllIdentical(T* in, unsigned int num, ai_real epsilon)
{
if (num <= 1) {
return true;
@@ -338,32 +339,37 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
{
bool ret = false;
- std::vector<bool> dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false));
+ std::vector<bool> dirtyMask(pMesh->mNumVertices, pMesh->mNumFaces != 0);
// 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) {
+ for (unsigned int m = 0; m < pMesh->mNumFaces; ++m) {
const aiFace& f = pMesh->mFaces[m];
- for (unsigned int i = 0; i < f.mNumIndices;++i) {
+ 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)) {
+ 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)) {
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) {
+ if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) {
+ pMesh->mNumUVComponents[i] = 0;
// 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;
+ for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+ delete[] pMesh->mTextureCoords[a];
+ pMesh->mTextureCoords[a] = NULL;
+ pMesh->mNumUVComponents[a] = 0;
}
+
ret = true;
}
}
diff --git a/src/3rdparty/assimp/code/FindInvalidDataProcess.h b/src/3rdparty/assimp/code/FindInvalidDataProcess.h
index 371569380..cc0ef946d 100644
--- a/src/3rdparty/assimp/code/FindInvalidDataProcess.h
+++ b/src/3rdparty/assimp/code/FindInvalidDataProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -97,7 +98,7 @@ public:
void ProcessAnimationChannel (aiNodeAnim* anim);
private:
- float configEpsilon;
+ ai_real configEpsilon;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/FixNormalsStep.cpp b/src/3rdparty/assimp/code/FixNormalsStep.cpp
index 9249b13e9..05d05e873 100644
--- a/src/3rdparty/assimp/code/FixNormalsStep.cpp
+++ b/src/3rdparty/assimp/code/FixNormalsStep.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -148,9 +149,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 * std::sqrt( fDelta1_yz ))return false;
+ if (fDelta1_y < 0.05f * std::sqrt( fDelta1_z * fDelta1_x ))return false;
+ if (fDelta1_z < 0.05f * std::sqrt( fDelta1_y * fDelta1_x ))return false;
// now compare the volumes of the bounding boxes
if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) <
diff --git a/src/3rdparty/assimp/code/FixNormalsStep.h b/src/3rdparty/assimp/code/FixNormalsStep.h
index 5dea5d868..71309c7e5 100644
--- a/src/3rdparty/assimp/code/FixNormalsStep.h
+++ b/src/3rdparty/assimp/code/FixNormalsStep.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -55,14 +56,11 @@ namespace Assimp
* vectors of an object are facing inwards. In this case they will be
* flipped.
*/
-class FixInfacingNormalsProcess : public BaseProcess
-{
+class FixInfacingNormalsProcess : public BaseProcess {
public:
-
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
diff --git a/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp b/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp
index 9218d9db8..82d80db77 100644
--- a/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp
+++ b/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/GenFaceNormalsProcess.h b/src/3rdparty/assimp/code/GenFaceNormalsProcess.h
index f56570078..024c74a28 100644
--- a/src/3rdparty/assimp/code/GenFaceNormalsProcess.h
+++ b/src/3rdparty/assimp/code/GenFaceNormalsProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
index 165c3f8fb..93c0e1351 100644
--- a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
+++ b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -78,8 +79,8 @@ bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
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));
+ configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,(ai_real)175.0);
+ configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,(ai_real)175.0),(ai_real)0.0));
}
// ------------------------------------------------------------------------------------------------
@@ -123,7 +124,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
}
// Allocate the array to hold the output normals
- const float qnan = std::numeric_limits<float>::quiet_NaN();
+ const float qnan = std::numeric_limits<ai_real>::quiet_NaN();
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
// Compute per-face normals but store them per-vertex
@@ -154,13 +155,13 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
// check whether we can reuse the SpatialSort of a previous step.
SpatialSort* vertexFinder = NULL;
SpatialSort _vertexFinder;
- float posEpsilon = 1e-5f;
+ ai_real posEpsilon = ai_real( 1e-5 );
if (shared) {
- std::vector<std::pair<SpatialSort,float> >* avf;
+ std::vector<std::pair<SpatialSort,ai_real> >* avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
if (avf)
{
- std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
+ std::pair<SpatialSort,ai_real>& blubb = avf->operator [] (meshIndex);
vertexFinder = &blubb.first;
posEpsilon = blubb.second;
}
@@ -205,13 +206,13 @@ 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 = std::cos(configMaxAngle);
+ const ai_real 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();
+ ai_real vrlen = vr.Length();
aiVector3D pcNor;
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
diff --git a/src/3rdparty/assimp/code/GenVertexNormalsProcess.h b/src/3rdparty/assimp/code/GenVertexNormalsProcess.h
index 5d8b61ead..0471ed6b0 100644
--- a/src/3rdparty/assimp/code/GenVertexNormalsProcess.h
+++ b/src/3rdparty/assimp/code/GenVertexNormalsProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -86,7 +87,7 @@ public:
// setter for configMaxAngle
- inline void SetMaxSmoothAngle(float f)
+ inline void SetMaxSmoothAngle(ai_real f)
{
configMaxAngle =f;
}
@@ -104,10 +105,9 @@ public:
private:
/** Configuration option: maximum smoothing angle, in radians*/
- float configMaxAngle;
+ ai_real configMaxAngle;
};
} // end of namespace Assimp
#endif // !!AI_GENVERTEXNORMALPROCESS_H_INC
-
diff --git a/src/3rdparty/assimp/code/GenericProperty.h b/src/3rdparty/assimp/code/GenericProperty.h
index 507bfb693..454f4952b 100644
--- a/src/3rdparty/assimp/code/GenericProperty.h
+++ b/src/3rdparty/assimp/code/GenericProperty.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -110,7 +111,7 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
// ------------------------------------------------------------------------------------------------
template <class T>
-inline const bool HasGenericProperty(const std::map< unsigned int, T >& list,
+inline bool HasGenericProperty(const std::map< unsigned int, T >& list,
const char* szName)
{
ai_assert(NULL != szName);
diff --git a/src/3rdparty/assimp/code/HMPFileData.h b/src/3rdparty/assimp/code/HMPFileData.h
index cff3b6b18..3c060ba1a 100644
--- a/src/3rdparty/assimp/code/HMPFileData.h
+++ b/src/3rdparty/assimp/code/HMPFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/HMPLoader.cpp b/src/3rdparty/assimp/code/HMPLoader.cpp
index 560852691..2a669201e 100644
--- a/src/3rdparty/assimp/code/HMPLoader.cpp
+++ b/src/3rdparty/assimp/code/HMPLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -51,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
using namespace Assimp;
@@ -127,8 +129,7 @@ void HMPImporter::InternReadFile( const std::string& pFile,
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];
+ mBuffer = new uint8_t[fileSize];
file->Read( (void*)mBuffer, 1, fileSize);
iFileSize = (unsigned int)fileSize;
@@ -174,7 +175,9 @@ void HMPImporter::InternReadFile( const std::string& pFile,
// Set the AI_SCENE_FLAGS_TERRAIN bit
pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
- // File buffer destructs automatically now
+ delete[] mBuffer;
+ mBuffer= nullptr;
+
}
// ------------------------------------------------------------------------------------------------
@@ -445,15 +448,18 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
const unsigned char** szCursorOut)
{
- ai_assert(0 != iNumSkins && NULL != szCursor);
+ ai_assert( 0 != iNumSkins );
+ ai_assert( nullptr != 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);
+ 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);
+ iType = *((uint32_t*)szCursor);
+ szCursor += sizeof(uint32_t);
if (!iType)
throw DeadlyImportError("Unable to read HMP7 skin chunk");
diff --git a/src/3rdparty/assimp/code/HMPLoader.h b/src/3rdparty/assimp/code/HMPLoader.h
index 4dd0d9840..546643e8d 100644
--- a/src/3rdparty/assimp/code/HMPLoader.h
+++ b/src/3rdparty/assimp/code/HMPLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,11 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_HMPLOADER_H_INCLUDED
#define AI_HMPLOADER_H_INCLUDED
-// public ASSIMP headers
-#include <assimp/types.h>
-#include <assimp/texture.h>
-#include <assimp/material.h>
-
// internal headers
#include "BaseImporter.h"
#include "MDLLoader.h"
diff --git a/src/3rdparty/assimp/code/HalfLifeFileData.h b/src/3rdparty/assimp/code/HalfLifeFileData.h
index 54fe83734..3a36d2422 100644
--- a/src/3rdparty/assimp/code/HalfLifeFileData.h
+++ b/src/3rdparty/assimp/code/HalfLifeFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,7 +50,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MDLFILEHELPER2_H_INC
#define AI_MDLFILEHELPER2_H_INC
-#include "MDLFileData.h"
#include "./../include/assimp/Compiler/pushpack1.h"
namespace Assimp {
@@ -66,8 +66,7 @@ namespace MDL {
* \brief Data structure for the HL2 main header
*/
// ---------------------------------------------------------------------------
-struct Header_HL2
-{
+struct Header_HL2 {
//! magic number: "IDST"/"IDSQ"
char ident[4];
@@ -139,7 +138,7 @@ struct Header_HL2
//! Number of animation transitions
int32_t numtransitions;
int32_t transitionindex;
-} PACK_STRUCT;
+} /* 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 cd7ca6def..a567adbc3 100644
--- a/src/3rdparty/assimp/code/Hash.h
+++ b/src/3rdparty/assimp/code/Hash.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/IFCBoolean.cpp b/src/3rdparty/assimp/code/IFCBoolean.cpp
index 042515311..d250fbe36 100644
--- a/src/3rdparty/assimp/code/IFCBoolean.cpp
+++ b/src/3rdparty/assimp/code/IFCBoolean.cpp
@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IFCUtil.h"
#include "PolyTools.h"
#include "ProcessHelper.h"
-#include "Defines.h"
+#include <assimp/Defines.h>
#include <iterator>
#include <tuple>
@@ -109,7 +109,7 @@ void FilterPolygon(std::vector<IfcVector3>& resultpoly)
}
IfcVector3 vmin, vmax;
- ArrayBounds(resultpoly.data(), resultpoly.size(), vmin, vmax);
+ ArrayBounds(resultpoly.data(), static_cast<unsigned int>(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
@@ -132,7 +132,7 @@ void WritePolygon(std::vector<IfcVector3>& resultpoly, TempMesh& result)
if( resultpoly.size() > 2 )
{
result.verts.insert(result.verts.end(), resultpoly.begin(), resultpoly.end());
- result.vertcnt.push_back(resultpoly.size());
+ result.vertcnt.push_back(static_cast<unsigned int>(resultpoly.size()));
}
}
@@ -272,7 +272,6 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const
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)
@@ -281,6 +280,7 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const
// no solutions (parallel lines)
continue;
}
+ IfcFloat b_sqlen_inv = 1.0 / b.SquareLength();
const IfcFloat x = b0.x - e0.x;
const IfcFloat y = b0.y - e0.y;
@@ -381,7 +381,6 @@ bool PointInPoly(const IfcVector3& p, const std::vector<IfcVector3>& boundary)
IntersectsBoundaryProfile(p, p + IfcVector3(0.6, -0.6, 0.0), boundary, true, intersected_boundary, true);
votes += intersected_boundary.size() % 2;
-// ai_assert(votes == 3 || votes == 0);
return votes > 1;
}
@@ -589,7 +588,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
// to result mesh unchanged
if( !startedInside )
{
- outvertcnt.push_back(blackside.size());
+ outvertcnt.push_back(static_cast<unsigned int>(blackside.size()));
outvert.insert(outvert.end(), blackside.begin(), blackside.end());
continue;
}
diff --git a/src/3rdparty/assimp/code/IFCCurve.cpp b/src/3rdparty/assimp/code/IFCCurve.cpp
index 97d9fd574..2aa3ef6a4 100644
--- a/src/3rdparty/assimp/code/IFCCurve.cpp
+++ b/src/3rdparty/assimp/code/IFCCurve.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,28 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Read profile and curves entities from IFC files
*/
-
-
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
namespace Assimp {
- namespace IFC {
- namespace {
+namespace IFC {
+namespace {
// --------------------------------------------------------------------------------
// Conic is the base class for Circle and Ellipse
// --------------------------------------------------------------------------------
-class Conic : public Curve
-{
-
+class Conic : public Curve {
public:
-
// --------------------------------------------------
Conic(const IfcConic& entity, ConversionData& conv)
- : Curve(entity,conv)
- {
+ : Curve(entity,conv) {
IfcMatrix4 trafo;
ConvertAxisPlacement(trafo,*entity.Position,conv);
@@ -74,8 +69,6 @@ public:
p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
}
-public:
-
// --------------------------------------------------
bool IsClosed() const {
return true;
@@ -83,7 +76,8 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
+ ai_assert( InRange( a ) );
+ ai_assert( InRange( b ) );
a *= conv.angle_scale;
b *= conv.angle_scale;
@@ -103,15 +97,11 @@ protected:
IfcVector3 location, p[3];
};
-
// --------------------------------------------------------------------------------
// Circle
// --------------------------------------------------------------------------------
-class Circle : public Conic
-{
-
+class Circle : public Conic {
public:
-
// --------------------------------------------------
Circle(const IfcCircle& entity, ConversionData& conv)
: Conic(entity,conv)
@@ -119,8 +109,6 @@ public:
{
}
-public:
-
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u;
@@ -136,20 +124,15 @@ private:
// --------------------------------------------------------------------------------
// Ellipse
// --------------------------------------------------------------------------------
-class Ellipse : public Conic
-{
-
+class Ellipse : public Conic {
public:
-
// --------------------------------------------------
Ellipse(const IfcEllipse& entity, ConversionData& conv)
- : Conic(entity,conv)
- , entity(entity)
- {
+ : Conic(entity,conv)
+ , entity(entity) {
+ // empty
}
-public:
-
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u;
@@ -161,25 +144,18 @@ private:
const IfcEllipse& entity;
};
-
// --------------------------------------------------------------------------------
// Line
// --------------------------------------------------------------------------------
-class Line : public Curve
-{
-
+class Line : public Curve {
public:
-
// --------------------------------------------------
Line(const IfcLine& entity, ConversionData& conv)
- : Curve(entity,conv)
- {
+ : Curve(entity,conv) {
ConvertCartesianPoint(p,entity.Pnt);
ConvertVector(v,entity.Dir);
}
-public:
-
// --------------------------------------------------
bool IsClosed() const {
return false;
@@ -192,16 +168,17 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
+ ai_assert( InRange( a ) );
+ ai_assert( 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));
+ void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
+ ai_assert( InRange( a ) );
+ ai_assert( InRange( b ) );
if (a == b) {
out.verts.push_back(Eval(a));
@@ -226,18 +203,14 @@ private:
// --------------------------------------------------------------------------------
// CompositeCurve joins multiple smaller, bounded curves
// --------------------------------------------------------------------------------
-class CompositeCurve : public BoundedCurve
-{
-
+class CompositeCurve : public BoundedCurve {
typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry;
public:
-
// --------------------------------------------------
CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
- : BoundedCurve(entity,conv)
- , total()
- {
+ : 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
@@ -262,8 +235,6 @@ public:
}
}
-public:
-
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
if (curves.empty()) {
@@ -286,7 +257,8 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
+ ai_assert( InRange( a ) );
+ ai_assert( InRange( b ) );
size_t cnt = 0;
IfcFloat acc = 0;
@@ -305,9 +277,9 @@ public:
}
// --------------------------------------------------
- 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 ) );
+ ai_assert( InRange( b ) );
const size_t cnt = EstimateSampleCount(a,b);
out.verts.reserve(out.verts.size() + cnt);
@@ -329,19 +301,14 @@ public:
private:
std::vector< CurveEntry > curves;
-
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)
@@ -408,8 +375,6 @@ public:
ai_assert(maxval >= 0);
}
-public:
-
// --------------------------------------------------
IfcVector3 Eval(IfcFloat p) const {
ai_assert(InRange(p));
@@ -418,7 +383,8 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
+ ai_assert( InRange( a ) );
+ ai_assert( InRange( b ) );
return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
}
@@ -434,13 +400,11 @@ public:
}
private:
-
// --------------------------------------------------
IfcFloat TrimParam(IfcFloat f) const {
return agree_sense ? f + range.first : range.second - f;
}
-
private:
ParamRange range;
IfcFloat maxval;
@@ -453,11 +417,8 @@ private:
// --------------------------------------------------------------------------------
// 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)
@@ -471,8 +432,6 @@ public:
}
}
-public:
-
// --------------------------------------------------
IfcVector3 Eval(IfcFloat p) const {
ai_assert(InRange(p));
@@ -501,13 +460,10 @@ private:
std::vector<IfcVector3> points;
};
-
} // anon
-
// ------------------------------------------------------------------------------------------------
-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);
@@ -518,9 +474,6 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& 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>()) {
@@ -542,13 +495,10 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
#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());
- //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;
@@ -556,24 +506,24 @@ bool Curve :: InRange(IfcFloat u) const
#endif
// ------------------------------------------------------------------------------------------------
-IfcFloat Curve :: GetParametricRangeDelta() const
-{
+IfcFloat Curve::GetParametricRangeDelta() const {
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));
+size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+ (void)(a); (void)(b);
+ ai_assert( InRange( a ) );
+ ai_assert( InRange( b ) );
// 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)
-{
+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();
@@ -595,7 +545,8 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
}
}
- ai_assert(min_diff[0] != inf && min_diff[1] != inf);
+ ai_assert( min_diff[ 0 ] != inf );
+ ai_assert( min_diff[ 1 ] != inf );
if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
return min_point[0];
}
@@ -616,15 +567,15 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
}
// ------------------------------------------------------------------------------------------------
-bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
+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.
// XXX derive threshold from curve topology
- const IfcFloat threshold = 1e-4f;
- const unsigned int samples = 16;
+ static const IfcFloat threshold = 1e-4f;
+ static const unsigned int samples = 16;
const ParamRange& range = GetParametricRange();
paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);
@@ -633,9 +584,9 @@ bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
}
// ------------------------------------------------------------------------------------------------
-void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
-{
- ai_assert(InRange(a) && InRange(b));
+void Curve::SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
+ ai_assert( InRange( a ) );
+ ai_assert( InRange( b ) );
const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
out.verts.reserve( out.verts.size() + cnt + 1);
@@ -647,16 +598,15 @@ void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
}
// ------------------------------------------------------------------------------------------------
-bool BoundedCurve :: IsClosed() const
-{
+bool BoundedCurve::IsClosed() const {
return false;
}
// ------------------------------------------------------------------------------------------------
-void BoundedCurve :: SampleDiscrete(TempMesh& out) const
-{
+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());
+ ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
+ ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );
return SampleDiscrete(out,range.first,range.second);
}
diff --git a/src/3rdparty/assimp/code/IFCGeometry.cpp b/src/3rdparty/assimp/code/IFCGeometry.cpp
index 5a2e4a09d..908f5e065 100644
--- a/src/3rdparty/assimp/code/IFCGeometry.cpp
+++ b/src/3rdparty/assimp/code/IFCGeometry.cpp
@@ -70,7 +70,7 @@ bool ProcessPolyloop(const IfcPolyLoop& loop, TempMesh& meshout, ConversionData&
++cnt;
}
- meshout.vertcnt.push_back(cnt);
+ meshout.vertcnt.push_back(static_cast<unsigned int>(cnt));
// zero- or one- vertex polyloops simply ignored
if (meshout.vertcnt.back() > 1) {
@@ -180,7 +180,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
// fill a mesh with ONLY the main polygon
TempMesh temp;
temp.verts.reserve(outer_polygon_size);
- temp.vertcnt.push_back(outer_polygon_size);
+ temp.vertcnt.push_back(static_cast<unsigned int>(outer_polygon_size));
std::copy(outer_vit, outer_vit+outer_polygon_size,
std::back_inserter(temp.verts));
@@ -258,7 +258,7 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
return;
}
- const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
+ const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(conv.settings.cylindricalTessellation * 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;
@@ -282,7 +282,7 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
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];
+ 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);
@@ -305,8 +305,8 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
for(size_t i = 0; i < size; ++i ) {
out.push_back(out[i*4]);
}
- result.vertcnt.push_back(size);
- result.vertcnt.push_back(size);
+ result.vertcnt.push_back(static_cast<unsigned int>(size));
+ result.vertcnt.push_back(static_cast<unsigned int>(size));
}
IfcMatrix4 trafo;
@@ -327,7 +327,7 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
return;
}
- const unsigned int cnt_segments = 16;
+ const unsigned int cnt_segments = conv.settings.cylindricalTessellation;
const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments;
const size_t samples = curve->EstimateSampleCount(solid.StartParam,solid.EndParam);
@@ -638,7 +638,7 @@ void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curv
out.push_back(in[i]);
}
- curmesh.vertcnt.push_back(in.size());
+ curmesh.vertcnt.push_back(static_cast<unsigned int>(in.size()));
if( openings && in.size() > 2 ) {
if( GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
++sides_with_v_openings;
@@ -665,7 +665,7 @@ void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curv
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());
+ profile2D->vertcnt.push_back(static_cast<unsigned int>(in.size()));
conv.collect_openings->push_back(TempOpening(&solid, dir, profile, profile2D));
ai_assert(result.IsEmpty());
@@ -810,7 +810,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid,
aiMesh* const mesh = meshtmp->ToMesh();
if(mesh) {
mesh->mMaterialIndex = matid;
- mesh_indices.push_back(conv.meshes.size());
+ mesh_indices.push_back(static_cast<unsigned int>(conv.meshes.size()));
conv.meshes.push_back(mesh);
return true;
}
@@ -827,9 +827,8 @@ void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,
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);
+ nd->mNumMeshes = static_cast<unsigned int>(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];
diff --git a/src/3rdparty/assimp/code/IFCLoader.cpp b/src/3rdparty/assimp/code/IFCLoader.cpp
index 34977f5b0..85382d467 100644
--- a/src/3rdparty/assimp/code/IFCLoader.cpp
+++ b/src/3rdparty/assimp/code/IFCLoader.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -58,14 +59,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IFCUtil.h"
-#include "StreamReader.h"
#include "MemoryIOWrapper.h"
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
+#include <assimp/importerdesc.h>
namespace Assimp {
- template<> const std::string LogFunctions<IFCImporter>::log_prefix = "IFC: ";
+ template<> const char* LogFunctions<IFCImporter>::Prefix()
+ {
+ static auto prefix = "IFC: ";
+ return prefix;
+ }
}
using namespace Assimp;
@@ -108,7 +113,7 @@ static const aiImporterDesc desc = {
0,
0,
0,
- "ifc ifczip"
+ "ifc ifczip stp"
};
@@ -128,11 +133,9 @@ IFCImporter::~IFCImporter()
bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string& extension = GetExtension(pFile);
- if (extension == "ifc" || extension == "ifczip") {
+ if (extension == "ifc" || extension == "ifczip" || extension == "stp" ) {
return true;
- }
-
- else if ((!extension.length() || checkSig) && pIOHandler) {
+ } 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.
@@ -155,11 +158,10 @@ const aiImporterDesc* IFCImporter::GetInfo () const
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.conicSamplingAngle = 10.f;
- settings.skipAnnotations = true;
+ settings.conicSamplingAngle = std::min(std::max((float) pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f);
+ settings.cylindricalTessellation = std::min(std::max(pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION, AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION), 3), 180);
+ settings.skipAnnotations = true;
}
@@ -707,15 +709,11 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
}
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));
-
+ aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(properties.size()) );
+ unsigned int index( 0 );
+ for ( const Metadata::value_type& kv : properties ) {
+ data->Set( index++, kv.first, aiString( kv.second ) );
+ }
nd->mMetaData = data;
}
}
@@ -888,6 +886,7 @@ void ProcessSpatialStructures(ConversionData& conv)
}
}
+ std::vector<aiNode*> nodes;
for(const STEP::LazyObject* lz : *range) {
const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
@@ -896,20 +895,19 @@ void ProcessSpatialStructures(ConversionData& conv)
}
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
+ // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them 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>()) {
+ STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID());
+ for(; ref_range.first != ref_range.second; ++ref_range.first) {
+ if(const IfcRelAggregates* const aggr = conv.db.GetObject((*ref_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;
+ // got it, this is one primary site.
+ nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
}
}
@@ -917,19 +915,42 @@ void ProcessSpatialStructures(ConversionData& conv)
}
}
+ size_t nb_nodes = nodes.size();
- 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;
- }
+ if (nb_nodes == 0) {
+ IFCImporter::LogWarn("failed to determine primary site element, taking all the 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;
- }
+ nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
+ }
+
+ nb_nodes = nodes.size();
+ }
+
+ if (nb_nodes == 1) {
+ conv.out->mRootNode = nodes[0];
+ }
+ else if (nb_nodes > 1) {
+ conv.out->mRootNode = new aiNode("Root");
+ conv.out->mRootNode->mParent = NULL;
+ conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
+ conv.out->mRootNode->mChildren = new aiNode*[conv.out->mRootNode->mNumChildren];
+
+ for (size_t i = 0; i < nb_nodes; ++i) {
+ aiNode* node = nodes[i];
+
+ node->mParent = conv.out->mRootNode;
- IFCImporter::ThrowException("failed to determine primary site element");
+ conv.out->mRootNode->mChildren[i] = node;
+ }
+ }
+ else {
+ IFCImporter::ThrowException("failed to determine primary site element");
+ }
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/IFCLoader.h b/src/3rdparty/assimp/code/IFCLoader.h
index e301a329d..4cf116f8e 100644
--- a/src/3rdparty/assimp/code/IFCLoader.h
+++ b/src/3rdparty/assimp/code/IFCLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -107,18 +108,18 @@ public:
{
Settings()
: skipSpaceRepresentations()
- , skipCurveRepresentations()
, useCustomTriangulation()
, skipAnnotations()
, conicSamplingAngle(10.f)
+ , cylindricalTessellation(32)
{}
bool skipSpaceRepresentations;
- bool skipCurveRepresentations;
bool useCustomTriangulation;
bool skipAnnotations;
float conicSamplingAngle;
+ int cylindricalTessellation;
};
diff --git a/src/3rdparty/assimp/code/IFCMaterial.cpp b/src/3rdparty/assimp/code/IFCMaterial.cpp
index 7525db089..aa11c5c22 100644
--- a/src/3rdparty/assimp/code/IFCMaterial.cpp
+++ b/src/3rdparty/assimp/code/IFCMaterial.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,19 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of conversion routines to convert IFC materials to aiMaterial
*/
-
-
#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)
-{
+static int ConvertShadingMode(const std::string& name) {
if (name == "BLINN") {
return aiShadingMode_Blinn;
}
@@ -69,8 +68,7 @@ int ConvertShadingMode(const std::string& name)
}
// ------------------------------------------------------------------------------------------------
-void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionData& conv)
-{
+static 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);
@@ -134,8 +132,7 @@ void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionDat
}
// ------------------------------------------------------------------------------------------------
-unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat)
-{
+unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat) {
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>()) {
@@ -159,34 +156,36 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
FillMaterial(mat.get(), surf, conv);
conv.materials.push_back(mat.release());
- unsigned int matindex = conv.materials.size() - 1;
+ unsigned int matindex = static_cast<unsigned int>(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() )
+ 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 )
+ 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 )
- {
+ 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;
+ if ( name == mname ) {
+ return ( unsigned int )a;
+ }
}
// we're here, yet - no default material with suitable color available. Generate one
@@ -203,4 +202,4 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
} // ! IFC
} // ! Assimp
-#endif
+#endif // ASSIMP_BUILD_NO_IFC_IMPORTER
diff --git a/src/3rdparty/assimp/code/IFCOpenings.cpp b/src/3rdparty/assimp/code/IFCOpenings.cpp
index 51ea14314..4d57cd473 100644
--- a/src/3rdparty/assimp/code/IFCOpenings.cpp
+++ b/src/3rdparty/assimp/code/IFCOpenings.cpp
@@ -364,7 +364,7 @@ void InsertWindowContours(const ContourVector& contours,
}
if (const size_t d = curmesh.verts.size()-old) {
- curmesh.vertcnt.push_back(d);
+ curmesh.vertcnt.push_back(static_cast<unsigned int>(d));
std::reverse(curmesh.verts.rbegin(),curmesh.verts.rbegin()+d);
}
if (n == very_first_hit) {
@@ -549,7 +549,7 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
clipper.Execute(ClipperLib::ctIntersection,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
for(const ClipperLib::ExPolygon& ex : clipped) {
- iold.push_back(ex.outer.size());
+ iold.push_back(static_cast<unsigned int>(ex.outer.size()));
for(const ClipperLib::IntPoint& point : ex.outer) {
vold.push_back(IfcVector3(
from_int64(point.X),
@@ -715,14 +715,14 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
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()];
+ 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()];
+ const IfcVector2 m0 = mcontour[m];
+ const IfcVector2 m1 = mcontour[(m+1) % mcontour.size()];
IfcVector2 isect0, isect1;
if (IntersectingLineSegments(n0,n1, m0, m1, isect0, isect1)) {
@@ -901,13 +901,21 @@ size_t CloseWindows(ContourVector& contours,
curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4);
curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size());
+ bool reverseCountourFaces = false;
+
// 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;
+ if(curmesh.vertcnt.size() > 0) {
+ 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());
+
+ reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0;
+ }
// XXX this algorithm is really a bit inefficient - both in terms
// of constant factor and of asymptotic runtime.
@@ -1484,14 +1492,14 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
vmax -= vmin;
// If this happens then the projection must have been wrong.
- assert(vmax.Length());
+ ai_assert(vmax.Length());
ClipperLib::ExPolygons clipped;
ClipperLib::Polygons holes_union;
IfcVector3 wall_extrusion;
- bool do_connections = false, first = true;
+ bool first = true;
try {
@@ -1519,7 +1527,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
if (first) {
first = false;
if (dot > 0.f) {
- do_connections = true;
wall_extrusion = t.extrusionDir;
if (is_extruded_side) {
wall_extrusion = - wall_extrusion;
@@ -1599,44 +1606,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
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) {
@@ -1697,7 +1666,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
static_cast<IfcFloat>( tri->GetPoint(i)->y )
);
- assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0);
+ ai_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);
diff --git a/src/3rdparty/assimp/code/IFCProfile.cpp b/src/3rdparty/assimp/code/IFCProfile.cpp
index 01b9008e4..595159a6b 100644
--- a/src/3rdparty/assimp/code/IFCProfile.cpp
+++ b/src/3rdparty/assimp/code/IFCProfile.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -59,7 +60,7 @@ void ProcessPolyLine(const IfcPolyline& def, TempMesh& meshout, ConversionData&
ConvertCartesianPoint(t,cp);
meshout.verts.push_back(t);
}
- meshout.vertcnt.push_back(meshout.verts.size());
+ meshout.vertcnt.push_back(static_cast<unsigned int>(meshout.verts.size()));
}
// ------------------------------------------------------------------------------------------------
@@ -80,7 +81,7 @@ bool ProcessCurve(const IfcCurve& curve, TempMesh& meshout, ConversionData& con
IFCImporter::LogError(cv.s+ " (error occurred while processing curve)");
return false;
}
- meshout.vertcnt.push_back(meshout.verts.size());
+ meshout.vertcnt.push_back(static_cast<unsigned int>(meshout.verts.size()));
return true;
}
@@ -101,7 +102,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout
}
// ------------------------------------------------------------------------------------------------
-void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
+void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
{
if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
@@ -117,7 +118,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
if(def.ToPtr<IfcCircleHollowProfileDef>()) {
// TODO
}
- const size_t segments = 32;
+ const size_t segments = conv.settings.cylindricalTessellation;
const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius;
meshout.verts.reserve(segments);
@@ -127,7 +128,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
}
- meshout.vertcnt.push_back(segments);
+ meshout.vertcnt.push_back(static_cast<unsigned int>(segments));
}
else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) {
// construct simplified IBeam shape
diff --git a/src/3rdparty/assimp/code/IFCReaderGen1.cpp b/src/3rdparty/assimp/code/IFCReaderGen1.cpp
index 0377be5d7..bd526d454 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,3233 +50,3115 @@ using namespace IFC;
namespace {
- 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 )
+ 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);
+ out = EXPRESS::ConversionSchema(schema_raw);
}
namespace STEP {
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
+template <> size_t GenericFill<NotImplemented>(const STEP::DB& /*db*/, const LIST& /*params*/, NotImplemented* /*in*/)
{
- return 0;
+ 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
+ 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
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
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
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;
-}
-// -----------------------------------------------------------------------------------------------------------
-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
- 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<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<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<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;
+ 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));
+ 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<IfcTypeProduct>(const DB& db, const LIST& params, IfcTypeProduct* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeObject*>(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<IfcElementType>(const DB& db, const LIST& params, IfcElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(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<IfcDistributionElementType>(const DB& db, const LIST& params, IfcDistributionElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(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<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<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;
+ 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));
+ 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<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<IfcAirTerminalBoxType>(const DB& db, const LIST& params, IfcAirTerminalBoxType* in)
+template <> size_t GenericFill<IfcElectricTimeControlType>(const DB& db, const LIST& params, IfcElectricTimeControlType* 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<IfcFlowTerminalType>(const DB& db, const LIST& params, IfcFlowTerminalType* in)
+template <> size_t GenericFill<IfcRepresentation>(const DB& db, const LIST& params, IfcRepresentation* 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 = 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<IfcAirTerminalType>(const DB& db, const LIST& params, IfcAirTerminalType* in)
+template <> size_t GenericFill<IfcShapeModel>(const DB& db, const LIST& params, IfcShapeModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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<IfcEnergyConversionDeviceType>(const DB& db, const LIST& params, IfcEnergyConversionDeviceType* in)
+template <> size_t GenericFill<IfcTopologyRepresentation>(const DB& db, const LIST& params, IfcTopologyRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(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<IfcAirToAirHeatRecoveryType>(const DB& db, const LIST& params, IfcAirToAirHeatRecoveryType* in)
+template <> size_t GenericFill<IfcRelationship>(const DB& db, const LIST& params, IfcRelationship* 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<IfcRoot*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRelationship"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAlarmType>(const DB& db, const LIST& params, IfcAlarmType* in)
+template <> size_t GenericFill<IfcRelConnects>(const DB& db, const LIST& params, IfcRelConnects* 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;
+ 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<IfcDraughtingCallout>(const DB& db, const LIST& params, IfcDraughtingCallout* in)
+template <> size_t GenericFill<IfcFlowFittingType>(const DB& db, const LIST& params, IfcFlowFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcDimensionCurveDirectedCallout>(const DB& db, const LIST& params, IfcDimensionCurveDirectedCallout* in)
+template <> size_t GenericFill<IfcCableCarrierFittingType>(const DB& db, const LIST& params, IfcCableCarrierFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDraughtingCallout*>(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<IfcAngularDimension>(const DB& db, const LIST& params, IfcAngularDimension* in)
+template <> size_t GenericFill<IfcEnergyConversionDeviceType>(const DB& db, const LIST& params, IfcEnergyConversionDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(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<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
- 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; }
- 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
- 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; }
- 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<IfcAnnotation>(const DB& db, const LIST& params, IfcAnnotation* in)
+template <> size_t GenericFill<IfcCoilType>(const DB& db, const LIST& params, IfcCoilType* 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<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<IfcStyledItem>(const DB& db, const LIST& params, IfcStyledItem* in)
+template <> size_t GenericFill<IfcObject>(const DB& db, const LIST& params, IfcObject* 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
+ 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::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
- 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);
- 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 ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcObject,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 2 to IfcStyledItem to be a `IfcLabel`")); }
+ 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;
+ 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<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<IfcAnnotationFillArea>(const DB& db, const LIST& params, IfcAnnotationFillArea* in)
+template <> size_t GenericFill<IfcControl>(const DB& db, const LIST& params, IfcControl* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcAnnotationFillAreaOccurrence>(const DB& db, const LIST& params, IfcAnnotationFillAreaOccurrence* in)
+template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST& params, IfcPerformanceHistory* 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<IfcAnnotationSurface>(const DB& db, const LIST& params, IfcAnnotationSurface* in)
+template <> size_t GenericFill<IfcRepresentationItem>(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*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 = 0;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationSurfaceOccurrence>(const DB& db, const LIST& params, IfcAnnotationSurfaceOccurrence* in)
+template <> size_t GenericFill<IfcGeometricRepresentationItem>(const DB& db, const LIST& params, IfcGeometricRepresentationItem* 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;
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationSymbolOccurrence>(const DB& db, const LIST& params, IfcAnnotationSymbolOccurrence* in)
+template <> size_t GenericFill<IfcTextLiteral>(const DB& db, const LIST& params, IfcTextLiteral* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(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<IfcAnnotationTextOccurrence>(const DB& db, const LIST& params, IfcAnnotationTextOccurrence* 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<IfcProfileDef>(const DB& db, const LIST& params, IfcProfileDef* in)
+template <> size_t GenericFill<IfcProductRepresentation>(const DB& db, const LIST& params, IfcProductRepresentation* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProfileDef"); } do { // convert the 'ProfileType' argument
+ 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::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`")); }
+ 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 'ProfileName' argument
+ do { // convert the 'Description' 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 ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::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`")); }
+ 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);
- 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
+ do { // convert the 'Representations' 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`")); }
+ 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<IfcArbitraryOpenProfileDef>(const DB& db, const LIST& params, IfcArbitraryOpenProfileDef* in)
+template <> size_t GenericFill<IfcProduct>(const DB& db, const LIST& params, IfcProduct* 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
+ 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::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`")); }
+ 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
+ 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; }
+ 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<IfcArbitraryProfileDefWithVoids>(const DB& db, const LIST& params, IfcArbitraryProfileDefWithVoids* in)
+template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, IfcElement* in)
{
- 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
+ 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++];
- 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGroup>(const DB& db, const LIST& params, IfcGroup* in)
+template <> size_t GenericFill<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(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<IfcAsset>(const DB& db, const LIST& params, IfcAsset* in)
+template <> size_t GenericFill<IfcDistributionFlowElement>(const DB& db, const LIST& params, IfcDistributionFlowElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(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<IfcParameterizedProfileDef>(const DB& db, const LIST& params, IfcParameterizedProfileDef* in)
+template <> size_t GenericFill<IfcCurve>(const DB& db, const LIST& params, IfcCurve* 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;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcIShapeProfileDef>(const DB& db, const LIST& params, IfcIShapeProfileDef* in)
+template <> size_t GenericFill<IfcBoundedCurve>(const DB& db, const LIST& params, IfcBoundedCurve* 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
+ 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::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`")); }
+ 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 'FilletRadius' argument
+ do { // convert the 'SelfIntersect' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAsymmetricIShapeProfileDef>(const DB& db, const LIST& params, IfcAsymmetricIShapeProfileDef* in)
+template <> size_t GenericFill<Ifc2DCompositeCurve>(const DB& db, const LIST& params, Ifc2DCompositeCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcIShapeProfileDef*>(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<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
- 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator>(const DB& db, const LIST& params, IfcCartesianTransformationOperator* 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
+ 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->Axis, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis1Placement to be a `IfcDirection`")); }
+ 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);
- 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
+ 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->RefDirection, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement2D to be a `IfcDirection`")); }
+ 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);
- 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
+ do { // convert the 'LocalOrigin' 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`")); }
+ 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 'RefDirection' argument
+ 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->RefDirection, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcAxis2Placement3D to be a `IfcDirection`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBSplineCurve>(const DB& db, const LIST& params, IfcBSplineCurve* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator3D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3D* 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);
- do { // convert the 'SelfIntersect' argument
+ 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::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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, IfcElement* in)
+template <> size_t GenericFill<IfcProperty>(const DB& db, const LIST& params, IfcProperty* 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
+ 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::IfcElement,1>::aux_is_derived[0]=true; break; }
+ 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->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->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<IfcBuildingElement>(const DB& db, const LIST& params, IfcBuildingElement* in)
+template <> size_t GenericFill<IfcSimpleProperty>(const DB& db, const LIST& params, IfcSimpleProperty* 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<IfcProperty*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcSimpleProperty"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBeam>(const DB& db, const LIST& params, IfcBeam* in)
+template <> size_t GenericFill<IfcPropertyEnumeratedValue>(const DB& db, const LIST& params, IfcPropertyEnumeratedValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcBuildingElementType>(const DB& db, const LIST& params, IfcBuildingElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(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<IfcStairFlightType>(const DB& db, const LIST& params, IfcStairFlightType* 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<IfcBezierCurve>(const DB& db, const LIST& params, IfcBezierCurve* in)
+template <> size_t GenericFill<IfcSurface>(const DB& db, const LIST& params, IfcSurface* 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;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCsgPrimitive3D>(const DB& db, const LIST& params, IfcCsgPrimitive3D* in)
+template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& params, IfcElementarySurface* 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<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<IfcBlock>(const DB& db, const LIST& params, IfcBlock* in)
+template <> size_t GenericFill<IfcPlane>(const DB& db, const LIST& params, IfcPlane* 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<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;
+ 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
+ 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; }
+ 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; }
+ 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; }
+ 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;
+ 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;
+ 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<IfcSurface>(const DB& db, const LIST& params, IfcSurface* in)
+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<IfcGeometricRepresentationItem*>(in));
- return base;
+ 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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBoundedSurface>(const DB& db, const LIST& params, IfcBoundedSurface* in)
+template <> size_t GenericFill<IfcFlowTerminalType>(const DB& db, const LIST& params, IfcFlowTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSurface*>(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<IfcBoundingBox>(const DB& db, const LIST& params, IfcBoundingBox* in)
+template <> size_t GenericFill<IfcStackTerminalType>(const DB& db, const LIST& params, IfcStackTerminalType* 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
- 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 '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;
+ 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<IfcHalfSpaceSolid>(const DB& db, const LIST& params, IfcHalfSpaceSolid* in)
+template <> size_t GenericFill<IfcStructuralItem>(const DB& db, const LIST& params, IfcStructuralItem* 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
- 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;
+ 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<IfcBoxedHalfSpace>(const DB& db, const LIST& params, IfcBoxedHalfSpace* in)
+template <> size_t GenericFill<IfcStructuralConnection>(const DB& db, const LIST& params, IfcStructuralConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcHalfSpaceSolid*>(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<IfcSpatialStructureElement>(const DB& db, const LIST& params, IfcSpatialStructureElement* in)
+template <> size_t GenericFill<IfcStructuralCurveConnection>(const DB& db, const LIST& params, IfcStructuralCurveConnection* 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
- 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;
+ 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<IfcBuilding>(const DB& db, const LIST& params, IfcBuilding* in)
+template <> size_t GenericFill<IfcJunctionBoxType>(const DB& db, const LIST& params, IfcJunctionBoxType* 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
- 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
+ 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
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`")); }
+ 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 'BuildingAddress' argument
+ do { // convert the 'RelatedBuildingElement' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElementComponent>(const DB& db, const LIST& params, IfcBuildingElementComponent* in)
+template <> size_t GenericFill<IfcProcedure>(const DB& db, const LIST& params, IfcProcedure* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcBuildingElementPart>(const DB& db, const LIST& params, IfcBuildingElementPart* in)
+template <> size_t GenericFill<IfcProxy>(const DB& db, const LIST& params, IfcProxy* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementComponent*>(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<IfcBuildingElementProxy>(const DB& db, const LIST& params, IfcBuildingElementProxy* in)
+template <> size_t GenericFill<IfcResource>(const DB& db, const LIST& params, IfcResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcBuildingElementProxyType>(const DB& db, const LIST& params, IfcBuildingElementProxyType* in)
+template <> size_t GenericFill<IfcConstructionResource>(const DB& db, const LIST& params, IfcConstructionResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(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<IfcBuildingStorey>(const DB& db, const LIST& params, IfcBuildingStorey* in)
+template <> size_t GenericFill<IfcSubContractResource>(const DB& db, const LIST& params, IfcSubContractResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(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<IfcCShapeProfileDef>(const DB& db, const LIST& params, IfcCShapeProfileDef* in)
+template <> size_t GenericFill<IfcRelContainedInSpatialStructure>(const DB& db, const LIST& params, IfcRelContainedInSpatialStructure* 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<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<IfcFlowFittingType>(const DB& db, const LIST& params, IfcFlowFittingType* in)
+template <> size_t GenericFill<IfcTopologicalRepresentationItem>(const DB& db, const LIST& params, IfcTopologicalRepresentationItem* 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<IfcRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCableCarrierFittingType>(const DB& db, const LIST& params, IfcCableCarrierFittingType* 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<IfcFlowSegmentType>(const DB& db, const LIST& params, IfcFlowSegmentType* in)
+template <> size_t GenericFill<IfcEdgeCurve>(const DB& db, const LIST& params, IfcEdgeCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(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<IfcCableCarrierSegmentType>(const DB& db, const LIST& params, IfcCableCarrierSegmentType* in)
+template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, IfcPlateType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(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<IfcCableSegmentType>(const DB& db, const LIST& params, IfcCableSegmentType* in)
+template <> size_t GenericFill<IfcObjectPlacement>(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPoint>(const DB& db, const LIST& params, IfcPoint* in)
+template <> size_t GenericFill<IfcFireSuppressionTerminalType>(const DB& db, const LIST& params, IfcFireSuppressionTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- 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<IfcCartesianPoint>(const DB& db, const LIST& params, IfcCartesianPoint* in)
+template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& params, IfcFlowStorageDevice* 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
- 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;
+ 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<IfcCartesianTransformationOperator>(const DB& db, const LIST& params, IfcCartesianTransformationOperator* in)
+template <> size_t GenericFill<IfcSweptSurface>(const DB& db, const LIST& params, IfcSweptSurface* 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
- 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);
- 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;
+ 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<IfcCartesianTransformationOperator2D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2D* in)
+template <> size_t GenericFill<IfcSurfaceOfRevolution>(const DB& db, const LIST& params, IfcSurfaceOfRevolution* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator*>(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<IfcCartesianTransformationOperator2DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2DnonUniform* in)
+template <> size_t GenericFill<IfcOrientedEdge>(const DB& db, const LIST& params, IfcOrientedEdge* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator2D*>(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<IfcCartesianTransformationOperator3D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3D* in)
+template <> size_t GenericFill<IfcDirection>(const DB& db, const LIST& params, IfcDirection* 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
+ 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++];
- 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`")); }
+ 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<IfcCartesianTransformationOperator3DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3DnonUniform* in)
+template <> size_t GenericFill<IfcProfileDef>(const DB& db, const LIST& params, IfcProfileDef* 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
+ 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 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`")); }
+ 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 'Scale3' argument
+ 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->Scale3, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcCartesianTransformationOperator3DnonUniform 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;
+}
+// -----------------------------------------------------------------------------------------------------------
+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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCenterLineProfileDef>(const DB& db, const LIST& params, IfcCenterLineProfileDef* in)
+template <> size_t GenericFill<IfcCShapeProfileDef>(const DB& db, const LIST& params, IfcCShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcArbitraryOpenProfileDef*>(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<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<IfcChillerType>(const DB& db, const LIST& params, IfcChillerType* in)
+template <> size_t GenericFill<IfcBuildingElement>(const DB& db, const LIST& params, IfcBuildingElement* 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<IfcElement*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcBuildingElement"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcConic* in)
+template <> size_t GenericFill<IfcColumn>(const DB& db, const LIST& params, IfcColumn* 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
- 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;
+ 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<IfcCircle>(const DB& db, const LIST& params, IfcCircle* in)
+template <> size_t GenericFill<IfcPropertyReferenceValue>(const DB& db, const LIST& params, IfcPropertyReferenceValue* 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
- 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;
+ 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<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* in)
+template <> size_t GenericFill<IfcElectricMotorType>(const DB& db, const LIST& params, IfcElectricMotorType* 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
- 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;
+ 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<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* in)
+template <> size_t GenericFill<IfcSpatialStructureElementType>(const DB& db, const LIST& params, IfcSpatialStructureElementType* 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
- 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;
+ 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<IfcTopologicalRepresentationItem>(const DB& db, const LIST& params, IfcTopologicalRepresentationItem* in)
+template <> size_t GenericFill<IfcSpaceType>(const DB& db, const LIST& params, IfcSpaceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
- return base;
+ 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<IfcConnectedFaceSet>(const DB& db, const LIST& params, IfcConnectedFaceSet* in)
+template <> size_t GenericFill<IfcColumnType>(const DB& db, const LIST& params, IfcColumnType* 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
- 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;
+ 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<IfcClosedShell>(const DB& db, const LIST& params, IfcClosedShell* in)
+template <> size_t GenericFill<IfcCraneRailAShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailAShapeProfileDef* 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;
+ 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<IfcCoilType>(const DB& db, const LIST& params, IfcCoilType* in)
+template <> size_t GenericFill<IfcCondenserType>(const DB& db, const LIST& params, IfcCondenserType* 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<IfcColourSpecification>(const DB& db, const LIST& params, IfcColourSpecification* in)
+template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcColourSpecification"); } do { // convert the 'Name' argument
+ 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::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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcColourRgb>(const DB& db, const LIST& params, IfcColourRgb* in)
+template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* 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
- 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);
- do { // convert the 'Blue' argument
+ 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->Blue, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
+ 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;
+ 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<IfcColumnType>(const DB& db, const LIST& params, IfcColumnType* in)
+template <> size_t GenericFill<IfcPlacement>(const DB& db, const LIST& params, IfcPlacement* 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<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<IfcProperty>(const DB& db, const LIST& params, IfcProperty* in)
+template <> size_t GenericFill<IfcAxis2Placement3D>(const DB& db, const LIST& params, IfcAxis2Placement3D* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProperty"); } do { // convert the 'Name' argument
+ 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 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`")); }
+ 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 'Description' argument
+ do { // convert the 'RefDirection' 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->Description, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProperty to be a `IfcText`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcComplexProperty>(const DB& db, const LIST& params, IfcComplexProperty* in)
+template <> size_t GenericFill<IfcPresentationStyle>(const DB& db, const LIST& params, IfcPresentationStyle* 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
+ 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++];
- 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`")); }
+ 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;
+ 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
+ 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; }
+ 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
std::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->SameSense, arg, db ); break; }
+ 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
std::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ParentCurve, arg, db ); break; }
+ 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<IfcCompositeProfileDef>(const DB& db, const LIST& params, IfcCompositeProfileDef* in)
+template <> size_t GenericFill<IfcRectangleProfileDef>(const DB& db, const LIST& params, IfcRectangleProfileDef* 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;
+ 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 '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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowMovingDeviceType>(const DB& db, const LIST& params, IfcFlowMovingDeviceType* in)
+template <> size_t GenericFill<IfcBuildingElementProxy>(const DB& db, const LIST& params, IfcBuildingElementProxy* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(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<IfcCompressorType>(const DB& db, const LIST& params, IfcCompressorType* in)
+template <> size_t GenericFill<IfcDistributionControlElementType>(const DB& db, const LIST& params, IfcDistributionControlElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(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<IfcCondenserType>(const DB& db, const LIST& params, IfcCondenserType* in)
+template <> size_t GenericFill<IfcFlowInstrumentType>(const DB& db, const LIST& params, IfcFlowInstrumentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcCondition>(const DB& db, const LIST& params, IfcCondition* in)
+template <> size_t GenericFill<IfcDraughtingCallout>(const DB& db, const LIST& params, IfcDraughtingCallout* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(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<IfcConditionCriterion>(const DB& db, const LIST& params, IfcConditionCriterion* in)
+template <> size_t GenericFill<IfcDimensionCurveDirectedCallout>(const DB& db, const LIST& params, IfcDimensionCurveDirectedCallout* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcResource>(const DB& db, const LIST& params, IfcResource* in)
+template <> size_t GenericFill<IfcLinearDimension>(const DB& db, const LIST& params, IfcLinearDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(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<IfcConstructionResource>(const DB& db, const LIST& params, IfcConstructionResource* in)
+template <> size_t GenericFill<IfcElementAssembly>(const DB& db, const LIST& params, IfcElementAssembly* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcResource*>(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<IfcConstructionEquipmentResource>(const DB& db, const LIST& params, IfcConstructionEquipmentResource* in)
+template <> size_t GenericFill<IfcCsgPrimitive3D>(const DB& db, const LIST& params, IfcCsgPrimitive3D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(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<IfcRightCircularCone>(const DB& db, const LIST& params, IfcRightCircularCone* 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<IfcConstructionProductResource>(const DB& db, const LIST& params, IfcConstructionProductResource* in)
+template <> size_t GenericFill<IfcProjectOrder>(const DB& db, const LIST& params, IfcProjectOrder* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(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<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
- 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcContextDependentUnit>(const DB& db, const LIST& params, IfcContextDependentUnit* in)
+template <> size_t GenericFill<IfcLShapeProfileDef>(const DB& db, const LIST& params, IfcLShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcControllerType>(const DB& db, const LIST& params, IfcControllerType* in)
+template <> size_t GenericFill<IfcAngularDimension>(const DB& db, const LIST& params, IfcAngularDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(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<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* in)
+template <> size_t GenericFill<IfcLocalPlacement>(const DB& db, const LIST& params, IfcLocalPlacement* 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
+ 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++];
- 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`")); }
+ 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 'ConversionFactor' argument
+ do { // convert the 'RelativePlacement' 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`")); }
+ 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<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<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<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<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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCovering>(const DB& db, const LIST& params, IfcCovering* in)
+template <> size_t GenericFill<IfcSweptAreaSolid>(const DB& db, const LIST& params, IfcSweptAreaSolid* 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<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 '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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCoveringType>(const DB& db, const LIST& params, IfcCoveringType* in)
+template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* 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<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 '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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCraneRailAShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailAShapeProfileDef* in)
+template <> size_t GenericFill<IfcStructuralSurfaceConnection>(const DB& db, const LIST& params, IfcStructuralSurfaceConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcCraneRailFShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailFShapeProfileDef* in)
+template <> size_t GenericFill<IfcRadiusDimension>(const DB& db, const LIST& params, IfcRadiusDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcCrewResource>(const DB& db, const LIST& params, IfcCrewResource* in)
+template <> size_t GenericFill<IfcSweptDiskSolid>(const DB& db, const LIST& params, IfcSweptDiskSolid* 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<IfcSolidModel>(const DB& db, const LIST& params, IfcSolidModel* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- 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<IfcCsgSolid>(const DB& db, const LIST& params, IfcCsgSolid* in)
+template <> size_t GenericFill<IfcHalfSpaceSolid>(const DB& db, const LIST& params, IfcHalfSpaceSolid* 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;
+ 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<IfcCurtainWall>(const DB& db, const LIST& params, IfcCurtainWall* in)
+template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const LIST& params, IfcPolygonalBoundedHalfSpace* 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<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 '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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCurtainWallType>(const DB& db, const LIST& params, IfcCurtainWallType* in)
+template <> size_t GenericFill<IfcTimeSeriesSchedule>(const DB& db, const LIST& params, IfcTimeSeriesSchedule* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(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<IfcCurveBoundedPlane>(const DB& db, const LIST& params, IfcCurveBoundedPlane* in)
+template <> size_t GenericFill<IfcCooledBeamType>(const DB& db, const LIST& params, IfcCooledBeamType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedSurface*>(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<IfcPresentationStyle>(const DB& db, const LIST& params, IfcPresentationStyle* in)
+template <> size_t GenericFill<IfcProject>(const DB& db, const LIST& params, IfcProject* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPresentationStyle"); } do { // convert the 'Name' argument
+ 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 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`")); }
+ 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);
- return base;
+ 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<IfcDamperType>(const DB& db, const LIST& params, IfcDamperType* in)
+template <> size_t GenericFill<IfcEvaporatorType>(const DB& db, const LIST& params, IfcEvaporatorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(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<IfcLaborResource>(const DB& db, const LIST& params, IfcLaborResource* 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<IfcDerivedProfileDef>(const DB& db, const LIST& params, IfcDerivedProfileDef* in)
+template <> size_t GenericFill<IfcPropertyBoundedValue>(const DB& db, const LIST& params, IfcPropertyBoundedValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(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<IfcDiameterDimension>(const DB& db, const LIST& params, IfcDiameterDimension* in)
+template <> size_t GenericFill<IfcRampFlightType>(const DB& db, const LIST& params, IfcRampFlightType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(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<IfcDimensionCurve>(const DB& db, const LIST& params, IfcDimensionCurve* in)
+template <> size_t GenericFill<IfcMember>(const DB& db, const LIST& params, IfcMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationCurveOccurrence*>(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<IfcTerminatorSymbol>(const DB& db, const LIST& params, IfcTerminatorSymbol* in)
+template <> size_t GenericFill<IfcTubeBundleType>(const DB& db, const LIST& params, IfcTubeBundleType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationSymbolOccurrence*>(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<IfcDimensionCurveTerminator>(const DB& db, const LIST& params, IfcDimensionCurveTerminator* in)
+template <> size_t GenericFill<IfcValveType>(const DB& db, const LIST& params, IfcValveType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTerminatorSymbol*>(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<IfcDirection>(const DB& db, const LIST& params, IfcDirection* in)
+template <> size_t GenericFill<IfcTrimmedCurve>(const DB& db, const LIST& params, IfcTrimmedCurve* 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
+ 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->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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementComponent>(const DB& db, const LIST& params, IfcElementComponent* in)
+template <> size_t GenericFill<IfcRelDefines>(const DB& db, const LIST& params, IfcRelDefines* 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<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<IfcDiscreteAccessory>(const DB& db, const LIST& params, IfcDiscreteAccessory* in)
+template <> size_t GenericFill<IfcRelDefinesByProperties>(const DB& db, const LIST& params, IfcRelDefinesByProperties* 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;
+ 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<IfcElementComponentType>(const DB& db, const LIST& params, IfcElementComponentType* 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<IfcDiscreteAccessoryType>(const DB& db, const LIST& params, IfcDiscreteAccessoryType* in)
+template <> size_t GenericFill<IfcOccupant>(const DB& db, const LIST& params, IfcOccupant* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponentType*>(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<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* in)
+template <> size_t GenericFill<IfcHumidifierType>(const DB& db, const LIST& params, IfcHumidifierType* 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<IfcDistributionFlowElement>(const DB& db, const LIST& params, IfcDistributionFlowElement* in)
+template <> size_t GenericFill<IfcArbitraryOpenProfileDef>(const DB& db, const LIST& params, IfcArbitraryOpenProfileDef* 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;
+ 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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionChamberElement>(const DB& db, const LIST& params, IfcDistributionChamberElement* in)
+template <> size_t GenericFill<IfcPermit>(const DB& db, const LIST& params, IfcPermit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcDistributionChamberElementType>(const DB& db, const LIST& params, IfcDistributionChamberElementType* in)
+template <> size_t GenericFill<IfcOffsetCurve3D>(const DB& db, const LIST& params, IfcOffsetCurve3D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(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<IfcDistributionControlElement>(const DB& db, const LIST& params, IfcDistributionControlElement* in)
+template <> size_t GenericFill<IfcLightSource>(const DB& db, const LIST& params, IfcLightSource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionElement*>(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<IfcPort>(const DB& db, const LIST& params, IfcPort* in)
+template <> size_t GenericFill<IfcLightSourcePositional>(const DB& db, const LIST& params, IfcLightSourcePositional* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(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<IfcDistributionPort>(const DB& db, const LIST& params, IfcDistributionPort* in)
+template <> size_t GenericFill<IfcCompositeProfileDef>(const DB& db, const LIST& params, IfcCompositeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPort*>(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<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;
+ 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)
+template <> size_t GenericFill<IfcRamp>(const DB& db, const LIST& params, IfcRamp* 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<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<IfcDoorStyle>(const DB& db, const LIST& params, IfcDoorStyle* in)
+template <> size_t GenericFill<IfcFlowMovingDevice>(const DB& db, const LIST& params, IfcFlowMovingDevice* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(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<IfcDuctFittingType>(const DB& db, const LIST& params, IfcDuctFittingType* in)
+template <> size_t GenericFill<IfcSpaceHeaterType>(const DB& db, const LIST& params, IfcSpaceHeaterType* 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<IfcDuctSegmentType>(const DB& db, const LIST& params, IfcDuctSegmentType* in)
+template <> size_t GenericFill<IfcLampType>(const DB& db, const LIST& params, IfcLampType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(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<IfcFlowTreatmentDeviceType>(const DB& db, const LIST& params, IfcFlowTreatmentDeviceType* in)
+template <> size_t GenericFill<IfcBuildingElementComponent>(const DB& db, const LIST& params, IfcBuildingElementComponent* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(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<IfcDuctSilencerType>(const DB& db, const LIST& params, IfcDuctSilencerType* in)
+template <> size_t GenericFill<IfcReinforcingElement>(const DB& db, const LIST& params, IfcReinforcingElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTreatmentDeviceType*>(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<IfcEdge>(const DB& db, const LIST& params, IfcEdge* in)
+template <> size_t GenericFill<IfcReinforcingBar>(const DB& db, const LIST& params, IfcReinforcingBar* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(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<IfcEdgeCurve>(const DB& db, const LIST& params, IfcEdgeCurve* in)
+template <> size_t GenericFill<IfcElectricHeaterType>(const DB& db, const LIST& params, IfcElectricHeaterType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdge*>(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<IfcLoop>(const DB& db, const LIST& params, IfcLoop* in)
+template <> size_t GenericFill<IfcTShapeProfileDef>(const DB& db, const LIST& params, IfcTShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
- return base;
+ 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<IfcEdgeLoop>(const DB& db, const LIST& params, IfcEdgeLoop* in)
+template <> size_t GenericFill<IfcStructuralActivity>(const DB& db, const LIST& params, IfcStructuralActivity* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLoop*>(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<IfcElectricApplianceType>(const DB& db, const LIST& params, IfcElectricApplianceType* in)
+template <> size_t GenericFill<IfcStructuralAction>(const DB& db, const LIST& params, IfcStructuralAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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<IfcFlowController>(const DB& db, const LIST& params, IfcFlowController* in)
+template <> size_t GenericFill<IfcDuctFittingType>(const DB& db, const LIST& params, IfcDuctFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcElectricDistributionPoint>(const DB& db, const LIST& params, IfcElectricDistributionPoint* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator2D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowController*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowStorageDeviceType>(const DB& db, const LIST& params, IfcFlowStorageDeviceType* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator2DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2DnonUniform* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricFlowStorageDeviceType>(const DB& db, const LIST& params, IfcElectricFlowStorageDeviceType* in)
+template <> size_t GenericFill<IfcVirtualElement>(const DB& db, const LIST& params, IfcVirtualElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowStorageDeviceType*>(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<IfcElectricGeneratorType>(const DB& db, const LIST& params, IfcElectricGeneratorType* in)
+template <> size_t GenericFill<IfcRightCircularCylinder>(const DB& db, const LIST& params, IfcRightCircularCylinder* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcElectricHeaterType>(const DB& db, const LIST& params, IfcElectricHeaterType* in)
+template <> size_t GenericFill<IfcOutletType>(const DB& db, const LIST& params, IfcOutletType* 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<IfcElectricMotorType>(const DB& db, const LIST& params, IfcElectricMotorType* in)
+template <> size_t GenericFill<IfcRelDecomposes>(const DB& db, const LIST& params, IfcRelDecomposes* 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<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<IfcElectricTimeControlType>(const DB& db, const LIST& params, IfcElectricTimeControlType* in)
+template <> size_t GenericFill<IfcCovering>(const DB& db, const LIST& params, IfcCovering* 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<IfcSystem>(const DB& db, const LIST& params, IfcSystem* in)
+template <> size_t GenericFill<IfcPolyline>(const DB& db, const LIST& params, IfcPolyline* 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<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<IfcElectricalCircuit>(const DB& db, const LIST& params, IfcElectricalCircuit* in)
+template <> size_t GenericFill<IfcPath>(const DB& db, const LIST& params, IfcPath* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSystem*>(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<IfcElectricalElement>(const DB& db, const LIST& params, IfcElectricalElement* in)
+template <> size_t GenericFill<IfcElementComponent>(const DB& db, const LIST& params, IfcElementComponent* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(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<IfcElementAssembly>(const DB& db, const LIST& params, IfcElementAssembly* in)
+template <> size_t GenericFill<IfcFastener>(const DB& db, const LIST& params, IfcFastener* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(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<IfcElementQuantity>(const DB& db, const LIST& params, IfcElementQuantity* in)
+template <> size_t GenericFill<IfcMappedItem>(const DB& db, const LIST& params, IfcMappedItem* 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
+ 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++];
- 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`")); }
+ 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 'Quantities' argument
+ do { // convert the 'MappingTarget' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& params, IfcElementarySurface* in)
+template <> size_t GenericFill<IfcRectangularPyramid>(const DB& db, const LIST& params, IfcRectangularPyramid* 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;
+ 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<IfcEllipse>(const DB& db, const LIST& params, IfcEllipse* in)
+template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, IfcNamedUnit* 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
+ 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++];
- 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`")); }
+ 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 'SemiAxis2' argument
+ do { // convert the 'UnitType' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEllipseProfileDef>(const DB& db, const LIST& params, IfcEllipseProfileDef* in)
+template <> size_t GenericFill<IfcContextDependentUnit>(const DB& db, const LIST& params, IfcContextDependentUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcEnergyConversionDevice>(const DB& db, const LIST& params, IfcEnergyConversionDevice* in)
+template <> size_t GenericFill<IfcUnitaryEquipmentType>(const DB& db, const LIST& params, IfcUnitaryEquipmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcEquipmentElement>(const DB& db, const LIST& params, IfcEquipmentElement* in)
+template <> size_t GenericFill<IfcRoof>(const DB& db, const LIST& params, IfcRoof* 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<IfcEquipmentStandard>(const DB& db, const LIST& params, IfcEquipmentStandard* in)
+template <> size_t GenericFill<IfcStructuralMember>(const DB& db, const LIST& params, IfcStructuralMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcEvaporativeCoolerType>(const DB& db, const LIST& params, IfcEvaporativeCoolerType* in)
+template <> size_t GenericFill<IfcStyleModel>(const DB& db, const LIST& params, IfcStyleModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcEvaporatorType>(const DB& db, const LIST& params, IfcEvaporatorType* in)
+template <> size_t GenericFill<IfcStyledRepresentation>(const DB& db, const LIST& params, IfcStyledRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcSweptAreaSolid>(const DB& db, const LIST& params, IfcSweptAreaSolid* in)
+template <> size_t GenericFill<IfcSpatialStructureElement>(const DB& db, const LIST& params, IfcSpatialStructureElement* 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
+ 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::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`")); }
+ 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 'Position' argument
+ do { // convert the 'CompositionType' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcExtrudedAreaSolid>(const DB& db, const LIST& params, IfcExtrudedAreaSolid* in)
+template <> size_t GenericFill<IfcBuilding>(const DB& db, const LIST& params, IfcBuilding* 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
- 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 'Depth' argument
+ 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++];
- 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`")); }
+ 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);
- 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
+ do { // convert the 'ElevationOfTerrain' 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`")); }
+ 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);
- 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
+ do { // convert the 'BuildingAddress' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, IfcFaceBound* in)
+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() < 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
+ 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::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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFaceOuterBound>(const DB& db, const LIST& params, IfcFaceOuterBound* in)
+template <> size_t GenericFill<IfcOpenShell>(const DB& db, const LIST& params, IfcOpenShell* 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;
+ 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<IfcFaceSurface>(const DB& db, const LIST& params, IfcFaceSurface* in)
+template <> size_t GenericFill<IfcFacetedBrep>(const DB& db, const LIST& params, IfcFacetedBrep* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFace*>(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<IfcManifoldSolidBrep>(const DB& db, const LIST& params, IfcManifoldSolidBrep* in)
+template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcConic* 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
+ 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::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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFacetedBrep>(const DB& db, const LIST& params, IfcFacetedBrep* in)
+template <> size_t GenericFill<IfcCoveringType>(const DB& db, const LIST& params, IfcCoveringType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcManifoldSolidBrep*>(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<IfcFacetedBrepWithVoids>(const DB& db, const LIST& params, IfcFacetedBrepWithVoids* in)
+template <> size_t GenericFill<IfcRoundedRectangleProfileDef>(const DB& db, const LIST& params, IfcRoundedRectangleProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcManifoldSolidBrep*>(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<IfcFanType>(const DB& db, const LIST& params, IfcFanType* in)
+template <> size_t GenericFill<IfcAirTerminalType>(const DB& db, const LIST& params, IfcAirTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(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<IfcFastener>(const DB& db, const LIST& params, IfcFastener* in)
+template <> size_t GenericFill<IfcFlowMovingDeviceType>(const DB& db, const LIST& params, IfcFlowMovingDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponent*>(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<IfcFastenerType>(const DB& db, const LIST& params, IfcFastenerType* in)
+template <> size_t GenericFill<IfcCompressorType>(const DB& db, const LIST& params, IfcCompressorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponentType*>(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<IfcFeatureElementAddition>(const DB& db, const LIST& params, IfcFeatureElementAddition* in)
+template <> size_t GenericFill<IfcIShapeProfileDef>(const DB& db, const LIST& params, IfcIShapeProfileDef* 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;
+ 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<IfcFillAreaStyleHatching>(const DB& db, const LIST& params, IfcFillAreaStyleHatching* in)
+template <> size_t GenericFill<IfcAsymmetricIShapeProfileDef>(const DB& db, const LIST& params, IfcAsymmetricIShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcFillAreaStyleTileSymbolWithStyle>(const DB& db, const LIST& params, IfcFillAreaStyleTileSymbolWithStyle* in)
+template <> size_t GenericFill<IfcControllerType>(const DB& db, const LIST& params, IfcControllerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcFillAreaStyleTiles>(const DB& db, const LIST& params, IfcFillAreaStyleTiles* in)
+template <> size_t GenericFill<IfcRailing>(const DB& db, const LIST& params, IfcRailing* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcFilterType>(const DB& db, const LIST& params, IfcFilterType* in)
+template <> size_t GenericFill<IfcGroup>(const DB& db, const LIST& params, IfcGroup* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTreatmentDeviceType*>(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<IfcFireSuppressionTerminalType>(const DB& db, const LIST& params, IfcFireSuppressionTerminalType* in)
+template <> size_t GenericFill<IfcAsset>(const DB& db, const LIST& params, IfcAsset* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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<IfcFlowFitting>(const DB& db, const LIST& params, IfcFlowFitting* in)
+template <> size_t GenericFill<IfcMaterialDefinitionRepresentation>(const DB& db, const LIST& params, IfcMaterialDefinitionRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcFlowInstrumentType>(const DB& db, const LIST& params, IfcFlowInstrumentType* 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<IfcFlowMeterType>(const DB& db, const LIST& params, IfcFlowMeterType* in)
+template <> size_t GenericFill<IfcWall>(const DB& db, const LIST& params, IfcWall* 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<IfcFlowMovingDevice>(const DB& db, const LIST& params, IfcFlowMovingDevice* in)
+template <> size_t GenericFill<IfcStructuralPointConnection>(const DB& db, const LIST& params, IfcStructuralPointConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcFlowSegment>(const DB& db, const LIST& params, IfcFlowSegment* in)
+template <> size_t GenericFill<IfcPropertyListValue>(const DB& db, const LIST& params, IfcPropertyListValue* 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<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);
+ 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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& params, IfcFlowStorageDevice* in)
+template <> size_t GenericFill<IfcFurnitureStandard>(const DB& db, const LIST& params, IfcFurnitureStandard* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcFlowTerminal>(const DB& db, const LIST& params, IfcFlowTerminal* in)
+template <> size_t GenericFill<IfcElectricGeneratorType>(const DB& db, const LIST& params, IfcElectricGeneratorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(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<IfcFlowTreatmentDevice>(const DB& db, const LIST& params, IfcFlowTreatmentDevice* in)
+template <> size_t GenericFill<IfcDoor>(const DB& db, const LIST& params, IfcDoor* 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<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<IfcFooting>(const DB& db, const LIST& params, IfcFooting* in)
+template <> size_t GenericFill<IfcStyledItem>(const DB& db, const LIST& params, IfcStyledItem* 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<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->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);
+ 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<IfcFurnishingElement>(const DB& db, const LIST& params, IfcFurnishingElement* 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<IfcFurnishingElementType>(const DB& db, const LIST& params, IfcFurnishingElementType* in)
+template <> size_t GenericFill<IfcAnnotationSymbolOccurrence>(const DB& db, const LIST& params, IfcAnnotationSymbolOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(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<IfcFurnitureStandard>(const DB& db, const LIST& params, IfcFurnitureStandard* in)
+template <> size_t GenericFill<IfcArbitraryClosedProfileDef>(const DB& db, const LIST& params, IfcArbitraryClosedProfileDef* 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<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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFurnitureType>(const DB& db, const LIST& params, IfcFurnitureType* in)
+template <> size_t GenericFill<IfcArbitraryProfileDefWithVoids>(const DB& db, const LIST& params, IfcArbitraryProfileDefWithVoids* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFurnishingElementType*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGasTerminalType>(const DB& db, const LIST& params, IfcGasTerminalType* in)
+template <> size_t GenericFill<IfcLine>(const DB& db, const LIST& params, IfcLine* 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;
+ 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);
+ 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<IfcGeometricSet>(const DB& db, const LIST& params, IfcGeometricSet* in)
+template <> size_t GenericFill<IfcFlowSegmentType>(const DB& db, const LIST& params, IfcFlowSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcGeometricCurveSet>(const DB& db, const LIST& params, IfcGeometricCurveSet* in)
+template <> size_t GenericFill<IfcAirTerminalBoxType>(const DB& db, const LIST& params, IfcAirTerminalBoxType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricSet*>(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<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
- 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->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
- 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->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<IfcGeometricRepresentationContext>(const DB& db, const LIST& params, IfcGeometricRepresentationContext* in)
+template <> size_t GenericFill<IfcPropertySingleValue>(const DB& db, const LIST& params, IfcPropertySingleValue* 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
+ 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 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`")); }
+ 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 'TrueNorth' argument
+ do { // convert the 'Unit' 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`")); }
+ 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<IfcGeometricRepresentationSubContext>(const DB& db, const LIST& params, IfcGeometricRepresentationSubContext* in)
+template <> size_t GenericFill<IfcAlarmType>(const DB& db, const LIST& params, IfcAlarmType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationContext*>(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<IfcGrid>(const DB& db, const LIST& params, IfcGrid* in)
+template <> size_t GenericFill<IfcEllipseProfileDef>(const DB& db, const LIST& params, IfcEllipseProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(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<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
-{
- size_t base = 0;
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGridPlacement>(const DB& db, const LIST& params, IfcGridPlacement* in)
+template <> size_t GenericFill<IfcStair>(const DB& db, const LIST& params, IfcStair* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObjectPlacement*>(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<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* in)
+template <> size_t GenericFill<IfcSurfaceStyleShading>(const DB& db, const LIST& params, IfcSurfaceStyleShading* 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 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<IfcHumidifierType>(const DB& db, const LIST& params, IfcHumidifierType* in)
+template <> size_t GenericFill<IfcPumpType>(const DB& db, const LIST& params, IfcPumpType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcInventory>(const DB& db, const LIST& params, IfcInventory* in)
+template <> size_t GenericFill<IfcDefinedSymbol>(const DB& db, const LIST& params, IfcDefinedSymbol* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(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<IfcJunctionBoxType>(const DB& db, const LIST& params, IfcJunctionBoxType* in)
+template <> size_t GenericFill<IfcElementComponentType>(const DB& db, const LIST& params, IfcElementComponentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(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<IfcLShapeProfileDef>(const DB& db, const LIST& params, IfcLShapeProfileDef* in)
+template <> size_t GenericFill<IfcFastenerType>(const DB& db, const LIST& params, IfcFastenerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcLaborResource>(const DB& db, const LIST& params, IfcLaborResource* in)
+template <> size_t GenericFill<IfcMechanicalFastenerType>(const DB& db, const LIST& params, IfcMechanicalFastenerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(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<IfcLampType>(const DB& db, const LIST& params, IfcLampType* in)
+template <> size_t GenericFill<IfcFlowFitting>(const DB& db, const LIST& params, IfcFlowFitting* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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<IfcLightFixtureType>(const DB& db, const LIST& params, IfcLightFixtureType* in)
+template <> size_t GenericFill<IfcLightSourceDirectional>(const DB& db, const LIST& params, IfcLightSourceDirectional* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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;
}
// -----------------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/IFCReaderGen2.cpp b/src/3rdparty/assimp/code/IFCReaderGen2.cpp
index 8d67a4231..52979260c 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,24 +23,22 @@ 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.
----------------------------------------------------------------------
*/
-/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
-
-
+//#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCReaderGen.h"
@@ -50,1753 +48,1867 @@ using namespace IFC;
namespace STEP {
-template <> size_t GenericFill<IfcLightSource>(const DB& db, const LIST& params, IfcLightSource* in)
+template <> size_t GenericFill<IfcSurfaceStyle>(const DB& db, const LIST& params, IfcSurfaceStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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
+ 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<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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSourceAmbient>(const DB& db, const LIST& params, IfcLightSourceAmbient* in)
+template <> size_t GenericFill<IfcFlowController>(const DB& db, const LIST& params, IfcFlowController* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(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<IfcLightSourceDirectional>(const DB& db, const LIST& params, IfcLightSourceDirectional* in)
+template <> size_t GenericFill<IfcBuildingStorey>(const DB& db, const LIST& params, IfcBuildingStorey* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(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<IfcLightSourceGoniometric>(const DB& db, const LIST& params, IfcLightSourceGoniometric* in)
+template <> size_t GenericFill<IfcWorkControl>(const DB& db, const LIST& params, IfcWorkControl* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(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<IfcLightSourcePositional>(const DB& db, const LIST& params, IfcLightSourcePositional* in)
+template <> size_t GenericFill<IfcWorkSchedule>(const DB& db, const LIST& params, IfcWorkSchedule* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(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<IfcLightSourceSpot>(const DB& db, const LIST& params, IfcLightSourceSpot* in)
+template <> size_t GenericFill<IfcDuctSegmentType>(const DB& db, const LIST& params, IfcDuctSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSourcePositional*>(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<IfcLine>(const DB& db, const LIST& params, IfcLine* in)
+template <> size_t GenericFill<IfcFace>(const DB& db, const LIST& params, IfcFace* 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
- 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);
- do { // convert the 'Dir' argument
+ 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++];
- 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`")); }
+ 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<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<IfcLinearDimension>(const DB& db, const LIST& params, IfcLinearDimension* in)
+template <> size_t GenericFill<IfcPlanarBox>(const DB& db, const LIST& params, IfcPlanarBox* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(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<IfcLocalPlacement>(const DB& db, const LIST& params, IfcLocalPlacement* in)
+template <> size_t GenericFill<IfcColourSpecification>(const DB& db, const LIST& params, IfcColourSpecification* 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
+ 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->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`")); }
+ 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<IfcMappedItem>(const DB& db, const LIST& params, IfcMappedItem* in)
+template <> size_t GenericFill<IfcVector>(const DB& db, const LIST& params, IfcVector* 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
+ 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->MappingSource, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMappedItem to be a `IfcRepresentationMap`")); }
+ 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 'MappingTarget' argument
+ do { // convert the 'Magnitude' 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`")); }
+ 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<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<IfcProductRepresentation>(const DB& db, const LIST& params, IfcProductRepresentation* in)
+template <> size_t GenericFill<IfcColourRgb>(const DB& db, const LIST& params, IfcColourRgb* in)
{
- size_t base = 0;
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcProductRepresentation"); } do { // convert the 'Name' argument
+ 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++];
- 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`")); }
+ 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 'Description' argument
+ do { // convert the 'Green' 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`")); }
+ 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 'Representations' argument
+ do { // convert the 'Blue' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMaterialDefinitionRepresentation>(const DB& db, const LIST& params, IfcMaterialDefinitionRepresentation* in)
+template <> size_t GenericFill<IfcStructuralPlanarAction>(const DB& db, const LIST& params, IfcStructuralPlanarAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProductRepresentation*>(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<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* in)
+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 = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMeasureWithUnit"); } do { // convert the 'ValueComponent' argument
+ 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++];
- 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`")); }
+ 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 'UnitComponent' argument
+ do { // convert the 'RefLongitude' 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`")); }
+ 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);
- return base;
+ 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<IfcMechanicalFastener>(const DB& db, const LIST& params, IfcMechanicalFastener* in)
+template <> size_t GenericFill<IfcDiscreteAccessoryType>(const DB& db, const LIST& params, IfcDiscreteAccessoryType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFastener*>(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<IfcMechanicalFastenerType>(const DB& db, const LIST& params, IfcMechanicalFastenerType* in)
+template <> size_t GenericFill<IfcVibrationIsolatorType>(const DB& db, const LIST& params, IfcVibrationIsolatorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFastenerType*>(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<IfcMember>(const DB& db, const LIST& params, IfcMember* in)
+template <> size_t GenericFill<IfcEvaporativeCoolerType>(const DB& db, const LIST& params, IfcEvaporativeCoolerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcMemberType>(const DB& db, const LIST& params, IfcMemberType* in)
+template <> size_t GenericFill<IfcDistributionChamberElementType>(const DB& db, const LIST& params, IfcDistributionChamberElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(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<IfcMotorConnectionType>(const DB& db, const LIST& params, IfcMotorConnectionType* in)
+template <> size_t GenericFill<IfcFeatureElementAddition>(const DB& db, const LIST& params, IfcFeatureElementAddition* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProcess>(const DB& db, const LIST& params, IfcProcess* in)
+template <> size_t GenericFill<IfcStructuredDimensionCallout>(const DB& db, const LIST& params, IfcStructuredDimensionCallout* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(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<IfcTask>(const DB& db, const LIST& params, IfcTask* in)
+template <> size_t GenericFill<IfcCoolingTowerType>(const DB& db, const LIST& params, IfcCoolingTowerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProcess*>(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<IfcMove>(const DB& db, const LIST& params, IfcMove* in)
+template <> size_t GenericFill<IfcCenterLineProfileDef>(const DB& db, const LIST& params, IfcCenterLineProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTask*>(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<IfcOccupant>(const DB& db, const LIST& params, IfcOccupant* in)
+template <> size_t GenericFill<IfcWindowStyle>(const DB& db, const LIST& params, IfcWindowStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcActor*>(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<IfcOffsetCurve2D>(const DB& db, const LIST& params, IfcOffsetCurve2D* in)
+template <> size_t GenericFill<IfcLightSourceGoniometric>(const DB& db, const LIST& params, IfcLightSourceGoniometric* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(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<IfcOffsetCurve3D>(const DB& db, const LIST& params, IfcOffsetCurve3D* in)
+template <> size_t GenericFill<IfcTransformerType>(const DB& db, const LIST& params, IfcTransformerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(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<IfcOneDirectionRepeatFactor>(const DB& db, const LIST& params, IfcOneDirectionRepeatFactor* in)
+template <> size_t GenericFill<IfcMemberType>(const DB& db, const LIST& params, IfcMemberType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcOpenShell>(const DB& db, const LIST& params, IfcOpenShell* in)
+template <> size_t GenericFill<IfcSurfaceOfLinearExtrusion>(const DB& db, const LIST& params, IfcSurfaceOfLinearExtrusion* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConnectedFaceSet*>(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<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<IfcOrderAction>(const DB& db, const LIST& params, IfcOrderAction* in)
+template <> size_t GenericFill<IfcMotorConnectionType>(const DB& db, const LIST& params, IfcMotorConnectionType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTask*>(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<IfcOrientedEdge>(const DB& db, const LIST& params, IfcOrientedEdge* in)
+template <> size_t GenericFill<IfcFlowTreatmentDeviceType>(const DB& db, const LIST& params, IfcFlowTreatmentDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdge*>(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<IfcOutletType>(const DB& db, const LIST& params, IfcOutletType* in)
+template <> size_t GenericFill<IfcDuctSilencerType>(const DB& db, const LIST& params, IfcDuctSilencerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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<IfcPath>(const DB& db, const LIST& params, IfcPath* in)
+template <> size_t GenericFill<IfcFurnishingElementType>(const DB& db, const LIST& params, IfcFurnishingElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(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<IfcPerformanceHistory>(const DB& db, const LIST& params, IfcPerformanceHistory* in)
+template <> size_t GenericFill<IfcSystemFurnitureElementType>(const DB& db, const LIST& params, IfcSystemFurnitureElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcPermit>(const DB& db, const LIST& params, IfcPermit* in)
+template <> size_t GenericFill<IfcWasteTerminalType>(const DB& db, const LIST& params, IfcWasteTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcBSplineCurve>(const DB& db, const LIST& params, IfcBSplineCurve* 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<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);
+ 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<IfcPipeFittingType>(const DB& db, const LIST& params, IfcPipeFittingType* in)
+template <> size_t GenericFill<IfcBezierCurve>(const DB& db, const LIST& params, IfcBezierCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(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<IfcPipeSegmentType>(const DB& db, const LIST& params, IfcPipeSegmentType* in)
+template <> size_t GenericFill<IfcActuatorType>(const DB& db, const LIST& params, IfcActuatorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(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<IfcPlanarExtent>(const DB& db, const LIST& params, IfcPlanarExtent* in)
+template <> size_t GenericFill<IfcDistributionControlElement>(const DB& db, const LIST& params, IfcDistributionControlElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcPlanarBox>(const DB& db, const LIST& params, IfcPlanarBox* in)
+template <> size_t GenericFill<IfcAnnotation>(const DB& db, const LIST& params, IfcAnnotation* 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<IfcProduct*>(in));
+ if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcAnnotation"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlane>(const DB& db, const LIST& params, IfcPlane* in)
+template <> size_t GenericFill<IfcShellBasedSurfaceModel>(const DB& db, const LIST& params, IfcShellBasedSurfaceModel* 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<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<IfcPlate>(const DB& db, const LIST& params, IfcPlate* in)
+template <> size_t GenericFill<IfcActionRequest>(const DB& db, const LIST& params, IfcActionRequest* 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<IfcPlateType>(const DB& db, const LIST& params, IfcPlateType* in)
+template <> size_t GenericFill<IfcExtrudedAreaSolid>(const DB& db, const LIST& params, IfcExtrudedAreaSolid* 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<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 '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);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPointOnCurve>(const DB& db, const LIST& params, IfcPointOnCurve* in)
+template <> size_t GenericFill<IfcSystem>(const DB& db, const LIST& params, IfcSystem* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPoint*>(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<IfcPointOnSurface>(const DB& db, const LIST& params, IfcPointOnSurface* in)
+template <> size_t GenericFill<IfcFillAreaStyleHatching>(const DB& db, const LIST& params, IfcFillAreaStyleHatching* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPoint*>(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<IfcPolyLoop>(const DB& db, const LIST& params, IfcPolyLoop* in)
+template <> size_t GenericFill<IfcRelVoidsElement>(const DB& db, const LIST& params, IfcRelVoidsElement* 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
+ 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->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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const LIST& params, IfcPolygonalBoundedHalfSpace* in)
+template <> size_t GenericFill<IfcSurfaceCurveSweptAreaSolid>(const DB& db, const LIST& params, IfcSurfaceCurveSweptAreaSolid* 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
+ 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
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`")); }
+ 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 'PolygonalBoundary' argument
+ do { // convert the 'Scale3' 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`")); }
+ 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<IfcPolyline>(const DB& db, const LIST& params, IfcPolyline* in)
+template <> size_t GenericFill<IfcCurtainWallType>(const DB& db, const LIST& params, IfcCurtainWallType* 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
- 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;
+ 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<IfcPresentationStyleAssignment>(const DB& db, const LIST& params, IfcPresentationStyleAssignment* in)
+template <> size_t GenericFill<IfcEquipmentStandard>(const DB& db, const LIST& params, IfcEquipmentStandard* in)
{
- 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;
+ 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<IfcProcedure>(const DB& db, const LIST& params, IfcProcedure* in)
+template <> size_t GenericFill<IfcFlowStorageDeviceType>(const DB& db, const LIST& params, IfcFlowStorageDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProcess*>(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<IfcProductDefinitionShape>(const DB& db, const LIST& params, IfcProductDefinitionShape* in)
+template <> size_t GenericFill<IfcDiameterDimension>(const DB& db, const LIST& params, IfcDiameterDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProductRepresentation*>(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<IfcProject>(const DB& db, const LIST& params, IfcProject* in)
+template <> size_t GenericFill<IfcSwitchingDeviceType>(const DB& db, const LIST& params, IfcSwitchingDeviceType* 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
- 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;
+ 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<IfcProjectOrder>(const DB& db, const LIST& params, IfcProjectOrder* in)
+template <> size_t GenericFill<IfcWindow>(const DB& db, const LIST& params, IfcWindow* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcProjectOrderRecord>(const DB& db, const LIST& params, IfcProjectOrderRecord* in)
+template <> size_t GenericFill<IfcFlowTreatmentDevice>(const DB& db, const LIST& params, IfcFlowTreatmentDevice* 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<IfcProjectionCurve>(const DB& db, const LIST& params, IfcProjectionCurve* in)
+template <> size_t GenericFill<IfcChillerType>(const DB& db, const LIST& params, IfcChillerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationCurveOccurrence*>(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<IfcProjectionElement>(const DB& db, const LIST& params, IfcProjectionElement* in)
+template <> size_t GenericFill<IfcRectangleHollowProfileDef>(const DB& db, const LIST& params, IfcRectangleHollowProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFeatureElementAddition*>(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<IfcSimpleProperty>(const DB& db, const LIST& params, IfcSimpleProperty* in)
+template <> size_t GenericFill<IfcBoxedHalfSpace>(const DB& db, const LIST& params, IfcBoxedHalfSpace* 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<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<IfcPropertyBoundedValue>(const DB& db, const LIST& params, IfcPropertyBoundedValue* in)
+template <> size_t GenericFill<IfcAxis2Placement2D>(const DB& db, const LIST& params, IfcAxis2Placement2D* 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<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<IfcPropertyEnumeratedValue>(const DB& db, const LIST& params, IfcPropertyEnumeratedValue* in)
+template <> size_t GenericFill<IfcSpaceProgram>(const DB& db, const LIST& params, IfcSpaceProgram* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(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<IfcPropertyListValue>(const DB& db, const LIST& params, IfcPropertyListValue* in)
+template <> size_t GenericFill<IfcPoint>(const DB& db, const LIST& params, IfcPoint* 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
+ 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
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`")); }
+ 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);
- do { // convert the 'Unit' argument
+ 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
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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyReferenceValue>(const DB& db, const LIST& params, IfcPropertyReferenceValue* in)
+template <> size_t GenericFill<IfcTerminatorSymbol>(const DB& db, const LIST& params, IfcTerminatorSymbol* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(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<IfcPropertySet>(const DB& db, const LIST& params, IfcPropertySet* in)
+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 = GenericFill(db,params,static_cast<IfcPropertySetDefinition*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcPropertySet"); } do { // convert the 'HasProperties' argument
+ 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++];
- 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`")); }
+ 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
+ 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->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<IfcPropertySingleValue>(const DB& db, const LIST& params, IfcPropertySingleValue* in)
+template <> size_t GenericFill<IfcGeometricRepresentationContext>(const DB& db, const LIST& params, IfcGeometricRepresentationContext* 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
+ 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->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->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 'Unit' argument
+ 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->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->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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyTableValue>(const DB& db, const LIST& params, IfcPropertyTableValue* in)
+template <> size_t GenericFill<IfcCurveBoundedPlane>(const DB& db, const LIST& params, IfcCurveBoundedPlane* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(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<IfcProtectiveDeviceType>(const DB& db, const LIST& params, IfcProtectiveDeviceType* in)
+template <> size_t GenericFill<IfcSIUnit>(const DB& db, const LIST& params, IfcSIUnit* 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<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<IfcProxy>(const DB& db, const LIST& params, IfcProxy* 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<IfcPumpType>(const DB& db, const LIST& params, IfcPumpType* in)
+template <> size_t GenericFill<IfcStructuralPointReaction>(const DB& db, const LIST& params, IfcStructuralPointReaction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRadiusDimension>(const DB& db, const LIST& params, IfcRadiusDimension* in)
+template <> size_t GenericFill<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* 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;
+ 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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRailing>(const DB& db, const LIST& params, IfcRailing* in)
+template <> size_t GenericFill<IfcElectricApplianceType>(const DB& db, const LIST& params, IfcElectricApplianceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcRailingType>(const DB& db, const LIST& params, IfcRailingType* in)
+template <> size_t GenericFill<IfcSensorType>(const DB& db, const LIST& params, IfcSensorType* 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<IfcRamp>(const DB& db, const LIST& params, IfcRamp* in)
+template <> size_t GenericFill<IfcFurnishingElement>(const DB& db, const LIST& params, IfcFurnishingElement* 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<IfcRampFlight>(const DB& db, const LIST& params, IfcRampFlight* in)
+template <> size_t GenericFill<IfcProtectiveDeviceType>(const DB& db, const LIST& params, IfcProtectiveDeviceType* 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<IfcRampFlightType>(const DB& db, const LIST& params, IfcRampFlightType* in)
+template <> size_t GenericFill<IfcZShapeProfileDef>(const DB& db, const LIST& params, IfcZShapeProfileDef* 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<IfcRationalBezierCurve>(const DB& db, const LIST& params, IfcRationalBezierCurve* in)
+template <> size_t GenericFill<IfcScheduleTimeControl>(const DB& db, const LIST& params, IfcScheduleTimeControl* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBezierCurve*>(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<IfcRectangleProfileDef>(const DB& db, const LIST& params, IfcRectangleProfileDef* in)
+template <> size_t GenericFill<IfcRepresentationMap>(const DB& db, const LIST& params, IfcRepresentationMap* 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
+ 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++];
- 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`")); }
+ 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 'YDim' argument
+ do { // convert the 'MappedRepresentation' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRectangleHollowProfileDef>(const DB& db, const LIST& params, IfcRectangleHollowProfileDef* in)
+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<IfcRectangleProfileDef*>(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<IfcRectangularPyramid>(const DB& db, const LIST& params, IfcRectangularPyramid* in)
+template <> size_t GenericFill<IfcBlock>(const DB& db, const LIST& params, IfcBlock* 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<IfcRectangularTrimmedSurface>(const DB& db, const LIST& params, IfcRectangularTrimmedSurface* in)
+template <> size_t GenericFill<IfcLightFixtureType>(const DB& db, const LIST& params, IfcLightFixtureType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedSurface*>(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<IfcReinforcingElement>(const DB& db, const LIST& params, IfcReinforcingElement* in)
+template <> size_t GenericFill<IfcOpeningElement>(const DB& db, const LIST& params, IfcOpeningElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementComponent*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcReinforcingBar>(const DB& db, const LIST& params, IfcReinforcingBar* in)
+template <> size_t GenericFill<IfcTendonAnchor>(const DB& db, const LIST& params, IfcTendonAnchor* 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<IfcReinforcingMesh>(const DB& db, const LIST& params, IfcReinforcingMesh* in)
+template <> size_t GenericFill<IfcElectricFlowStorageDeviceType>(const DB& db, const LIST& params, IfcElectricFlowStorageDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(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<IfcRelationship>(const DB& db, const LIST& params, IfcRelationship* in)
+template <> size_t GenericFill<IfcSphere>(const DB& db, const LIST& params, IfcSphere* 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;
+ 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<IfcRelDecomposes>(const DB& db, const LIST& params, IfcRelDecomposes* in)
+template <> size_t GenericFill<IfcDamperType>(const DB& db, const LIST& params, IfcDamperType* 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
- 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;
+ 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<IfcRelAggregates>(const DB& db, const LIST& params, IfcRelAggregates* in)
+template <> size_t GenericFill<IfcProjectOrderRecord>(const DB& db, const LIST& params, IfcProjectOrderRecord* 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;
+ 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<IfcRelConnects>(const DB& db, const LIST& params, IfcRelConnects* in)
+template <> size_t GenericFill<IfcDistributionChamberElement>(const DB& db, const LIST& params, IfcDistributionChamberElement* 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;
+ 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<IfcRelContainedInSpatialStructure>(const DB& db, const LIST& params, IfcRelContainedInSpatialStructure* in)
+template <> size_t GenericFill<IfcMechanicalFastener>(const DB& db, const LIST& params, IfcMechanicalFastener* 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
- 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;
+ 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<IfcRelDefines>(const DB& db, const LIST& params, IfcRelDefines* in)
+template <> size_t GenericFill<IfcRectangularTrimmedSurface>(const DB& db, const LIST& params, IfcRectangularTrimmedSurface* 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
- 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;
+ 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<IfcRelDefinesByProperties>(const DB& db, const LIST& params, IfcRelDefinesByProperties* in)
+template <> size_t GenericFill<IfcZone>(const DB& db, const LIST& params, IfcZone* 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
- 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;
+ 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<IfcRelFillsElement>(const DB& db, const LIST& params, IfcRelFillsElement* in)
+template <> size_t GenericFill<IfcFanType>(const DB& db, const LIST& params, IfcFanType* 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
- 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;
+ 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<IfcRelOverridesProperties>(const DB& db, const LIST& params, IfcRelOverridesProperties* in)
+template <> size_t GenericFill<IfcGeometricSet>(const DB& db, const LIST& params, IfcGeometricSet* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelDefinesByProperties*>(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<IfcRelVoidsElement>(const DB& db, const LIST& params, IfcRelVoidsElement* in)
+template <> size_t GenericFill<IfcFillAreaStyleTiles>(const DB& db, const LIST& params, IfcFillAreaStyleTiles* 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
- 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;
+ 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<IfcRepresentation>(const DB& db, const LIST& params, IfcRepresentation* in)
+template <> size_t GenericFill<IfcCableSegmentType>(const DB& db, const LIST& params, IfcCableSegmentType* in)
{
- 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;
+ 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<IfcRepresentationMap>(const DB& db, const LIST& params, IfcRepresentationMap* in)
+template <> size_t GenericFill<IfcRelOverridesProperties>(const DB& db, const LIST& params, IfcRelOverridesProperties* in)
{
- 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;
+ 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<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* in)
+template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* 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
+ 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->Axis, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRevolvedAreaSolid to be a `IfcAxis1Placement`")); }
+ 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 'Angle' argument
+ do { // convert the 'UnitComponent' 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`")); }
+ 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<IfcRightCircularCone>(const DB& db, const LIST& params, IfcRightCircularCone* in)
+template <> size_t GenericFill<IfcSlabType>(const DB& db, const LIST& params, IfcSlabType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(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<IfcRightCircularCylinder>(const DB& db, const LIST& params, IfcRightCircularCylinder* in)
+template <> size_t GenericFill<IfcServiceLife>(const DB& db, const LIST& params, IfcServiceLife* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(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<IfcRoof>(const DB& db, const LIST& params, IfcRoof* in)
+template <> size_t GenericFill<IfcFurnitureType>(const DB& db, const LIST& params, IfcFurnitureType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcRoundedEdgeFeature>(const DB& db, const LIST& params, IfcRoundedEdgeFeature* in)
+template <> size_t GenericFill<IfcCostItem>(const DB& db, const LIST& params, IfcCostItem* 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<IfcRoundedRectangleProfileDef>(const DB& db, const LIST& params, IfcRoundedRectangleProfileDef* in)
+template <> size_t GenericFill<IfcReinforcingMesh>(const DB& db, const LIST& params, IfcReinforcingMesh* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRectangleProfileDef*>(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<IfcSIUnit>(const DB& db, const LIST& params, IfcSIUnit* in)
+template <> size_t GenericFill<IfcFacetedBrepWithVoids>(const DB& db, const LIST& params, IfcFacetedBrepWithVoids* 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
- 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;
+ 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<IfcSanitaryTerminalType>(const DB& db, const LIST& params, IfcSanitaryTerminalType* in)
+template <> size_t GenericFill<IfcGasTerminalType>(const DB& db, const LIST& params, IfcGasTerminalType* 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<IfcScheduleTimeControl>(const DB& db, const LIST& params, IfcScheduleTimeControl* in)
+template <> size_t GenericFill<IfcPile>(const DB& db, const LIST& params, IfcPile* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcSectionedSpine>(const DB& db, const LIST& params, IfcSectionedSpine* in)
+template <> size_t GenericFill<IfcFillAreaStyleTileSymbolWithStyle>(const DB& db, const LIST& params, IfcFillAreaStyleTileSymbolWithStyle* 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<IfcSensorType>(const DB& db, const LIST& params, IfcSensorType* in)
+template <> size_t GenericFill<IfcConstructionMaterialResource>(const DB& db, const LIST& params, IfcConstructionMaterialResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(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<IfcServiceLife>(const DB& db, const LIST& params, IfcServiceLife* in)
+template <> size_t GenericFill<IfcAnnotationCurveOccurrence>(const DB& db, const LIST& params, IfcAnnotationCurveOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcShapeModel>(const DB& db, const LIST& params, IfcShapeModel* in)
+template <> size_t GenericFill<IfcDimensionCurve>(const DB& db, const LIST& params, IfcDimensionCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentation*>(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<IfcShapeRepresentation>(const DB& db, const LIST& params, IfcShapeRepresentation* in)
+template <> size_t GenericFill<IfcGeometricCurveSet>(const DB& db, const LIST& params, IfcGeometricCurveSet* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcShapeModel*>(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<IfcShellBasedSurfaceModel>(const DB& db, const LIST& params, IfcShellBasedSurfaceModel* in)
+template <> size_t GenericFill<IfcRelAggregates>(const DB& db, const LIST& params, IfcRelAggregates* 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
- 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;
+ 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<IfcSite>(const DB& db, const LIST& params, IfcSite* in)
+template <> size_t GenericFill<IfcFaceBasedSurfaceModel>(const DB& db, const LIST& params, IfcFaceBasedSurfaceModel* 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
- 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
+ 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++];
- 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`")); }
+ 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);
- 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSlab>(const DB& db, const LIST& params, IfcSlab* in)
+template <> size_t GenericFill<IfcEnergyConversionDevice>(const DB& db, const LIST& params, IfcEnergyConversionDevice* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcSlabType>(const DB& db, const LIST& params, IfcSlabType* in)
+template <> size_t GenericFill<IfcRampFlight>(const DB& db, const LIST& params, IfcRampFlight* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(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<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
- 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 '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;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpaceHeaterType>(const DB& db, const LIST& params, IfcSpaceHeaterType* in)
+template <> size_t GenericFill<IfcVertexLoop>(const DB& db, const LIST& params, IfcVertexLoop* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcSpaceProgram>(const DB& db, const LIST& params, IfcSpaceProgram* in)
+template <> size_t GenericFill<IfcPlate>(const DB& db, const LIST& params, IfcPlate* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcSpatialStructureElementType>(const DB& db, const LIST& params, IfcSpatialStructureElementType* in)
+template <> size_t GenericFill<IfcUShapeProfileDef>(const DB& db, const LIST& params, IfcUShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(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<IfcSpaceType>(const DB& db, const LIST& params, IfcSpaceType* in)
+template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, IfcFaceBound* 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<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<IfcSphere>(const DB& db, const LIST& params, IfcSphere* in)
+template <> size_t GenericFill<IfcFaceOuterBound>(const DB& db, const LIST& params, IfcFaceOuterBound* 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<IfcFaceBound*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcFaceOuterBound"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStackTerminalType>(const DB& db, const LIST& params, IfcStackTerminalType* in)
+template <> size_t GenericFill<IfcOneDirectionRepeatFactor>(const DB& db, const LIST& params, IfcOneDirectionRepeatFactor* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(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<IfcStair>(const DB& db, const LIST& params, IfcStair* in)
+template <> size_t GenericFill<IfcBoilerType>(const DB& db, const LIST& params, IfcBoilerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcStairFlight>(const DB& db, const LIST& params, IfcStairFlight* in)
+template <> size_t GenericFill<IfcConstructionEquipmentResource>(const DB& db, const LIST& params, IfcConstructionEquipmentResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcStairFlightType>(const DB& db, const LIST& params, IfcStairFlightType* in)
+template <> size_t GenericFill<IfcComplexProperty>(const DB& db, const LIST& params, IfcComplexProperty* 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<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<IfcStructuralActivity>(const DB& db, const LIST& params, IfcStructuralActivity* in)
+template <> size_t GenericFill<IfcFooting>(const DB& db, const LIST& params, IfcFooting* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(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<IfcStructuralAction>(const DB& db, const LIST& params, IfcStructuralAction* in)
+template <> size_t GenericFill<IfcConstructionProductResource>(const DB& db, const LIST& params, IfcConstructionProductResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralActivity*>(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<IfcStructuralAnalysisModel>(const DB& db, const LIST& params, IfcStructuralAnalysisModel* in)
+template <> size_t GenericFill<IfcDerivedProfileDef>(const DB& db, const LIST& params, IfcDerivedProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSystem*>(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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralItem>(const DB& db, const LIST& params, IfcStructuralItem* in)
+template <> size_t GenericFill<IfcPropertyTableValue>(const DB& db, const LIST& params, IfcPropertyTableValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(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<IfcStructuralConnection>(const DB& db, const LIST& params, IfcStructuralConnection* in)
+template <> size_t GenericFill<IfcFlowMeterType>(const DB& db, const LIST& params, IfcFlowMeterType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralItem*>(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<IfcStructuralCurveConnection>(const DB& db, const LIST& params, IfcStructuralCurveConnection* in)
+template <> size_t GenericFill<IfcDoorStyle>(const DB& db, const LIST& params, IfcDoorStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(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<IfcStructuralMember>(const DB& db, const LIST& params, IfcStructuralMember* in)
+template <> size_t GenericFill<IfcUnitAssignment>(const DB& db, const LIST& params, IfcUnitAssignment* 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;
+ 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<IfcStructuralCurveMember>(const DB& db, const LIST& params, IfcStructuralCurveMember* in)
+template <> size_t GenericFill<IfcFlowTerminal>(const DB& db, const LIST& params, IfcFlowTerminal* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralMember*>(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<IfcStructuralCurveMemberVarying>(const DB& db, const LIST& params, IfcStructuralCurveMemberVarying* in)
+template <> size_t GenericFill<IfcCraneRailFShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailFShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralCurveMember*>(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<IfcStructuralLinearAction>(const DB& db, const LIST& params, IfcStructuralLinearAction* in)
+template <> size_t GenericFill<IfcFlowSegment>(const DB& db, const LIST& params, IfcFlowSegment* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(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<IfcStructuralLinearActionVarying>(const DB& db, const LIST& params, IfcStructuralLinearActionVarying* in)
+template <> size_t GenericFill<IfcElementQuantity>(const DB& db, const LIST& params, IfcElementQuantity* 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;
+ 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 '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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralLoadGroup>(const DB& db, const LIST& params, IfcStructuralLoadGroup* in)
+template <> size_t GenericFill<IfcCurtainWall>(const DB& db, const LIST& params, IfcCurtainWall* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(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<IfcStructuralPlanarAction>(const DB& db, const LIST& params, IfcStructuralPlanarAction* in)
+template <> size_t GenericFill<IfcDiscreteAccessory>(const DB& db, const LIST& params, IfcDiscreteAccessory* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(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<IfcStructuralPlanarActionVarying>(const DB& db, const LIST& params, IfcStructuralPlanarActionVarying* in)
+template <> size_t GenericFill<IfcGrid>(const DB& db, const LIST& params, IfcGrid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralPlanarAction*>(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<IfcStructuralPointAction>(const DB& db, const LIST& params, IfcStructuralPointAction* in)
+template <> size_t GenericFill<IfcSanitaryTerminalType>(const DB& db, const LIST& params, IfcSanitaryTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(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<IfcStructuralPointConnection>(const DB& db, const LIST& params, IfcStructuralPointConnection* in)
+template <> size_t GenericFill<IfcSubedge>(const DB& db, const LIST& params, IfcSubedge* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(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<IfcStructuralReaction>(const DB& db, const LIST& params, IfcStructuralReaction* in)
+template <> size_t GenericFill<IfcFilterType>(const DB& db, const LIST& params, IfcFilterType* 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<IfcStructuralPointReaction>(const DB& db, const LIST& params, IfcStructuralPointReaction* in)
+template <> size_t GenericFill<IfcTendon>(const DB& db, const LIST& params, IfcTendon* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralReaction*>(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<IfcStructuralResultGroup>(const DB& db, const LIST& params, IfcStructuralResultGroup* in)
+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<IfcStructuralSurfaceConnection>(const DB& db, const LIST& params, IfcStructuralSurfaceConnection* in)
+template <> size_t GenericFill<IfcPresentationStyleAssignment>(const DB& db, const LIST& params, IfcPresentationStyleAssignment* 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;
+ 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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralSurfaceMember>(const DB& db, const LIST& params, IfcStructuralSurfaceMember* in)
+template <> size_t GenericFill<IfcStructuralCurveMember>(const DB& db, const LIST& params, IfcStructuralCurveMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralMember*>(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<IfcStructuralSurfaceMemberVarying>(const DB& db, const LIST& params, IfcStructuralSurfaceMemberVarying* in)
+template <> size_t GenericFill<IfcLightSourceAmbient>(const DB& db, const LIST& params, IfcLightSourceAmbient* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralSurfaceMember*>(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<IfcStructuredDimensionCallout>(const DB& db, const LIST& params, IfcStructuredDimensionCallout* in)
+template <> size_t GenericFill<IfcCondition>(const DB& db, const LIST& params, IfcCondition* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDraughtingCallout*>(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<IfcStyleModel>(const DB& db, const LIST& params, IfcStyleModel* in)
+template <> size_t GenericFill<IfcPort>(const DB& db, const LIST& params, IfcPort* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentation*>(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<IfcStyledRepresentation>(const DB& db, const LIST& params, IfcStyledRepresentation* in)
+template <> size_t GenericFill<IfcSpace>(const DB& db, const LIST& params, IfcSpace* 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;
+ 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 '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;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSubContractResource>(const DB& db, const LIST& params, IfcSubContractResource* in)
+template <> size_t GenericFill<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(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<IfcSubedge>(const DB& db, const LIST& params, IfcSubedge* in)
+template <> size_t GenericFill<IfcTankType>(const DB& db, const LIST& params, IfcTankType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdge*>(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<IfcSurfaceCurveSweptAreaSolid>(const DB& db, const LIST& params, IfcSurfaceCurveSweptAreaSolid* in)
+template <> size_t GenericFill<IfcInventory>(const DB& db, const LIST& params, IfcInventory* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(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<IfcSweptSurface>(const DB& db, const LIST& params, IfcSweptSurface* in)
+template <> size_t GenericFill<IfcTransportElementType>(const DB& db, const LIST& params, IfcTransportElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSurface*>(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<IfcSurfaceOfLinearExtrusion>(const DB& db, const LIST& params, IfcSurfaceOfLinearExtrusion* in)
+template <> size_t GenericFill<IfcAirToAirHeatRecoveryType>(const DB& db, const LIST& params, IfcAirToAirHeatRecoveryType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptSurface*>(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<IfcSurfaceOfRevolution>(const DB& db, const LIST& params, IfcSurfaceOfRevolution* in)
+template <> size_t GenericFill<IfcStairFlight>(const DB& db, const LIST& params, IfcStairFlight* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptSurface*>(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<IfcSurfaceStyle>(const DB& db, const LIST& params, IfcSurfaceStyle* in)
+template <> size_t GenericFill<IfcElectricalElement>(const DB& db, const LIST& params, IfcElectricalElement* 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
- 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;
+ 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<IfcSurfaceStyleShading>(const DB& db, const LIST& params, IfcSurfaceStyleShading* in)
+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 IfcSurfaceStyleShading"); } do { // convert the 'SurfaceColour' argument
+ 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++];
- 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIST& params, IfcSurfaceStyleRendering* in)
+template <> size_t GenericFill<IfcBoundingBox>(const DB& db, const LIST& params, IfcBoundingBox* 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
+ 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++];
- 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`")); }
+ 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 'DiffuseColour' argument
+ do { // convert the 'XDim' 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`")); }
+ 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 '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
+ do { // convert the 'YDim' 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`")); }
+ 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 'SpecularHighlight' argument
+ do { // convert the 'ZDim' 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`")); }
+ 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);
- 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceStyleWithTextures>(const DB& db, const LIST& params, IfcSurfaceStyleWithTextures* in)
+template <> size_t GenericFill<IfcWallType>(const DB& db, const LIST& params, IfcWallType* in)
{
- 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;
+ 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<IfcSweptDiskSolid>(const DB& db, const LIST& params, IfcSweptDiskSolid* in)
+template <> size_t GenericFill<IfcMove>(const DB& db, const LIST& params, IfcMove* 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
- 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
+ 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
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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSwitchingDeviceType>(const DB& db, const LIST& params, IfcSwitchingDeviceType* in)
+template <> size_t GenericFill<IfcOffsetCurve2D>(const DB& db, const LIST& params, IfcOffsetCurve2D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(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<IfcSystemFurnitureElementType>(const DB& db, const LIST& params, IfcSystemFurnitureElementType* in)
+template <> size_t GenericFill<IfcPointOnCurve>(const DB& db, const LIST& params, IfcPointOnCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFurnishingElementType*>(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<IfcTShapeProfileDef>(const DB& db, const LIST& params, IfcTShapeProfileDef* in)
+template <> size_t GenericFill<IfcStructuralResultGroup>(const DB& db, const LIST& params, IfcStructuralResultGroup* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcSectionedSpine>(const DB& db, const LIST& params, IfcSectionedSpine* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowStorageDeviceType*>(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<IfcTendon>(const DB& db, const LIST& params, IfcTendon* in)
+template <> size_t GenericFill<IfcSlab>(const DB& db, const LIST& params, IfcSlab* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(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<IfcTendonAnchor>(const DB& db, const LIST& params, IfcTendonAnchor* in)
+template <> size_t GenericFill<IfcVertex>(const DB& db, const LIST& params, IfcVertex* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(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<IfcTextLiteral>(const DB& db, const LIST& params, IfcTextLiteral* in)
+template <> size_t GenericFill<IfcVertexPoint>(const DB& db, const LIST& params, IfcVertexPoint* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(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<IfcTextLiteralWithExtent>(const DB& db, const LIST& params, IfcTextLiteralWithExtent* in)
+template <> size_t GenericFill<IfcStructuralLinearAction>(const DB& db, const LIST& params, IfcStructuralLinearAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTextLiteral*>(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<IfcTimeSeriesSchedule>(const DB& db, const LIST& params, IfcTimeSeriesSchedule* in)
+template <> size_t GenericFill<IfcStructuralLinearActionVarying>(const DB& db, const LIST& params, IfcStructuralLinearActionVarying* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcTopologyRepresentation>(const DB& db, const LIST& params, IfcTopologyRepresentation* in)
+template <> size_t GenericFill<IfcBuildingElementProxyType>(const DB& db, const LIST& params, IfcBuildingElementProxyType* 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<IfcTransformerType>(const DB& db, const LIST& params, IfcTransformerType* in)
+template <> size_t GenericFill<IfcProjectionElement>(const DB& db, const LIST& params, IfcProjectionElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcTransportElement>(const DB& db, const LIST& params, IfcTransportElement* in)
+template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(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
+ 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 '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;
+}
+// -----------------------------------------------------------------------------------------------------------
+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<IfcTransportElementType>(const DB& db, const LIST& params, IfcTransportElementType* in)
+template <> size_t GenericFill<IfcAnnotationSurfaceOccurrence>(const DB& db, const LIST& params, IfcAnnotationSurfaceOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(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<IfcTrapeziumProfileDef>(const DB& db, const LIST& params, IfcTrapeziumProfileDef* in)
+template <> size_t GenericFill<IfcRoundedEdgeFeature>(const DB& db, const LIST& params, IfcRoundedEdgeFeature* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcTrimmedCurve>(const DB& db, const LIST& params, IfcTrimmedCurve* in)
+template <> size_t GenericFill<IfcElectricDistributionPoint>(const DB& db, const LIST& params, IfcElectricDistributionPoint* 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
- 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;
+ 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<IfcTubeBundleType>(const DB& db, const LIST& params, IfcTubeBundleType* in)
+template <> size_t GenericFill<IfcCableCarrierSegmentType>(const DB& db, const LIST& params, IfcCableCarrierSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<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<IfcUShapeProfileDef>(const DB& db, const LIST& params, IfcUShapeProfileDef* in)
+template <> size_t GenericFill<IfcCsgSolid>(const DB& db, const LIST& params, IfcCsgSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcUnitAssignment>(const DB& db, const LIST& params, IfcUnitAssignment* in)
+template <> size_t GenericFill<IfcBeamType>(const DB& db, const LIST& params, IfcBeamType* in)
{
- 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;
+ 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<IfcUnitaryEquipmentType>(const DB& db, const LIST& params, IfcUnitaryEquipmentType* in)
+template <> size_t GenericFill<IfcAnnotationFillArea>(const DB& db, const LIST& params, IfcAnnotationFillArea* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(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<IfcValveType>(const DB& db, const LIST& params, IfcValveType* in)
+template <> size_t GenericFill<IfcStructuralCurveMemberVarying>(const DB& db, const LIST& params, IfcStructuralCurveMemberVarying* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(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<IfcVector>(const DB& db, const LIST& params, IfcVector* in)
+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<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcVector"); } do { // convert the 'Orientation' argument
+ 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->Orientation, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcVector to be a `IfcDirection`")); }
+ 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 'Magnitude' argument
+ do { // convert the 'SemiAxis2' 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`")); }
+ 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;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVertex>(const DB& db, const LIST& params, IfcVertex* in)
+template <> size_t GenericFill<IfcProductDefinitionShape>(const DB& db, const LIST& params, IfcProductDefinitionShape* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(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<IfcVertexLoop>(const DB& db, const LIST& params, IfcVertexLoop* in)
+template <> size_t GenericFill<IfcProjectionCurve>(const DB& db, const LIST& params, IfcProjectionCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLoop*>(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<IfcVertexPoint>(const DB& db, const LIST& params, IfcVertexPoint* in)
+template <> size_t GenericFill<IfcElectricalCircuit>(const DB& db, const LIST& params, IfcElectricalCircuit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcVertex*>(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<IfcVibrationIsolatorType>(const DB& db, const LIST& params, IfcVibrationIsolatorType* in)
+template <> size_t GenericFill<IfcRationalBezierCurve>(const DB& db, const LIST& params, IfcRationalBezierCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDiscreteAccessoryType*>(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<IfcVirtualElement>(const DB& db, const LIST& params, IfcVirtualElement* in)
+template <> size_t GenericFill<IfcStructuralPointAction>(const DB& db, const LIST& params, IfcStructuralPointAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(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<IfcWall>(const DB& db, const LIST& params, IfcWall* in)
+template <> size_t GenericFill<IfcPipeSegmentType>(const DB& db, const LIST& params, IfcPipeSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(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<IfcWallStandardCase>(const DB& db, const LIST& params, IfcWallStandardCase* in)
+template <> size_t GenericFill<IfcTwoDirectionRepeatFactor>(const DB& db, const LIST& params, IfcTwoDirectionRepeatFactor* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcWall*>(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<IfcWallType>(const DB& db, const LIST& params, IfcWallType* in)
+template <> size_t GenericFill<IfcShapeRepresentation>(const DB& db, const LIST& params, IfcShapeRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(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<IfcWasteTerminalType>(const DB& db, const LIST& params, IfcWasteTerminalType* in)
+template <> size_t GenericFill<IfcPropertySet>(const DB& db, const LIST& params, IfcPropertySet* 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;
+ 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<IfcWindow>(const DB& db, const LIST& params, IfcWindow* in)
+template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIST& params, IfcSurfaceStyleRendering* 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<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<IfcWindowStyle>(const DB& db, const LIST& params, IfcWindowStyle* in)
+template <> size_t GenericFill<IfcDistributionPort>(const DB& db, const LIST& params, IfcDistributionPort* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(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<IfcWorkControl>(const DB& db, const LIST& params, IfcWorkControl* in)
+template <> size_t GenericFill<IfcPipeFittingType>(const DB& db, const LIST& params, IfcPipeFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(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<IfcWorkPlan>(const DB& db, const LIST& params, IfcWorkPlan* in)
+template <> size_t GenericFill<IfcTransportElement>(const DB& db, const LIST& params, IfcTransportElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcWorkControl*>(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<IfcWorkSchedule>(const DB& db, const LIST& params, IfcWorkSchedule* in)
+template <> size_t GenericFill<IfcAnnotationTextOccurrence>(const DB& db, const LIST& params, IfcAnnotationTextOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcWorkControl*>(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<IfcZShapeProfileDef>(const DB& db, const LIST& params, IfcZShapeProfileDef* in)
+template <> size_t GenericFill<IfcStructuralAnalysisModel>(const DB& db, const LIST& params, IfcStructuralAnalysisModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(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<IfcZone>(const DB& db, const LIST& params, IfcZone* in)
+template <> size_t GenericFill<IfcConditionCriterion>(const DB& db, const LIST& params, IfcConditionCriterion* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(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;
}
} // ! STEP
diff --git a/src/3rdparty/assimp/code/IFCUtil.cpp b/src/3rdparty/assimp/code/IFCUtil.cpp
index 89a6c78c5..f5bd56a00 100644
--- a/src/3rdparty/assimp/code/IFCUtil.cpp
+++ b/src/3rdparty/assimp/code/IFCUtil.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IFCUtil.h"
#include "PolyTools.h"
#include "ProcessHelper.h"
-#include "Defines.h"
+#include <assimp/Defines.h>
namespace Assimp {
namespace IFC {
@@ -180,7 +181,7 @@ IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bo
}
IfcVector3 nor;
- NewellNormal<3, 3, 3>(nor, cnt, &temp[0], &temp[1], &temp[2]);
+ NewellNormal<3, 3, 3>(nor, static_cast<int>(cnt), &temp[0], &temp[1], &temp[2]);
return normalize ? nor.Normalize() : nor;
}
@@ -548,7 +549,7 @@ 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[static_cast<unsigned int>(i)] = in.Coordinates[i];
}
}
@@ -564,7 +565,7 @@ void ConvertDirection(IfcVector3& out, const IfcDirection& in)
{
out = IfcVector3();
for(size_t i = 0; i < in.DirectionRatios.size(); ++i) {
- out[i] = in.DirectionRatios[i];
+ out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
}
const IfcFloat len = out.Length();
if (len<1e-6) {
diff --git a/src/3rdparty/assimp/code/IFCUtil.h b/src/3rdparty/assimp/code/IFCUtil.h
index 43d20a434..f90f421d6 100644
--- a/src/3rdparty/assimp/code/IFCUtil.h
+++ b/src/3rdparty/assimp/code/IFCUtil.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/IOStreamBuffer.h b/src/3rdparty/assimp/code/IOStreamBuffer.h
new file mode 100644
index 000000000..d7528de7e
--- /dev/null
+++ b/src/3rdparty/assimp/code/IOStreamBuffer.h
@@ -0,0 +1,350 @@
+#pragma once
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include <assimp/types.h>
+#include <assimp/IOStream.hpp>
+#include "ParsingUtils.h"
+
+#include <vector>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/**
+ * Implementation of a cached stream buffer.
+ */
+template<class T>
+class IOStreamBuffer {
+public:
+ /// @brief The class constructor.
+ IOStreamBuffer( size_t cache = 4096 * 4096 );
+
+ /// @brief The class destructor.
+ ~IOStreamBuffer();
+
+ /// @brief Will open the cached access for a given stream.
+ /// @param stream The stream to cache.
+ /// @return true if successful.
+ bool open( IOStream *stream );
+
+ /// @brief Will close the cached access.
+ /// @return true if successful.
+ bool close();
+
+ /// @brief Returns the file-size.
+ /// @return The file-size.
+ size_t size() const;
+
+ /// @brief Returns the cache size.
+ /// @return The cache size.
+ size_t cacheSize() const;
+
+ /// @brief Will read the next block.
+ /// @return true if successful.
+ bool readNextBlock();
+
+ /// @brief Returns the number of blocks to read.
+ /// @return The number of blocks.
+ size_t getNumBlocks() const;
+
+ /// @brief Returns the current block index.
+ /// @return The current block index.
+ size_t getCurrentBlockIndex() const;
+
+ /// @brief Returns the current file pos.
+ /// @return The current file pos.
+ size_t getFilePos() const;
+
+ /// @brief Will read the next line.
+ /// @param buffer The buffer for the next line.
+ /// @return true if successful.
+ bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
+
+ /// @brief Will read the next line ascii or binary end line char.
+ /// @param buffer The buffer for the next line.
+ /// @return true if successful.
+ bool getNextLine(std::vector<T> &buffer);
+
+ /// @brief Will read the next block.
+ /// @param buffer The buffer for the next block.
+ /// @return true if successful.
+ bool getNextBlock( std::vector<T> &buffer );
+
+private:
+ IOStream *m_stream;
+ size_t m_filesize;
+ size_t m_cacheSize;
+ size_t m_numBlocks;
+ size_t m_blockIdx;
+ std::vector<T> m_cache;
+ size_t m_cachePos;
+ size_t m_filePos;
+};
+
+template<class T>
+inline
+IOStreamBuffer<T>::IOStreamBuffer( size_t cache )
+: m_stream( nullptr )
+, m_filesize( 0 )
+, m_cacheSize( cache )
+, m_numBlocks( 0 )
+, m_blockIdx( 0 )
+, m_cachePos( 0 )
+, m_filePos( 0 ) {
+ m_cache.resize( cache );
+ std::fill( m_cache.begin(), m_cache.end(), '\n' );
+}
+
+template<class T>
+inline
+IOStreamBuffer<T>::~IOStreamBuffer() {
+ // empty
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::open( IOStream *stream ) {
+ // file still opened!
+ if ( nullptr != m_stream ) {
+ return false;
+ }
+
+ // Invalid stream pointer
+ if ( nullptr == stream ) {
+ return false;
+ }
+
+ m_stream = stream;
+ m_filesize = m_stream->FileSize();
+ if ( m_filesize == 0 ) {
+ return false;
+ }
+ if ( m_filesize < m_cacheSize ) {
+ m_cacheSize = m_filesize;
+ }
+
+ m_numBlocks = m_filesize / m_cacheSize;
+ if ( ( m_filesize % m_cacheSize ) > 0 ) {
+ m_numBlocks++;
+ }
+
+ return true;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::close() {
+ if ( nullptr == m_stream ) {
+ return false;
+ }
+
+ // init counters and state vars
+ m_stream = nullptr;
+ m_filesize = 0;
+ m_numBlocks = 0;
+ m_blockIdx = 0;
+ m_cachePos = 0;
+ m_filePos = 0;
+
+ return true;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::size() const {
+ return m_filesize;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::cacheSize() const {
+ return m_cacheSize;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::readNextBlock() {
+ m_stream->Seek( m_filePos, aiOrigin_SET );
+ size_t readLen = m_stream->Read( &m_cache[ 0 ], sizeof( T ), m_cacheSize );
+ if ( readLen == 0 ) {
+ return false;
+ }
+ if ( readLen < m_cacheSize ) {
+ m_cacheSize = readLen;
+ }
+ m_filePos += m_cacheSize;
+ m_cachePos = 0;
+ m_blockIdx++;
+
+ return true;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::getNumBlocks() const {
+ return m_numBlocks;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::getCurrentBlockIndex() const {
+ return m_blockIdx;
+}
+
+template<class T>
+inline
+size_t IOStreamBuffer<T>::getFilePos() const {
+ return m_filePos;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
+ buffer.resize( m_cacheSize );
+ if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+ }
+
+ bool continuationFound( false ), endOfDataLine( false );
+ size_t i = 0;
+ while ( !endOfDataLine ) {
+ if ( continuationToken == m_cache[ m_cachePos ] ) {
+ continuationFound = true;
+ ++m_cachePos;
+ }
+ if ( IsLineEnd( m_cache[ m_cachePos ] ) ) {
+ if ( !continuationFound ) {
+ // the end of the data line
+ break;
+ } else {
+ // skip line end
+ while ( m_cache[m_cachePos] != '\n') {
+ ++m_cachePos;
+ }
+ ++m_cachePos;
+ continuationFound = false;
+ }
+ }
+
+ buffer[ i ] = m_cache[ m_cachePos ];
+ m_cachePos++;
+ i++;
+ if ( m_cachePos >= m_cacheSize ) {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+ }
+ }
+
+ buffer[ i ] = '\n';
+ m_cachePos++;
+
+ return true;
+}
+
+static
+inline
+bool isEndOfCache( size_t pos, size_t cacheSize ) {
+ return ( pos == cacheSize );
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
+ buffer.resize(m_cacheSize);
+ if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) {
+ if (!readNextBlock()) {
+ return false;
+ }
+ }
+
+ if (IsLineEnd(m_cache[m_cachePos])) {
+ // skip line end
+ while (m_cache[m_cachePos] != '\n') {
+ ++m_cachePos;
+ }
+ ++m_cachePos;
+ if ( isEndOfCache( m_cachePos, m_cacheSize ) ) {
+ if ( !readNextBlock() ) {
+ return false;
+ }
+ }
+ }
+
+ size_t i = 0;
+ while (!IsLineEnd(m_cache[ m_cachePos ])) {
+ buffer[i] = m_cache[ m_cachePos ];
+ m_cachePos++;
+ i++;
+ if (m_cachePos >= m_cacheSize) {
+ if (!readNextBlock()) {
+ return false;
+ }
+ }
+ }
+ buffer[i] = '\n';
+ m_cachePos++;
+
+ return true;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
+ //just return the last blockvalue if getNextLine was used before
+ if ( m_cachePos != 0) {
+ buffer = std::vector<T>(m_cache.begin() + m_cachePos, m_cache.end());
+ m_cachePos = 0;
+ }
+ else {
+ if ( !readNextBlock() )
+ return false;
+
+ buffer = std::vector<T>(m_cache.begin(), m_cache.end());
+ }
+ return true;
+}
+
+} // !ns Assimp
diff --git a/src/3rdparty/assimp/code/IRRLoader.cpp b/src/3rdparty/assimp/code/IRRLoader.cpp
index 2d702523d..c29d5b072 100644
--- a/src/3rdparty/assimp/code/IRRLoader.cpp
+++ b/src/3rdparty/assimp/code/IRRLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "fast_atof.h"
#include "GenericProperty.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "StandardShapes.h"
#include "Importer.h"
@@ -65,7 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/postprocess.h>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
using namespace irr;
@@ -207,55 +208,55 @@ void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMateri
// 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
+ const ai_real l = 10.0; // 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;
+ SkyboxVertex(-l,-l,-l, 0, 0, 1, 1.0,1.0),
+ SkyboxVertex( l,-l,-l, 0, 0, 1, 0.0,1.0),
+ SkyboxVertex( l, l,-l, 0, 0, 1, 0.0,0.0),
+ SkyboxVertex(-l, l,-l, 0, 0, 1, 1.0,0.0)) );
+ meshes.back()->mMaterialIndex = static_cast<unsigned int>(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;
+ SkyboxVertex( l,-l,-l, -1, 0, 0, 1.0,1.0),
+ SkyboxVertex( l,-l, l, -1, 0, 0, 0.0,1.0),
+ SkyboxVertex( l, l, l, -1, 0, 0, 0.0,0.0),
+ SkyboxVertex( l, l,-l, -1, 0, 0, 1.0,0.0)) );
+ meshes.back()->mMaterialIndex = static_cast<unsigned int>(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;
+ SkyboxVertex( l,-l, l, 0, 0, -1, 1.0,1.0),
+ SkyboxVertex(-l,-l, l, 0, 0, -1, 0.0,1.0),
+ SkyboxVertex(-l, l, l, 0, 0, -1, 0.0,0.0),
+ SkyboxVertex( l, l, l, 0, 0, -1, 1.0,0.0)) );
+ meshes.back()->mMaterialIndex = static_cast<unsigned int>(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;
+ SkyboxVertex(-l,-l, l, 1, 0, 0, 1.0,1.0),
+ SkyboxVertex(-l,-l,-l, 1, 0, 0, 0.0,1.0),
+ SkyboxVertex(-l, l,-l, 1, 0, 0, 0.0,0.0),
+ SkyboxVertex(-l, l, l, 1, 0, 0, 1.0,0.0)) );
+ meshes.back()->mMaterialIndex = static_cast<unsigned int>(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;
+ SkyboxVertex( l, l,-l, 0, -1, 0, 1.0,1.0),
+ SkyboxVertex( l, l, l, 0, -1, 0, 0.0,1.0),
+ SkyboxVertex(-l, l, l, 0, -1, 0, 0.0,0.0),
+ SkyboxVertex(-l, l,-l, 0, -1, 0, 1.0,0.0)) );
+ meshes.back()->mMaterialIndex = static_cast<unsigned int>(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;
+ SkyboxVertex( l,-l, l, 0, 1, 0, 0.0,0.0),
+ SkyboxVertex( l,-l,-l, 0, 1, 0, 1.0,0.0),
+ SkyboxVertex(-l,-l,-l, 0, 1, 0, 1.0,1.0),
+ SkyboxVertex(-l,-l, l, 0, 1, 0, 0.0,1.0)) );
+ meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-1u);
}
// ------------------------------------------------------------------------------------------------
@@ -269,14 +270,15 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
if (UINT_MAX == defMatIdx)
{
defMatIdx = (unsigned int)materials.size();
- aiMaterial* mat = new aiMaterial();
+ //TODO: add this materials to someone?
+ /*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);
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);*/
}
mesh->mMaterialIndex = defMatIdx;
return;
@@ -392,7 +394,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
angles[1] %= 360;
angles[2] %= 360;
- if ((angles[0]*angles[1]) && (angles[1]*angles[2]))
+ if ( (angles[0]*angles[1]) != 0 && (angles[1]*angles[2]) != 0 )
{
FindSuitableMultiple(angles[0]);
FindSuitableMultiple(angles[1]);
@@ -479,7 +481,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
aiVectorKey& key = anim->mPositionKeys[i];
key.mTime = i * tdelta;
- const float t = (float) ( in.speed * key.mTime );
+ const ai_real t = (ai_real) ( in.speed * key.mTime );
key.mValue = in.circleCenter + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t)));
}
@@ -498,7 +500,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
aiVector3D diff = in.direction - in.circleCenter;
- const float lengthOfWay = diff.Length();
+ const ai_real lengthOfWay = diff.Length();
diff.Normalize();
const double timeFactor = lengthOfWay / in.timeForWay;
@@ -507,7 +509,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
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);
+ key.mValue = in.circleCenter + diff * ai_real(timeFactor * key.mTime);
}
}
break;
@@ -542,8 +544,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 - std::floor(dt);
+ const ai_real dt = (i * in.speed * ai_real( 0.001 ) );
+ const ai_real u = dt - std::floor(dt);
const int idx = (int)std::floor(dt) % size;
// get the 4 current points to evaluate the spline
@@ -553,13 +555,13 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
const aiVector3D& p3 = in.splineKeys[ ClampSpline( idx + 2, size ) ].mValue;
// compute polynomials
- const float u2 = u*u;
- const float u3 = u2*2;
+ const ai_real u2 = u*u;
+ const ai_real 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;
+ const ai_real h1 = ai_real( 2.0 ) * u3 - ai_real( 3.0 ) * u2 + ai_real( 1.0 );
+ const ai_real h2 = ai_real( -2.0 ) * u3 + ai_real( 3.0 ) * u3;
+ const ai_real h3 = u3 - ai_real( 2.0 ) * u3;
+ const ai_real h4 = u3 - u2;
// compute the spline tangents
const aiVector3D t1 = ( p2 - p0 ) * in.tightness;
@@ -641,7 +643,7 @@ void SetupMapping (aiMaterial* mat, aiTextureMapping mode, const aiVector3D& axi
delete[] mat->mProperties;
mat->mProperties = new aiMaterialProperty*[p.size()*2];
- mat->mNumAllocated = p.size()*2;
+ mat->mNumAllocated = static_cast<unsigned int>(p.size()*2);
}
mat->mNumProperties = (unsigned int)p.size();
::memcpy(mat->mProperties,&p[0],sizeof(void*)*mat->mNumProperties);
diff --git a/src/3rdparty/assimp/code/IRRLoader.h b/src/3rdparty/assimp/code/IRRLoader.h
index 129e0cc03..d07199c0b 100644
--- a/src/3rdparty/assimp/code/IRRLoader.h
+++ b/src/3rdparty/assimp/code/IRRLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_IRRLOADER_H_INCLUDED
#include "IRRShared.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "Importer.h"
#include "StringUtils.h"
#include <assimp/anim.h>
@@ -116,10 +117,10 @@ private:
explicit Animator(AT t = UNKNOWN)
: type (t)
- , speed (0.001f)
- , direction (0.f,1.f,0.f)
- , circleRadius (1.f)
- , tightness (0.5f)
+ , speed ( ai_real( 0.001 ) )
+ , direction ( ai_real( 0.0 ), ai_real( 1.0 ), ai_real( 0.0 ) )
+ , circleRadius ( ai_real( 1.0) )
+ , tightness ( ai_real( 0.5 ) )
, loop (true)
, timeForWay (100)
{
@@ -127,15 +128,15 @@ private:
// common parameters
- float speed;
+ ai_real speed;
aiVector3D direction;
// FLY_CIRCLE
aiVector3D circleCenter;
- float circleRadius;
+ ai_real circleRadius;
// FOLLOW_SPLINE
- float tightness;
+ ai_real tightness;
std::vector<aiVectorKey> splineKeys;
// ROTATION (angles given in direction)
@@ -166,11 +167,11 @@ private:
explicit Node(ET t)
: type (t)
- , scaling (1.f,1.f,1.f) // assume uniform scaling by default
+ , scaling (1.0,1.0,1.0) // assume uniform scaling by default
, parent()
- , framesPerSecond (0.f)
+ , framesPerSecond (0.0)
, id()
- , sphereRadius (1.f)
+ , sphereRadius (1.0)
, spherePolyCountX (100)
, spherePolyCountY (100)
{
@@ -202,7 +203,7 @@ private:
// Animated meshes: frames per second
// 0.f if not specified
- float framesPerSecond;
+ ai_real framesPerSecond;
// Meshes: path to the mesh to be loaded
std::string meshPath;
@@ -213,7 +214,7 @@ private:
std::vector< std::pair<aiMaterial*, unsigned int> > materials;
// Spheres: radius of the sphere to be generates
- float sphereRadius;
+ ai_real sphereRadius;
// Spheres: Number of polygons in the x,y direction
unsigned int spherePolyCountX,spherePolyCountY;
@@ -230,13 +231,13 @@ private:
{}
//! Construction from single vertex components
- SkyboxVertex(float px, float py, float pz,
- float nx, float ny, float nz,
- float uvx, float uvy)
+ SkyboxVertex(ai_real px, ai_real py, ai_real pz,
+ ai_real nx, ai_real ny, ai_real nz,
+ ai_real uvx, ai_real uvy)
: position (px,py,pz)
, normal (nx,ny,nz)
- , uv (uvx,uvy,0.f)
+ , uv (uvx,uvy,0.0)
{}
aiVector3D position, normal, uv;
diff --git a/src/3rdparty/assimp/code/IRRMeshLoader.cpp b/src/3rdparty/assimp/code/IRRMeshLoader.cpp
index 0a2a54e84..a63a2a134 100644
--- a/src/3rdparty/assimp/code/IRRMeshLoader.cpp
+++ b/src/3rdparty/assimp/code/IRRMeshLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/material.h>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include "Macros.h"
-
using namespace Assimp;
using namespace irr;
using namespace irr::io;
@@ -116,6 +117,20 @@ const aiImporterDesc* IRRMeshImporter::GetInfo () const
return &desc;
}
+static void releaseMaterial( aiMaterial **mat ) {
+ if(*mat!= nullptr) {
+ delete *mat;
+ *mat = nullptr;
+ }
+}
+
+static void releaseMesh( aiMesh **mesh ) {
+ if (*mesh != nullptr){
+ delete *mesh;
+ *mesh = nullptr;
+ }
+}
+
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void IRRMeshImporter::InternReadFile( const std::string& pFile,
@@ -135,11 +150,11 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
std::vector<aiMaterial*> materials;
std::vector<aiMesh*> meshes;
materials.reserve (5);
- meshes.reserve (5);
+ meshes.reserve(5);
// temporary data - current mesh buffer
- aiMaterial* curMat = NULL;
- aiMesh* curMesh = NULL;
+ aiMaterial* curMat = nullptr;
+ aiMesh* curMesh = nullptr;
unsigned int curMatFlags = 0;
std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
@@ -159,16 +174,15 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
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 {
+ DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
+ releaseMaterial( &curMat );
+ releaseMesh( &curMesh );
+ } else {
materials.push_back(curMat);
meshes.push_back(curMesh);
}
- curMat = NULL;
- curMesh = NULL;
+ curMat = nullptr;
+ curMesh = nullptr;
curVertices.clear();
curColors.clear();
@@ -183,7 +197,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
if (curMat) {
DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
- delete curMat;curMat = NULL;
+ releaseMaterial( &curMat );
}
curMat = ParseMaterial(curMatFlags);
}
@@ -195,17 +209,16 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// 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;
+ releaseMaterial( &curMat );
+ releaseMesh( &curMesh );
textMeaning = 0;
continue;
}
- curVertices.reserve (num);
- curNormals.reserve (num);
- curColors.reserve (num);
- curUVs.reserve (num);
+ curVertices.reserve(num);
+ curNormals.reserve(num);
+ curColors.reserve(num);
+ curUVs.reserve(num);
// Determine the file format
const char* t = reader->getAttributeValueSafe("type");
@@ -240,7 +253,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
vertexFormat = 2;
}
else if (ASSIMP_stricmp("standard", t)) {
- delete curMat;
+ releaseMaterial( &curMat );
DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
}
else vertexFormat = 0;
@@ -248,7 +261,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}
else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) {
if (curVertices.empty() && curMat) {
- delete curMat;
+ releaseMaterial( &curMat );
throw DeadlyImportError("IRRMESH: indices must come after vertices");
}
@@ -264,10 +277,10 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
// mesh - away
- delete curMesh; curMesh = NULL;
+ releaseMesh( &curMesh );
// material - away
- delete curMat;curMat = NULL;
+ releaseMaterial( &curMat );
textMeaning = 0;
continue;
@@ -469,7 +482,6 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
break;
default:
-
// GCC complains here ...
break;
@@ -480,8 +492,8 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
if (curMat || curMesh) {
if ( !curMat || !curMesh) {
DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
- delete curMat;
- delete curMesh;
+ releaseMaterial( &curMat );
+ releaseMesh( &curMesh );
}
else {
materials.push_back(curMat);
diff --git a/src/3rdparty/assimp/code/IRRMeshLoader.h b/src/3rdparty/assimp/code/IRRMeshLoader.h
index 6c208224c..312dbbfe0 100644
--- a/src/3rdparty/assimp/code/IRRMeshLoader.h
+++ b/src/3rdparty/assimp/code/IRRMeshLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/IRRShared.cpp b/src/3rdparty/assimp/code/IRRShared.cpp
index e38ad1378..bfe408629 100644
--- a/src/3rdparty/assimp/code/IRRShared.cpp
+++ b/src/3rdparty/assimp/code/IRRShared.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/Importer.cpp b/src/3rdparty/assimp/code/Importer.cpp
index 3599138eb..c6c6f0edd 100644
--- a/src/3rdparty/assimp/code/Importer.cpp
+++ b/src/3rdparty/assimp/code/Importer.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -44,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assimp/version.h>
+#include <assimp/config.h>
+#include <assimp/importerdesc.h>
// ------------------------------------------------------------------------------------------------
/* Uncomment this line to prevent Assimp from catching unknown exceptions.
@@ -64,8 +67,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "BaseProcess.h"
-#include "DefaultIOStream.h"
-#include "DefaultIOSystem.h"
#include "DefaultProgressHandler.h"
#include "GenericProperty.h"
#include "ProcessHelper.h"
@@ -80,6 +81,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <cctype>
+#include <assimp/DefaultIOStream.h>
+#include <assimp/DefaultIOSystem.h>
+
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
# include "ValidateDataStructure.h"
#endif
@@ -270,10 +274,6 @@ aiReturn Importer::UnregisterLoader(BaseImporter* 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;
}
@@ -653,7 +653,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
uint32_t fileSize = 0;
if (fileIO)
{
- fileSize = fileIO->FileSize();
+ fileSize = static_cast<uint32_t>(fileIO->FileSize());
pimpl->mIOHandler->Close( fileIO );
}
@@ -789,7 +789,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* process = pimpl->mPostProcessingSteps[a];
- pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
+ pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
if( process->IsActive( pFlags)) {
if (profiler) {
@@ -824,11 +824,11 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
}
#endif // ! DEBUG
}
- pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
+ pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
// update private scene flags
- if( pimpl->mScene )
- ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
+ if( pimpl->mScene )
+ ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
// clear any data allocated by post-process steps
pimpl->mPPShared->Clean();
@@ -1017,11 +1017,11 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue)
// ------------------------------------------------------------------------------------------------
// Set a configuration property
-bool Importer::SetPropertyFloat(const char* szName, float iValue)
+bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
{
bool exising;
ASSIMP_BEGIN_EXCEPTION_REGION();
- exising = SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue);
+ exising = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
ASSIMP_END_EXCEPTION_REGION(bool);
return exising;
}
@@ -1058,10 +1058,10 @@ int Importer::GetPropertyInteger(const char* szName,
// ------------------------------------------------------------------------------------------------
// Get a configuration property
-float Importer::GetPropertyFloat(const char* szName,
- float iErrorReturn /*= 10e10*/) const
+ai_real Importer::GetPropertyFloat(const char* szName,
+ ai_real iErrorReturn /*= 10e10*/) const
{
- return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn);
+ return GetGenericProperty<ai_real>(pimpl->mFloatProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/Importer.h b/src/3rdparty/assimp/code/Importer.h
index 750b9bbbd..e0fb57f5b 100644
--- a/src/3rdparty/assimp/code/Importer.h
+++ b/src/3rdparty/assimp/code/Importer.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -39,12 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Importer.h mostly internal stuff for use by #Assimp::Importer */
+#pragma once
#ifndef INCLUDED_AI_IMPORTER_H
#define INCLUDED_AI_IMPORTER_H
#include <map>
-#include <string>
#include <vector>
+#include <string>
#include <assimp/matrix4x4.h>
struct aiScene;
@@ -75,7 +77,7 @@ public:
// 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, ai_real> FloatPropertyMap;
typedef std::map<KeyType, std::string> StringPropertyMap;
typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
@@ -133,12 +135,11 @@ struct BatchData;
* 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 ASSIMP_API BatchLoader
{
// friend of Importer
public:
-
//! @cond never
// -------------------------------------------------------------------
/** Wraps a full list of configuration properties for an importer.
@@ -162,16 +163,30 @@ public:
//! @endcond
public:
-
-
// -------------------------------------------------------------------
/** Construct a batch loader from a given IO system to be used
- * to access external files */
- explicit BatchLoader(IOSystem* pIO);
- ~BatchLoader();
+ * to access external files
+ */
+ explicit BatchLoader(IOSystem* pIO, bool validate = false );
+ // -------------------------------------------------------------------
+ /** The class destructor.
+ */
+ ~BatchLoader();
// -------------------------------------------------------------------
+ /** Sets the validation step. True for enable validation during postprocess.
+ * @param enable True for validation.
+ */
+ void setValidation( bool enabled );
+
+ // -------------------------------------------------------------------
+ /** Returns the current validation step.
+ * @return The current validation step.
+ */
+ bool getValidation() const;
+
+ // -------------------------------------------------------------------
/** Add a new file to the list of files to be loaded.
* @param file File to be loaded
* @param steps Post-processing steps to be executed on the file
@@ -185,7 +200,6 @@ public:
const PropertyMap* map = NULL
);
-
// -------------------------------------------------------------------
/** Get an imported scene.
* This polls the import from the internal request list.
@@ -199,20 +213,16 @@ public:
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;
+ BatchData *m_data;
};
-}
-
-
+} // Namespace Assimp
-#endif
+#endif // INCLUDED_AI_IMPORTER_H
diff --git a/src/3rdparty/assimp/code/ImporterRegistry.cpp b/src/3rdparty/assimp/code/ImporterRegistry.cpp
index d6a175963..b4d2c3dcf 100644
--- a/src/3rdparty/assimp/code/ImporterRegistry.cpp
+++ b/src/3rdparty/assimp/code/ImporterRegistry.cpp
@@ -1,9 +1,10 @@
-/*
+/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -46,6 +47,9 @@ directly (unless you are adding new loaders), instead use the
corresponding preprocessor flag to selectively disable formats.
*/
+#include <vector>
+#include "BaseImporter.h"
+
// ------------------------------------------------------------------------------------------------
// Importers
// (include_new_importers_here)
@@ -53,6 +57,9 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_X_IMPORTER
# include "XFileImporter.h"
#endif
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+# include "AMFImporter.hpp"
+#endif
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
# include "3DSLoader.h"
#endif
@@ -175,6 +182,7 @@ corresponding preprocessor flag to selectively disable formats.
#endif
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
# include "glTFImporter.h"
+# include "glTF2Importer.h"
#endif
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
# include "C4DImporter.h"
@@ -182,6 +190,12 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
# include "D3MFImporter.h"
#endif
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+# include "X3DImporter.hpp"
+#endif
+#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
+# include "MMDImporter.h"
+#endif
namespace Assimp {
@@ -199,6 +213,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
out.push_back( new ObjFileImporter());
#endif
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+ out.push_back( new AMFImporter() );
+#endif
#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
out.push_back( new Discreet3DSImporter());
#endif
@@ -215,7 +232,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
out.push_back( new MDLImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
+ #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
out.push_back( new ASEImporter());
+# endif
#endif
#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
out.push_back( new HMPImporter());
@@ -318,12 +337,19 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#endif
#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
out.push_back( new glTFImporter() );
+ out.push_back( new glTF2Importer() );
#endif
#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
out.push_back( new C4DImporter() );
#endif
#if ( !defined ASSIMP_BUILD_NO_3MF_IMPORTER )
- out.push_back(new D3MFImporter() );
+ out.push_back( new D3MFImporter() );
+#endif
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+ out.push_back( new X3DImporter() );
+#endif
+#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
+ out.push_back( new MMDImporter() );
#endif
}
diff --git a/src/3rdparty/assimp/code/ImproveCacheLocality.cpp b/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
index 9fd76508b..2ac32aa84 100644
--- a/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
+++ b/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -222,6 +223,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
iMaxRefTris = std::max(iMaxRefTris,*piCur);
}
}
+ ai_assert(iMaxRefTris > 0);
unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
unsigned int iCacheMisses = 0;
diff --git a/src/3rdparty/assimp/code/ImproveCacheLocality.h b/src/3rdparty/assimp/code/ImproveCacheLocality.h
index d43f37f50..d91388c41 100644
--- a/src/3rdparty/assimp/code/ImproveCacheLocality.h
+++ b/src/3rdparty/assimp/code/ImproveCacheLocality.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/JoinVerticesProcess.cpp b/src/3rdparty/assimp/code/JoinVerticesProcess.cpp
index 9cd34e1d0..17b0ab07f 100644
--- a/src/3rdparty/assimp/code/JoinVerticesProcess.cpp
+++ b/src/3rdparty/assimp/code/JoinVerticesProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/JoinVerticesProcess.h b/src/3rdparty/assimp/code/JoinVerticesProcess.h
index af92040d2..a3204782a 100644
--- a/src/3rdparty/assimp/code/JoinVerticesProcess.h
+++ b/src/3rdparty/assimp/code/JoinVerticesProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -62,7 +63,6 @@ namespace Assimp
class ASSIMP_API JoinVerticesProcess : public BaseProcess
{
public:
-
JoinVerticesProcess();
~JoinVerticesProcess();
diff --git a/src/3rdparty/assimp/code/LWOAnimation.cpp b/src/3rdparty/assimp/code/LWOAnimation.cpp
index 9f23c13b2..4b5338f7a 100644
--- a/src/3rdparty/assimp/code/LWOAnimation.cpp
+++ b/src/3rdparty/assimp/code/LWOAnimation.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers
#include "LWOFileData.h"
+#include <assimp/anim.h>
using namespace Assimp;
using namespace Assimp::LWO;
@@ -160,9 +162,9 @@ 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;
+ [start_time](double t) { return start_time > t; }),m;
size_t ofs = 0;
if (n != (*it).keys.end()) {
@@ -444,8 +446,6 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
// 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();
@@ -501,7 +501,7 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time);
}
}
- lasttime = fill.mTime;
+ double lasttime = fill.mTime;
out.push_back(fill);
if (lasttime >= (*cur_x).time) {
@@ -565,7 +565,7 @@ void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0
std::vector<aiVectorKey> keys;
GetKeys(keys,trans_x,trans_y,trans_z,flags);
- anim->mPositionKeys = new aiVectorKey[ anim->mNumPositionKeys = keys.size() ];
+ anim->mPositionKeys = new aiVectorKey[ anim->mNumPositionKeys = static_cast<unsigned int>(keys.size()) ];
std::copy(keys.begin(),keys.end(),anim->mPositionKeys);
}
@@ -574,7 +574,7 @@ void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0
std::vector<aiVectorKey> keys;
GetKeys(keys,rotat_x,rotat_y,rotat_z,flags);
- anim->mRotationKeys = new aiQuatKey[ anim->mNumRotationKeys = keys.size() ];
+ anim->mRotationKeys = new aiQuatKey[ anim->mNumRotationKeys = static_cast<unsigned int>(keys.size()) ];
// convert heading, pitch, bank to quaternion
// mValue.x=Heading=Rot(Y), mValue.y=Pitch=Rot(X), mValue.z=Bank=Rot(Z)
@@ -594,7 +594,7 @@ void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0
std::vector<aiVectorKey> keys;
GetKeys(keys,scale_x,scale_y,scale_z,flags);
- anim->mScalingKeys = new aiVectorKey[ anim->mNumScalingKeys = keys.size() ];
+ anim->mScalingKeys = new aiVectorKey[ anim->mNumScalingKeys = static_cast<unsigned int>(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 257abecdd..f0c578ad9 100644
--- a/src/3rdparty/assimp/code/LWOAnimation.h
+++ b/src/3rdparty/assimp/code/LWOAnimation.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,11 +48,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;
+struct aiVectorKey;
namespace Assimp {
namespace LWO {
@@ -165,7 +167,6 @@ struct Envelope
//! Keyframes for this envelope
std::vector<Key> keys;
-
// temporary data for AnimResolver
size_t old_first,old_last;
};
@@ -197,8 +198,7 @@ public:
* @param Output tick rate, per second
* @note The input envelopes are possibly modified.
*/
- AnimResolver(std::list<Envelope>& envelopes,
- double tick);
+ AnimResolver(std::list<Envelope>& envelopes, double tick);
public:
diff --git a/src/3rdparty/assimp/code/LWOBLoader.cpp b/src/3rdparty/assimp/code/LWOBLoader.cpp
index 639675294..6a07f81a7 100644
--- a/src/3rdparty/assimp/code/LWOBLoader.cpp
+++ b/src/3rdparty/assimp/code/LWOBLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/LWOFileData.h b/src/3rdparty/assimp/code/LWOFileData.h
index d67cf7ec8..7fa9a216d 100644
--- a/src/3rdparty/assimp/code/LWOFileData.h
+++ b/src/3rdparty/assimp/code/LWOFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/LWOLoader.cpp b/src/3rdparty/assimp/code/LWOLoader.cpp
index 222ec8e2c..5ec07800d 100644
--- a/src/3rdparty/assimp/code/LWOLoader.cpp
+++ b/src/3rdparty/assimp/code/LWOLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,10 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ProcessHelper.h"
#include "ConvertToLHProcess.h"
#include <assimp/IOSystem.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
#include <sstream>
#include <iomanip>
-
+#include <map>
using namespace Assimp;
@@ -65,7 +67,7 @@ static const aiImporterDesc desc = {
"LightWave/Modo Object Importer",
"",
"",
- "http://www.newtek.com/lightwave.html\nhttp://www.luxology.com/modo/",
+ "https://www.lightwave3d.com/lightwave_sdk/",
aiImporterFlags_SupportTextFlavour,
0,
0,
@@ -426,7 +428,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
}
// Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes
- unsigned int num = apcMeshes.size() - meshStart;
+ unsigned int num = static_cast<unsigned int>(apcMeshes.size() - meshStart);
if (layer.mName != "<LWODefault>" || num > 0) {
aiNode* pcNode = new aiNode();
apcNodes[layer.mIndex] = pcNode;
@@ -781,7 +783,7 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
// Determine the type of the polygons
switch (type)
{
- // read unsupported stuff too (although we wont process it)
+ // read unsupported stuff too (although we won't process it)
case AI_LWO_MBAL:
DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)");
break;
@@ -1058,8 +1060,6 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
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();
@@ -1123,10 +1123,12 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
}
}
}
+
+ std::unique_ptr<float[]> temp(new float[type]);
for (unsigned int l = 0; l < type;++l)
temp[l] = GetF4();
- DoRecursiveVMAPAssignment(base,type,idx, temp);
+ DoRecursiveVMAPAssignment(base,type,idx, temp.get());
mFileBuffer += diff;
}
}
diff --git a/src/3rdparty/assimp/code/LWOLoader.h b/src/3rdparty/assimp/code/LWOLoader.h
index 09d66cf24..b92e5aab4 100644
--- a/src/3rdparty/assimp/code/LWOLoader.h
+++ b/src/3rdparty/assimp/code/LWOLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,6 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "LWOFileData.h"
#include "BaseImporter.h"
+#include <map>
+
struct aiTexture;
struct aiNode;
struct aiMaterial;
diff --git a/src/3rdparty/assimp/code/LWOMaterial.cpp b/src/3rdparty/assimp/code/LWOMaterial.cpp
index 24a2458cf..621a2edc6 100644
--- a/src/3rdparty/assimp/code/LWOMaterial.cpp
+++ b/src/3rdparty/assimp/code/LWOMaterial.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -141,13 +142,13 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
aiVector3D v;
switch (texture.majorAxis) {
case Texture::AXIS_X:
- v = aiVector3D(1.f,0.f,0.f);
+ v = aiVector3D(1.0,0.0,0.0);
break;
case Texture::AXIS_Y:
- v = aiVector3D(0.f,1.f,0.f);
+ v = aiVector3D(0.0,1.0,0.0);
break;
default: // case Texture::AXIS_Z:
- v = aiVector3D(0.f,0.f,1.f);
+ v = aiVector3D(0.0,0.0,1.0);
break;
}
@@ -159,7 +160,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
trafo.mScaling.x = texture.wrapAmountW;
trafo.mScaling.y = texture.wrapAmountH;
- static_assert(sizeof(aiUVTransform)/sizeof(float) == 5, "sizeof(aiUVTransform)/sizeof(float) == 5");
+ static_assert(sizeof(aiUVTransform)/sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
}
DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
@@ -286,17 +287,17 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
{
float fGloss;
if (mIsLWO2) {
- fGloss = std::pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
+ fGloss = std::pow( surf.mGlossiness*ai_real( 10.0 )+ ai_real( 2.0 ), ai_real( 2.0 ) );
}
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;
+ if (16.0 >= surf.mGlossiness)
+ fGloss = 6.0;
+ else if (64.0 >= surf.mGlossiness)
+ fGloss = 20.0;
+ else if (256.0 >= surf.mGlossiness)
+ fGloss = 50.0;
+ else fGloss = 80.0;
}
pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
@@ -306,17 +307,17 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
else m = aiShadingMode_Gouraud;
// specular color
- aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
+ aiColor3D clr = lerp( aiColor3D(1.0,1.0,1.0), 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;
+ clr.g = clr.b = clr.r = surf.mLuminosity*ai_real( 0.8 );
pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
// opacity ... either additive or default-blended, please
- if (0.f != surf.mAdditiveTransparency) {
+ if (0.0 != surf.mAdditiveTransparency) {
const int add = aiBlendMode_Additive;
pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
@@ -361,13 +362,13 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + shader.functionName);
}
}
- if (surf.mMaximumSmoothAngle <= 0.0f)
+ if (surf.mMaximumSmoothAngle <= 0.0)
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 = (b && false ? aiColor3D(1.0,1.0,1.0) : surf.mColor);
clr.r *= surf.mDiffuseValue;
clr.g *= surf.mDiffuseValue;
clr.b *= surf.mDiffuseValue;
@@ -454,7 +455,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf,
++extra;
out[next++] = i;
}
- // B�h ... seems not to be used at all. Push to end if enough space is available.
+ // Bah ... seems not to be used at all. Push to end if enough space is available.
else {
out[extra++] = i;
++num_extra;
@@ -482,7 +483,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
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
+ // The vertex color map is explicitly 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];
}
@@ -497,7 +498,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
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 (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.0,0.0,0.0,1.0)) {
if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
@@ -851,7 +852,7 @@ void LWOImporter::LoadLWO2Surface(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;
}
// vertex color channel to be applied to the surface
diff --git a/src/3rdparty/assimp/code/LWSLoader.cpp b/src/3rdparty/assimp/code/LWSLoader.cpp
index a81c15a6e..2017cdb9d 100644
--- a/src/3rdparty/assimp/code/LWSLoader.cpp
+++ b/src/3rdparty/assimp/code/LWSLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -50,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
#include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "GenericProperty.h"
#include "SkeletonMeshBuilder.h"
#include "ConvertToLHProcess.h"
@@ -58,9 +59,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
-
using namespace Assimp;
static const aiImporterDesc desc = {
@@ -470,7 +471,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// Determine the exact location of a LWO file
std::string LWSImporter::FindLWOFile(const std::string& in)
{
- // insert missing directory seperator if necessary
+ // insert missing directory separator if necessary
std::string tmp;
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
{
@@ -902,7 +903,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
anim->mTicksPerSecond = fps;
anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels = anims.size()];
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels = static_cast<unsigned int>(anims.size())];
std::copy(anims.begin(),anims.end(),anim->mChannels);
}
diff --git a/src/3rdparty/assimp/code/LWSLoader.h b/src/3rdparty/assimp/code/LWSLoader.h
index 9547b67bb..e36d27b77 100644
--- a/src/3rdparty/assimp/code/LWSLoader.h
+++ b/src/3rdparty/assimp/code/LWSLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_LWSLOADER_H_INCLUDED
#include "LWOFileData.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "BaseImporter.h"
struct aiImporterDesc;
diff --git a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp
index e7fd9ab60..0bb4a4be3 100644
--- a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp
+++ b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -129,9 +130,9 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
std::sort( vit->begin(), vit->end());
// now kill everything beyond the maximum count
- unsigned int m = vit->size();
+ unsigned int m = static_cast<unsigned int>(vit->size());
vit->erase( vit->begin() + mMaxWeights, vit->end());
- removed += m-vit->size();
+ removed += static_cast<unsigned int>(m-vit->size());
// and renormalize the weights
float sum = 0.0f;
diff --git a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h
index f6907cf26..3826dbe58 100644
--- a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h
+++ b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/LineSplitter.h b/src/3rdparty/assimp/code/LineSplitter.h
index 0fa47380e..003b42d52 100644
--- a/src/3rdparty/assimp/code/LineSplitter.h
+++ b/src/3rdparty/assimp/code/LineSplitter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -68,27 +69,23 @@ for(LineSplitter splitter(stream);splitter;++splitter) {
std::cout << "Current line is: " << splitter.get_index() << std::endl;
}
-@endcode */
+@endcode
+*/
// ------------------------------------------------------------------------------------------------
-class LineSplitter
-{
+class LineSplitter {
public:
-
typedef size_t line_idx;
-public:
-
// -----------------------------------------
/** construct from existing stream reader
note: trim is *always* assumed true if skyp_empty_lines==true
*/
LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
- : idx( 0 )
- , stream(stream)
- , swallow()
- , skip_empty_lines(skip_empty_lines)
- , trim(trim)
- {
+ : idx( 0 )
+ , stream(stream)
+ , swallow()
+ , skip_empty_lines(skip_empty_lines)
+ , trim(trim) {
cur.reserve(1024);
operator++();
diff --git a/src/3rdparty/assimp/code/LogAux.h b/src/3rdparty/assimp/code/LogAux.h
index f754903c6..f2bc14d54 100644
--- a/src/3rdparty/assimp/code/LogAux.h
+++ b/src/3rdparty/assimp/code/LogAux.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -59,34 +60,34 @@ public:
// ------------------------------------------------------------------------------------------------
static void ThrowException(const std::string& msg)
{
- throw DeadlyImportError(log_prefix+msg);
+ throw DeadlyImportError(Prefix()+msg);
}
// ------------------------------------------------------------------------------------------------
static void LogWarn(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->warn(log_prefix+(std::string)message);
+ DefaultLogger::get()->warn(Prefix()+(std::string)message);
}
}
// ------------------------------------------------------------------------------------------------
static void LogError(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->error(log_prefix+(std::string)message);
+ DefaultLogger::get()->error(Prefix()+(std::string)message);
}
}
// ------------------------------------------------------------------------------------------------
static void LogInfo(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->info(log_prefix+(std::string)message);
+ DefaultLogger::get()->info(Prefix()+(std::string)message);
}
}
// ------------------------------------------------------------------------------------------------
static void LogDebug(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->debug(log_prefix+(std::string)message);
+ DefaultLogger::get()->debug(Prefix()+(std::string)message);
}
}
@@ -124,8 +125,7 @@ public:
#endif
private:
-
- static const std::string log_prefix;
+ static const char* Prefix();
};
diff --git a/src/3rdparty/assimp/code/MD2FileData.h b/src/3rdparty/assimp/code/MD2FileData.h
index f7a494335..f65193264 100644
--- a/src/3rdparty/assimp/code/MD2FileData.h
+++ b/src/3rdparty/assimp/code/MD2FileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,8 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MD2FILEHELPER_H_INC
#include <assimp/types.h>
-#include <assimp/mesh.h>
-#include <assimp/anim.h>
#include <stdint.h>
#include <assimp/Compiler/pushpack1.h>
diff --git a/src/3rdparty/assimp/code/MD2Loader.cpp b/src/3rdparty/assimp/code/MD2Loader.cpp
index b4c124774..f0a5432bf 100644
--- a/src/3rdparty/assimp/code/MD2Loader.cpp
+++ b/src/3rdparty/assimp/code/MD2Loader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -50,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
+
#include <memory>
using namespace Assimp;
@@ -271,11 +274,9 @@ void MD2Importer::InternReadFile( const std::string& pFile,
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);
-
- pcFrame += configFrameID;
+ // navigate to the begin of the current frame data
+ BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
+ m_pcHeader + m_pcHeader->offsetFrames + (m_pcHeader->frameSize * configFrameID));
// navigate to the begin of the triangle data
MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
diff --git a/src/3rdparty/assimp/code/MD2Loader.h b/src/3rdparty/assimp/code/MD2Loader.h
index 126c16359..a7566dc64 100644
--- a/src/3rdparty/assimp/code/MD2Loader.h
+++ b/src/3rdparty/assimp/code/MD2Loader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MD2NormalTable.h b/src/3rdparty/assimp/code/MD2NormalTable.h
index 5b1344bd6..98fbc1d7a 100644
--- a/src/3rdparty/assimp/code/MD2NormalTable.h
+++ b/src/3rdparty/assimp/code/MD2NormalTable.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MD3FileData.h b/src/3rdparty/assimp/code/MD3FileData.h
index 88a40f230..19740c30e 100644
--- a/src/3rdparty/assimp/code/MD3FileData.h
+++ b/src/3rdparty/assimp/code/MD3FileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -136,34 +137,33 @@ struct Frame
aiVector3D origin;
//! radius of bounding sphere
- float radius;
+ ai_real radius;
//! name of frame
char name[ AI_MD3_MAXFRAME ];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
// -------------------------------------------------------------------------------
-/** @brief Data structure for the tag header
+/**
+ * @brief Data structure for the tag header
*/
-struct Tag
-{
+struct Tag {
//! name of the tag
char NAME[ AI_MD3_MAXQPATH ];
//! Local tag origin and orientation
aiVector3D origin;
- float orientation[3][3];
+ ai_real orientation[3][3];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
// -------------------------------------------------------------------------------
/** @brief Data structure for the surface header
*/
-struct Surface
-{
+struct Surface {
//! magic number
int32_t IDENT;
@@ -185,7 +185,6 @@ struct Surface
//! number of triangles in the surface
uint32_t NUM_TRIANGLES;
-
//! offset to the triangle data
uint32_t OFS_TRIANGLES;
@@ -200,19 +199,18 @@ struct Surface
//! offset to the end of the Surface object
int32_t OFS_END;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
// -------------------------------------------------------------------------------
/** @brief Data structure for a shader defined in there
*/
-struct Shader
-{
+struct Shader {
//! filename of the shader
char NAME[ AI_MD3_MAXQPATH ];
//! index of the shader
uint32_t SHADER_INDEX;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
// -------------------------------------------------------------------------------
@@ -222,7 +220,7 @@ struct Triangle
{
//! triangle indices
uint32_t INDEXES[3];
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
// -------------------------------------------------------------------------------
@@ -231,8 +229,8 @@ struct Triangle
struct TexCoord
{
//! UV coordinates
- float U,V;
-} PACK_STRUCT;
+ ai_real U,V;
+} /*PACK_STRUCT*/;
// -------------------------------------------------------------------------------
@@ -245,7 +243,7 @@ struct Vertex
//! encoded normal vector
uint16_t NORMAL;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
#include "./../include/assimp/Compiler/poppack1.h"
@@ -257,17 +255,17 @@ struct Vertex
*
* @note This has been taken from q3 source (misc_model.c)
*/
-inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
+inline void LatLngNormalToVec3(uint16_t p_iNormal, ai_real* 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] = std::cos(lat) * std::sin(lng);
- p_afOut[1] = std::sin(lat) * std::sin(lng);
- p_afOut[2] = std::cos(lng);
- return;
+ ai_real lat = (ai_real)(( p_iNormal >> 8u ) & 0xff);
+ ai_real lng = (ai_real)(( p_iNormal & 0xff ));
+ const ai_real invVal( ai_real( 1.0 ) / ai_real( 128.0 ) );
+ lat *= ai_real( 3.141926 ) * invVal;
+ lng *= ai_real( 3.141926 ) * invVal;
+
+ p_afOut[ 0 ] = std::cos(lat) * std::sin(lng);
+ p_afOut[ 1 ] = std::sin(lat) * std::sin(lng);
+ p_afOut[ 2 ] = std::cos(lng);
}
@@ -298,10 +296,10 @@ inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut )
{
int a, b;
- a = int(57.2957795f * ( atan2f( p_vIn[1], p_vIn[0] ) ) * (255.0f / 360.0f ));
+ a = int(57.2957795f * ( std::atan2( 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 = int(57.2957795f * ( std::acos( p_vIn[2] ) ) * ( 255.0f / 360.0f ));
b &= 0xff;
((unsigned char*)&p_iOut)[0] = b; // longitude
@@ -313,4 +311,3 @@ inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut )
}
#endif // !! AI_MD3FILEHELPER_H_INC
-
diff --git a/src/3rdparty/assimp/code/MD3Loader.cpp b/src/3rdparty/assimp/code/MD3Loader.cpp
index 8294da489..11a6e56dd 100644
--- a/src/3rdparty/assimp/code/MD3Loader.cpp
+++ b/src/3rdparty/assimp/code/MD3Loader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
#include "MD3Loader.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "GenericProperty.h"
#include "RemoveComments.h"
#include "ParsingUtils.h"
@@ -62,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/material.h>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include <cctype>
-
-
using namespace Assimp;
static const aiImporterDesc desc = {
@@ -709,7 +709,7 @@ void MD3Importer::ConvertPath(const char* texture_name, const char* header_name,
}
}
else len2 = std::min (len1, (size_t)(end2 - texture_name ));
- if (!ASSIMP_strincmp(texture_name,header_name,len2)) {
+ if (!ASSIMP_strincmp(texture_name,header_name,static_cast<unsigned int>(len2))) {
// Use the file name only
out = end2+1;
return;
@@ -1018,11 +1018,11 @@ void MD3Importer::InternReadFile( const std::string& pFile,
// Convert the normal vector to uncompressed float3 format
aiVector3D& nor = pcMesh->mNormals[iCurrent];
- LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,(float*)&nor);
+ LatLngNormalToVec3(pcVertices[index].NORMAL,(ai_real*)&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;
+ pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U;
+ pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[index].V;
}
// Flip face order if necessary
if (!shader || shader->cull == Q3Shader::CULL_CW) {
diff --git a/src/3rdparty/assimp/code/MD3Loader.h b/src/3rdparty/assimp/code/MD3Loader.h
index 6b8143a97..ff5b56a52 100644
--- a/src/3rdparty/assimp/code/MD3Loader.h
+++ b/src/3rdparty/assimp/code/MD3Loader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MD5Loader.cpp b/src/3rdparty/assimp/code/MD5Loader.cpp
index 7927c9ab1..172c98a30 100644
--- a/src/3rdparty/assimp/code/MD5Loader.cpp
+++ b/src/3rdparty/assimp/code/MD5Loader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -56,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
using namespace Assimp;
@@ -228,8 +230,8 @@ 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();
+ const unsigned int iNewNum = static_cast<unsigned int>(meshSrc.mFaces.size()*3);
+ unsigned int iNewIndex = static_cast<unsigned int>(meshSrc.mVertices.size());
meshSrc.mVertices.resize(iNewNum);
// try to guess how much storage we'll need for new weights
@@ -475,7 +477,7 @@ void MD5Importer::LoadMD5MeshFile ()
*pv = aiVector3D();
// there are models which have weights which don't sum to 1 ...
- float fSum = 0.0f;
+ ai_real fSum = 0.0;
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
fSum += meshSrc.mWeights[w].mWeight;
if (!fSum) {
@@ -493,7 +495,7 @@ void MD5Importer::LoadMD5MeshFile ()
continue;
}
- const float fNewWeight = desc.mWeight / fSum;
+ const ai_real fNewWeight = desc.mWeight / fSum;
// transform the local position into worldspace
MD5::BoneDesc& boneSrc = meshParser.mJoints[desc.mBone];
@@ -501,7 +503,7 @@ void MD5Importer::LoadMD5MeshFile ()
// 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);
+ *pv += ((boneSrc.mPositionXYZ+v)* (ai_real)desc.mWeight);
aiBone* bone = mesh->mBones[boneSrc.mMap];
*bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);
@@ -719,16 +721,16 @@ void MD5Importer::LoadMD5CameraFile ()
// every cut is written to a separate aiAnimation
if (!cuts.size()) {
cuts.push_back(0);
- cuts.push_back(frames.size()-1);
+ cuts.push_back(static_cast<unsigned int>(frames.size()-1));
}
else {
cuts.insert(cuts.begin(),0);
if (cuts.back() < frames.size()-1)
- cuts.push_back(frames.size()-1);
+ cuts.push_back(static_cast<unsigned int>(frames.size()-1));
}
- pScene->mNumAnimations = cuts.size()-1;
+ pScene->mNumAnimations = static_cast<unsigned int>(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) {
diff --git a/src/3rdparty/assimp/code/MD5Loader.h b/src/3rdparty/assimp/code/MD5Loader.h
index 9dfc08226..afb07a62d 100644
--- a/src/3rdparty/assimp/code/MD5Loader.h
+++ b/src/3rdparty/assimp/code/MD5Loader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MD5Parser.cpp b/src/3rdparty/assimp/code/MD5Parser.cpp
index df666751b..8076e5bc4 100644
--- a/src/3rdparty/assimp/code/MD5Parser.cpp
+++ b/src/3rdparty/assimp/code/MD5Parser.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -195,7 +196,7 @@ bool MD5Parser::ParseSection(Section& out)
#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++) \
@@ -210,7 +211,7 @@ bool MD5Parser::ParseSection(Section& out)
if (')' != *sz++) \
MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber);
- // parse a string, enclosed in quotation marks or not
+ // parse a string, enclosed in quotation marks or not
#define AI_MD5_PARSE_STRING(out) \
bool bQuota = (*sz == '\"'); \
const char* szStart = sz; \
@@ -228,6 +229,15 @@ bool MD5Parser::ParseSection(Section& out)
::memcpy(out.data,szStart,out.length); \
out.data[out.length] = '\0';
+ // parse a string, enclosed in quotation marks
+#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
+ while('\"'!=*sz)++sz; \
+ const char* szStart = ++sz; \
+ while('\"'!=*sz)++sz; \
+ const char* szEnd = (sz++); \
+ out.length = (size_t)(szEnd - szStart); \
+ ::memcpy(out.data,szStart,out.length); \
+ out.data[out.length] = '\0';
// ------------------------------------------------------------------------------------------------
// .MD5MESH parsing function
MD5MeshParser::MD5MeshParser(SectionList& mSections)
@@ -247,9 +257,9 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections)
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_PARSE_STRING_IN_QUOTATION(desc.mName);
AI_MD5_SKIP_SPACES();
// negative values, at least -1, is allowed here
@@ -269,7 +279,7 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections)
// shader attribute
if (TokenMatch(sz,"shader",6)) {
AI_MD5_SKIP_SPACES();
- AI_MD5_PARSE_STRING(desc.mShader);
+ AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader);
}
// numverts attribute
else if (TokenMatch(sz,"numverts",8)) {
@@ -362,7 +372,7 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
AnimBoneDesc& desc = mAnimatedBones.back();
const char* sz = elem.szStart;
- AI_MD5_PARSE_STRING(desc.mName);
+ AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
AI_MD5_SKIP_SPACES();
// parent index - negative values are allowed (at least -1)
diff --git a/src/3rdparty/assimp/code/MD5Parser.h b/src/3rdparty/assimp/code/MD5Parser.h
index 78ade8430..bafcaf962 100644
--- a/src/3rdparty/assimp/code/MD5Parser.h
+++ b/src/3rdparty/assimp/code/MD5Parser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MDCFileData.h b/src/3rdparty/assimp/code/MDCFileData.h
index c98828c28..9ea3d8f5e 100644
--- a/src/3rdparty/assimp/code/MDCFileData.h
+++ b/src/3rdparty/assimp/code/MDCFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -156,7 +157,7 @@ struct Frame
//! Name of the frame
char name [ 16 ] ;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
// ---------------------------------------------------------------------------
/** \brief Data structure for a MDC triangle
diff --git a/src/3rdparty/assimp/code/MDCLoader.cpp b/src/3rdparty/assimp/code/MDCLoader.cpp
index 661447acf..21aca53ff 100644
--- a/src/3rdparty/assimp/code/MDCLoader.cpp
+++ b/src/3rdparty/assimp/code/MDCLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include <memory>
@@ -408,7 +410,7 @@ void MDCImporter::InternReadFile(
// copy texture coordinates
pcUVCur->x = pcUVs[quak].u;
- pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL
+ pcUVCur->y = ai_real( 1.0 )-pcUVs[quak].v; // DX to OGL
}
pcVertCur->x += pcFrame->localOrigin[0] ;
pcVertCur->y += pcFrame->localOrigin[1] ;
diff --git a/src/3rdparty/assimp/code/MDCLoader.h b/src/3rdparty/assimp/code/MDCLoader.h
index fcfbc642d..5f3b365fd 100644
--- a/src/3rdparty/assimp/code/MDCLoader.h
+++ b/src/3rdparty/assimp/code/MDCLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MDLDefaultColorMap.h b/src/3rdparty/assimp/code/MDLDefaultColorMap.h
index 6db696af0..800c717c5 100644
--- a/src/3rdparty/assimp/code/MDLDefaultColorMap.h
+++ b/src/3rdparty/assimp/code/MDLDefaultColorMap.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MDLFileData.h b/src/3rdparty/assimp/code/MDLFileData.h
index 536bf082a..3ef58ca5a 100644
--- a/src/3rdparty/assimp/code/MDLFileData.h
+++ b/src/3rdparty/assimp/code/MDLFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -52,10 +53,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MDLFILEHELPER_H_INC
#define AI_MDLFILEHELPER_H_INC
+#include <assimp/anim.h>
+#include <assimp/mesh.h>
+#include <assimp/Compiler/pushpack1.h>
#include "ByteSwapper.h"
-#include "./../include/assimp/anim.h"
-#include "./../include/assimp/mesh.h"
-#include "./../include/assimp/Compiler/pushpack1.h"
#include <stdint.h>
#include <vector>
@@ -89,7 +90,6 @@ namespace MDL {
#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)
@@ -118,8 +118,7 @@ namespace MDL {
/** \struct Header
* \brief Data structure for the MDL main header
*/
-struct Header
-{
+struct Header {
//! magic number: "IDPO"
uint32_t ident;
@@ -127,16 +126,16 @@ struct Header
int32_t version;
//! scale factors for each axis
- aiVector3D scale;
+ ai_real scale[3];
//! translation factors for each axis
- aiVector3D translate;
+ ai_real translate[3];
//! bounding radius of the mesh
float boundingradius;
//! Position of the viewer's exe. Ignored
- aiVector3D vEyePos;
+ ai_real vEyePos[3];
//! Number of textures
int32_t num_skins;
@@ -172,8 +171,7 @@ struct Header
/** \struct Header_MDL7
* \brief Data structure for the MDL 7 main header
*/
-struct Header_MDL7
-{
+struct Header_MDL7 {
//! magic number: "MDL7"
char ident[4];
@@ -232,8 +230,7 @@ struct Header_MDL7
/** \struct Bone_MDL7
* \brief Data structure for a bone in a MDL7 file
*/
-struct Bone_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;
@@ -267,8 +264,7 @@ struct Bone_MDL7
/** \struct Group_MDL7
* \brief Group in a MDL7 file
*/
-struct Group_MDL7
-{
+struct Group_MDL7 {
//! = '1' -> triangle based Mesh
unsigned char typ;
@@ -309,8 +305,7 @@ struct Group_MDL7
/** \struct Deformer_MDL7
* \brief Deformer in a MDL7 file
*/
-struct Deformer_MDL7
-{
+struct Deformer_MDL7 {
int8_t deformer_version; // 0
int8_t deformer_typ; // 0 - bones
int8_t _unused_[2];
@@ -324,27 +319,23 @@ struct Deformer_MDL7
/** \struct DeformerElement_MDL7
* \brief Deformer element in a MDL7 file
*/
-struct DeformerElement_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;
} PACK_STRUCT;
-
// -------------------------------------------------------------------------------------
/** \struct DeformerWeight_MDL7
* \brief Deformer weight in a MDL7 file
*/
-struct DeformerWeight_MDL7
-{
+struct DeformerWeight_MDL7 {
//! for deformer_typ==0 (==bones) index == vertex index
int32_t index;
float weight;
} PACK_STRUCT;
-
// don't know why this was in the original headers ...
typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
@@ -352,8 +343,7 @@ typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
/** \struct ColorValue_MDL7
* \brief Data structure for a color value in a MDL7 file
*/
-struct ColorValue_MDL7
-{
+struct ColorValue_MDL7 {
float r,g,b,a;
} PACK_STRUCT;
@@ -361,8 +351,7 @@ struct ColorValue_MDL7
/** \struct Material_MDL7
* \brief Data structure for a Material in a MDL7 file
*/
-struct Material_MDL7
-{
+struct Material_MDL7 {
//! Diffuse base color of the material
ColorValue_MDL7 Diffuse;
@@ -379,13 +368,11 @@ struct Material_MDL7
float Power;
} PACK_STRUCT;
-
// -------------------------------------------------------------------------------------
/** \struct Skin
* \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
*/
-struct Skin
-{
+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:
@@ -409,8 +396,7 @@ struct Skin
* \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
* \see Skin
*/
-struct Skin_MDL5
-{
+struct Skin_MDL5 {
int32_t size, width, height;
uint8_t *data;
} PACK_STRUCT;
@@ -424,8 +410,7 @@ struct Skin_MDL5
/** \struct Skin_MDL7
* \brief Skin data structure #3 - used by MDL7 and HMP7
*/
-struct Skin_MDL7
-{
+struct Skin_MDL7 {
uint8_t typ;
int8_t _unused_[3];
int32_t width;
@@ -437,8 +422,7 @@ struct Skin_MDL7
/** \struct RGB565
* \brief Data structure for a RGB565 pixel in a texture
*/
-struct RGB565
-{
+struct RGB565 {
uint16_t r : 5;
uint16_t g : 6;
uint16_t b : 5;
@@ -448,20 +432,18 @@ struct RGB565
/** \struct ARGB4
* \brief Data structure for a ARGB4444 pixel in a texture
*/
-struct ARGB4
-{
+struct ARGB4 {
uint16_t a : 4;
uint16_t r : 4;
uint16_t g : 4;
uint16_t b : 4;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
// -------------------------------------------------------------------------------------
/** \struct GroupSkin
* \brief Skin data structure #2 (group of pictures)
*/
-struct GroupSkin
-{
+struct GroupSkin {
//! 0 = single (Skin), 1 = group (GroupSkin)
int32_t group;
@@ -479,8 +461,7 @@ struct GroupSkin
/** \struct TexCoord
* \brief Texture coordinate data structure used by the Quake1 MDL format
*/
-struct TexCoord
-{
+struct TexCoord {
//! Is the vertex on the noundary between front and back piece?
int32_t onseam;
@@ -495,8 +476,7 @@ struct TexCoord
/** \struct TexCoord_MDL3
* \brief Data structure for an UV coordinate in the 3DGS MDL3 format
*/
-struct TexCoord_MDL3
-{
+struct TexCoord_MDL3 {
//! position, horizontally in range 0..skinwidth-1
int16_t u;
@@ -508,8 +488,7 @@ struct TexCoord_MDL3
/** \struct TexCoord_MDL7
* \brief Data structure for an UV coordinate in the 3DGS MDL7 format
*/
-struct TexCoord_MDL7
-{
+struct TexCoord_MDL7 {
//! position, horizontally in range 0..1
float u;
@@ -626,7 +605,6 @@ struct Vertex_MDL7
};
} PACK_STRUCT;
-
// -------------------------------------------------------------------------------------
/** \struct BoneTransform_MDL7
* \brief bone transformation matrix structure used in MDL7 files
@@ -647,7 +625,6 @@ struct BoneTransform_MDL7
#define AI_MDL7_MAX_FRAMENAMESIZE 16
-
// -------------------------------------------------------------------------------------
/** \struct Frame_MDL7
* \brief Frame data structure used by MDL7 files
@@ -737,8 +714,7 @@ struct GroupFrame
/** \struct IntFace_MDL7
* \brief Internal data structure to temporarily represent a face
*/
-struct IntFace_MDL7
-{
+struct IntFace_MDL7 {
// provide a constructor for our own convenience
IntFace_MDL7()
{
diff --git a/src/3rdparty/assimp/code/MDLLoader.cpp b/src/3rdparty/assimp/code/MDLLoader.cpp
index ba5c4c32c..2025d79b3 100644
--- a/src/3rdparty/assimp/code/MDLLoader.cpp
+++ b/src/3rdparty/assimp/code/MDLLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -58,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
-
using namespace Assimp;
static const aiImporterDesc desc = {
@@ -172,8 +173,7 @@ void MDLImporter::InternReadFile( const std::string& pFile,
}
// Allocate storage and copy the contents of the file to a memory buffer
- std::vector<unsigned char> buffer(iFileSize+1);
- mBuffer = &buffer[0];
+ mBuffer =new unsigned char[iFileSize+1];
file->Read( (void*)mBuffer, 1, iFileSize);
// Append a binary zero to the end of the buffer.
@@ -239,7 +239,8 @@ void MDLImporter::InternReadFile( const std::string& pFile,
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);
+ delete [] mBuffer;
+ mBuffer= nullptr;
AI_DEBUG_INVALIDATE_PTR(pIOHandler);
AI_DEBUG_INVALIDATE_PTR(pScene);
}
@@ -1131,7 +1132,9 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
const unsigned char* szCurrent,
const unsigned char** szCurrentOut)
{
- ai_assert(NULL != szCurrent && NULL != szCurrentOut);
+ ai_assert( nullptr != szCurrent );
+ ai_assert( nullptr != szCurrentOut);
+
const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer;
// if we have no bones we can simply skip all frames,
@@ -1557,7 +1560,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
} else {
pcNode->mName.length = ::strlen(szBuffer);
}
- ::strcpy(pcNode->mName.data,szBuffer);
+ ::strncpy(pcNode->mName.data,szBuffer,MAXLEN-1);
++p;
}
}
diff --git a/src/3rdparty/assimp/code/MDLLoader.h b/src/3rdparty/assimp/code/MDLLoader.h
index 62e451cbe..8709426e6 100644
--- a/src/3rdparty/assimp/code/MDLLoader.h
+++ b/src/3rdparty/assimp/code/MDLLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MDLMaterialLoader.cpp b/src/3rdparty/assimp/code/MDLMaterialLoader.cpp
index d1502d6fb..9086925aa 100644
--- a/src/3rdparty/assimp/code/MDLMaterialLoader.cpp
+++ b/src/3rdparty/assimp/code/MDLMaterialLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,8 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/Defines.h>
#include "qnan.h"
-#include "Defines.h"
using namespace Assimp;
@@ -488,7 +489,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
unsigned int iWidth,
unsigned int iHeight)
{
- aiTexture* pcNew = NULL;
+ aiTexture* pcNew = nullptr;
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
@@ -522,7 +523,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
szCurrent += iWidth;
}
- if (0x7 == iMasked)
+ else if (0x7 == iMasked)
{
// ***** REFERENCE TO EXTERNAL FILE *****
if (1 != iHeight)
@@ -545,7 +546,6 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
}
else if (iMasked || !iType || (iType && iWidth && iHeight))
{
- // ***** STANDARD COLOR TEXTURE *****
pcNew = new aiTexture();
if (!iHeight || !iWidth)
{
@@ -657,7 +657,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
if (is_not_qnan(clrTexture.r)) {
clrTemp.r *= clrTexture.a;
}
- pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY);
+ pcMatOut->AddProperty<ai_real>(&clrTemp.r,1,AI_MATKEY_OPACITY);
// read phong power
int iShadingMode = (int)aiShadingMode_Gouraud;
@@ -665,7 +665,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
if (0.0f != pcMatIn->Power)
{
iShadingMode = (int)aiShadingMode_Phong;
- pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
+ // pcMatIn is packed, we can't form pointers to its members
+ float power = pcMatIn->Power;
+ pcMatOut->AddProperty<float>(&power,1,AI_MATKEY_SHININESS);
}
pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
}
@@ -731,6 +733,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
}
VALIDATE_FILE_SIZE(szCurrent);
*szCurrentOut = szCurrent;
+ if ( nullptr != pcNew ) {
+ delete pcNew;
+ }
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/MMDCpp14.h b/src/3rdparty/assimp/code/MMDCpp14.h
new file mode 100644
index 000000000..f6f81f827
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDCpp14.h
@@ -0,0 +1,82 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#ifndef MMD_CPP14_H
+#define MMD_CPP14_H
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace mmd {
+ template<class T> struct _Unique_if {
+ typedef std::unique_ptr<T> _Single_object;
+ };
+
+ template<class T> struct _Unique_if<T[]> {
+ typedef std::unique_ptr<T[]> _Unknown_bound;
+ };
+
+ template<class T, size_t N> struct _Unique_if<T[N]> {
+ typedef void _Known_bound;
+ };
+
+ template<class T, class... Args>
+ typename _Unique_if<T>::_Single_object
+ make_unique(Args&&... args) {
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ }
+
+ template<class T>
+ typename _Unique_if<T>::_Unknown_bound
+ make_unique(size_t n) {
+ typedef typename std::remove_extent<T>::type U;
+ return std::unique_ptr<T>(new U[n]());
+ }
+
+ template<class T, class... Args>
+ typename _Unique_if<T>::_Known_bound
+ make_unique(Args&&...) = delete;
+}
+
+#endif
diff --git a/src/3rdparty/assimp/code/MMDImporter.cpp b/src/3rdparty/assimp/code/MMDImporter.cpp
new file mode 100644
index 000000000..01f009519
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDImporter.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.
+---------------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
+
+#include "MMDImporter.h"
+#include "MMDPmdParser.h"
+#include "MMDPmxParser.h"
+#include "MMDVmdParser.h"
+#include "ConvertToLHProcess.h"
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/Importer.hpp>
+#include <assimp/ai_assert.h>
+#include <assimp/scene.h>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+
+static const aiImporterDesc desc = {"MMD Importer",
+ "",
+ "",
+ "surfaces supported?",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "pmx"};
+
+namespace Assimp {
+
+using namespace std;
+
+// ------------------------------------------------------------------------------------------------
+// Default constructor
+MMDImporter::MMDImporter()
+ : m_Buffer(),
+ // m_pRootObject( NULL ),
+ m_strAbsPath("") {
+ DefaultIOSystem io;
+ m_strAbsPath = io.getOsSeparator();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor.
+MMDImporter::~MMDImporter() {
+ // delete m_pRootObject;
+ // m_pRootObject = NULL;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns true, if file is an pmx file.
+bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler,
+ bool checkSig) const {
+ if (!checkSig) // Check File Extension
+ {
+ return SimpleExtensionCheck(pFile, "pmx");
+ } else // Check file Header
+ {
+ static const char *pTokens[] = {"PMX "};
+ return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens,
+ 1);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc *MMDImporter::GetInfo() const { return &desc; }
+
+// ------------------------------------------------------------------------------------------------
+// MMD import implementation
+void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
+ IOSystem * /*pIOHandler*/) {
+ // Read file by istream
+ std::filebuf fb;
+ if (!fb.open(file, std::ios::in | std::ios::binary)) {
+ throw DeadlyImportError("Failed to open file " + file + ".");
+ }
+
+ std::istream fileStream(&fb);
+
+ // Get the file-size and validate it, throwing an exception when fails
+ fileStream.seekg(0, fileStream.end);
+ size_t fileSize = static_cast<size_t>(fileStream.tellg());
+ fileStream.seekg(0, fileStream.beg);
+
+ if (fileSize < sizeof(pmx::PmxModel)) {
+ throw DeadlyImportError(file + " is too small.");
+ }
+
+ pmx::PmxModel model;
+ model.Read(&fileStream);
+
+ CreateDataFromImport(&model, pScene);
+}
+
+// ------------------------------------------------------------------------------------------------
+void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel,
+ aiScene *pScene) {
+ if (pModel == NULL) {
+ return;
+ }
+
+ aiNode *pNode = new aiNode;
+ if (!pModel->model_name.empty()) {
+ pNode->mName.Set(pModel->model_name);
+ } else {
+ ai_assert(false);
+ }
+
+ pScene->mRootNode = pNode;
+
+ pNode = new aiNode;
+ pScene->mRootNode->addChildren(1, &pNode);
+ pNode->mName.Set(string(pModel->model_name) + string("_mesh"));
+
+ // split mesh by materials
+ pNode->mNumMeshes = pModel->material_count;
+ pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
+ for (unsigned int index = 0; index < pNode->mNumMeshes; index++) {
+ pNode->mMeshes[index] = index;
+ }
+
+ pScene->mNumMeshes = pModel->material_count;
+ pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
+ for (unsigned int i = 0, indexStart = 0; i < pScene->mNumMeshes; i++) {
+ const int indexCount = pModel->materials[i].index_count;
+
+ pScene->mMeshes[i] = CreateMesh(pModel, indexStart, indexCount);
+ pScene->mMeshes[i]->mName = pModel->materials[i].material_name;
+ pScene->mMeshes[i]->mMaterialIndex = i;
+ indexStart += indexCount;
+ }
+
+ // create node hierarchy for bone position
+ aiNode **ppNode = new aiNode *[pModel->bone_count];
+ for (auto i = 0; i < pModel->bone_count; i++) {
+ ppNode[i] = new aiNode(pModel->bones[i].bone_name);
+ }
+
+ for (auto i = 0; i < pModel->bone_count; i++) {
+ const pmx::PmxBone &bone = pModel->bones[i];
+
+ if (bone.parent_index < 0) {
+ pScene->mRootNode->addChildren(1, ppNode + i);
+ } else {
+ ppNode[bone.parent_index]->addChildren(1, ppNode + i);
+
+ aiVector3D v3 = aiVector3D(
+ bone.position[0] - pModel->bones[bone.parent_index].position[0],
+ bone.position[1] - pModel->bones[bone.parent_index].position[1],
+ bone.position[2] - pModel->bones[bone.parent_index].position[2]);
+ aiMatrix4x4::Translation(v3, ppNode[i]->mTransformation);
+ }
+ }
+
+ // create materials
+ pScene->mNumMaterials = pModel->material_count;
+ pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
+ for (unsigned int i = 0; i < pScene->mNumMaterials; i++) {
+ pScene->mMaterials[i] = CreateMaterial(&pModel->materials[i], pModel);
+ }
+
+ // Convert everything to OpenGL space
+ MakeLeftHandedProcess convertProcess;
+ convertProcess.Execute(pScene);
+
+ FlipUVsProcess uvFlipper;
+ uvFlipper.Execute(pScene);
+
+ FlipWindingOrderProcess windingFlipper;
+ windingFlipper.Execute(pScene);
+}
+
+// ------------------------------------------------------------------------------------------------
+aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
+ const int indexStart, const int indexCount) {
+ aiMesh *pMesh = new aiMesh;
+
+ pMesh->mNumVertices = indexCount;
+
+ pMesh->mNumFaces = indexCount / 3;
+ pMesh->mFaces = new aiFace[pMesh->mNumFaces];
+
+ const int numIndices = 3; // trianglular face
+ for (unsigned int index = 0; index < pMesh->mNumFaces; index++) {
+ pMesh->mFaces[index].mNumIndices = numIndices;
+ unsigned int *indices = new unsigned int[numIndices];
+ indices[0] = numIndices * index;
+ indices[1] = numIndices * index + 1;
+ indices[2] = numIndices * index + 2;
+ pMesh->mFaces[index].mIndices = indices;
+ }
+
+ pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mNumUVComponents[0] = 2;
+
+ // additional UVs
+ for (int i = 1; i <= pModel->setting.uv; i++) {
+ pMesh->mTextureCoords[i] = new aiVector3D[pMesh->mNumVertices];
+ pMesh->mNumUVComponents[i] = 4;
+ }
+
+ map<int, vector<aiVertexWeight>> bone_vertex_map;
+
+ // fill in contents and create bones
+ for (int index = 0; index < indexCount; index++) {
+ const pmx::PmxVertex *v =
+ &pModel->vertices[pModel->indices[indexStart + index]];
+ const float *position = v->position;
+ pMesh->mVertices[index].Set(position[0], position[1], position[2]);
+ const float *normal = v->normal;
+
+ pMesh->mNormals[index].Set(normal[0], normal[1], normal[2]);
+ pMesh->mTextureCoords[0][index].x = v->uv[0];
+ pMesh->mTextureCoords[0][index].y = v->uv[1];
+
+ for (int i = 1; i <= pModel->setting.uv; i++) {
+ // TODO: wrong here? use quaternion transform?
+ pMesh->mTextureCoords[i][index].x = v->uva[i][0];
+ pMesh->mTextureCoords[i][index].y = v->uva[i][1];
+ }
+
+ // handle bone map
+ const auto vsBDEF1_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningBDEF1 *>(v->skinning.get());
+ const auto vsBDEF2_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningBDEF2 *>(v->skinning.get());
+ const auto vsBDEF4_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningBDEF4 *>(v->skinning.get());
+ const auto vsSDEF_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningSDEF *>(v->skinning.get());
+ switch (v->skinning_type) {
+ case pmx::PmxVertexSkinningType::BDEF1:
+ bone_vertex_map[vsBDEF1_ptr->bone_index].push_back(
+ aiVertexWeight(index, 1.0));
+ break;
+ case pmx::PmxVertexSkinningType::BDEF2:
+ bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsBDEF2_ptr->bone_weight));
+ bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back(
+ aiVertexWeight(index, 1.0f - vsBDEF2_ptr->bone_weight));
+ break;
+ case pmx::PmxVertexSkinningType::BDEF4:
+ bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight1));
+ bone_vertex_map[vsBDEF4_ptr->bone_index2].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight2));
+ bone_vertex_map[vsBDEF4_ptr->bone_index3].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight3));
+ bone_vertex_map[vsBDEF4_ptr->bone_index4].push_back(
+ aiVertexWeight(index, vsBDEF4_ptr->bone_weight4));
+ break;
+ case pmx::PmxVertexSkinningType::SDEF: // TODO: how to use sdef_c, sdef_r0,
+ // sdef_r1?
+ bone_vertex_map[vsSDEF_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsSDEF_ptr->bone_weight));
+ bone_vertex_map[vsSDEF_ptr->bone_index2].push_back(
+ aiVertexWeight(index, 1.0f - vsSDEF_ptr->bone_weight));
+ break;
+ case pmx::PmxVertexSkinningType::QDEF:
+ const auto vsQDEF_ptr =
+ dynamic_cast<pmx::PmxVertexSkinningQDEF *>(v->skinning.get());
+ bone_vertex_map[vsQDEF_ptr->bone_index1].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight1));
+ bone_vertex_map[vsQDEF_ptr->bone_index2].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight2));
+ bone_vertex_map[vsQDEF_ptr->bone_index3].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight3));
+ bone_vertex_map[vsQDEF_ptr->bone_index4].push_back(
+ aiVertexWeight(index, vsQDEF_ptr->bone_weight4));
+ break;
+ }
+ }
+
+ // make all bones for each mesh
+ // assign bone weights to skinned bones (otherwise just initialize)
+ auto bone_ptr_ptr = new aiBone *[pModel->bone_count];
+ pMesh->mNumBones = pModel->bone_count;
+ pMesh->mBones = bone_ptr_ptr;
+ for (auto ii = 0; ii < pModel->bone_count; ++ii) {
+ auto pBone = new aiBone;
+ const auto &pmxBone = pModel->bones[ii];
+ pBone->mName = pmxBone.bone_name;
+ aiVector3D pos(pmxBone.position[0], pmxBone.position[1], pmxBone.position[2]);
+ aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix);
+ auto it = bone_vertex_map.find(ii);
+ if (it != bone_vertex_map.end()) {
+ pBone->mNumWeights = static_cast<unsigned int>(it->second.size());
+ pBone->mWeights = it->second.data();
+ it->second.swap(*(new vector<aiVertexWeight>));
+ }
+ bone_ptr_ptr[ii] = pBone;
+ }
+
+ return pMesh;
+}
+
+// ------------------------------------------------------------------------------------------------
+aiMaterial *MMDImporter::CreateMaterial(const pmx::PmxMaterial *pMat,
+ const pmx::PmxModel *pModel) {
+ aiMaterial *mat = new aiMaterial();
+ aiString name(pMat->material_english_name);
+ mat->AddProperty(&name, AI_MATKEY_NAME);
+
+ aiColor3D diffuse(pMat->diffuse[0], pMat->diffuse[1], pMat->diffuse[2]);
+ mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ aiColor3D specular(pMat->specular[0], pMat->specular[1], pMat->specular[2]);
+ mat->AddProperty(&specular, 1, AI_MATKEY_COLOR_SPECULAR);
+ aiColor3D ambient(pMat->ambient[0], pMat->ambient[1], pMat->ambient[2]);
+ mat->AddProperty(&ambient, 1, AI_MATKEY_COLOR_AMBIENT);
+
+ float opacity = pMat->diffuse[3];
+ mat->AddProperty(&opacity, 1, AI_MATKEY_OPACITY);
+ float shininess = pMat->specularlity;
+ mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
+
+ aiString texture_path(pModel->textures[pMat->diffuse_texture_index]);
+ mat->AddProperty(&texture_path, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
+ int mapping_uvwsrc = 0;
+ mat->AddProperty(&mapping_uvwsrc, 1,
+ AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE, 0));
+
+ return mat;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_MMD_IMPORTER
diff --git a/src/3rdparty/assimp/code/MMDImporter.h b/src/3rdparty/assimp/code/MMDImporter.h
new file mode 100644
index 000000000..2620ccc9f
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDImporter.h
@@ -0,0 +1,96 @@
+/*
+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 MMD_FILE_IMPORTER_H_INC
+#define MMD_FILE_IMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include "MMDPmxParser.h"
+#include <assimp/material.h>
+#include <vector>
+
+struct aiMesh;
+
+namespace Assimp {
+
+// ------------------------------------------------------------------------------------------------
+/// \class MMDImporter
+/// \brief Imports MMD a pmx/pmd/vmd file
+// ------------------------------------------------------------------------------------------------
+class MMDImporter : public BaseImporter {
+public:
+ /// \brief Default constructor
+ MMDImporter();
+
+ /// \brief Destructor
+ ~MMDImporter();
+
+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;
+
+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 pmx::PmxModel* pModel, aiScene* pScene);
+
+ //! \brief Create the mesh
+ aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount);
+
+ //! \brief Create the material
+ aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel);
+
+private:
+ //! Data buffer
+ std::vector<char> m_Buffer;
+ //! Absolute pathname of model in file system
+ std::string m_strAbsPath;
+};
+
+// ------------------------------------------------------------------------------------------------
+
+} // Namespace Assimp
+
+#endif
diff --git a/src/3rdparty/assimp/code/MMDPmdParser.h b/src/3rdparty/assimp/code/MMDPmdParser.h
new file mode 100644
index 000000000..586f20a5f
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDPmdParser.h
@@ -0,0 +1,596 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <vector>
+#include <string>
+#include <memory>
+#include <iostream>
+#include <fstream>
+#include "MMDCpp14.h"
+
+namespace pmd
+{
+ class PmdHeader
+ {
+ public:
+ std::string name;
+ std::string name_english;
+ std::string comment;
+ std::string comment_english;
+
+ bool Read(std::ifstream* stream)
+ {
+ char buffer[256];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ stream->read(buffer, 256);
+ comment = std::string(buffer);
+ return true;
+ }
+
+ bool ReadExtension(std::ifstream* stream)
+ {
+ char buffer[256];
+ stream->read(buffer, 20);
+ name_english = std::string(buffer);
+ stream->read(buffer, 256);
+ comment_english = std::string(buffer);
+ return true;
+ }
+ };
+
+ class PmdVertex
+ {
+ public:
+ float position[3];
+
+ float normal[3];
+
+ float uv[2];
+
+ uint16_t bone_index[2];
+
+ uint8_t bone_weight;
+
+ bool edge_invisible;
+
+ bool Read(std::ifstream* stream)
+ {
+ stream->read((char*) position, sizeof(float) * 3);
+ stream->read((char*) normal, sizeof(float) * 3);
+ stream->read((char*) uv, sizeof(float) * 2);
+ stream->read((char*) bone_index, sizeof(uint16_t) * 2);
+ stream->read((char*) &bone_weight, sizeof(uint8_t));
+ stream->read((char*) &edge_invisible, sizeof(uint8_t));
+ return true;
+ }
+ };
+
+ class PmdMaterial
+ {
+ public:
+ float diffuse[4];
+ float power;
+ float specular[3];
+ float ambient[3];
+ uint8_t toon_index;
+ uint8_t edge_flag;
+ uint32_t index_count;
+ std::string texture_filename;
+ std::string sphere_filename;
+
+ bool Read(std::ifstream* stream)
+ {
+ char buffer[20];
+ stream->read((char*) &diffuse, sizeof(float) * 4);
+ stream->read((char*) &power, sizeof(float));
+ stream->read((char*) &specular, sizeof(float) * 3);
+ stream->read((char*) &ambient, sizeof(float) * 3);
+ stream->read((char*) &toon_index, sizeof(uint8_t));
+ stream->read((char*) &edge_flag, sizeof(uint8_t));
+ stream->read((char*) &index_count, sizeof(uint32_t));
+ stream->read((char*) &buffer, sizeof(char) * 20);
+ char* pstar = strchr(buffer, '*');
+ if (NULL == pstar)
+ {
+ texture_filename = std::string(buffer);
+ sphere_filename.clear();
+ }
+ else {
+ *pstar = 0;
+ texture_filename = std::string(buffer);
+ sphere_filename = std::string(pstar+1);
+ }
+ return true;
+ }
+ };
+
+ enum class BoneType : uint8_t
+ {
+ Rotation,
+ RotationAndMove,
+ IkEffector,
+ Unknown,
+ IkEffectable,
+ RotationEffectable,
+ IkTarget,
+ Invisible,
+ Twist,
+ RotationMovement
+ };
+
+ class PmdBone
+ {
+ public:
+ std::string name;
+ std::string name_english;
+ uint16_t parent_bone_index;
+ uint16_t tail_pos_bone_index;
+ BoneType bone_type;
+ uint16_t ik_parent_bone_index;
+ float bone_head_pos[3];
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ stream->read((char*) &parent_bone_index, sizeof(uint16_t));
+ stream->read((char*) &tail_pos_bone_index, sizeof(uint16_t));
+ stream->read((char*) &bone_type, sizeof(uint8_t));
+ stream->read((char*) &ik_parent_bone_index, sizeof(uint16_t));
+ stream->read((char*) &bone_head_pos, sizeof(float) * 3);
+ }
+
+ void ReadExpantion(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name_english = std::string(buffer);
+ }
+ };
+
+ class PmdIk
+ {
+ public:
+ uint16_t ik_bone_index;
+ uint16_t target_bone_index;
+ uint16_t interations;
+ float angle_limit;
+ std::vector<uint16_t> ik_child_bone_index;
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char *) &ik_bone_index, sizeof(uint16_t));
+ stream->read((char *) &target_bone_index, sizeof(uint16_t));
+ uint8_t ik_chain_length;
+ stream->read((char*) &ik_chain_length, sizeof(uint8_t));
+ stream->read((char *) &interations, sizeof(uint16_t));
+ stream->read((char *) &angle_limit, sizeof(float));
+ ik_child_bone_index.resize(ik_chain_length);
+ for (int i = 0; i < ik_chain_length; i++)
+ {
+ stream->read((char *) &ik_child_bone_index[i], sizeof(uint16_t));
+ }
+ }
+ };
+
+ class PmdFaceVertex
+ {
+ public:
+ int vertex_index;
+ float position[3];
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char *) &vertex_index, sizeof(int));
+ stream->read((char *) position, sizeof(float) * 3);
+ }
+ };
+
+ enum class FaceCategory : uint8_t
+ {
+ Base,
+ Eyebrow,
+ Eye,
+ Mouth,
+ Other
+ };
+
+ class PmdFace
+ {
+ public:
+ std::string name;
+ FaceCategory type;
+ std::vector<PmdFaceVertex> vertices;
+ std::string name_english;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ int vertex_count;
+ stream->read((char*) &vertex_count, sizeof(int));
+ stream->read((char*) &type, sizeof(uint8_t));
+ vertices.resize(vertex_count);
+ for (int i = 0; i < vertex_count; i++)
+ {
+ vertices[i].Read(stream);
+ }
+ }
+
+ void ReadExpantion(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name_english = std::string(buffer);
+ }
+ };
+
+ class PmdBoneDispName
+ {
+ public:
+ std::string bone_disp_name;
+ std::string bone_disp_name_english;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[50];
+ stream->read(buffer, 50);
+ bone_disp_name = std::string(buffer);
+ bone_disp_name_english.clear();
+ }
+ void ReadExpantion(std::istream *stream)
+ {
+ char buffer[50];
+ stream->read(buffer, 50);
+ bone_disp_name_english = std::string(buffer);
+ }
+ };
+
+ class PmdBoneDisp
+ {
+ public:
+ uint16_t bone_index;
+ uint8_t bone_disp_index;
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char*) &bone_index, sizeof(uint16_t));
+ stream->read((char*) &bone_disp_index, sizeof(uint8_t));
+ }
+ };
+
+ enum class RigidBodyShape : uint8_t
+ {
+ Sphere = 0,
+ Box = 1,
+ Cpusel = 2
+ };
+
+ enum class RigidBodyType : uint8_t
+ {
+ BoneConnected = 0,
+ Physics = 1,
+ ConnectedPhysics = 2
+ };
+
+ class PmdRigidBody
+ {
+ public:
+ std::string name;
+ uint16_t related_bone_index;
+ uint8_t group_index;
+ uint16_t mask;
+ RigidBodyShape shape;
+ float size[3];
+ float position[3];
+ float orientation[3];
+ float weight;
+ float linear_damping;
+ float anglar_damping;
+ float restitution;
+ float friction;
+ RigidBodyType rigid_type;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, sizeof(char) * 20);
+ name = (std::string(buffer));
+ stream->read((char*) &related_bone_index, sizeof(uint16_t));
+ stream->read((char*) &group_index, sizeof(uint8_t));
+ stream->read((char*) &mask, sizeof(uint16_t));
+ stream->read((char*) &shape, sizeof(uint8_t));
+ stream->read((char*) size, sizeof(float) * 3);
+ stream->read((char*) position, sizeof(float) * 3);
+ stream->read((char*) orientation, sizeof(float) * 3);
+ stream->read((char*) &weight, sizeof(float));
+ stream->read((char*) &linear_damping, sizeof(float));
+ stream->read((char*) &anglar_damping, sizeof(float));
+ stream->read((char*) &restitution, sizeof(float));
+ stream->read((char*) &friction, sizeof(float));
+ stream->read((char*) &rigid_type, sizeof(char));
+ }
+ };
+
+ class PmdConstraint
+ {
+ public:
+ std::string name;
+ uint32_t rigid_body_index_a;
+ uint32_t rigid_body_index_b;
+ float position[3];
+ float orientation[3];
+ float linear_lower_limit[3];
+ float linear_upper_limit[3];
+ float angular_lower_limit[3];
+ float angular_upper_limit[3];
+ float linear_stiffness[3];
+ float angular_stiffness[3];
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read(buffer, 20);
+ name = std::string(buffer);
+ stream->read((char *) &rigid_body_index_a, sizeof(uint32_t));
+ stream->read((char *) &rigid_body_index_b, sizeof(uint32_t));
+ stream->read((char *) position, sizeof(float) * 3);
+ stream->read((char *) orientation, sizeof(float) * 3);
+ stream->read((char *) linear_lower_limit, sizeof(float) * 3);
+ stream->read((char *) linear_upper_limit, sizeof(float) * 3);
+ stream->read((char *) angular_lower_limit, sizeof(float) * 3);
+ stream->read((char *) angular_upper_limit, sizeof(float) * 3);
+ stream->read((char *) linear_stiffness, sizeof(float) * 3);
+ stream->read((char *) angular_stiffness, sizeof(float) * 3);
+ }
+ };
+
+ class PmdModel
+ {
+ public:
+ float version;
+ PmdHeader header;
+ std::vector<PmdVertex> vertices;
+ std::vector<uint16_t> indices;
+ std::vector<PmdMaterial> materials;
+ std::vector<PmdBone> bones;
+ std::vector<PmdIk> iks;
+ std::vector<PmdFace> faces;
+ std::vector<uint16_t> faces_indices;
+ std::vector<PmdBoneDispName> bone_disp_name;
+ std::vector<PmdBoneDisp> bone_disp;
+ std::vector<std::string> toon_filenames;
+ std::vector<PmdRigidBody> rigid_bodies;
+ std::vector<PmdConstraint> constraints;
+
+ static std::unique_ptr<PmdModel> LoadFromFile(const char *filename)
+ {
+ std::ifstream stream(filename, std::ios::binary);
+ if (stream.fail())
+ {
+ std::cerr << "could not open \"" << filename << "\"" << std::endl;
+ return nullptr;
+ }
+ auto result = LoadFromStream(&stream);
+ stream.close();
+ return result;
+ }
+
+ static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
+ {
+ auto result = mmd::make_unique<PmdModel>();
+ char buffer[100];
+
+ // magic
+ char magic[3];
+ stream->read(magic, 3);
+ if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd')
+ {
+ std::cerr << "invalid file" << std::endl;
+ return nullptr;
+ }
+
+ // version
+ stream->read((char*) &(result->version), sizeof(float));
+ if (result ->version != 1.0f)
+ {
+ std::cerr << "invalid version" << std::endl;
+ return nullptr;
+ }
+
+ // header
+ result->header.Read(stream);
+
+ // vertices
+ uint32_t vertex_num;
+ stream->read((char*) &vertex_num, sizeof(uint32_t));
+ result->vertices.resize(vertex_num);
+ for (uint32_t i = 0; i < vertex_num; i++)
+ {
+ result->vertices[i].Read(stream);
+ }
+
+ // indices
+ uint32_t index_num;
+ stream->read((char*) &index_num, sizeof(uint32_t));
+ result->indices.resize(index_num);
+ for (uint32_t i = 0; i < index_num; i++)
+ {
+ stream->read((char*) &result->indices[i], sizeof(uint16_t));
+ }
+
+ // materials
+ uint32_t material_num;
+ stream->read((char*) &material_num, sizeof(uint32_t));
+ result->materials.resize(material_num);
+ for (uint32_t i = 0; i < material_num; i++)
+ {
+ result->materials[i].Read(stream);
+ }
+
+ // bones
+ uint16_t bone_num;
+ stream->read((char*) &bone_num, sizeof(uint16_t));
+ result->bones.resize(bone_num);
+ for (uint32_t i = 0; i < bone_num; i++)
+ {
+ result->bones[i].Read(stream);
+ }
+
+ // iks
+ uint16_t ik_num;
+ stream->read((char*) &ik_num, sizeof(uint16_t));
+ result->iks.resize(ik_num);
+ for (uint32_t i = 0; i < ik_num; i++)
+ {
+ result->iks[i].Read(stream);
+ }
+
+ // faces
+ uint16_t face_num;
+ stream->read((char*) &face_num, sizeof(uint16_t));
+ result->faces.resize(face_num);
+ for (uint32_t i = 0; i < face_num; i++)
+ {
+ result->faces[i].Read(stream);
+ }
+
+ // face frames
+ uint8_t face_frame_num;
+ stream->read((char*) &face_frame_num, sizeof(uint8_t));
+ result->faces_indices.resize(face_frame_num);
+ for (uint32_t i = 0; i < face_frame_num; i++)
+ {
+ stream->read((char*) &result->faces_indices[i], sizeof(uint16_t));
+ }
+
+ // bone names
+ uint8_t bone_disp_num;
+ stream->read((char*) &bone_disp_num, sizeof(uint8_t));
+ result->bone_disp_name.resize(bone_disp_num);
+ for (uint32_t i = 0; i < bone_disp_num; i++)
+ {
+ result->bone_disp_name[i].Read(stream);
+ }
+
+ // bone frame
+ uint32_t bone_frame_num;
+ stream->read((char*) &bone_frame_num, sizeof(uint32_t));
+ result->bone_disp.resize(bone_frame_num);
+ for (uint32_t i = 0; i < bone_frame_num; i++)
+ {
+ result->bone_disp[i].Read(stream);
+ }
+
+ // english name
+ bool english;
+ stream->read((char*) &english, sizeof(char));
+ if (english)
+ {
+ result->header.ReadExtension(stream);
+ for (uint32_t i = 0; i < bone_num; i++)
+ {
+ result->bones[i].ReadExpantion(stream);
+ }
+ for (uint32_t i = 0; i < face_num; i++)
+ {
+ if (result->faces[i].type == pmd::FaceCategory::Base)
+ {
+ continue;
+ }
+ result->faces[i].ReadExpantion(stream);
+ }
+ for (uint32_t i = 0; i < result->bone_disp_name.size(); i++)
+ {
+ result->bone_disp_name[i].ReadExpantion(stream);
+ }
+ }
+
+ // toon textures
+ if (stream->peek() == std::ios::traits_type::eof())
+ {
+ result->toon_filenames.clear();
+ }
+ else {
+ result->toon_filenames.resize(10);
+ for (uint32_t i = 0; i < 10; i++)
+ {
+ stream->read(buffer, 100);
+ result->toon_filenames[i] = std::string(buffer);
+ }
+ }
+
+ // physics
+ if (stream->peek() == std::ios::traits_type::eof())
+ {
+ result->rigid_bodies.clear();
+ result->constraints.clear();
+ }
+ else {
+ uint32_t rigid_body_num;
+ stream->read((char*) &rigid_body_num, sizeof(uint32_t));
+ result->rigid_bodies.resize(rigid_body_num);
+ for (uint32_t i = 0; i < rigid_body_num; i++)
+ {
+ result->rigid_bodies[i].Read(stream);
+ }
+ uint32_t constraint_num;
+ stream->read((char*) &constraint_num, sizeof(uint32_t));
+ result->constraints.resize(constraint_num);
+ for (uint32_t i = 0; i < constraint_num; i++)
+ {
+ result->constraints[i].Read(stream);
+ }
+ }
+
+ if (stream->peek() != std::ios::traits_type::eof())
+ {
+ std::cerr << "there is unknown data" << std::endl;
+ }
+
+ return result;
+ }
+ };
+}
diff --git a/src/3rdparty/assimp/code/MMDPmxParser.cpp b/src/3rdparty/assimp/code/MMDPmxParser.cpp
new file mode 100644
index 000000000..970cbc31e
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDPmxParser.cpp
@@ -0,0 +1,637 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 <utility>
+#include "MMDPmxParser.h"
+#include "../contrib/utf8cpp/source/utf8.h"
+#include "Exceptional.h"
+
+namespace pmx
+{
+ int ReadIndex(std::istream *stream, int size)
+ {
+ switch (size)
+ {
+ case 1:
+ uint8_t tmp8;
+ stream->read((char*) &tmp8, sizeof(uint8_t));
+ if (255 == tmp8)
+ {
+ return -1;
+ }
+ else {
+ return (int) tmp8;
+ }
+ case 2:
+ uint16_t tmp16;
+ stream->read((char*) &tmp16, sizeof(uint16_t));
+ if (65535 == tmp16)
+ {
+ return -1;
+ }
+ else {
+ return (int) tmp16;
+ }
+ case 4:
+ int tmp32;
+ stream->read((char*) &tmp32, sizeof(int));
+ return tmp32;
+ default:
+ return -1;
+ }
+ }
+
+ std::string ReadString(std::istream *stream, uint8_t encoding)
+ {
+ int size;
+ stream->read((char*) &size, sizeof(int));
+ std::vector<char> buffer;
+ if (size == 0)
+ {
+ return std::string("");
+ }
+ buffer.reserve(size);
+ stream->read((char*) buffer.data(), size);
+ if (encoding == 0)
+ {
+ // UTF16 to UTF8
+ std::string result;
+
+ const char* sourceStart = buffer.data();
+ const unsigned int targetSize = size * 3; // enough to encode
+ char* targetStart = new char[targetSize]();
+ const char* targetReserved = targetStart;
+ utf8::utf16to8( sourceStart, sourceStart + size, targetStart );
+
+ result.assign(targetReserved, targetStart - targetReserved);
+ delete[] targetReserved;
+ return result;
+ }
+ else
+ {
+ // the name is already UTF8
+ return std::string((const char*)buffer.data(), size);
+ }
+ }
+
+ void PmxSetting::Read(std::istream *stream)
+ {
+ uint8_t count;
+ stream->read((char*) &count, sizeof(uint8_t));
+ if (count < 8)
+ {
+ throw;
+ }
+ stream->read((char*) &encoding, sizeof(uint8_t));
+ stream->read((char*) &uv, sizeof(uint8_t));
+ stream->read((char*) &vertex_index_size, sizeof(uint8_t));
+ stream->read((char*) &texture_index_size, sizeof(uint8_t));
+ stream->read((char*) &material_index_size, sizeof(uint8_t));
+ stream->read((char*) &bone_index_size, sizeof(uint8_t));
+ stream->read((char*) &morph_index_size, sizeof(uint8_t));
+ stream->read((char*) &rigidbody_index_size, sizeof(uint8_t));
+ uint8_t temp;
+ for (int i = 8; i < count; i++)
+ {
+ stream->read((char*)&temp, sizeof(uint8_t));
+ }
+ }
+
+ void PmxVertexSkinningBDEF1::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index = ReadIndex(stream, setting->bone_index_size);
+ }
+
+ void PmxVertexSkinningBDEF2::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight, sizeof(float));
+ }
+
+ void PmxVertexSkinningBDEF4::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index3 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index4 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight1, sizeof(float));
+ stream->read((char*) &this->bone_weight2, sizeof(float));
+ stream->read((char*) &this->bone_weight3, sizeof(float));
+ stream->read((char*) &this->bone_weight4, sizeof(float));
+ }
+
+ void PmxVertexSkinningSDEF::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight, sizeof(float));
+ stream->read((char*) this->sdef_c, sizeof(float) * 3);
+ stream->read((char*) this->sdef_r0, sizeof(float) * 3);
+ stream->read((char*) this->sdef_r1, sizeof(float) * 3);
+ }
+
+ void PmxVertexSkinningQDEF::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index1 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index2 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index3 = ReadIndex(stream, setting->bone_index_size);
+ this->bone_index4 = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->bone_weight1, sizeof(float));
+ stream->read((char*) &this->bone_weight2, sizeof(float));
+ stream->read((char*) &this->bone_weight3, sizeof(float));
+ stream->read((char*) &this->bone_weight4, sizeof(float));
+ }
+
+ void PmxVertex::Read(std::istream *stream, PmxSetting *setting)
+ {
+ stream->read((char*) this->position, sizeof(float) * 3);
+ stream->read((char*) this->normal, sizeof(float) * 3);
+ stream->read((char*) this->uv, sizeof(float) * 2);
+ for (int i = 0; i < setting->uv; ++i)
+ {
+ stream->read((char*) this->uva[i], sizeof(float) * 4);
+ }
+ stream->read((char*) &this->skinning_type, sizeof(PmxVertexSkinningType));
+ switch (this->skinning_type)
+ {
+ case PmxVertexSkinningType::BDEF1:
+ this->skinning = mmd::make_unique<PmxVertexSkinningBDEF1>();
+ break;
+ case PmxVertexSkinningType::BDEF2:
+ this->skinning = mmd::make_unique<PmxVertexSkinningBDEF2>();
+ break;
+ case PmxVertexSkinningType::BDEF4:
+ this->skinning = mmd::make_unique<PmxVertexSkinningBDEF4>();
+ break;
+ case PmxVertexSkinningType::SDEF:
+ this->skinning = mmd::make_unique<PmxVertexSkinningSDEF>();
+ break;
+ case PmxVertexSkinningType::QDEF:
+ this->skinning = mmd::make_unique<PmxVertexSkinningQDEF>();
+ break;
+ default:
+ throw "invalid skinning type";
+ }
+ this->skinning->Read(stream, setting);
+ stream->read((char*) &this->edge, sizeof(float));
+ }
+
+ void PmxMaterial::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->material_name = ReadString(stream, setting->encoding);
+ this->material_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) this->diffuse, sizeof(float) * 4);
+ stream->read((char*) this->specular, sizeof(float) * 3);
+ stream->read((char*) &this->specularlity, sizeof(float));
+ stream->read((char*) this->ambient, sizeof(float) * 3);
+ stream->read((char*) &this->flag, sizeof(uint8_t));
+ stream->read((char*) this->edge_color, sizeof(float) * 4);
+ stream->read((char*) &this->edge_size, sizeof(float));
+ this->diffuse_texture_index = ReadIndex(stream, setting->texture_index_size);
+ this->sphere_texture_index = ReadIndex(stream, setting->texture_index_size);
+ stream->read((char*) &this->sphere_op_mode, sizeof(uint8_t));
+ stream->read((char*) &this->common_toon_flag, sizeof(uint8_t));
+ if (this->common_toon_flag)
+ {
+ stream->read((char*) &this->toon_texture_index, sizeof(uint8_t));
+ }
+ else {
+ this->toon_texture_index = ReadIndex(stream, setting->texture_index_size);
+ }
+ this->memo = ReadString(stream, setting->encoding);
+ stream->read((char*) &this->index_count, sizeof(int));
+ }
+
+ void PmxIkLink::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->link_target = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->angle_lock, sizeof(uint8_t));
+ if (angle_lock == 1)
+ {
+ stream->read((char*) this->max_radian, sizeof(float) * 3);
+ stream->read((char*) this->min_radian, sizeof(float) * 3);
+ }
+ }
+
+ void PmxBone::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_name = ReadString(stream, setting->encoding);
+ this->bone_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) this->position, sizeof(float) * 3);
+ this->parent_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->level, sizeof(int));
+ stream->read((char*) &this->bone_flag, sizeof(uint16_t));
+ if (this->bone_flag & 0x0001) {
+ this->target_index = ReadIndex(stream, setting->bone_index_size);
+ }
+ else {
+ stream->read((char*)this->offset, sizeof(float) * 3);
+ }
+ if (this->bone_flag & (0x0100 | 0x0200)) {
+ this->grant_parent_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->grant_weight, sizeof(float));
+ }
+ if (this->bone_flag & 0x0400) {
+ stream->read((char*)this->lock_axis_orientation, sizeof(float) * 3);
+ }
+ if (this->bone_flag & 0x0800) {
+ stream->read((char*)this->local_axis_x_orientation, sizeof(float) * 3);
+ stream->read((char*)this->local_axis_y_orientation, sizeof(float) * 3);
+ }
+ if (this->bone_flag & 0x2000) {
+ stream->read((char*) &this->key, sizeof(int));
+ }
+ if (this->bone_flag & 0x0020) {
+ this->ik_target_bone_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &ik_loop, sizeof(int));
+ stream->read((char*) &ik_loop_angle_limit, sizeof(float));
+ stream->read((char*) &ik_link_count, sizeof(int));
+ this->ik_links = mmd::make_unique<PmxIkLink []>(ik_link_count);
+ for (int i = 0; i < ik_link_count; i++) {
+ ik_links[i].Read(stream, setting);
+ }
+ }
+ }
+
+ void PmxMorphVertexOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->vertex_index = ReadIndex(stream, setting->vertex_index_size);
+ stream->read((char*)this->position_offset, sizeof(float) * 3);
+ }
+
+ void PmxMorphUVOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->vertex_index = ReadIndex(stream, setting->vertex_index_size);
+ stream->read((char*)this->uv_offset, sizeof(float) * 4);
+ }
+
+ void PmxMorphBoneOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->bone_index = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*)this->translation, sizeof(float) * 3);
+ stream->read((char*)this->rotation, sizeof(float) * 4);
+ }
+
+ void PmxMorphMaterialOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->material_index = ReadIndex(stream, setting->material_index_size);
+ stream->read((char*) &this->offset_operation, sizeof(uint8_t));
+ stream->read((char*)this->diffuse, sizeof(float) * 4);
+ stream->read((char*)this->specular, sizeof(float) * 3);
+ stream->read((char*) &this->specularity, sizeof(float));
+ stream->read((char*)this->ambient, sizeof(float) * 3);
+ stream->read((char*)this->edge_color, sizeof(float) * 4);
+ stream->read((char*) &this->edge_size, sizeof(float));
+ stream->read((char*)this->texture_argb, sizeof(float) * 4);
+ stream->read((char*)this->sphere_texture_argb, sizeof(float) * 4);
+ stream->read((char*)this->toon_texture_argb, sizeof(float) * 4);
+ }
+
+ void PmxMorphGroupOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->morph_index = ReadIndex(stream, setting->morph_index_size);
+ stream->read((char*) &this->morph_weight, sizeof(float));
+ }
+
+ void PmxMorphFlipOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->morph_index = ReadIndex(stream, setting->morph_index_size);
+ stream->read((char*) &this->morph_value, sizeof(float));
+ }
+
+ void PmxMorphImplusOffset::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->rigid_body_index = ReadIndex(stream, setting->rigidbody_index_size);
+ stream->read((char*) &this->is_local, sizeof(uint8_t));
+ stream->read((char*)this->velocity, sizeof(float) * 3);
+ stream->read((char*)this->angular_torque, sizeof(float) * 3);
+ }
+
+ void PmxMorph::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->morph_name = ReadString(stream, setting->encoding);
+ this->morph_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) &category, sizeof(MorphCategory));
+ stream->read((char*) &morph_type, sizeof(MorphType));
+ stream->read((char*) &this->offset_count, sizeof(int));
+ switch (this->morph_type)
+ {
+ case MorphType::Group:
+ group_offsets = mmd::make_unique<PmxMorphGroupOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ group_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::Vertex:
+ vertex_offsets = mmd::make_unique<PmxMorphVertexOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ vertex_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::Bone:
+ bone_offsets = mmd::make_unique<PmxMorphBoneOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ bone_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::Matrial:
+ material_offsets = mmd::make_unique<PmxMorphMaterialOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ material_offsets[i].Read(stream, setting);
+ }
+ break;
+ case MorphType::UV:
+ case MorphType::AdditionalUV1:
+ case MorphType::AdditionalUV2:
+ case MorphType::AdditionalUV3:
+ case MorphType::AdditionalUV4:
+ uv_offsets = mmd::make_unique<PmxMorphUVOffset []>(this->offset_count);
+ for (int i = 0; i < offset_count; i++)
+ {
+ uv_offsets[i].Read(stream, setting);
+ }
+ break;
+ default:
+ throw;
+ }
+ }
+
+ void PmxFrameElement::Read(std::istream *stream, PmxSetting *setting)
+ {
+ stream->read((char*) &this->element_target, sizeof(uint8_t));
+ if (this->element_target == 0x00)
+ {
+ this->index = ReadIndex(stream, setting->bone_index_size);
+ }
+ else {
+ this->index = ReadIndex(stream, setting->morph_index_size);
+ }
+ }
+
+ void PmxFrame::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->frame_name = ReadString(stream, setting->encoding);
+ this->frame_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) &this->frame_flag, sizeof(uint8_t));
+ stream->read((char*) &this->element_count, sizeof(int));
+ this->elements = mmd::make_unique<PmxFrameElement []>(this->element_count);
+ for (int i = 0; i < this->element_count; i++)
+ {
+ this->elements[i].Read(stream, setting);
+ }
+ }
+
+ void PmxRigidBody::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->girid_body_name = ReadString(stream, setting->encoding);
+ this->girid_body_english_name = ReadString(stream, setting->encoding);
+ this->target_bone = ReadIndex(stream, setting->bone_index_size);
+ stream->read((char*) &this->group, sizeof(uint8_t));
+ stream->read((char*) &this->mask, sizeof(uint16_t));
+ stream->read((char*) &this->shape, sizeof(uint8_t));
+ stream->read((char*) this->size, sizeof(float) * 3);
+ stream->read((char*) this->position, sizeof(float) * 3);
+ stream->read((char*) this->orientation, sizeof(float) * 3);
+ stream->read((char*) &this->mass, sizeof(float));
+ stream->read((char*) &this->move_attenuation, sizeof(float));
+ stream->read((char*) &this->rotation_attenuation, sizeof(float));
+ stream->read((char*) &this->repulsion, sizeof(float));
+ stream->read((char*) &this->friction, sizeof(float));
+ stream->read((char*) &this->physics_calc_type, sizeof(uint8_t));
+ }
+
+ void PmxJointParam::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->rigid_body1 = ReadIndex(stream, setting->rigidbody_index_size);
+ this->rigid_body2 = ReadIndex(stream, setting->rigidbody_index_size);
+ stream->read((char*) this->position, sizeof(float) * 3);
+ stream->read((char*) this->orientaiton, sizeof(float) * 3);
+ stream->read((char*) this->move_limitation_min, sizeof(float) * 3);
+ stream->read((char*) this->move_limitation_max, sizeof(float) * 3);
+ stream->read((char*) this->rotation_limitation_min, sizeof(float) * 3);
+ stream->read((char*) this->rotation_limitation_max, sizeof(float) * 3);
+ stream->read((char*) this->spring_move_coefficient, sizeof(float) * 3);
+ stream->read((char*) this->spring_rotation_coefficient, sizeof(float) * 3);
+ }
+
+ void PmxJoint::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->joint_name = ReadString(stream, setting->encoding);
+ this->joint_english_name = ReadString(stream, setting->encoding);
+ stream->read((char*) &this->joint_type, sizeof(uint8_t));
+ this->param.Read(stream, setting);
+ }
+
+ void PmxAncherRigidBody::Read(std::istream *stream, PmxSetting *setting)
+ {
+ this->related_rigid_body = ReadIndex(stream, setting->rigidbody_index_size);
+ this->related_vertex = ReadIndex(stream, setting->vertex_index_size);
+ stream->read((char*) &this->is_near, sizeof(uint8_t));
+ }
+
+ void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/)
+ {
+ // 未実装
+ std::cerr << "Not Implemented Exception" << std::endl;
+ throw;
+ }
+
+ void PmxModel::Init()
+ {
+ this->version = 0.0f;
+ this->model_name.clear();
+ this->model_english_name.clear();
+ this->model_comment.clear();
+ this->model_english_comment.clear();
+ this->vertex_count = 0;
+ this->vertices = nullptr;
+ this->index_count = 0;
+ this->indices = nullptr;
+ this->texture_count = 0;
+ this->textures = nullptr;
+ this->material_count = 0;
+ this->materials = nullptr;
+ this->bone_count = 0;
+ this->bones = nullptr;
+ this->morph_count = 0;
+ this->morphs = nullptr;
+ this->frame_count = 0;
+ this->frames = nullptr;
+ this->rigid_body_count = 0;
+ this->rigid_bodies = nullptr;
+ this->joint_count = 0;
+ this->joints = nullptr;
+ this->soft_body_count = 0;
+ this->soft_bodies = nullptr;
+ }
+
+ void PmxModel::Read(std::istream *stream)
+ {
+ // マジック
+ char magic[4];
+ stream->read((char*) magic, sizeof(char) * 4);
+ if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
+ {
+ std::cerr << "invalid magic number." << std::endl;
+ throw;
+ }
+ // バージョン
+ stream->read((char*) &version, sizeof(float));
+ if (version != 2.0f && version != 2.1f)
+ {
+ std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl;
+ throw;
+ }
+ // ファイル設定
+ this->setting.Read(stream);
+
+ // モデル情報
+ this->model_name = ReadString(stream, setting.encoding);
+ this->model_english_name = ReadString(stream, setting.encoding);
+ this->model_comment = ReadString(stream, setting.encoding);
+ this->model_english_comment = ReadString(stream, setting.encoding);
+
+ // 頂点
+ stream->read((char*) &vertex_count, sizeof(int));
+ this->vertices = mmd::make_unique<PmxVertex []>(vertex_count);
+ for (int i = 0; i < vertex_count; i++)
+ {
+ vertices[i].Read(stream, &setting);
+ }
+
+ // 面
+ stream->read((char*) &index_count, sizeof(int));
+ this->indices = mmd::make_unique<int []>(index_count);
+ for (int i = 0; i < index_count; i++)
+ {
+ this->indices[i] = ReadIndex(stream, setting.vertex_index_size);
+ }
+
+ // テクスチャ
+ stream->read((char*) &texture_count, sizeof(int));
+ this->textures = mmd::make_unique<std::string []>(texture_count);
+ for (int i = 0; i < texture_count; i++)
+ {
+ this->textures[i] = ReadString(stream, setting.encoding);
+ }
+
+ // マテリアル
+ stream->read((char*) &material_count, sizeof(int));
+ this->materials = mmd::make_unique<PmxMaterial []>(material_count);
+ for (int i = 0; i < material_count; i++)
+ {
+ this->materials[i].Read(stream, &setting);
+ }
+
+ // ボーン
+ stream->read((char*) &this->bone_count, sizeof(int));
+ this->bones = mmd::make_unique<PmxBone []>(this->bone_count);
+ for (int i = 0; i < this->bone_count; i++)
+ {
+ this->bones[i].Read(stream, &setting);
+ }
+
+ // モーフ
+ stream->read((char*) &this->morph_count, sizeof(int));
+ this->morphs = mmd::make_unique<PmxMorph []>(this->morph_count);
+ for (int i = 0; i < this->morph_count; i++)
+ {
+ this->morphs[i].Read(stream, &setting);
+ }
+
+ // 表示枠
+ stream->read((char*) &this->frame_count, sizeof(int));
+ this->frames = mmd::make_unique<PmxFrame []>(this->frame_count);
+ for (int i = 0; i < this->frame_count; i++)
+ {
+ this->frames[i].Read(stream, &setting);
+ }
+
+ // 剛体
+ stream->read((char*) &this->rigid_body_count, sizeof(int));
+ this->rigid_bodies = mmd::make_unique<PmxRigidBody []>(this->rigid_body_count);
+ for (int i = 0; i < this->rigid_body_count; i++)
+ {
+ this->rigid_bodies[i].Read(stream, &setting);
+ }
+
+ // ジョイント
+ stream->read((char*) &this->joint_count, sizeof(int));
+ this->joints = mmd::make_unique<PmxJoint []>(this->joint_count);
+ for (int i = 0; i < this->joint_count; i++)
+ {
+ this->joints[i].Read(stream, &setting);
+ }
+
+ //if (this->version == 2.1f)
+ //{
+ // stream->read((char*) &this->soft_body_count, sizeof(int));
+ // this->soft_bodies = mmd::make_unique<PmxSoftBody []>(this->soft_body_count);
+ // for (int i = 0; i < this->soft_body_count; i++)
+ // {
+ // this->soft_bodies[i].Read(stream, &setting);
+ // }
+ //}
+ }
+
+ //std::unique_ptr<PmxModel> ReadFromFile(const char *filename)
+ //{
+ // auto stream = std::ifstream(filename, std::ios_base::binary);
+ // auto pmx = PmxModel::ReadFromStream(&stream);
+ // if (!stream.eof())
+ // {
+ // std::cerr << "don't reach the end of file." << std::endl;
+ // }
+ // stream.close();
+ // return pmx;
+ //}
+
+ //std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream)
+ //{
+ // auto pmx = mmd::make_unique<PmxModel>();
+ // pmx->Read(stream);
+ // return pmx;
+ //}
+}
diff --git a/src/3rdparty/assimp/code/MMDPmxParser.h b/src/3rdparty/assimp/code/MMDPmxParser.h
new file mode 100644
index 000000000..989cffed6
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDPmxParser.h
@@ -0,0 +1,780 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include "MMDCpp14.h"
+
+namespace pmx
+{
+ class PmxSetting
+ {
+ public:
+ PmxSetting()
+ : encoding(0)
+ , uv(0)
+ , vertex_index_size(0)
+ , texture_index_size(0)
+ , material_index_size(0)
+ , bone_index_size(0)
+ , morph_index_size(0)
+ , rigidbody_index_size(0)
+ {}
+
+ uint8_t encoding;
+ uint8_t uv;
+ uint8_t vertex_index_size;
+ uint8_t texture_index_size;
+ uint8_t material_index_size;
+ uint8_t bone_index_size;
+ uint8_t morph_index_size;
+ uint8_t rigidbody_index_size;
+ void Read(std::istream *stream);
+ };
+
+ enum class PmxVertexSkinningType : uint8_t
+ {
+ BDEF1 = 0,
+ BDEF2 = 1,
+ BDEF4 = 2,
+ SDEF = 3,
+ QDEF = 4,
+ };
+
+ class PmxVertexSkinning
+ {
+ public:
+ virtual void Read(std::istream *stream, PmxSetting *setting) = 0;
+ };
+
+ class PmxVertexSkinningBDEF1 : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningBDEF1()
+ : bone_index(0)
+ {}
+
+ int bone_index;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningBDEF2 : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningBDEF2()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_weight(0.0f)
+ {}
+
+ int bone_index1;
+ int bone_index2;
+ float bone_weight;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningBDEF4 : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningBDEF4()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_index3(0)
+ , bone_index4(0)
+ , bone_weight1(0.0f)
+ , bone_weight2(0.0f)
+ , bone_weight3(0.0f)
+ , bone_weight4(0.0f)
+ {}
+
+ int bone_index1;
+ int bone_index2;
+ int bone_index3;
+ int bone_index4;
+ float bone_weight1;
+ float bone_weight2;
+ float bone_weight3;
+ float bone_weight4;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningSDEF : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningSDEF()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_weight(0.0f)
+ {
+ for (int i = 0; i < 3; ++i) {
+ sdef_c[i] = 0.0f;
+ sdef_r0[i] = 0.0f;
+ sdef_r1[i] = 0.0f;
+ }
+ }
+
+ int bone_index1;
+ int bone_index2;
+ float bone_weight;
+ float sdef_c[3];
+ float sdef_r0[3];
+ float sdef_r1[3];
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertexSkinningQDEF : public PmxVertexSkinning
+ {
+ public:
+ PmxVertexSkinningQDEF()
+ : bone_index1(0)
+ , bone_index2(0)
+ , bone_index3(0)
+ , bone_index4(0)
+ , bone_weight1(0.0f)
+ , bone_weight2(0.0f)
+ , bone_weight3(0.0f)
+ , bone_weight4(0.0f)
+ {}
+
+ int bone_index1;
+ int bone_index2;
+ int bone_index3;
+ int bone_index4;
+ float bone_weight1;
+ float bone_weight2;
+ float bone_weight3;
+ float bone_weight4;
+ void Read(std::istream *stresam, PmxSetting *setting);
+ };
+
+ class PmxVertex
+ {
+ public:
+ PmxVertex()
+ : edge(0.0f)
+ {
+ uv[0] = uv[1] = 0.0f;
+ for (int i = 0; i < 3; ++i) {
+ position[i] = 0.0f;
+ normal[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ for (int k = 0; k < 4; ++k) {
+ uva[i][k] = 0.0f;
+ }
+ }
+ }
+
+ float position[3];
+ float normal[3];
+ float uv[2];
+ float uva[4][4];
+ PmxVertexSkinningType skinning_type;
+ std::unique_ptr<PmxVertexSkinning> skinning;
+ float edge;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxMaterial
+ {
+ public:
+ PmxMaterial()
+ : specularlity(0.0f)
+ , flag(0)
+ , edge_size(0.0f)
+ , diffuse_texture_index(0)
+ , sphere_texture_index(0)
+ , sphere_op_mode(0)
+ , common_toon_flag(0)
+ , toon_texture_index(0)
+ , index_count(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ specular[i] = 0.0f;
+ ambient[i] = 0.0f;
+ edge_color[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ diffuse[i] = 0.0f;
+ }
+ }
+
+ std::string material_name;
+ std::string material_english_name;
+ float diffuse[4];
+ float specular[3];
+ float specularlity;
+ float ambient[3];
+ uint8_t flag;
+ float edge_color[4];
+ float edge_size;
+ int diffuse_texture_index;
+ int sphere_texture_index;
+ uint8_t sphere_op_mode;
+ uint8_t common_toon_flag;
+ int toon_texture_index;
+ std::string memo;
+ int index_count;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxIkLink
+ {
+ public:
+ PmxIkLink()
+ : link_target(0)
+ , angle_lock(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ max_radian[i] = 0.0f;
+ min_radian[i] = 0.0f;
+ }
+ }
+
+ int link_target;
+ uint8_t angle_lock;
+ float max_radian[3];
+ float min_radian[3];
+ void Read(std::istream *stream, PmxSetting *settingn);
+ };
+
+ class PmxBone
+ {
+ public:
+ PmxBone()
+ : parent_index(0)
+ , level(0)
+ , bone_flag(0)
+ , target_index(0)
+ , grant_parent_index(0)
+ , grant_weight(0.0f)
+ , key(0)
+ , ik_target_bone_index(0)
+ , ik_loop(0)
+ , ik_loop_angle_limit(0.0f)
+ , ik_link_count(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ position[i] = 0.0f;
+ offset[i] = 0.0f;
+ lock_axis_orientation[i] = 0.0f;
+ local_axis_x_orientation[i] = 0.0f;
+ local_axis_y_orientation[i] = 0.0f;
+ }
+ }
+
+ std::string bone_name;
+ std::string bone_english_name;
+ float position[3];
+ int parent_index;
+ int level;
+ uint16_t bone_flag;
+ float offset[3];
+ int target_index;
+ int grant_parent_index;
+ float grant_weight;
+ float lock_axis_orientation[3];
+ float local_axis_x_orientation[3];
+ float local_axis_y_orientation[3];
+ int key;
+ int ik_target_bone_index;
+ int ik_loop;
+ float ik_loop_angle_limit;
+ int ik_link_count;
+ std::unique_ptr<PmxIkLink []> ik_links;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ enum class MorphType : uint8_t
+ {
+ Group = 0,
+ Vertex = 1,
+ Bone = 2,
+ UV = 3,
+ AdditionalUV1 = 4,
+ AdditionalUV2 = 5,
+ AdditionalUV3 = 6,
+ AdditionalUV4 = 7,
+ Matrial = 8,
+ Flip = 9,
+ Implus = 10,
+ };
+
+ enum class MorphCategory : uint8_t
+ {
+ ReservedCategory = 0,
+ Eyebrow = 1,
+ Eye = 2,
+ Mouth = 3,
+ Other = 4,
+ };
+
+ class PmxMorphOffset
+ {
+ public:
+ void virtual Read(std::istream *stream, PmxSetting *setting) = 0;
+ };
+
+ class PmxMorphVertexOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphVertexOffset()
+ : vertex_index(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ position_offset[i] = 0.0f;
+ }
+ }
+ int vertex_index;
+ float position_offset[3];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphUVOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphUVOffset()
+ : vertex_index(0)
+ {
+ for (int i = 0; i < 4; ++i) {
+ uv_offset[i] = 0.0f;
+ }
+ }
+ int vertex_index;
+ float uv_offset[4];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphBoneOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphBoneOffset()
+ : bone_index(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ translation[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ rotation[i] = 0.0f;
+ }
+ }
+ int bone_index;
+ float translation[3];
+ float rotation[4];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphMaterialOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphMaterialOffset()
+ : specularity(0.0f)
+ , edge_size(0.0f)
+ {
+ for (int i = 0; i < 3; ++i) {
+ specular[i] = 0.0f;
+ ambient[i] = 0.0f;
+ }
+ for (int i = 0; i < 4; ++i) {
+ diffuse[i] = 0.0f;
+ edge_color[i] = 0.0f;
+ texture_argb[i] = 0.0f;
+ sphere_texture_argb[i] = 0.0f;
+ toon_texture_argb[i] = 0.0f;
+ }
+ }
+ int material_index;
+ uint8_t offset_operation;
+ float diffuse[4];
+ float specular[3];
+ float specularity;
+ float ambient[3];
+ float edge_color[4];
+ float edge_size;
+ float texture_argb[4];
+ float sphere_texture_argb[4];
+ float toon_texture_argb[4];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphGroupOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphGroupOffset()
+ : morph_index(0)
+ , morph_weight(0.0f)
+ {}
+ int morph_index;
+ float morph_weight;
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphFlipOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphFlipOffset()
+ : morph_index(0)
+ , morph_value(0.0f)
+ {}
+ int morph_index;
+ float morph_value;
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorphImplusOffset : public PmxMorphOffset
+ {
+ public:
+ PmxMorphImplusOffset()
+ : rigid_body_index(0)
+ , is_local(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ velocity[i] = 0.0f;
+ angular_torque[i] = 0.0f;
+ }
+ }
+ int rigid_body_index;
+ uint8_t is_local;
+ float velocity[3];
+ float angular_torque[3];
+ void Read(std::istream *stream, PmxSetting *setting); //override;
+ };
+
+ class PmxMorph
+ {
+ public:
+ PmxMorph()
+ : offset_count(0)
+ {
+ }
+ std::string morph_name;
+ std::string morph_english_name;
+ MorphCategory category;
+ MorphType morph_type;
+ int offset_count;
+ std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets;
+ std::unique_ptr<PmxMorphUVOffset []> uv_offsets;
+ std::unique_ptr<PmxMorphBoneOffset []> bone_offsets;
+ std::unique_ptr<PmxMorphMaterialOffset []> material_offsets;
+ std::unique_ptr<PmxMorphGroupOffset []> group_offsets;
+ std::unique_ptr<PmxMorphFlipOffset []> flip_offsets;
+ std::unique_ptr<PmxMorphImplusOffset []> implus_offsets;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxFrameElement
+ {
+ public:
+ PmxFrameElement()
+ : element_target(0)
+ , index(0)
+ {
+ }
+ uint8_t element_target;
+ int index;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxFrame
+ {
+ public:
+ PmxFrame()
+ : frame_flag(0)
+ , element_count(0)
+ {
+ }
+ std::string frame_name;
+ std::string frame_english_name;
+ uint8_t frame_flag;
+ int element_count;
+ std::unique_ptr<PmxFrameElement []> elements;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxRigidBody
+ {
+ public:
+ PmxRigidBody()
+ : target_bone(0)
+ , group(0)
+ , mask(0)
+ , shape(0)
+ , mass(0.0f)
+ , move_attenuation(0.0f)
+ , rotation_attenuation(0.0f)
+ , repulsion(0.0f)
+ , friction(0.0f)
+ , physics_calc_type(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ size[i] = 0.0f;
+ position[i] = 0.0f;
+ orientation[i] = 0.0f;
+ }
+ }
+ std::string girid_body_name;
+ std::string girid_body_english_name;
+ int target_bone;
+ uint8_t group;
+ uint16_t mask;
+ uint8_t shape;
+ float size[3];
+ float position[3];
+ float orientation[3];
+ float mass;
+ float move_attenuation;
+ float rotation_attenuation;
+ float repulsion;
+ float friction;
+ uint8_t physics_calc_type;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ enum class PmxJointType : uint8_t
+ {
+ Generic6DofSpring = 0,
+ Generic6Dof = 1,
+ Point2Point = 2,
+ ConeTwist = 3,
+ Slider = 5,
+ Hinge = 6
+ };
+
+ class PmxJointParam
+ {
+ public:
+ PmxJointParam()
+ : rigid_body1(0)
+ , rigid_body2(0)
+ {
+ for (int i = 0; i < 3; ++i) {
+ position[i] = 0.0f;
+ orientaiton[i] = 0.0f;
+ move_limitation_min[i] = 0.0f;
+ move_limitation_max[i] = 0.0f;
+ rotation_limitation_min[i] = 0.0f;
+ rotation_limitation_max[i] = 0.0f;
+ spring_move_coefficient[i] = 0.0f;
+ spring_rotation_coefficient[i] = 0.0f;
+ }
+ }
+ int rigid_body1;
+ int rigid_body2;
+ float position[3];
+ float orientaiton[3];
+ float move_limitation_min[3];
+ float move_limitation_max[3];
+ float rotation_limitation_min[3];
+ float rotation_limitation_max[3];
+ float spring_move_coefficient[3];
+ float spring_rotation_coefficient[3];
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxJoint
+ {
+ public:
+ std::string joint_name;
+ std::string joint_english_name;
+ PmxJointType joint_type;
+ PmxJointParam param;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ enum PmxSoftBodyFlag : uint8_t
+ {
+ BLink = 0x01,
+ Cluster = 0x02,
+ Link = 0x04
+ };
+
+ class PmxAncherRigidBody
+ {
+ public:
+ PmxAncherRigidBody()
+ : related_rigid_body(0)
+ , related_vertex(0)
+ , is_near(false)
+ {}
+ int related_rigid_body;
+ int related_vertex;
+ bool is_near;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxSoftBody
+ {
+ public:
+ PmxSoftBody()
+ : shape(0)
+ , target_material(0)
+ , group(0)
+ , mask(0)
+ , blink_distance(0)
+ , cluster_count(0)
+ , mass(0.0)
+ , collisioni_margin(0.0)
+ , aero_model(0)
+ , VCF(0.0f)
+ , DP(0.0f)
+ , DG(0.0f)
+ , LF(0.0f)
+ , PR(0.0f)
+ , VC(0.0f)
+ , DF(0.0f)
+ , MT(0.0f)
+ , CHR(0.0f)
+ , KHR(0.0f)
+ , SHR(0.0f)
+ , AHR(0.0f)
+ , SRHR_CL(0.0f)
+ , SKHR_CL(0.0f)
+ , SSHR_CL(0.0f)
+ , SR_SPLT_CL(0.0f)
+ , SK_SPLT_CL(0.0f)
+ , SS_SPLT_CL(0.0f)
+ , V_IT(0)
+ , P_IT(0)
+ , D_IT(0)
+ , C_IT(0)
+ , LST(0.0f)
+ , AST(0.0f)
+ , VST(0.0f)
+ , anchor_count(0)
+ , pin_vertex_count(0)
+ {}
+ std::string soft_body_name;
+ std::string soft_body_english_name;
+ uint8_t shape;
+ int target_material;
+ uint8_t group;
+ uint16_t mask;
+ PmxSoftBodyFlag flag;
+ int blink_distance;
+ int cluster_count;
+ float mass;
+ float collisioni_margin;
+ int aero_model;
+ float VCF;
+ float DP;
+ float DG;
+ float LF;
+ float PR;
+ float VC;
+ float DF;
+ float MT;
+ float CHR;
+ float KHR;
+ float SHR;
+ float AHR;
+ float SRHR_CL;
+ float SKHR_CL;
+ float SSHR_CL;
+ float SR_SPLT_CL;
+ float SK_SPLT_CL;
+ float SS_SPLT_CL;
+ int V_IT;
+ int P_IT;
+ int D_IT;
+ int C_IT;
+ float LST;
+ float AST;
+ float VST;
+ int anchor_count;
+ std::unique_ptr<PmxAncherRigidBody []> anchers;
+ int pin_vertex_count;
+ std::unique_ptr<int []> pin_vertices;
+ void Read(std::istream *stream, PmxSetting *setting);
+ };
+
+ class PmxModel
+ {
+ public:
+ PmxModel()
+ : version(0.0f)
+ , vertex_count(0)
+ , index_count(0)
+ , texture_count(0)
+ , material_count(0)
+ , bone_count(0)
+ , morph_count(0)
+ , frame_count(0)
+ , rigid_body_count(0)
+ , joint_count(0)
+ , soft_body_count(0)
+ {}
+
+ float version;
+ PmxSetting setting;
+ std::string model_name;
+ std::string model_english_name;
+ std::string model_comment;
+ std::string model_english_comment;
+ int vertex_count;
+ std::unique_ptr<PmxVertex []> vertices;
+ int index_count;
+ std::unique_ptr<int []> indices;
+ int texture_count;
+ std::unique_ptr< std::string []> textures;
+ int material_count;
+ std::unique_ptr<PmxMaterial []> materials;
+ int bone_count;
+ std::unique_ptr<PmxBone []> bones;
+ int morph_count;
+ std::unique_ptr<PmxMorph []> morphs;
+ int frame_count;
+ std::unique_ptr<PmxFrame [] > frames;
+ int rigid_body_count;
+ std::unique_ptr<PmxRigidBody []> rigid_bodies;
+ int joint_count;
+ std::unique_ptr<PmxJoint []> joints;
+ int soft_body_count;
+ std::unique_ptr<PmxSoftBody []> soft_bodies;
+ void Init();
+ void Read(std::istream *stream);
+ //static std::unique_ptr<PmxModel> ReadFromFile(const char *filename);
+ //static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream);
+ };
+}
diff --git a/src/3rdparty/assimp/code/MMDVmdParser.h b/src/3rdparty/assimp/code/MMDVmdParser.h
new file mode 100644
index 000000000..43e7a923a
--- /dev/null
+++ b/src/3rdparty/assimp/code/MMDVmdParser.h
@@ -0,0 +1,375 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <vector>
+#include <string>
+#include <memory>
+#include <iostream>
+#include <fstream>
+#include <ostream>
+#include "MMDCpp14.h"
+
+namespace vmd
+{
+ class VmdBoneFrame
+ {
+ public:
+ std::string name;
+ int frame;
+ float position[3];
+ float orientation[4];
+ char interpolation[4][4][4];
+
+ void Read(std::istream* stream)
+ {
+ char buffer[15];
+ stream->read((char*) buffer, sizeof(char)*15);
+ name = std::string(buffer);
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) position, sizeof(float)*3);
+ stream->read((char*) orientation, sizeof(float)*4);
+ stream->read((char*) interpolation, sizeof(char) * 4 * 4 * 4);
+ }
+
+ void Write(std::ostream* stream)
+ {
+ stream->write((char*)name.c_str(), sizeof(char) * 15);
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)position, sizeof(float) * 3);
+ stream->write((char*)orientation, sizeof(float) * 4);
+ stream->write((char*)interpolation, sizeof(char) * 4 * 4 * 4);
+ }
+ };
+
+ class VmdFaceFrame
+ {
+ public:
+ std::string face_name;
+ float weight;
+ uint32_t frame;
+
+ void Read(std::istream* stream)
+ {
+ char buffer[15];
+ stream->read((char*) &buffer, sizeof(char) * 15);
+ face_name = std::string(buffer);
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) &weight, sizeof(float));
+ }
+
+ void Write(std::ostream* stream)
+ {
+ stream->write((char*)face_name.c_str(), sizeof(char) * 15);
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)&weight, sizeof(float));
+ }
+ };
+
+ class VmdCameraFrame
+ {
+ public:
+ int frame;
+ float distance;
+ float position[3];
+ float orientation[3];
+ char interpolation[6][4];
+ float angle;
+ char unknown[3];
+
+ void Read(std::istream *stream)
+ {
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) &distance, sizeof(float));
+ stream->read((char*) position, sizeof(float) * 3);
+ stream->read((char*) orientation, sizeof(float) * 3);
+ stream->read((char*) interpolation, sizeof(char) * 24);
+ stream->read((char*) &angle, sizeof(float));
+ stream->read((char*) unknown, sizeof(char) * 3);
+ }
+
+ void Write(std::ostream *stream)
+ {
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)&distance, sizeof(float));
+ stream->write((char*)position, sizeof(float) * 3);
+ stream->write((char*)orientation, sizeof(float) * 3);
+ stream->write((char*)interpolation, sizeof(char) * 24);
+ stream->write((char*)&angle, sizeof(float));
+ stream->write((char*)unknown, sizeof(char) * 3);
+ }
+ };
+
+ class VmdLightFrame
+ {
+ public:
+ int frame;
+ float color[3];
+ float position[3];
+
+ void Read(std::istream* stream)
+ {
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) color, sizeof(float) * 3);
+ stream->read((char*) position, sizeof(float) * 3);
+ }
+
+ void Write(std::ostream* stream)
+ {
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)color, sizeof(float) * 3);
+ stream->write((char*)position, sizeof(float) * 3);
+ }
+ };
+
+ class VmdIkEnable
+ {
+ public:
+ std::string ik_name;
+ bool enable;
+ };
+
+ class VmdIkFrame
+ {
+ public:
+ int frame;
+ bool display;
+ std::vector<VmdIkEnable> ik_enable;
+
+ void Read(std::istream *stream)
+ {
+ char buffer[20];
+ stream->read((char*) &frame, sizeof(int));
+ stream->read((char*) &display, sizeof(uint8_t));
+ int ik_count;
+ stream->read((char*) &ik_count, sizeof(int));
+ ik_enable.resize(ik_count);
+ for (int i = 0; i < ik_count; i++)
+ {
+ stream->read(buffer, 20);
+ ik_enable[i].ik_name = std::string(buffer);
+ stream->read((char*) &ik_enable[i].enable, sizeof(uint8_t));
+ }
+ }
+
+ void Write(std::ostream *stream)
+ {
+ stream->write((char*)&frame, sizeof(int));
+ stream->write((char*)&display, sizeof(uint8_t));
+ int ik_count = static_cast<int>(ik_enable.size());
+ stream->write((char*)&ik_count, sizeof(int));
+ for (int i = 0; i < ik_count; i++)
+ {
+ const VmdIkEnable& ik_enable = this->ik_enable.at(i);
+ stream->write(ik_enable.ik_name.c_str(), 20);
+ stream->write((char*)&ik_enable.enable, sizeof(uint8_t));
+ }
+ }
+ };
+
+ class VmdMotion
+ {
+ public:
+ std::string model_name;
+ int version;
+ std::vector<VmdBoneFrame> bone_frames;
+ std::vector<VmdFaceFrame> face_frames;
+ std::vector<VmdCameraFrame> camera_frames;
+ std::vector<VmdLightFrame> light_frames;
+ std::vector<VmdIkFrame> ik_frames;
+
+ static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)
+ {
+ std::ifstream stream(filename, std::ios::binary);
+ auto result = LoadFromStream(&stream);
+ stream.close();
+ return result;
+ }
+
+ static std::unique_ptr<VmdMotion> LoadFromStream(std::ifstream *stream)
+ {
+
+ char buffer[30];
+ auto result = mmd::make_unique<VmdMotion>();
+
+ // magic and version
+ stream->read((char*) buffer, 30);
+ if (strncmp(buffer, "Vocaloid Motion Data", 20))
+ {
+ std::cerr << "invalid vmd file." << std::endl;
+ return nullptr;
+ }
+ result->version = std::atoi(buffer + 20);
+
+ // name
+ stream->read(buffer, 20);
+ result->model_name = std::string(buffer);
+
+ // bone frames
+ int bone_frame_num;
+ stream->read((char*) &bone_frame_num, sizeof(int));
+ result->bone_frames.resize(bone_frame_num);
+ for (int i = 0; i < bone_frame_num; i++)
+ {
+ result->bone_frames[i].Read(stream);
+ }
+
+ // face frames
+ int face_frame_num;
+ stream->read((char*) &face_frame_num, sizeof(int));
+ result->face_frames.resize(face_frame_num);
+ for (int i = 0; i < face_frame_num; i++)
+ {
+ result->face_frames[i].Read(stream);
+ }
+
+ // camera frames
+ int camera_frame_num;
+ stream->read((char*) &camera_frame_num, sizeof(int));
+ result->camera_frames.resize(camera_frame_num);
+ for (int i = 0; i < camera_frame_num; i++)
+ {
+ result->camera_frames[i].Read(stream);
+ }
+
+ // light frames
+ int light_frame_num;
+ stream->read((char*) &light_frame_num, sizeof(int));
+ result->light_frames.resize(light_frame_num);
+ for (int i = 0; i < light_frame_num; i++)
+ {
+ result->light_frames[i].Read(stream);
+ }
+
+ // unknown2
+ stream->read(buffer, 4);
+
+ // ik frames
+ if (stream->peek() != std::ios::traits_type::eof())
+ {
+ int ik_num;
+ stream->read((char*) &ik_num, sizeof(int));
+ result->ik_frames.resize(ik_num);
+ for (int i = 0; i < ik_num; i++)
+ {
+ result->ik_frames[i].Read(stream);
+ }
+ }
+
+ if (stream->peek() != std::ios::traits_type::eof())
+ {
+ std::cerr << "vmd stream has unknown data." << std::endl;
+ }
+
+ return result;
+ }
+
+ bool SaveToFile(const std::u16string& /*filename*/)
+ {
+ // TODO: How to adapt u16string to string?
+ /*
+ std::ofstream stream(filename.c_str(), std::ios::binary);
+ auto result = SaveToStream(&stream);
+ stream.close();
+ return result;
+ */
+ return false;
+ }
+
+ bool SaveToStream(std::ofstream *stream)
+ {
+ std::string magic = "Vocaloid Motion Data 0002\0";
+ magic.resize(30);
+
+ // magic and version
+ stream->write(magic.c_str(), 30);
+
+ // name
+ stream->write(model_name.c_str(), 20);
+
+ // bone frames
+ const int bone_frame_num = static_cast<int>(bone_frames.size());
+ stream->write(reinterpret_cast<const char*>(&bone_frame_num), sizeof(int));
+ for (int i = 0; i < bone_frame_num; i++)
+ {
+ bone_frames[i].Write(stream);
+ }
+
+ // face frames
+ const int face_frame_num = static_cast<int>(face_frames.size());
+ stream->write(reinterpret_cast<const char*>(&face_frame_num), sizeof(int));
+ for (int i = 0; i < face_frame_num; i++)
+ {
+ face_frames[i].Write(stream);
+ }
+
+ // camera frames
+ const int camera_frame_num = static_cast<int>(camera_frames.size());
+ stream->write(reinterpret_cast<const char*>(&camera_frame_num), sizeof(int));
+ for (int i = 0; i < camera_frame_num; i++)
+ {
+ camera_frames[i].Write(stream);
+ }
+
+ // light frames
+ const int light_frame_num = static_cast<int>(light_frames.size());
+ stream->write(reinterpret_cast<const char*>(&light_frame_num), sizeof(int));
+ for (int i = 0; i < light_frame_num; i++)
+ {
+ light_frames[i].Write(stream);
+ }
+
+ // self shadow datas
+ const int self_shadow_num = 0;
+ stream->write(reinterpret_cast<const char*>(&self_shadow_num), sizeof(int));
+
+ // ik frames
+ const int ik_num = static_cast<int>(ik_frames.size());
+ stream->write(reinterpret_cast<const char*>(&ik_num), sizeof(int));
+ for (int i = 0; i < ik_num; i++)
+ {
+ ik_frames[i].Write(stream);
+ }
+
+ return true;
+ }
+ };
+}
diff --git a/src/3rdparty/assimp/code/MS3DLoader.cpp b/src/3rdparty/assimp/code/MS3DLoader.cpp
index ef16a756a..64ec1e076 100644
--- a/src/3rdparty/assimp/code/MS3DLoader.cpp
+++ b/src/3rdparty/assimp/code/MS3DLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -53,7 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <assimp/IOSystem.hpp>
-
+#include <assimp/importerdesc.h>
+#include <map>
using namespace Assimp;
@@ -423,7 +425,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
for (unsigned int i = 0; i < groups.size(); ++i) {
TempGroup& g = groups[i];
if (g.mat == UINT_MAX) {
- g.mat = materials.size()-1;
+ g.mat = static_cast<unsigned int>(materials.size()-1);
}
}
}
@@ -483,7 +485,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
m->mMaterialIndex = g.mat;
m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- m->mFaces = new aiFace[m->mNumFaces = g.triangles.size()];
+ m->mFaces = new aiFace[m->mNumFaces = static_cast<unsigned int>(g.triangles.size())];
m->mNumVertices = m->mNumFaces*3;
// storage for vertices - verbose format, as requested by the postprocessing pipeline
diff --git a/src/3rdparty/assimp/code/MS3DLoader.h b/src/3rdparty/assimp/code/MS3DLoader.h
index 22d12e3cf..b4b19b3ad 100644
--- a/src/3rdparty/assimp/code/MS3DLoader.h
+++ b/src/3rdparty/assimp/code/MS3DLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MakeVerboseFormat.cpp b/src/3rdparty/assimp/code/MakeVerboseFormat.cpp
index d51642cf6..720d44519 100644
--- a/src/3rdparty/assimp/code/MakeVerboseFormat.cpp
+++ b/src/3rdparty/assimp/code/MakeVerboseFormat.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -168,20 +169,22 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
}
}
+
+
// build output vertex weights
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{
- delete pcMesh->mBones[i]->mWeights;
+ 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[] newWeights;
// delete the old members
delete[] pcMesh->mVertices;
@@ -190,14 +193,14 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
p = 0;
while (pcMesh->HasTextureCoords(p))
{
- delete pcMesh->mTextureCoords[p];
+ delete[] pcMesh->mTextureCoords[p];
pcMesh->mTextureCoords[p] = apvTextureCoords[p];
++p;
}
p = 0;
while (pcMesh->HasVertexColors(p))
{
- delete pcMesh->mColors[p];
+ delete[] pcMesh->mColors[p];
pcMesh->mColors[p] = apvColorSets[p];
++p;
}
diff --git a/src/3rdparty/assimp/code/MakeVerboseFormat.h b/src/3rdparty/assimp/code/MakeVerboseFormat.h
index 1b32cf19e..9832a3f65 100644
--- a/src/3rdparty/assimp/code/MakeVerboseFormat.h
+++ b/src/3rdparty/assimp/code/MakeVerboseFormat.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MaterialSystem.cpp b/src/3rdparty/assimp/code/MaterialSystem.cpp
index 94ca4364e..55f1a4ff5 100644
--- a/src/3rdparty/assimp/code/MaterialSystem.cpp
+++ b/src/3rdparty/assimp/code/MaterialSystem.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,8 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the material system of the library
*/
-
-
#include "Hash.h"
#include "fast_atof.h"
#include "ParsingUtils.h"
@@ -71,7 +70,7 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
* 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) {
+ for ( unsigned int i = 0; i < pMat->mNumProperties; ++i ) {
aiMaterialProperty* prop = pMat->mProperties[i];
if (prop /* just for safety ... */
@@ -93,7 +92,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
const char* pKey,
unsigned int type,
unsigned int index,
- float* pOut,
+ ai_real* pOut,
unsigned int* pMax)
{
ai_assert (pOut != NULL);
@@ -105,7 +104,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
return AI_FAILURE;
}
- // data is given in floats, simply copy it
+ // data is given in floats, convert to ai_real
unsigned int iWrite = 0;
if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
iWrite = prop->mDataLength / sizeof(float);
@@ -113,7 +112,20 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
iWrite = std::min(*pMax,iWrite); ;
}
for (unsigned int a = 0; a < iWrite;++a) {
- pOut[a] = static_cast<float> ( reinterpret_cast<float*>(prop->mData)[a] );
+ pOut[a] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] );
+ }
+ if (pMax) {
+ *pMax = iWrite;
+ }
+ }
+ // data is given in doubles, convert to float
+ else if( aiPTI_Double == prop->mType) {
+ iWrite = prop->mDataLength / sizeof(double);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite); ;
+ }
+ for (unsigned int a = 0; a < iWrite;++a) {
+ pOut[a] = static_cast<ai_real> ( reinterpret_cast<double*>(prop->mData)[a] );
}
if (pMax) {
*pMax = iWrite;
@@ -126,7 +138,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
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] );
+ pOut[a] = static_cast<ai_real> ( reinterpret_cast<int32_t*>(prop->mData)[a] );
}
if (pMax) {
*pMax = iWrite;
@@ -138,14 +150,15 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
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) {
+ const char *cur = prop->mData + 4;
+ ai_assert( prop->mDataLength >= 5 );
+ ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
+ for ( unsigned int a = 0; ;++a) {
+ cur = fast_atoreal_move<ai_real>(cur,pOut[a]);
+ if ( a==iWrite-1 ) {
break;
}
- if(!IsSpace(*cur)) {
+ 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;
@@ -157,7 +170,6 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
}
}
return AI_SUCCESS;
-
}
// ------------------------------------------------------------------------------------------------
@@ -211,8 +223,9 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
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]);
+ const char *cur = prop->mData+4;
+ ai_assert( prop->mDataLength >= 5 );
+ ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
for (unsigned int a = 0; ;++a) {
pOut[a] = strtol10(cur,&cur);
if(a==iWrite-1) {
@@ -241,11 +254,11 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat,
aiColor4D* pOut)
{
unsigned int iMax = 4;
- const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
+ const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
// if no alpha channel is defined: set it to 1.0
if (3 == iMax) {
- pOut->a = 1.0f;
+ pOut->a = 1.0;
}
return eRet;
@@ -260,7 +273,7 @@ aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
aiUVTransform* pOut)
{
unsigned int iMax = 4;
- return aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
+ return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
}
// ------------------------------------------------------------------------------------------------
@@ -285,7 +298,8 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
// 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]);
+ ai_assert( pOut->length+1+4==prop->mDataLength );
+ ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
memcpy(pOut->data,prop->mData+4,pOut->length+1);
}
else {
@@ -304,12 +318,12 @@ ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMa
{
ai_assert (pMat != NULL);
- /* Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again) */
+ // 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 ... */
+ if ( prop /* just a sanity check ... */
&& 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
&& prop->mSemantic == type) {
@@ -326,7 +340,7 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
C_STRUCT aiString* path,
aiTextureMapping* _mapping /*= NULL*/,
unsigned int* uvindex /*= NULL*/,
- float* blend /*= NULL*/,
+ ai_real* blend /*= NULL*/,
aiTextureOp* op /*= NULL*/,
aiTextureMapMode* mapmode /*= NULL*/,
unsigned int* flags /*= NULL*/
@@ -368,14 +382,16 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
return AI_SUCCESS;
}
+static const unsigned int DefaultNumAllocated = 5;
+
// ------------------------------------------------------------------------------------------------
// Construction. Actually the one and only way to get an aiMaterial instance
-aiMaterial::aiMaterial()
-{
+aiMaterial::aiMaterial()
+: mProperties( NULL )
+, mNumProperties( 0 )
+, mNumAllocated( DefaultNumAllocated ) {
// Allocate 5 entries by default
- mNumProperties = 0;
- mNumAllocated = 5;
- mProperties = new aiMaterialProperty*[5];
+ mProperties = new aiMaterialProperty*[ DefaultNumAllocated ];
}
// ------------------------------------------------------------------------------------------------
@@ -440,6 +456,9 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
ai_assert (pKey != NULL);
ai_assert (0 != pSizeInBytes);
+ if ( 0 == pSizeInBytes ) {
+
+ }
// first search the list whether there is already an entry with this key
unsigned int iOutIndex = UINT_MAX;
for (unsigned int i = 0; i < mNumProperties;++i) {
@@ -514,7 +533,7 @@ aiReturn aiMaterial::AddProperty (const aiString* pInput,
s[1] = static_cast<uint32_t>(pInput->length);
return AddBinaryProperty(s+1,
- pInput->length+1+4,
+ static_cast<unsigned int>(pInput->length+1+4),
pKey,
type,
index,
@@ -522,7 +541,7 @@ aiReturn aiMaterial::AddProperty (const aiString* pInput,
}
ai_assert(sizeof(size_t)==4);
return AddBinaryProperty(pInput,
- pInput->length+1+4,
+ static_cast<unsigned int>(pInput->length+1+4),
pKey,
type,
index,
@@ -530,10 +549,10 @@ aiReturn aiMaterial::AddProperty (const aiString* pInput,
}
// ------------------------------------------------------------------------------------------------
-uint32_t Assimp :: ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/)
+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) {
+ for ( unsigned int i = 0; i < mat->mNumProperties; ++i ) {
aiMaterialProperty* prop;
// Exclude all properties whose first character is '?' from the hash
@@ -572,15 +591,16 @@ void aiMaterial::CopyPropertyList(aiMaterial* pcDest,
}
}
- if(pcOld)
- delete[] pcOld;
+ 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) {
+ 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) {
@@ -604,5 +624,4 @@ void aiMaterial::CopyPropertyList(aiMaterial* pcDest,
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 6726e0518..b083a5bb8 100644
--- a/src/3rdparty/assimp/code/MaterialSystem.h
+++ b/src/3rdparty/assimp/code/MaterialSystem.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/MemoryIOWrapper.h b/src/3rdparty/assimp/code/MemoryIOWrapper.h
index d6aaafae0..9bd245337 100644
--- a/src/3rdparty/assimp/code/MemoryIOWrapper.h
+++ b/src/3rdparty/assimp/code/MemoryIOWrapper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/NDOLoader.cpp b/src/3rdparty/assimp/code/NDOLoader.cpp
index f04eb5345..2586bac3e 100644
--- a/src/3rdparty/assimp/code/NDOLoader.cpp
+++ b/src/3rdparty/assimp/code/NDOLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -49,7 +50,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include "StreamReader.h"
+#include <map>
using namespace Assimp;
@@ -257,7 +260,8 @@ void NDOImporter::InternReadFile( const std::string& pFile,
}
aiMesh* mesh = new aiMesh();
- aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()];
+ mesh->mNumFaces=static_cast<unsigned int>(face_table.size());
+ aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
vertices.clear();
vertices.reserve(4 * face_table.size()); // arbitrarily chosen
@@ -278,7 +282,7 @@ void NDOImporter::InternReadFile( const std::string& pFile,
next_edge = obj.edges[cur_edge].edge[4];
next_vert = obj.edges[cur_edge].edge[0];
}
- indices.push_back( vertices.size() );
+ indices.push_back( static_cast<unsigned int>(vertices.size()) );
vertices.push_back(obj.vertices[ next_vert ].val);
cur_edge = next_edge;
@@ -287,18 +291,19 @@ void NDOImporter::InternReadFile( const std::string& pFile,
}
}
- f.mIndices = new unsigned int[f.mNumIndices = indices.size()];
+ f.mIndices = new unsigned int[f.mNumIndices = static_cast<unsigned int>(indices.size())];
std::copy(indices.begin(),indices.end(),f.mIndices);
}
- mesh->mVertices = new aiVector3D[mesh->mNumVertices = vertices.size()];
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices = static_cast<unsigned int>(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++;
- }
+ }else
+ delete mesh;
}
}
diff --git a/src/3rdparty/assimp/code/NFFLoader.cpp b/src/3rdparty/assimp/code/NFFLoader.cpp
index 8bec63ea3..a51c500f1 100644
--- a/src/3rdparty/assimp/code/NFFLoader.cpp
+++ b/src/3rdparty/assimp/code/NFFLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include <memory>
@@ -241,8 +243,6 @@ void NFFImporter::InternReadFile( const std::string& pFile,
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;
@@ -467,7 +467,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
for (unsigned int a = 0; a < numIdx;++a)
{
SkipSpaces(sz,&sz);
- m = ::strtoul10(sz,&sz);
+ unsigned int m = ::strtoul10(sz,&sz);
if (m >= (unsigned int)tempPositions.size())
{
DefaultLogger::get()->error("NFF2: Vertex index overflow");
@@ -633,7 +633,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
for (std::vector<unsigned int>::const_iterator it = tempIdx.begin(), end = tempIdx.end();
it != end;++it)
{
- m = *it;
+ unsigned int m = *it;
// copy colors -vertex color specifications override polygon color specifications
if (hasColor)
@@ -733,7 +733,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
sz = &line[1];out = currentMesh;
}
SkipSpaces(sz,&sz);
- m = strtoul10(sz);
+ unsigned int m = strtoul10(sz);
// ---- flip the face order
out->vertices.resize(out->vertices.size()+m);
@@ -965,7 +965,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
// 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;
+ currentMesh.center = center1+currentMesh.dir/(ai_real)2.0;
float f;
if (( f = currentMesh.dir.Length()) < 10e-3f )
@@ -1079,7 +1079,9 @@ void NFFImporter::InternReadFile( const std::string& pFile,
// generate the camera
if (hasCam)
{
- aiNode* nd = *ppcChildren = new aiNode();
+ ai_assert(ppcChildren);
+ aiNode* nd = new aiNode();
+ *ppcChildren = nd;
nd->mName.Set("<NFF_Camera>");
nd->mParent = root;
@@ -1103,13 +1105,15 @@ void NFFImporter::InternReadFile( const std::string& pFile,
// generate light sources
if (!lights.empty())
{
+ ai_assert(ppcChildren);
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();
+ aiNode* nd = new aiNode();
+ *ppcChildren = nd;
nd->mParent = root;
nd->mName.length = ::ai_snprintf(nd->mName.data,1024,"<NFF_Light%u>",i);
@@ -1126,7 +1130,8 @@ void NFFImporter::InternReadFile( const std::string& pFile,
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)
+ unsigned int m = 0;
+ for (it = meshes.begin(); it != end;++it)
{
if ((*it).faces.empty())continue;
@@ -1159,7 +1164,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
++ppcChildren;
} else {
*pMeshes++ = m;
- }
+ }
// copy vertex positions
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
diff --git a/src/3rdparty/assimp/code/NFFLoader.h b/src/3rdparty/assimp/code/NFFLoader.h
index 2b5232645..0640d4405 100644
--- a/src/3rdparty/assimp/code/NFFLoader.h
+++ b/src/3rdparty/assimp/code/NFFLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OFFLoader.cpp b/src/3rdparty/assimp/code/OFFLoader.cpp
index fd0542fdf..5038176e2 100644
--- a/src/3rdparty/assimp/code/OFFLoader.cpp
+++ b/src/3rdparty/assimp/code/OFFLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
@@ -93,7 +94,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
{
if (!pIOHandler)return true;
const char* tokens[] = {"off"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3);
}
return false;
}
@@ -161,9 +162,9 @@ void OFFImporter::InternReadFile( const std::string& pFile,
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);
+ sz = fast_atoreal_move<ai_real>(sz,(ai_real&)v.x); SkipSpaces(&sz);
+ sz = fast_atoreal_move<ai_real>(sz,(ai_real&)v.y); SkipSpaces(&sz);
+ fast_atoreal_move<ai_real>(sz,(ai_real&)v.z);
}
@@ -242,7 +243,7 @@ void OFFImporter::InternReadFile( const std::string& pFile,
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
aiMaterial* pcMat = new aiMaterial();
- aiColor4D clr(0.6f,0.6f,0.6f,1.0f);
+ aiColor4D clr( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 1.0 ) );
pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
pScene->mMaterials[0] = pcMat;
diff --git a/src/3rdparty/assimp/code/OFFLoader.h b/src/3rdparty/assimp/code/OFFLoader.h
index f01dc6244..29a4927bd 100644
--- a/src/3rdparty/assimp/code/OFFLoader.h
+++ b/src/3rdparty/assimp/code/OFFLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ObjExporter.cpp b/src/3rdparty/assimp/code/ObjExporter.cpp
index ca07730bc..a8bf9935a 100644
--- a/src/3rdparty/assimp/code/ObjExporter.cpp
+++ b/src/3rdparty/assimp/code/ObjExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -38,8 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-
-
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
@@ -53,17 +52,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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, const ExportProperties* pProperties)
-{
+void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
// invoke the exporter
ObjExporter exporter(pFile, pScene);
+ if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+ }
+
// 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"));
@@ -81,16 +83,46 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
}
}
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp
+void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) {
+ // invoke the exporter
+ ObjExporter exporter(pFile, pScene, true);
+
+ if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+ }
+
+ // 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);
+ }
+
+
+}
+
} // end of namespace Assimp
static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------
-ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
+ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
: filename(_filename)
, pScene(pScene)
-, endl("\n")
-{
+, vp()
+, vn()
+, vt()
+, vc()
+, mVpMap()
+, mVnMap()
+, mVtMap()
+, mVcMap()
+, mMeshes()
+, 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);
@@ -98,8 +130,14 @@ ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
mOutputMat.imbue(l);
mOutputMat.precision(16);
- WriteGeometryFile();
- WriteMaterialFile();
+ WriteGeometryFile(noMtl);
+ if (!noMtl)
+ WriteMaterialFile();
+}
+
+// ------------------------------------------------------------------------------------------------
+ObjExporter::~ObjExporter() {
+
}
// ------------------------------------------------------------------------------------------------
@@ -116,22 +154,31 @@ std::string ObjExporter :: GetMaterialLibName()
}
// ------------------------------------------------------------------------------------------------
-std::string ObjExporter :: GetMaterialLibFileName()
-{
+std::string ObjExporter::GetMaterialLibFileName() {
+ // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
+ size_t lastdot = filename.find_last_of('.');
+ if (lastdot != std::string::npos)
+ return filename.substr(0, lastdot) + MaterialExt;
+
return filename + MaterialExt;
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter :: WriteHeader(std::ostringstream& out)
-{
+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 << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
+ << aiGetVersionRevision() << ")" << endl << endl;
}
// ------------------------------------------------------------------------------------------------
-std::string ObjExporter :: GetMaterialName(unsigned int index)
+std::string ObjExporter::GetMaterialName(unsigned int index)
{
const aiMaterial* const mat = pScene->mMaterials[index];
+ if ( nullptr == mat ) {
+ static const std::string EmptyStr;
+ return EmptyStr;
+ }
+
aiString s;
if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
return std::string(s.data,s.length);
@@ -166,11 +213,17 @@ void ObjExporter::WriteMaterialFile()
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
}
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_TRANSPARENT,c)) {
+ mOutputMat << "Tf " << c.r << " " << c.g << " " << c.b << endl;
+ }
- float o;
+ ai_real o;
if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
mOutputMat << "d " << o << endl;
}
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_REFRACTI,o)) {
+ mOutputMat << "Ni " << o << endl;
+ }
if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
mOutputMat << "Ns " << o << endl;
@@ -205,26 +258,37 @@ void ObjExporter::WriteMaterialFile()
}
}
-// ------------------------------------------------------------------------------------------------
-void ObjExporter :: WriteGeometryFile()
-{
+void ObjExporter::WriteGeometryFile(bool noMtl) {
WriteHeader(mOutput);
- mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
+ if (!noMtl)
+ 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;
+ // write vertex positions with colors, if any
+ mVpMap.getVectors( vp );
+ mVcMap.getColors( vc );
+ if ( vc.empty() ) {
+ mOutput << "# " << vp.size() << " vertex positions" << endl;
+ for ( const aiVector3D& v : vp ) {
+ mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
+ }
+ } else {
+ mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
+ size_t colIdx = 0;
+ for ( const aiVector3D& v : vp ) {
+ if ( colIdx < vc.size() ) {
+ mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl;
+ }
+ ++colIdx;
+ }
}
mOutput << endl;
// write uv coordinates
- vtMap.getVectors(vt);
+ mVtMap.getVectors(vt);
mOutput << "# " << vt.size() << " UV coordinates" << endl;
for(const aiVector3D& v : vt) {
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
@@ -232,7 +296,7 @@ void ObjExporter :: WriteGeometryFile()
mOutput << endl;
// write vertex normals
- vnMap.getVectors(vn);
+ mVnMap.getVectors(vn);
mOutput << "# " << vn.size() << " vertex normals" << endl;
for(const aiVector3D& v : vn) {
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
@@ -240,12 +304,13 @@ void ObjExporter :: WriteGeometryFile()
mOutput << endl;
// now write all mesh instances
- for(const MeshInstance& m : meshes) {
+ for(const MeshInstance& m : mMeshes) {
mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
if (!m.name.empty()) {
mOutput << "g " << m.name << endl;
}
- mOutput << "usemtl " << m.matname << endl;
+ if (!noMtl)
+ mOutput << "usemtl " << m.matname << endl;
for(const Face& f : m.faces) {
mOutput << f.kind << ' ';
@@ -272,8 +337,7 @@ void ObjExporter :: WriteGeometryFile()
}
// ------------------------------------------------------------------------------------------------
-int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
-{
+int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) {
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
// vertex already exists, so reference it
if(vertIt != vecMap.end()){
@@ -286,8 +350,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
-{
+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;
@@ -295,12 +358,33 @@ void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
-{
- meshes.push_back(MeshInstance());
- MeshInstance& mesh = meshes.back();
+int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) {
+ colIndexMap::dataType::iterator vertIt = colMap.find( col );
+ // vertex already exists, so reference it
+ if ( vertIt != colMap.end() ) {
+ return vertIt->second;
+ }
+ colMap[ col ] = mNextIndex;
+ int ret = mNextIndex;
+ mNextIndex++;
- mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : "");
+ return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
+ colors.resize( colMap.size() );
+ for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) {
+ colors[ it->second - 1 ] = it->first;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
+ mMeshes.push_back(MeshInstance());
+ MeshInstance& mesh = mMeshes.back();
+
+ mesh.name = std::string( name.data, name.length );
mesh.matname = GetMaterialName(m->mMaterialIndex);
mesh.faces.resize(m->mNumFaces);
@@ -325,20 +409,25 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
const unsigned int idx = f.mIndices[a];
aiVector3D vert = mat * m->mVertices[idx];
- face.indices[a].vp = vpMap.getIndex(vert);
+ face.indices[a].vp = mVpMap.getIndex(vert);
if (m->mNormals) {
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
- face.indices[a].vn = vnMap.getIndex(norm);
- }
- else{
+ face.indices[a].vn = mVnMap.getIndex(norm);
+ } else {
face.indices[a].vn = 0;
}
- if (m->mTextureCoords[0]) {
- face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
+ if ( nullptr != m->mColors[ 0 ] ) {
+ aiColor4D col4 = m->mColors[ 0 ][ idx ];
+ face.indices[ a ].vc = mVcMap.getIndex( col4 );
+ } else {
+ face.indices[ a ].vc = 0;
}
- else{
+
+ if ( m->mTextureCoords[ 0 ] ) {
+ face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
+ } else {
face.indices[a].vt = 0;
}
}
diff --git a/src/3rdparty/assimp/code/ObjExporter.h b/src/3rdparty/assimp/code/ObjExporter.h
index 9d817f067..391f8416d 100644
--- a/src/3rdparty/assimp/code/ObjExporter.h
+++ b/src/3rdparty/assimp/code/ObjExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,40 +54,35 @@ struct aiScene;
struct aiNode;
struct aiMesh;
-namespace Assimp
-{
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to an OBJ file. */
// ------------------------------------------------------------------------------------------------
-class ObjExporter
-{
+class ObjExporter {
public:
/// Constructor for a specific scene to export
- ObjExporter(const char* filename, const aiScene* pScene);
-
-public:
-
+ ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false);
+ ~ObjExporter();
std::string GetMaterialLibName();
std::string GetMaterialLibFileName();
-
-public:
-
- /// public stringstreams to write all output into
+
+ /// public string-streams to write all output into
std::ostringstream mOutput, mOutputMat;
private:
-
// intermediate data structures
- struct FaceVertex
- {
+ struct FaceVertex {
FaceVertex()
- : vp(),vn(),vt()
- {
+ : vp()
+ , vn()
+ , vt()
+ , vc() {
+ // empty
}
// one-based, 0 means: 'does not exist'
- unsigned int vp,vn,vt;
+ unsigned int vp, vn, vt, vc;
};
struct Face {
@@ -95,33 +91,25 @@ private:
};
struct MeshInstance {
-
std::string name, matname;
std::vector<Face> faces;
};
void WriteHeader(std::ostringstream& out);
-
void WriteMaterialFile();
- void WriteGeometryFile();
-
+ void WriteGeometryFile(bool noMtl=false);
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);
private:
-
- const std::string filename;
+ std::string filename;
const aiScene* const pScene;
-
std::vector<aiVector3D> vp, vn, vt;
+ std::vector<aiColor4D> vc;
-
- struct aiVectorCompare
- {
- bool operator() (const aiVector3D& a, const aiVector3D& b) const
- {
+ 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;
@@ -131,22 +119,53 @@ private:
}
};
- class vecIndexMap
- {
+ struct aiColor4Compare {
+ bool operator() ( const aiColor4D& a, const aiColor4D& b ) const {
+ if ( a.r < b.r ) return true;
+ if ( a.r > b.r ) return false;
+ if ( a.g < b.g ) return true;
+ if ( a.g > b.g ) return false;
+ if ( a.b < b.b ) return true;
+ if ( a.b > b.b ) return false;
+ if ( a.a < b.a ) return true;
+ if ( a.a > b.a ) return false;
+ return false;
+ }
+ };
+
+ class vecIndexMap {
int mNextIndex;
typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
dataType vecMap;
+
public:
-
- vecIndexMap():mNextIndex(1)
- {}
+ vecIndexMap()
+ : mNextIndex(1) {
+ // empty
+ }
int getIndex(const aiVector3D& vec);
void getVectors( std::vector<aiVector3D>& vecs );
};
- vecIndexMap vpMap, vnMap, vtMap;
- std::vector<MeshInstance> meshes;
+ class colIndexMap {
+ int mNextIndex;
+ typedef std::map<aiColor4D, int, aiColor4Compare> dataType;
+ dataType colMap;
+
+ public:
+ colIndexMap()
+ : mNextIndex( 1 ) {
+ // empty
+ }
+
+ int getIndex( const aiColor4D& col );
+ void getColors( std::vector<aiColor4D> &colors );
+ };
+
+ vecIndexMap mVpMap, mVnMap, mVtMap;
+ colIndexMap mVcMap;
+ std::vector<MeshInstance> mMeshes;
// 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 f4abd643f..2658f8a2a 100644
--- a/src/3rdparty/assimp/code/ObjFileData.h
+++ b/src/3rdparty/assimp/code/ObjFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -38,6 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
+#pragma once
#ifndef OBJ_FILEDATA_H_INC
#define OBJ_FILEDATA_H_INC
@@ -56,59 +58,43 @@ struct Material;
// ------------------------------------------------------------------------------------------------
//! \struct Face
//! \brief Data structure for a simple obj-face, describes discredit,l.ation and materials
-struct Face
-{
+// ------------------------------------------------------------------------------------------------
+struct Face {
typedef std::vector<unsigned int> IndexArray;
//! Primitive type
aiPrimitiveType m_PrimitiveType;
//! Vertex indices
- IndexArray *m_pVertices;
+ IndexArray m_vertices;
//! Normal indices
- IndexArray *m_pNormals;
+ IndexArray m_normals;
//! Texture coordinates indices
- IndexArray *m_pTexturCoords;
+ IndexArray m_texturCoords;
//! 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 )
- {
+ Face( aiPrimitiveType pt = aiPrimitiveType_POLYGON)
+ : m_PrimitiveType( pt )
+ , m_vertices()
+ , m_normals()
+ , m_texturCoords()
+ , 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;
+ ~Face() {
+ // empty
}
};
// ------------------------------------------------------------------------------------------------
//! \struct Object
-//! \brief Stores all objects of an objfile object definition
-struct Object
-{
- enum ObjectType
- {
+//! \brief Stores all objects of an obj-file object definition
+// ------------------------------------------------------------------------------------------------
+struct Object {
+ enum ObjectType {
ObjType,
GroupType
};
@@ -123,29 +109,24 @@ struct Object
std::vector<unsigned int> m_Meshes;
//! \brief Default constructor
- Object() :
- m_strObjName("")
- {
+ Object()
+ : m_strObjName("") {
// empty
}
//! \brief Destructor
- ~Object()
- {
- for (std::vector<Object*>::iterator it = m_SubObjects.begin();
- it != m_SubObjects.end(); ++it)
- {
+ ~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
-{
+// ------------------------------------------------------------------------------------------------
+struct Material {
//! Name of material description
aiString MaterialName;
@@ -160,8 +141,8 @@ struct Material
aiString textureSpecularity;
aiString textureOpacity;
aiString textureDisp;
- enum TextureType
- {
+
+ enum TextureType {
TextureDiffuseType = 0,
TextureSpecularType,
TextureAmbientType,
@@ -191,32 +172,32 @@ struct Material
//! Emissive color
aiColor3D emissive;
//! Alpha value
- float alpha;
+ ai_real alpha;
//! Shineness factor
- float shineness;
+ ai_real shineness;
//! Illumination model
int illumination_model;
//! Index of refraction
- float ior;
+ ai_real ior;
+ //! Transparency color
+ aiColor3D transparent;
//! Constructor
Material()
- : diffuse (0.6f,0.6f,0.6f)
- , alpha (1.f)
- , shineness (0.0f)
- , illumination_model (1)
- , ior (1.f)
- {
+ : diffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) )
+ , alpha (ai_real( 1.0 ) )
+ , shineness ( ai_real( 0.0) )
+ , illumination_model (1)
+ , ior ( ai_real( 1.0 ) )
+ , transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) {
// empty
- for (size_t i = 0; i < TextureTypeCount; ++i)
- {
- clamp[i] = false;
+ for (size_t i = 0; i < TextureTypeCount; ++i) {
+ clamp[ i ] = false;
}
}
// Destructor
- ~Material()
- {
+ ~Material() {
// empty
}
};
@@ -224,6 +205,7 @@ struct Material
// ------------------------------------------------------------------------------------------------
//! \struct Mesh
//! \brief Data structure to store a mesh
+// ------------------------------------------------------------------------------------------------
struct Mesh {
static const unsigned int NoMaterial = ~0u;
/// The name for the mesh
@@ -244,7 +226,7 @@ struct Mesh {
bool m_hasVertexColors;
/// Constructor
- explicit Mesh( const std::string &name )
+ explicit Mesh( const std::string &name )
: m_name( name )
, m_pMaterial(NULL)
, m_uiNumIndices(0)
@@ -254,8 +236,7 @@ struct Mesh {
}
/// Destructor
- ~Mesh()
- {
+ ~Mesh() {
for (std::vector<Face*>::iterator it = m_Faces.begin();
it != m_Faces.end(); ++it)
{
@@ -267,8 +248,8 @@ struct Mesh {
// ------------------------------------------------------------------------------------------------
//! \struct Model
//! \brief Data structure to store all obj-specific model datas
-struct Model
-{
+// ------------------------------------------------------------------------------------------------
+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;
@@ -285,8 +266,6 @@ struct Model
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
@@ -322,8 +301,7 @@ struct Model
}
//! \brief The class destructor
- ~Model()
- {
+ ~Model() {
// Clear all stored object instances
for (std::vector<Object*>::iterator it = m_Objects.begin();
it != m_Objects.end(); ++it) {
@@ -354,4 +332,4 @@ struct Model
} // Namespace ObjFile
} // Namespace Assimp
-#endif
+#endif // OBJ_FILEDATA_H_INC
diff --git a/src/3rdparty/assimp/code/ObjFileImporter.cpp b/src/3rdparty/assimp/code/ObjFileImporter.cpp
index 082709dc7..9f3bdef97 100644
--- a/src/3rdparty/assimp/code/ObjFileImporter.cpp
+++ b/src/3rdparty/assimp/code/ObjFileImporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -39,19 +40,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
-#include "DefaultIOSystem.h"
#include "ObjFileImporter.h"
#include "ObjFileParser.h"
#include "ObjFileData.h"
+#include "IOStreamBuffer.h"
#include <memory>
+#include <assimp/DefaultIOSystem.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
-
+#include <assimp/importerdesc.h>
static const aiImporterDesc desc = {
"Wavefront Object Importer",
@@ -128,8 +129,11 @@ void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene,
throw DeadlyImportError( "OBJ-file is too small.");
}
+ IOStreamBuffer<char> streamedBuffer;
+ streamedBuffer.open( fileStream.get() );
+
// Allocate buffer and read file into it
- TextFileToBuffer( fileStream.get(),m_Buffer);
+ //TextFileToBuffer( fileStream.get(),m_Buffer);
// Get the model name
std::string modelName, folderName;
@@ -147,12 +151,12 @@ void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene,
// 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 progress = 0;
unsigned int progressCounter = 0;
const unsigned int updateProgressEveryBytes = 100 * 1024;
- const unsigned int progressTotal = (3*m_Buffer.size()/updateProgressEveryBytes);
+ const unsigned int progressTotal = static_cast<unsigned int>(3*m_Buffer.size()/updateProgressEveryBytes);*/
// process all '\'
- std::vector<char> ::iterator iter = m_Buffer.begin();
+ /*std::vector<char> ::iterator iter = m_Buffer.begin();
while (iter != m_Buffer.end())
{
if (*iter == '\\')
@@ -171,17 +175,19 @@ void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene,
m_progress->UpdateFileRead(++progress, progressTotal);
progressCounter = 0;
}
- }
+ }*/
// 1/3rd progress
m_progress->UpdateFileRead(1, 3);
// parse the file into a temporary representation
- ObjFileParser parser(m_Buffer, modelName, pIOHandler, m_progress, file);
+ ObjFileParser parser( streamedBuffer, modelName, pIOHandler, m_progress, file);
// And create the proper return structures out of it
CreateDataFromImport(parser.GetModel(), pScene);
+ streamedBuffer.close();
+
// Clean up allocated storage for the next import
m_Buffer.clear();
@@ -293,9 +299,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
// ------------------------------------------------------------------------------------------------
// Create topology data
-aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
- unsigned int meshIndex )
-{
+aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData, unsigned int meshIndex ) {
// Checking preconditions
ai_assert( NULL != pModel );
@@ -324,14 +328,14 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
ai_assert( NULL != inp );
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
- pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+ pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
- pMesh->mNumFaces += inp->m_pVertices->size();
+ pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size());
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
} else {
++pMesh->mNumFaces;
- if (inp->m_pVertices->size() > 3) {
+ if (inp->m_vertices.size() > 3) {
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
} else {
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
@@ -352,7 +356,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
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) {
+ for(size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
aiFace& f = pMesh->mFaces[ outIndex++ ];
uiIdxCount += f.mNumIndices = 2;
f.mIndices = new unsigned int[2];
@@ -360,7 +364,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
continue;
}
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
- for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
+ for(size_t i = 0; i < inp->m_vertices.size(); ++i) {
aiFace& f = pMesh->mFaces[ outIndex++ ];
uiIdxCount += f.mNumIndices = 1;
f.mIndices = new unsigned int[1];
@@ -369,7 +373,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
}
aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
- const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
+ const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_vertices.size();
uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
if (pFace->mNumIndices > 0) {
pFace->mIndices = new unsigned int[ uiNumIndices ];
@@ -389,8 +393,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
const ObjFile::Object* pCurrentObject,
unsigned int uiMeshIndex,
aiMesh* pMesh,
- unsigned int numIndices)
-{
+ unsigned int numIndices) {
// Checking preconditions
ai_assert( NULL != pCurrentObject );
@@ -400,8 +403,9 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
// Get current mesh
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
- if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
+ if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1 ) {
return;
+ }
// Copy vertices of this mesh instance
pMesh->mNumVertices = numIndices;
@@ -429,27 +433,25 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
// 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++ )
- {
+ 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() )
+ for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_vertices.size(); vertexIndex++ ) {
+ const unsigned int vertex = pSourceFace->m_vertices.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");
-
+ if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_normals.size()) {
+ const unsigned int normal = pSourceFace->m_normals.at( vertexIndex );
+ if ( normal >= pModel->m_Normals.size() ) {
+ throw DeadlyImportError( "OBJ: vertex normal index out of range" );
+ }
pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
}
@@ -461,9 +463,9 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
}
// Copy all texture coordinates
- if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
+ if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_texturCoords.size())
{
- const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
+ const unsigned int tex = pSourceFace->m_texturCoords.at( vertexIndex );
ai_assert( tex < pModel->m_TextureCoord.size() );
if ( tex >= pModel->m_TextureCoord.size() )
@@ -480,20 +482,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
// Get destination face
aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
- const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 );
- if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last)
- {
+ const bool last = ( vertexIndex == pSourceFace->m_vertices.size() - 1 );
+ if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
pDestFace->mIndices[ outVertexIndex ] = newIndex;
outVertexIndex++;
}
- if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT)
- {
+ if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) {
outIndex++;
outVertexIndex = 0;
- }
- else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE)
- {
+ } else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) {
outVertexIndex = 0;
if(!last)
@@ -502,7 +500,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
if (vertexIndex) {
if(!last) {
pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
- if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
+ if ( !pSourceFace->m_normals.empty() && !pModel->m_Normals.empty()) {
pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
}
if ( !pModel->m_TextureCoord.empty() ) {
@@ -546,20 +544,21 @@ void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects
// ------------------------------------------------------------------------------------------------
// 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));
+void ObjFileImporter::addTextureMappingModeProperty( aiMaterial* mat, aiTextureType type, int clampMode, int index) {
+ if ( nullptr == mat ) {
+ return;
+ }
+
+ mat->AddProperty<int>( &clampMode, 1, AI_MATKEY_MAPPINGMODE_U( type, index ) );
+ mat->AddProperty<int>( &clampMode, 1, AI_MATKEY_MAPPINGMODE_V( type, index ) );
}
// ------------------------------------------------------------------------------------------------
// Creates the material
-void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
-{
- ai_assert( NULL != pScene );
- if ( NULL == pScene )
+void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene ) {
+ if ( NULL == pScene ) {
return;
+ }
const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
pScene->mNumMaterials = 0;
@@ -603,9 +602,6 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
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 );
@@ -613,14 +609,18 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
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 );
+ mat->AddProperty( &pCurrentMaterial->transparent,1,AI_MATKEY_COLOR_TRANSPARENT);
// Adding refraction index
mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
// Adding textures
+ const int uvwIndex = 0;
+
if ( 0 != pCurrentMaterial->texture.length )
{
mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_DIFFUSE(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
{
addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
@@ -630,6 +630,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
if ( 0 != pCurrentMaterial->textureAmbient.length )
{
mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_AMBIENT(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
{
addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
@@ -637,11 +638,15 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
}
if ( 0 != pCurrentMaterial->textureEmissive.length )
+ {
mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_EMISSIVE(0) );
+ }
if ( 0 != pCurrentMaterial->textureSpecular.length )
{
mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_SPECULAR(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
{
addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
@@ -651,6 +656,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
if ( 0 != pCurrentMaterial->textureBump.length )
{
mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_HEIGHT(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
{
addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
@@ -660,6 +666,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
if ( 0 != pCurrentMaterial->textureNormal.length )
{
mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_NORMALS(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
{
addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
@@ -674,17 +681,19 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
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));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_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(pCurrentMaterial->clamp[type])
+ addTextureMappingModeProperty(mat, aiTextureType_REFLECTION, 1, i);
+ }
}
if ( 0 != pCurrentMaterial->textureDisp.length )
{
mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_DISPLACEMENT(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
{
addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
@@ -694,6 +703,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
if ( 0 != pCurrentMaterial->textureOpacity.length )
{
mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_OPACITY(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
{
addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
@@ -703,6 +713,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc
if ( 0 != pCurrentMaterial->textureSpecularity.length )
{
mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
+ mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_SHININESS(0) );
if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
{
addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
diff --git a/src/3rdparty/assimp/code/ObjFileImporter.h b/src/3rdparty/assimp/code/ObjFileImporter.h
index b03d00b9b..302cf951a 100644
--- a/src/3rdparty/assimp/code/ObjFileImporter.h
+++ b/src/3rdparty/assimp/code/ObjFileImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -37,8 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-
-
#ifndef OBJ_FILE_IMPORTER_H_INC
#define OBJ_FILE_IMPORTER_H_INC
@@ -49,21 +48,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMesh;
struct aiNode;
-namespace Assimp
-{
+namespace Assimp {
-namespace ObjFile
-{
-struct Object;
-struct Model;
+namespace ObjFile {
+ struct Object;
+ struct Model;
}
// ------------------------------------------------------------------------------------------------
/// \class ObjFileImporter
/// \brief Imports a waveform obj file
// ------------------------------------------------------------------------------------------------
-class ObjFileImporter : public BaseImporter
-{
+class ObjFileImporter : public BaseImporter {
public:
/// \brief Default constructor
ObjFileImporter();
@@ -77,7 +73,6 @@ public:
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
private:
-
//! \brief Appends the supported extension.
const aiImporterDesc* GetInfo () const;
@@ -106,7 +101,7 @@ private:
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);
+ void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1, int index = 0);
//! \brief Appends a child node to a parent node and updates the data structures.
void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
diff --git a/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp b/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp
index 2b3847bbb..6ef655f8a 100644
--- a/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp
+++ b/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,20 +55,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 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";
+// Material specific token (case insensitive compare)
+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 EmissiveTexture1 = "map_emissive";
+static const std::string EmissiveTexture2 = "map_Ke";
+static const std::string BumpTexture1 = "map_bump";
+static const std::string BumpTexture2 = "bump";
+static const std::string NormalTexture = "map_Kn";
+static const std::string ReflectionTexture = "refl";
+static const std::string DisplacementTexture1 = "map_disp";
+static const std::string DisplacementTexture2 = "disp";
+static const std::string SpecularityTexture = "map_ns";
// texture option specific token
static const std::string BlendUOption = "-blendu";
@@ -163,8 +164,18 @@ void ObjFileMtlImporter::load()
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
-
- case 'd':
+ case 'T':
+ {
+ ++m_DataIt;
+ if (*m_DataIt == 'f') // Material transmission
+ {
+ ++m_DataIt;
+ getColorRGBA( &m_pModel->m_pCurrentMaterial->transparent);
+ }
+ 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
@@ -232,7 +243,7 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
{
ai_assert( NULL != pColor );
- float r( 0.0f ), g( 0.0f ), b( 0.0f );
+ ai_real r( 0.0 ), g( 0.0 ), b( 0.0 );
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
pColor->r = r;
@@ -255,10 +266,10 @@ void ObjFileMtlImporter::getIlluminationModel( int &illum_model )
// -------------------------------------------------------------------
// Loads a single float value.
-void ObjFileMtlImporter::getFloatValue( float &value )
+void ObjFileMtlImporter::getFloatValue( ai_real &value )
{
m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
- value = (float) fast_atof(m_buffer);
+ value = (ai_real) fast_atof(m_buffer);
}
// -------------------------------------------------------------------
@@ -292,6 +303,9 @@ void ObjFileMtlImporter::createMaterial()
// New Material created
m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
+ if (m_pModel->m_pCurrentMesh) {
+ m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
+ }
m_pModel->m_MaterialLib.push_back( name );
m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
} else {
@@ -307,49 +321,46 @@ void ObjFileMtlImporter::getTexture() {
int clampIndex = -1;
const char *pPtr( &(*m_DataIt) );
- if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), DiffuseTexture.size() ) ) {
+ if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), static_cast<unsigned int>(DiffuseTexture.size()) ) ) {
// Diffuse texture
out = & m_pModel->m_pCurrentMaterial->texture;
clampIndex = ObjFile::Material::TextureDiffuseType;
- } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(),AmbientTexture.size() ) ) {
+ } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(), static_cast<unsigned int>(AmbientTexture.size()) ) ) {
// Ambient texture
out = & m_pModel->m_pCurrentMaterial->textureAmbient;
clampIndex = ObjFile::Material::TextureAmbientType;
- } else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), SpecularTexture.size())) {
+ } else if ( !ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()) ) ) {
// Specular texture
out = & m_pModel->m_pCurrentMaterial->textureSpecular;
clampIndex = ObjFile::Material::TextureSpecularType;
- } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), OpacityTexture.size() ) ) {
+ } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()) ) ) {
// Opacity texture
out = & m_pModel->m_pCurrentMaterial->textureOpacity;
clampIndex = ObjFile::Material::TextureOpacityType;
- } else if (!ASSIMP_strincmp( pPtr, EmmissiveTexture.c_str(), EmmissiveTexture.size())) {
+ } else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture1.c_str(), static_cast<unsigned int>(EmissiveTexture1.size()) ) ||
+ !ASSIMP_strincmp( pPtr, EmissiveTexture2.c_str(), static_cast<unsigned int>(EmissiveTexture2.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() ) ) {
+ } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size()) ) ||
+ !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()) ) ) {
// Bump texture
out = & m_pModel->m_pCurrentMaterial->textureBump;
clampIndex = ObjFile::Material::TextureBumpType;
- } else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), NormalTexture.size())) {
+ } else if ( !ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast<unsigned int>(NormalTexture.size()) ) ) {
// Normal map
out = & m_pModel->m_pCurrentMaterial->textureNormal;
clampIndex = ObjFile::Material::TextureNormalType;
- } else if(!ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), ReflectionTexture.size() ) ) {
+ } else if( !ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()) ) ) {
// Reflection texture(s)
//Do nothing here
return;
- } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), DisplacementTexture.size() ) ) {
+ } else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size()) ) ||
+ !ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()) ) ) {
// Displacement texture
out = &m_pModel->m_pCurrentMaterial->textureDisp;
clampIndex = ObjFile::Material::TextureDispType;
- } else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(),SpecularityTexture.size() ) ) {
+ } else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()) ) ) {
// Specularity scaling (glossiness)
out = & m_pModel->m_pCurrentMaterial->textureSpecularity;
clampIndex = ObjFile::Material::TextureSpecularityType;
@@ -394,7 +405,7 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
//skip option key and value
int skipToken = 1;
- if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), ClampOption.size()))
+ if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), static_cast<unsigned int>(ClampOption.size())))
{
DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
char value[3];
@@ -406,7 +417,7 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
skipToken = 2;
}
- else if( !ASSIMP_strincmp( pPtr, TypeOption.c_str(), TypeOption.size() ) )
+ else if( !ASSIMP_strincmp( pPtr, TypeOption.c_str(), static_cast<unsigned int>(TypeOption.size()) ) )
{
DataArrayIt it = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
char value[ 12 ];
@@ -449,22 +460,22 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
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()))
+ else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size()))
+ || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size()))
+ || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size()))
+ || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size()))
+ || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size()))
+ || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size())))
{
skipToken = 2;
}
- else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), ModifyMapOption.size()))
+ else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(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())
+ else if ( !ASSIMP_strincmp(pPtr, OffsetOption.c_str(), static_cast<unsigned int>(OffsetOption.size()))
+ || !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), static_cast<unsigned int>(ScaleOption.size()))
+ || !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), static_cast<unsigned int>(TurbulenceOption.size()))
)
{
skipToken = 4;
diff --git a/src/3rdparty/assimp/code/ObjFileMtlImporter.h b/src/3rdparty/assimp/code/ObjFileMtlImporter.h
index f2c1ba820..c9bcc9a9f 100644
--- a/src/3rdparty/assimp/code/ObjFileMtlImporter.h
+++ b/src/3rdparty/assimp/code/ObjFileMtlImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <string>
+#include <assimp/defs.h>
struct aiColor3D;
struct aiString;
@@ -85,7 +87,7 @@ private:
/// Get illumination model from loaded data
void getIlluminationModel( int &illum_model );
/// Gets a float value from data.
- void getFloatValue( float &value );
+ void getFloatValue( ai_real &value );
/// Creates a new material from loaded data.
void createMaterial();
/// Get texture name from loaded data.
@@ -111,4 +113,4 @@ private:
} // Namespace Assimp
-#endif
+#endif // OBJFILEMTLIMPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/ObjFileParser.cpp b/src/3rdparty/assimp/code/ObjFileParser.cpp
index 79bc299bc..d89d52977 100644
--- a/src/3rdparty/assimp/code/ObjFileParser.cpp
+++ b/src/3rdparty/assimp/code/ObjFileParser.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -38,8 +39,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-
-
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include "ObjFileParser.h"
@@ -47,23 +46,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ObjTools.h"
#include "ObjFileData.h"
#include "ParsingUtils.h"
-#include "DefaultIOSystem.h"
#include "BaseImporter.h"
+#include <assimp/DefaultIOSystem.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;
-// -------------------------------------------------------------------
-// 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()),
+ObjFileParser::ObjFileParser()
+: m_DataIt()
+, m_DataItEnd()
+, m_pModel( NULL )
+, m_uiLine( 0 )
+, m_pIO( nullptr )
+, m_progress( nullptr )
+, m_originalObjFileName() {
+ // empty
+}
+
+ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::string &modelName,
+ IOSystem *io, ProgressHandler* progress,
+ const std::string &originalObjFileName) :
+ m_DataIt(),
+ m_DataItEnd(),
m_pModel(NULL),
m_uiLine(0),
m_pIO( io ),
@@ -83,71 +92,68 @@ ObjFileParser::ObjFileParser(std::vector<char> &data, const std::string &modelNa
m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
// Start parsing the file
- parseFile();
+ parseFile( streamBuffer );
}
-// -------------------------------------------------------------------
-// Destructor
-ObjFileParser::~ObjFileParser()
-{
+ObjFileParser::~ObjFileParser() {
delete m_pModel;
m_pModel = NULL;
}
-// -------------------------------------------------------------------
-// Returns a pointer to the model instance.
-ObjFile::Model *ObjFileParser::GetModel() const
-{
- return m_pModel;
+void ObjFileParser::setBuffer( std::vector<char> &buffer ) {
+ m_DataIt = buffer.begin();
+ m_DataItEnd = buffer.end();
}
-// -------------------------------------------------------------------
-// File parsing method.
-void ObjFileParser::parseFile()
-{
- if (m_DataIt == m_DataItEnd)
- return;
+ObjFile::Model *ObjFileParser::GetModel() const {
+ return m_pModel;
+}
+void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
// only update every 100KB or it'll be too slow
- const unsigned int updateProgressEveryBytes = 100 * 1024;
+ //const unsigned int updateProgressEveryBytes = 100 * 1024;
unsigned int progressCounter = 0;
- const unsigned int bytesToProcess = std::distance(m_DataIt, m_DataItEnd);
+ const unsigned int bytesToProcess = static_cast<unsigned int>(streamBuffer.size());
const unsigned int progressTotal = 3 * bytesToProcess;
const unsigned int progressOffset = bytesToProcess;
unsigned int processed = 0;
+ size_t lastFilePos( 0 );
- DataArrayIt lastDataIt = m_DataIt;
+ std::vector<char> buffer;
+ while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
+ m_DataIt = buffer.begin();
+ m_DataItEnd = buffer.end();
- while (m_DataIt != m_DataItEnd)
- {
// Handle progress reporting
- processed += std::distance(lastDataIt, m_DataIt);
- lastDataIt = m_DataIt;
- if (processed > (progressCounter * updateProgressEveryBytes))
- {
+ const size_t filePos( streamBuffer.getFilePos() );
+ if ( lastFilePos < filePos ) {
+ processed += static_cast<unsigned int>(filePos);
+ lastFilePos = filePos;
progressCounter++;
- m_progress->UpdateFileRead(progressOffset + processed*2, progressTotal);
+ m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
}
// parse line
- switch (*m_DataIt)
- {
+ switch (*m_DataIt) {
case 'v': // Parse a vertex texture coordinate
{
++m_DataIt;
if (*m_DataIt == ' ' || *m_DataIt == '\t') {
- size_t numComponents = getNumComponentsInLine();
+ size_t numComponents = getNumComponentsInDataDefinition();
if (numComponents == 3) {
// read in vertex definition
getVector3(m_pModel->m_Vertices);
+ } else if (numComponents == 4) {
+ // read in vertex definition (homogeneous coords)
+ getHomogeneousVector3(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 );
+ ++m_DataIt;
+ getVector( m_pModel->m_TextureCoord );
} else if (*m_DataIt == 'n') {
// Read in normal vector definition
++m_DataIt;
@@ -173,16 +179,37 @@ void ObjFileParser::parseFile()
case 'u': // Parse a material desc. setter
{
- getMaterialDesc();
+ std::string name;
+
+ getNameNoSpace(m_DataIt, m_DataItEnd, name);
+
+ size_t nextSpace = name.find(" ");
+ if (nextSpace != std::string::npos)
+ name = name.substr(0, nextSpace);
+
+ if(name == "usemtl")
+ {
+ getMaterialDesc();
+ }
}
break;
case 'm': // Parse a material library or merging group ('mg')
{
- if (*(m_DataIt + 1) == 'g')
+ std::string name;
+
+ getNameNoSpace(m_DataIt, m_DataItEnd, name);
+
+ size_t nextSpace = name.find(" ");
+ if (nextSpace != std::string::npos)
+ name = name.substr(0, nextSpace);
+
+ if (name == "mg")
getGroupNumberAndResolution();
- else
+ else if(name == "mtllib")
getMaterialLib();
+ else
+ goto pf_skip_line;
}
break;
@@ -206,6 +233,7 @@ void ObjFileParser::parseFile()
default:
{
+pf_skip_line:
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
@@ -213,12 +241,14 @@ void ObjFileParser::parseFile()
}
}
-// -------------------------------------------------------------------
-// Copy the next word in a temporary buffer
-void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
-{
+void ObjFileParser::copyNextWord(char *pBuffer, size_t length) {
size_t index = 0;
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+ if ( *m_DataIt == '\\' ) {
+ m_DataIt++;
+ m_DataIt++;
+ m_DataIt = getNextWord<DataArrayIt>( m_DataIt, m_DataItEnd );
+ }
while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
pBuffer[index] = *m_DataIt;
index++;
@@ -232,70 +262,61 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t 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;
+static bool isDataDefinitionEnd( const char *tmp ) {
+ if ( *tmp == '\\' ) {
+ tmp++;
+ if ( IsLineEnd( *tmp ) ) {
+ tmp++;
+ return true;
}
-
- if (c == '\n' || c == '\r') {
- if(continuation) {
- pBuffer[ index++ ] = ' ';
- continue;
- }
- break;
- }
-
- continuation = false;
- pBuffer[ index++ ] = c;
}
- ai_assert(index < length);
- pBuffer[ index ] = '\0';
+ return false;
}
-size_t ObjFileParser::getNumComponentsInLine() {
+size_t ObjFileParser::getNumComponentsInDataDefinition() {
size_t numComponents( 0 );
const char* tmp( &m_DataIt[0] );
- while( !IsLineEnd( *tmp ) ) {
+ bool end_of_definition = false;
+ while ( !end_of_definition ) {
+ if ( isDataDefinitionEnd( tmp ) ) {
+ tmp += 2;
+ } else if ( IsLineEnd( *tmp ) ) {
+ end_of_definition = true;
+ }
if ( !SkipSpaces( &tmp ) ) {
break;
}
+ const bool isNum( IsNumeric( *tmp ) );
SkipToken( tmp );
- ++numComponents;
+ if ( isNum ) {
+ ++numComponents;
+ }
+ if ( !SkipSpaces( &tmp ) ) {
+ break;
+ }
}
return numComponents;
}
-// -------------------------------------------------------------------
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
- size_t numComponents = getNumComponentsInLine();
- float x, y, z;
+ size_t numComponents = getNumComponentsInDataDefinition();
+ ai_real x, y, z;
if( 2 == numComponents ) {
copyNextWord( m_buffer, Buffersize );
- x = ( float ) fast_atof( m_buffer );
+ x = ( ai_real ) fast_atof( m_buffer );
copyNextWord( m_buffer, Buffersize );
- y = ( float ) fast_atof( m_buffer );
+ y = ( ai_real ) fast_atof( m_buffer );
z = 0.0;
} else if( 3 == numComponents ) {
copyNextWord( m_buffer, Buffersize );
- x = ( float ) fast_atof( m_buffer );
+ x = ( ai_real ) fast_atof( m_buffer );
copyNextWord( m_buffer, Buffersize );
- y = ( float ) fast_atof( m_buffer );
+ y = ( ai_real ) fast_atof( m_buffer );
copyNextWord( m_buffer, Buffersize );
- z = ( float ) fast_atof( m_buffer );
+ z = ( ai_real ) fast_atof( m_buffer );
} else {
throw DeadlyImportError( "OBJ: Invalid number of components" );
}
@@ -303,61 +324,75 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
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;
+ ai_real x, y, z;
copyNextWord(m_buffer, Buffersize);
- x = (float) fast_atof(m_buffer);
+ x = (ai_real) fast_atof(m_buffer);
copyNextWord(m_buffer, Buffersize);
- y = (float) fast_atof(m_buffer);
+ y = (ai_real) fast_atof(m_buffer);
copyNextWord( m_buffer, Buffersize );
- z = ( float ) fast_atof( m_buffer );
+ z = ( ai_real ) 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::getHomogeneousVector3( std::vector<aiVector3D> &point3d_array ) {
+ ai_real x, y, z, w;
+ copyNextWord(m_buffer, Buffersize);
+ x = (ai_real) fast_atof(m_buffer);
+
+ copyNextWord(m_buffer, Buffersize);
+ y = (ai_real) fast_atof(m_buffer);
+
+ copyNextWord( m_buffer, Buffersize );
+ z = ( ai_real ) fast_atof( m_buffer );
+
+ copyNextWord( m_buffer, Buffersize );
+ w = ( ai_real ) fast_atof( m_buffer );
+
+ ai_assert( w != 0 );
+
+ point3d_array.push_back( aiVector3D( x/w, y/w, z/w ) );
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+}
+
void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b ) {
- float x, y, z;
+ ai_real x, y, z;
copyNextWord(m_buffer, Buffersize);
- x = (float) fast_atof(m_buffer);
+ x = (ai_real) fast_atof(m_buffer);
copyNextWord(m_buffer, Buffersize);
- y = (float) fast_atof(m_buffer);
+ y = (ai_real) fast_atof(m_buffer);
copyNextWord( m_buffer, Buffersize );
- z = ( float ) fast_atof( m_buffer );
+ z = ( ai_real ) fast_atof( m_buffer );
point3d_array_a.push_back( aiVector3D( x, y, z ) );
copyNextWord(m_buffer, Buffersize);
- x = (float) fast_atof(m_buffer);
+ x = (ai_real) fast_atof(m_buffer);
copyNextWord(m_buffer, Buffersize);
- y = (float) fast_atof(m_buffer);
+ y = (ai_real) fast_atof(m_buffer);
copyNextWord( m_buffer, Buffersize );
- z = ( float ) fast_atof( m_buffer );
+ z = ( ai_real ) 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
void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
- float x, y;
+ ai_real x, y;
copyNextWord(m_buffer, Buffersize);
- x = (float) fast_atof(m_buffer);
+ x = (ai_real) fast_atof(m_buffer);
copyNextWord(m_buffer, Buffersize);
- y = (float) fast_atof(m_buffer);
+ y = (ai_real) fast_atof(m_buffer);
point2d_array.push_back(aiVector2D(x, y));
@@ -366,37 +401,30 @@ void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
static const std::string DefaultObjName = "defaultobject";
-// -------------------------------------------------------------------
-// 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' ) {
+void ObjFileParser::getFace( aiPrimitiveType type ) {
+ m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
+ if ( m_DataIt == m_DataItEnd || *m_DataIt == '\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>;
+ ObjFile::Face *face = new ObjFile::Face( type );
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 int vSize = static_cast<unsigned int>(m_pModel->m_Vertices.size());
+ const int vtSize = static_cast<unsigned int>(m_pModel->m_TextureCoord.size());
+ const int vnSize = static_cast<unsigned int>(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) {
+ while ( m_DataIt != m_DataItEnd ) {
iStep = 1;
- if ( IsLineEnd( *pPtr ) ) {
+ if ( IsLineEnd( *m_DataIt ) ) {
break;
}
- if (*pPtr=='/' ) {
+ if ( *m_DataIt =='/' ) {
if (type == aiPrimitiveType_POINT) {
DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
}
@@ -408,11 +436,11 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
}
}
iPos++;
- } else if( IsSpaceOrNewLine( *pPtr ) ) {
+ } else if( IsSpaceOrNewLine( *m_DataIt ) ) {
iPos = 0;
} else {
//OBJ USES 1 Base ARRAYS!!!!
- const int iVal( ::atoi( pPtr ) );
+ const int iVal( ::atoi( & ( *m_DataIt ) ) );
// increment iStep position based off of the sign and # of digits
int tmp = iVal;
@@ -423,65 +451,50 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
++iStep;
}
- if ( iVal > 0 )
- {
+ 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 );
+ if ( 0 == iPos ) {
+ face->m_vertices.push_back( iVal - 1 );
+ } else if ( 1 == iPos ) {
+ face->m_texturCoords.push_back( iVal - 1 );
+ } else if ( 2 == iPos ) {
+ face->m_normals.push_back( iVal - 1 );
hasNormal = true;
- }
- else
- {
+ } else {
reportErrorTokenInFace();
}
- }
- else if ( iVal < 0 )
- {
+ } 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 );
+ if ( 0 == iPos ) {
+ face->m_vertices.push_back( vSize + iVal );
+ } else if ( 1 == iPos ) {
+ face->m_texturCoords.push_back( vtSize + iVal );
+ } else if ( 2 == iPos ) {
+ face->m_normals.push_back( vnSize + iVal );
hasNormal = true;
- }
- else
- {
+ } else {
reportErrorTokenInFace();
}
+ } else {
+ //On error, std::atoi will return 0 which is not a valid value
+ delete face;
+ delete m_pModel;
+ m_pModel = nullptr;
+ throw DeadlyImportError("OBJ: Invalid face indice");
}
+
}
- pPtr += iStep;
+ m_DataIt += iStep;
}
- if ( pIndices->empty() ) {
+ if ( face->m_vertices.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;
-
+ delete face;
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;
@@ -501,8 +514,8 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
// 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();
+ m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int) face->m_vertices.size();
+ m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int) face->m_texturCoords.size();
if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) {
m_pModel->m_pCurrentMesh->m_hasNormals = true;
}
@@ -510,10 +523,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
-// -------------------------------------------------------------------
-// Get values for a new material description
-void ObjFileParser::getMaterialDesc()
-{
+void ObjFileParser::getMaterialDesc() {
// Get next data for material data
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if (m_DataIt == m_DataItEnd) {
@@ -536,28 +546,31 @@ void ObjFileParser::getMaterialDesc()
// 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))
+ if ( m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString( strName ) ) {
skip = true;
+ }
- if (!skip)
- {
+ 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
- {
+ if (it == m_pModel->m_MaterialMap.end()) {
+ // Not found, so we don't know anything about the material except for its name.
+ // This may be the case if the material library is missing. We don't want to lose all
+ // materials if that happens, so create a new named material instead of discarding it
+ // completely.
+ DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", creating new material");
+ m_pModel->m_pCurrentMaterial = new ObjFile::Material();
+ m_pModel->m_pCurrentMaterial->MaterialName.Set(strName);
+ m_pModel->m_MaterialLib.push_back(strName);
+ m_pModel->m_MaterialMap[strName] = m_pModel->m_pCurrentMaterial;
+ } else {
// Found, using detected material
m_pModel->m_pCurrentMaterial = (*it).second;
}
- if (needsNewMesh(strName))
- createMesh(strName);
+ if ( needsNewMesh( strName ) ) {
+ createMesh( strName );
+ }
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
}
@@ -568,26 +581,13 @@ void ObjFileParser::getMaterialDesc()
// -------------------------------------------------------------------
// 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;
- }
- }
+void ObjFileParser::getComment() {
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
// Get material library from file.
-void ObjFileParser::getMaterialLib()
-{
+void ObjFileParser::getMaterialLib() {
// Translate tuple
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if( m_DataIt == m_DataItEnd ) {
@@ -602,6 +602,13 @@ void ObjFileParser::getMaterialLib()
// Check for existence
const std::string strMatName(pStart, &(*m_DataIt));
std::string absName;
+
+ // Check if directive is valid.
+ if ( 0 == strMatName.length() ) {
+ DefaultLogger::get()->warn( "OBJ: no name for material library specified." );
+ return;
+ }
+
if ( m_pIO->StackSize() > 0 ) {
std::string path = m_pIO->CurrentDirectory();
if ( '/' != *path.rbegin() ) {
@@ -619,7 +626,7 @@ void ObjFileParser::getMaterialLib()
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);
+ DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatFallbackName);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
return;
}
@@ -639,8 +646,7 @@ void ObjFileParser::getMaterialLib()
// -------------------------------------------------------------------
// Set a new material definition as the current material.
-void ObjFileParser::getNewMaterial()
-{
+void ObjFileParser::getNewMaterial() {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
if( m_DataIt == m_DataItEnd ) {
@@ -653,17 +659,13 @@ void ObjFileParser::getNewMaterial()
++m_DataIt;
}
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
- if ( it == m_pModel->m_MaterialMap.end() )
- {
+ 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
- {
+ } else {
// Set new material
- if ( needsNewMesh( strMat ) )
- {
+ if ( needsNewMesh( strMat ) ) {
createMesh( strMat );
}
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
@@ -692,36 +694,36 @@ int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
// -------------------------------------------------------------------
// Getter for a group name.
-void ObjFileParser::getGroupName()
-{
- std::string strGroupName;
+void ObjFileParser::getGroupName() {
+ std::string groupName;
- m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
+ // here we skip 'g ' from line
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, groupName);
if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
return;
}
// Change active group, if necessary
- if ( m_pModel->m_strActiveGroup != strGroupName )
- {
+ if ( m_pModel->m_strActiveGroup != groupName ) {
// Search for already existing entry
- ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
+ ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(groupName);
// We are mapping groups into the object structure
- createObject( strGroupName );
+ createObject( groupName );
// 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_Groups[ groupName ] = pFaceIDArray;
m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
}
else
{
m_pModel->m_pGroupFaceIDs = (*it).second;
}
- m_pModel->m_strActiveGroup = strGroupName;
+ m_pModel->m_strActiveGroup = groupName;
}
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
@@ -809,7 +811,7 @@ void ObjFileParser::createMesh( const std::string &meshName )
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;
+ unsigned int meshId = static_cast<unsigned int>(m_pModel->m_Meshes.size()-1);
if ( NULL != m_pModel->m_pCurrent )
{
m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
@@ -832,7 +834,11 @@ bool ObjFileParser::needsNewMesh( const std::string &materialName )
bool newMat = false;
int matIdx = getMaterialIndex( materialName );
int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
- if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx )
+ if ( curMatIdx != int(ObjFile::Mesh::NoMaterial)
+ && curMatIdx != matIdx
+ // no need create a new mesh if no faces in current
+ // lets say 'usemtl' goes straight after 'g'
+ && m_pModel->m_pCurrentMesh->m_Faces.size() > 0 )
{
// New material -> only one material per mesh, so we need to create a new
// material
diff --git a/src/3rdparty/assimp/code/ObjFileParser.h b/src/3rdparty/assimp/code/ObjFileParser.h
index f1be764f0..fa5b3ca31 100644
--- a/src/3rdparty/assimp/code/ObjFileParser.h
+++ b/src/3rdparty/assimp/code/ObjFileParser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/vector2.h>
#include <assimp/vector3.h>
#include <assimp/mesh.h>
+#include "IOStreamBuffer.h"
namespace Assimp {
@@ -63,7 +65,7 @@ class ProgressHandler;
/// \class ObjFileParser
/// \brief Parser for a obj waveform file
-class ObjFileParser {
+class ASSIMP_API ObjFileParser {
public:
static const size_t Buffersize = 4096;
typedef std::vector<char> DataArray;
@@ -71,24 +73,32 @@ public:
typedef std::vector<char>::const_iterator ConstDataArrayIt;
public:
- /// \brief Constructor with data array.
- ObjFileParser(std::vector<char> &Data, const std::string &strModelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName);
- /// \brief Destructor
+ /// @brief The default constructor.
+ ObjFileParser();
+ /// @brief Constructor with data array.
+ ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName);
+ /// @brief Destructor
~ObjFileParser();
- /// \brief Model getter.
+ /// @brief If you want to load in-core data.
+ void setBuffer( std::vector<char> &buffer );
+ /// @brief Model getter.
ObjFile::Model *GetModel() const;
-private:
+protected:
/// Parse the loaded file
- void parseFile();
+ void parseFile( IOStreamBuffer<char> &streamBuffer );
/// 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);
+// void copyNextLine(char *pBuffer, size_t length);
+ /// Get the number of components in a line.
+ size_t getNumComponentsInDataDefinition();
/// 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 homogeneous vector as a 3D vector
+ void getHomogeneousVector3( 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.
@@ -121,8 +131,6 @@ private:
bool needsNewMesh( const std::string &rMaterialName );
/// Error report in token
void reportErrorTokenInFace();
- /// Get the number of components in a line.
- size_t getNumComponentsInLine();
private:
// Copy and assignment constructor should be private
@@ -146,9 +154,8 @@ private:
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;
+ /// Path to the current model, name of the obj file where the buffer comes from
+ const std::string m_originalObjFileName;
};
} // Namespace Assimp
diff --git a/src/3rdparty/assimp/code/ObjTools.h b/src/3rdparty/assimp/code/ObjTools.h
index 311965ce3..7236cedc0 100644
--- a/src/3rdparty/assimp/code/ObjTools.h
+++ b/src/3rdparty/assimp/code/ObjTools.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,8 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
#include <vector>
-namespace Assimp
-{
+namespace Assimp {
/** @brief Returns true, if the last entry of the buffer is reached.
* @param it Iterator of current position.
@@ -57,15 +57,14 @@ namespace Assimp
* @return true, if the end of the buffer is reached.
*/
template<class char_t>
-inline bool isEndOfBuffer( char_t it, char_t end )
-{
+inline bool isEndOfBuffer( char_t it, char_t end ) {
if ( it == end )
{
return true;
}
else
{
- end--;
+ --end;
}
return ( it == end );
}
@@ -80,8 +79,10 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
{
while ( !isEndOfBuffer( pBuffer, pEnd ) )
{
- if( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) )
- break;
+ if ( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) ) {
+ //if ( *pBuffer != '\\' )
+ break;
+ }
pBuffer++;
}
return pBuffer;
@@ -115,14 +116,16 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
++it;
}
- if ( it != end )
- {
+
+ 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 == ' ') )
+ while ( it != end && ( *it == '\t' || *it == ' ' ) ) {
++it;
+ }
+
return it;
}
@@ -142,11 +145,50 @@ inline char_t getName( char_t it, char_t end, std::string &name )
}
char *pStart = &( *it );
- while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
+ while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )) {
++it;
}
- while( isEndOfBuffer( it, end ) || IsLineEnd( *it ) || IsSpaceOrNewLine( *it ) ) {
+ while(IsSpace( *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 a name from the current line. Do not 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
+ */
+template<class char_t>
+inline char_t getNameNoSpace( char_t it, char_t end, std::string &name )
+{
+ name = "";
+ if( isEndOfBuffer( it, end ) ) {
+ return end;
+ }
+
+ char *pStart = &( *it );
+ while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )
+ && !IsSpaceOrNewLine( *it ) ) {
+ ++it;
+ }
+
+ while( isEndOfBuffer( it, end ) || IsLineEnd( *it )
+ || IsSpaceOrNewLine( *it ) ) {
--it;
}
++it;
@@ -196,12 +238,12 @@ inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length
* @return Current-iterator with new position
*/
template<class char_t>
-inline char_t getFloat( char_t it, char_t end, float &value )
+inline char_t getFloat( char_t it, char_t end, ai_real &value )
{
static const size_t BUFFERSIZE = 1024;
char buffer[ BUFFERSIZE ];
it = CopyNextWord<char_t>( it, end, buffer, BUFFERSIZE );
- value = (float) fast_atof( buffer );
+ value = (ai_real) fast_atof( buffer );
return it;
}
@@ -246,6 +288,20 @@ string_type trim_whitespaces(string_type str)
return str;
}
+template<class T>
+bool hasLineEnd( T it, T end ) {
+ bool hasLineEnd( false );
+ while ( !isEndOfBuffer( it, end ) ) {
+ it++;
+ if ( IsLineEnd( it ) ) {
+ hasLineEnd = true;
+ break;
+ }
+ }
+
+ return hasLineEnd;
+}
+
} // Namespace Assimp
#endif // OBJ_TOOLS_H_INC
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
index ce17cea6a..95aec221f 100644
--- a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
+++ b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -483,7 +484,7 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh)
NormalizeBoneWeights(submesh->vertexData);
- submesh->index = mesh->subMeshes.size();
+ submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
mesh->subMeshes.push_back(submesh);
}
@@ -498,7 +499,7 @@ void OgreBinarySerializer::NormalizeBoneWeights(VertexData *vertexData) const
}
/** Normalize bone weights.
- Some exporters wont care if the sum of all bone weights
+ Some exporters won't 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)
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.h b/src/3rdparty/assimp/code/OgreBinarySerializer.h
index 067e36a63..c48e33dd6 100644
--- a/src/3rdparty/assimp/code/OgreBinarySerializer.h
+++ b/src/3rdparty/assimp/code/OgreBinarySerializer.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OgreImporter.cpp b/src/3rdparty/assimp/code/OgreImporter.cpp
index 504f6a96f..4dc802574 100644
--- a/src/3rdparty/assimp/code/OgreImporter.cpp
+++ b/src/3rdparty/assimp/code/OgreImporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -40,12 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-
-
#include "OgreImporter.h"
#include "OgreBinarySerializer.h"
#include "OgreXmlSerializer.h"
#include <assimp/Importer.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
static const aiImporterDesc desc = {
diff --git a/src/3rdparty/assimp/code/OgreImporter.h b/src/3rdparty/assimp/code/OgreImporter.h
index 8b2179502..2b3009096 100644
--- a/src/3rdparty/assimp/code/OgreImporter.h
+++ b/src/3rdparty/assimp/code/OgreImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OgreMaterial.cpp b/src/3rdparty/assimp/code/OgreMaterial.cpp
index f9da9d584..1abca2cf1 100644
--- a/src/3rdparty/assimp/code/OgreMaterial.cpp
+++ b/src/3rdparty/assimp/code/OgreMaterial.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -77,7 +78,7 @@ void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIO
aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
if (material)
{
- submesh->materialIndex = materials.size();
+ submesh->materialIndex = static_cast<int>(materials.size());
materials.push_back(material);
}
}
@@ -93,13 +94,13 @@ void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIO
// 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);
+ SubMeshXml *submesh = mesh->GetSubMesh( static_cast<uint16_t>(i));
if (submesh && !submesh->materialRef.empty())
{
aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
if (material)
{
- submesh->materialIndex = materials.size();
+ submesh->materialIndex = static_cast<int>(materials.size());
materials.push_back(material);
}
}
@@ -110,7 +111,7 @@ void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIO
void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials)
{
- pScene->mNumMaterials = materials.size();
+ pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
if (pScene->mNumMaterials > 0)
{
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
@@ -257,7 +258,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
ReadTechnique(Trim(techniqueName), ss, material);
}
- // Read informations from a custom material
+ // Read information 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.
diff --git a/src/3rdparty/assimp/code/OgreParsingUtils.h b/src/3rdparty/assimp/code/OgreParsingUtils.h
index def3cf733..b0c31e5be 100644
--- a/src/3rdparty/assimp/code/OgreParsingUtils.h
+++ b/src/3rdparty/assimp/code/OgreParsingUtils.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -90,11 +91,11 @@ 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>))));
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
}
else
{
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
}
return s;
}
@@ -104,11 +105,11 @@ 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());
+ s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
}
else
{
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
}
return s;
}
diff --git a/src/3rdparty/assimp/code/OgreStructs.cpp b/src/3rdparty/assimp/code/OgreStructs.cpp
index e2e8c8103..09597950a 100644
--- a/src/3rdparty/assimp/code/OgreStructs.cpp
+++ b/src/3rdparty/assimp/code/OgreStructs.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -274,12 +275,12 @@ AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices)
AssimpVertexBoneWeightList weights;
for(size_t vi=0; vi<vertices; ++vi)
{
- VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi];
+ VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[static_cast<unsigned int>(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));
+ boneWeights.push_back(aiVertexWeight(static_cast<unsigned int>(vi), iter->weight));
}
}
return weights;
@@ -319,7 +320,7 @@ uint32_t VertexData::VertexSize(uint16_t source) const
for(const auto &element : vertexElements)
{
if (element.source == source)
- size += element.Size();
+ size += static_cast<uint32_t>(element.Size());
}
return size;
}
@@ -460,7 +461,7 @@ void Mesh::ConvertToAssimpScene(aiScene* dest)
}
// Setup
- dest->mNumMeshes = NumSubMeshes();
+ dest->mNumMeshes = static_cast<unsigned int>(NumSubMeshes());
dest->mMeshes = new aiMesh*[dest->mNumMeshes];
// Create root node
@@ -471,7 +472,7 @@ void Mesh::ConvertToAssimpScene(aiScene* dest)
// Export meshes
for(size_t i=0; i<dest->mNumMeshes; ++i) {
dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
- dest->mRootNode->mMeshes[i] = i;
+ dest->mRootNode->mMeshes[i] = static_cast<unsigned int>(i);
}
// Export skeleton
@@ -481,7 +482,7 @@ void Mesh::ConvertToAssimpScene(aiScene* dest)
if (!skeleton->bones.empty())
{
BoneList rootBones = skeleton->RootBones();
- dest->mRootNode->mNumChildren = rootBones.size();
+ dest->mRootNode->mNumChildren = static_cast<unsigned int>(rootBones.size());
dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
for(size_t i=0, len=rootBones.size(); i<len; ++i)
@@ -493,7 +494,7 @@ void Mesh::ConvertToAssimpScene(aiScene* dest)
// Animations
if (!skeleton->animations.empty())
{
- dest->mNumAnimations = skeleton->animations.size();
+ dest->mNumAnimations = static_cast<unsigned int>(skeleton->animations.size());
dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
@@ -572,7 +573,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
// Assimp required unique vertices, we need to convert from Ogres shared indexing.
size_t uniqueVertexCount = dest->mNumFaces * 3;
- dest->mNumVertices = uniqueVertexCount;
+ dest->mNumVertices = static_cast<unsigned int>(uniqueVertexCount);
dest->mVertices = new aiVector3D[dest->mNumVertices];
// Source streams
@@ -604,7 +605,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
{
if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3)
{
- dest->mNumUVComponents[0] = uv1Element->ComponentCount();
+ dest->mNumUVComponents[0] = static_cast<unsigned int>(uv1Element->ComponentCount());
dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices];
}
else
@@ -617,7 +618,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
{
if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3)
{
- dest->mNumUVComponents[1] = uv2Element->ComponentCount();
+ dest->mNumUVComponents[1] = static_cast<unsigned int>(uv2Element->ComponentCount());
dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices];
}
else
@@ -665,11 +666,11 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
const size_t newIndex = pos + v;
// Write face index
- face.mIndices[v] = newIndex;
+ face.mIndices[v] = static_cast<unsigned int>(newIndex);
// Ogres vertex index to ref into the source buffers.
const size_t ogreVertexIndex = ogreFace.mIndices[v];
- src->AddVertexMapping(ogreVertexIndex, newIndex);
+ src->AddVertexMapping(static_cast<uint32_t>(ogreVertexIndex), static_cast<uint32_t>(newIndex));
// Position
positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET);
@@ -704,7 +705,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
- dest->mNumBones = referencedBones.size();
+ dest->mNumBones = static_cast<unsigned int>(referencedBones.size());
dest->mBones = new aiBone*[dest->mNumBones];
size_t assimpBoneIndex = 0;
@@ -758,7 +759,7 @@ SubMeshXml *MeshXml::GetSubMesh(uint16_t index) const
void MeshXml::ConvertToAssimpScene(aiScene* dest)
{
// Setup
- dest->mNumMeshes = NumSubMeshes();
+ dest->mNumMeshes = static_cast<unsigned int>(NumSubMeshes());
dest->mMeshes = new aiMesh*[dest->mNumMeshes];
// Create root node
@@ -770,7 +771,7 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
for(size_t i=0; i<dest->mNumMeshes; ++i)
{
dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
- dest->mRootNode->mMeshes[i] = i;
+ dest->mRootNode->mMeshes[i] = static_cast<unsigned int>(i);
}
// Export skeleton
@@ -780,7 +781,7 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
if (!skeleton->bones.empty())
{
BoneList rootBones = skeleton->RootBones();
- dest->mRootNode->mNumChildren = rootBones.size();
+ dest->mRootNode->mNumChildren = static_cast<unsigned int>(rootBones.size());
dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
for(size_t i=0, len=rootBones.size(); i<len; ++i)
@@ -792,7 +793,7 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
// Animations
if (!skeleton->animations.empty())
{
- dest->mNumAnimations = skeleton->animations.size();
+ dest->mNumAnimations = static_cast<unsigned int>(skeleton->animations.size());
dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
@@ -840,7 +841,7 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
// Assimp required unique vertices, we need to convert from Ogres shared indexing.
size_t uniqueVertexCount = dest->mNumFaces * 3;
- dest->mNumVertices = uniqueVertexCount;
+ dest->mNumVertices = static_cast<unsigned int>(uniqueVertexCount);
dest->mVertices = new aiVector3D[dest->mNumVertices];
VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
@@ -875,11 +876,11 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
const size_t newIndex = pos + v;
// Write face index
- face.mIndices[v] = newIndex;
+ face.mIndices[v] = static_cast<unsigned int>(newIndex);
// Ogres vertex index to ref into the source buffers.
const size_t ogreVertexIndex = ogreFace.mIndices[v];
- src->AddVertexMapping(ogreVertexIndex, newIndex);
+ src->AddVertexMapping(static_cast<uint32_t>(ogreVertexIndex), static_cast<uint32_t>(newIndex));
// Position
dest->mVertices[newIndex] = src->positions[ogreVertexIndex];
@@ -904,7 +905,7 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
- dest->mNumBones = referencedBones.size();
+ dest->mNumBones = static_cast<unsigned int>(referencedBones.size());
dest->mBones = new aiBone*[dest->mNumBones];
size_t assimpBoneIndex = 0;
@@ -958,7 +959,7 @@ aiAnimation *Animation::ConvertToAssimpAnimation()
// Tracks
if (!tracks.empty())
{
- anim->mNumChannels = tracks.size();
+ anim->mNumChannels = static_cast<unsigned int>(tracks.size());
anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
for(size_t i=0, len=tracks.size(); i<len; ++i)
@@ -1099,7 +1100,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
// Children
if (!children.empty())
{
- node->mNumChildren = children.size();
+ node->mNumChildren = static_cast<unsigned int>(children.size());
node->mChildren = new aiNode*[node->mNumChildren];
for(size_t i=0, len=children.size(); i<len; ++i)
@@ -1122,7 +1123,7 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVer
if (!boneWeights.empty())
{
- bone->mNumWeights = boneWeights.size();
+ bone->mNumWeights = static_cast<unsigned int>(boneWeights.size());
bone->mWeights = new aiVertexWeight[boneWeights.size()];
memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
}
@@ -1158,9 +1159,9 @@ aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleto
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->mNumPositionKeys = static_cast<unsigned int>(numKeyframes);
+ nodeAnim->mNumRotationKeys = static_cast<unsigned int>(numKeyframes);
+ nodeAnim->mNumScalingKeys = static_cast<unsigned int>(numKeyframes);
for(size_t kfi=0; kfi<numKeyframes; ++kfi)
{
diff --git a/src/3rdparty/assimp/code/OgreStructs.h b/src/3rdparty/assimp/code/OgreStructs.h
index c4e86a805..04383bc4e 100644
--- a/src/3rdparty/assimp/code/OgreStructs.h
+++ b/src/3rdparty/assimp/code/OgreStructs.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OgreXmlSerializer.cpp b/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
index 494d8e00c..b5d20cdf6 100644
--- a/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
+++ b/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -623,7 +624,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
SkipCurrentNode();
}
- submesh->index = mesh->subMeshes.size();
+ submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
mesh->subMeshes.push_back(submesh);
}
@@ -654,7 +655,7 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
}
/** Normalize bone weights.
- Some exporters wont care if the sum of all bone weights
+ Some exporters won't 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)
diff --git a/src/3rdparty/assimp/code/OgreXmlSerializer.h b/src/3rdparty/assimp/code/OgreXmlSerializer.h
index 47b4cafc0..01b9a7b23 100644
--- a/src/3rdparty/assimp/code/OgreXmlSerializer.h
+++ b/src/3rdparty/assimp/code/OgreXmlSerializer.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OpenGEXExporter.cpp b/src/3rdparty/assimp/code/OpenGEXExporter.cpp
index 77a60fdfb..0f2b1c35b 100644
--- a/src/3rdparty/assimp/code/OpenGEXExporter.cpp
+++ b/src/3rdparty/assimp/code/OpenGEXExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -50,6 +51,10 @@ OpenGEXExporter::OpenGEXExporter() {
OpenGEXExporter::~OpenGEXExporter() {
}
+bool OpenGEXExporter::exportScene( const char * /*filename*/, const aiScene* /*pScene*/ ) {
+ return true;
+}
+
#endif // ASSIMP_BUILD_NO_OPENGEX_EXPORTER
} // Namespace OpenGEX
diff --git a/src/3rdparty/assimp/code/OpenGEXExporter.h b/src/3rdparty/assimp/code/OpenGEXExporter.h
index f9757f41c..9df9d853e 100644
--- a/src/3rdparty/assimp/code/OpenGEXExporter.h
+++ b/src/3rdparty/assimp/code/OpenGEXExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OpenGEXImporter.cpp b/src/3rdparty/assimp/code/OpenGEXImporter.cpp
index f3a886a96..025356c1d 100644
--- a/src/3rdparty/assimp/code/OpenGEXImporter.cpp
+++ b/src/3rdparty/assimp/code/OpenGEXImporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -40,7 +41,7 @@ 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/DefaultIOSystem.h>
#include <assimp/DefaultLogger.hpp>
#include "MakeVerboseFormat.h"
#include "StringComparison.h"
@@ -48,11 +49,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <openddlparser/OpenDDLParser.h>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
+#include <assimp/importerdesc.h>
#include <vector>
-static const std::string OpenGexExt = "ogex";
-
static const aiImporterDesc desc = {
"Open Game Engine Exchange",
"",
@@ -63,7 +63,7 @@ static const aiImporterDesc desc = {
0,
0,
0,
- OpenGexExt.c_str()
+ "ogex"
};
namespace Grammar {
@@ -124,7 +124,7 @@ namespace Grammar {
MaterialToken,
ColorToken,
ParamToken,
- TextureToken,
+ TextureToken,
AttenToken
};
@@ -196,7 +196,6 @@ namespace Grammar {
return NoneType;
}
-
} // Namespace Grammar
namespace Assimp {
@@ -223,19 +222,21 @@ static void propId2StdString( Property *prop, std::string &name, std::string &ke
OpenGEXImporter::VertexContainer::VertexContainer()
: m_numVerts( 0 )
, m_vertices( nullptr )
+, m_numColors( 0 )
+, m_colors( nullptr )
, m_numNormals( 0 )
, m_normals( nullptr )
, m_numUVComps()
-, m_textureCoords()
- {
+, m_textureCoords() {
// empty
}
//------------------------------------------------------------------------------------------------
OpenGEXImporter::VertexContainer::~VertexContainer() {
delete[] m_vertices;
+ delete[] m_colors;
delete[] m_normals;
-
+
for(auto &texcoords : m_textureCoords) {
delete [] texcoords;
}
@@ -260,6 +261,7 @@ OpenGEXImporter::OpenGEXImporter()
, m_nodeChildMap()
, m_meshCache()
, m_mesh2refMap()
+, m_material2refMap()
, m_ctx( nullptr )
, m_metrics()
, m_currentNode( nullptr )
@@ -279,14 +281,14 @@ OpenGEXImporter::OpenGEXImporter()
//------------------------------------------------------------------------------------------------
OpenGEXImporter::~OpenGEXImporter() {
- m_ctx = NULL;
+ m_ctx = nullptr;
}
//------------------------------------------------------------------------------------------------
bool OpenGEXImporter::CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const {
bool canRead( false );
if( !checkSig ) {
- canRead = SimpleExtensionCheck( file, OpenGexExt.c_str() );
+ canRead = SimpleExtensionCheck( file, "ogex" );
} else {
static const char *token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
canRead = BaseImporter::SearchFileHeaderForToken( pIOHandler, file, token, 4 );
@@ -305,6 +307,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce
std::vector<char> buffer;
TextFileToBuffer( file, buffer );
+ pIOHandler->Close( file );
OpenDDLParser myParser;
myParser.setBuffer( &buffer[ 0 ], buffer.size() );
@@ -319,6 +322,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce
copyMeshes( pScene );
copyCameras( pScene );
copyLights( pScene );
+ copyMaterials( pScene );
resolveReferences();
createNodeTree( pScene );
}
@@ -411,7 +415,7 @@ void OpenGEXImporter::handleNodes( DDLNode *node, aiScene *pScene ) {
case Grammar::ColorToken:
handleColorNode( *it, pScene );
break;
-
+
case Grammar::ParamToken:
handleParamNode( *it, pScene );
break;
@@ -427,7 +431,7 @@ void OpenGEXImporter::handleNodes( DDLNode *node, aiScene *pScene ) {
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == node || nullptr == m_ctx ) {
return;
}
@@ -463,32 +467,35 @@ void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) {
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) {
- if( NULL == m_currentNode ) {
+void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene * /*pScene*/ ) {
+ if( nullptr == m_currentNode ) {
throw DeadlyImportError( "No current node for name." );
return;
}
Value *val( node->getValue() );
- if( NULL != val ) {
+ if( nullptr != 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
+ 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 ) {
-
+ aiString aiName;
+ aiName.Set( name );
+ m_currentMaterial->AddProperty( &aiName, AI_MATKEY_NAME );
+ m_material2refMap[ name ] = m_materialCache.size() - 1;
}
}
}
//------------------------------------------------------------------------------------------------
static void getRefNames( DDLNode *node, std::vector<std::string> &names ) {
- ai_assert( NULL != node );
+ ai_assert( nullptr != node );
Reference *ref = node->getReferences();
if( nullptr != ref ) {
@@ -505,7 +512,7 @@ static void getRefNames( DDLNode *node, std::vector<std::string> &names ) {
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == m_currentNode ) {
throw DeadlyImportError( "No parent node for name." );
return;
@@ -513,19 +520,23 @@ void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) {
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->mNumMeshes = static_cast<unsigned int>(objRefNames.size());
m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ];
if ( !objRefNames.empty() ) {
- m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) );
+ m_unresolvedRefStack.push_back( std::unique_ptr<RefInfo>( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) ) );
}
+ } else if ( m_tokenType == Grammar::LightNodeToken ) {
+ // TODO!
+ } else if ( m_tokenType == Grammar::CameraNodeToken ) {
+ // TODO!
}
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == m_currentNode ) {
throw DeadlyImportError( "No parent node for name." );
return;
@@ -534,7 +545,7 @@ void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene
std::vector<std::string> matRefNames;
getRefNames( node, matRefNames );
if( !matRefNames.empty() ) {
- m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) );
+ m_unresolvedRefStack.push_back( std::unique_ptr<RefInfo>( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) ) );
}
}
@@ -594,12 +605,19 @@ void OpenGEXImporter::handleGeometryObject( DDLNode *node, aiScene *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 ) {
+ aiLight *light( new aiLight );
+ m_lightCache.push_back( light );
+ std::string objName = node->getName();
+ if ( !objName.empty() ) {
+ light->mName.Set( objName );
+ }
+ m_currentLight = light;
Property *prop( node->findPropertyByName( "type" ) );
if ( nullptr != prop ) {
@@ -634,6 +652,8 @@ static void setMatrix( aiNode *node, DataArrayList *transformData ) {
i++;
}
+ ai_assert(i == 16);
+
node->mTransformation.a1 = m[ 0 ];
node->mTransformation.a2 = m[ 4 ];
node->mTransformation.a3 = m[ 8 ];
@@ -656,7 +676,7 @@ static void setMatrix( aiNode *node, DataArrayList *transformData ) {
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == m_currentNode ) {
throw DeadlyImportError( "No parent node for name." );
return;
@@ -710,6 +730,7 @@ void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene
enum MeshAttribute {
None,
Position,
+ Color,
Normal,
TexCoord
};
@@ -718,8 +739,10 @@ enum MeshAttribute {
static MeshAttribute getAttributeByName( const char *attribName ) {
ai_assert( nullptr != attribName );
- if( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) {
+ if ( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) {
return Position;
+ } else if ( 0 == strncmp( "color", attribName, strlen( "color" ) ) ) {
+ return Color;
} else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) {
return Normal;
} else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) {
@@ -748,6 +771,21 @@ static void fillVector3( aiVector3D *vec3, Value *vals ) {
}
//------------------------------------------------------------------------------------------------
+static void fillColor4( aiColor4D *col4, Value *vals ) {
+ ai_assert( nullptr != col4 );
+ ai_assert( nullptr != vals );
+
+ Value *next( vals );
+ col4->r = next->getFloat();
+ next = next->m_next;
+ col4->g = next->getFloat();
+ next = next->m_next;
+ col4->b = next->getFloat();
+ next = next->m_next;
+ col4->a = next->getFloat();
+}
+
+//------------------------------------------------------------------------------------------------
static size_t countDataArrayListItems( DataArrayList *vaList ) {
size_t numItems( 0 );
if( nullptr == vaList ) {
@@ -775,7 +813,15 @@ static void copyVectorArray( size_t numItems, DataArrayList *vaList, aiVector3D
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+static void copyColor4DArray( size_t numItems, DataArrayList *vaList, aiColor4D *colArray ) {
+ for ( size_t i = 0; i < numItems; i++ ) {
+ Value *next( vaList->m_dataList );
+ fillColor4( &colArray[ i ], next );
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == node ) {
throw DeadlyImportError( "No parent node for name." );
return;
@@ -801,6 +847,10 @@ void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene
m_currentVertices.m_numVerts = numItems;
m_currentVertices.m_vertices = new aiVector3D[ numItems ];
copyVectorArray( numItems, vaList, m_currentVertices.m_vertices );
+ } else if ( Color == attribType ) {
+ m_currentVertices.m_numColors = numItems;
+ m_currentVertices.m_colors = new aiColor4D[ numItems ];
+ copyColor4DArray( numItems, vaList, m_currentVertices.m_colors );
} else if( Normal == attribType ) {
m_currentVertices.m_numNormals = numItems;
m_currentVertices.m_normals = new aiVector3D[ numItems ];
@@ -814,7 +864,7 @@ void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == node ) {
throw DeadlyImportError( "No parent node for name." );
return;
@@ -831,10 +881,15 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *
}
const size_t numItems( countDataArrayListItems( vaList ) );
- m_currentMesh->mNumFaces = numItems;
+ m_currentMesh->mNumFaces = static_cast<unsigned int>(numItems);
m_currentMesh->mFaces = new aiFace[ numItems ];
- m_currentMesh->mNumVertices = numItems * 3;
+ m_currentMesh->mNumVertices = static_cast<unsigned int>(numItems * 3);
m_currentMesh->mVertices = new aiVector3D[ m_currentMesh->mNumVertices ];
+ bool hasColors( false );
+ if ( m_currentVertices.m_numColors > 0 ) {
+ m_currentMesh->mColors[0] = new aiColor4D[ m_currentVertices.m_numColors ];
+ hasColors = true;
+ }
bool hasNormalCoords( false );
if ( m_currentVertices.m_numNormals > 0 ) {
m_currentMesh->mNormals = new aiVector3D[ m_currentMesh->mNumVertices ];
@@ -858,6 +913,10 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *
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 ( hasColors ) {
+ aiColor4D &col = m_currentVertices.m_colors[ idx ];
+ m_currentMesh->mColors[ 0 ][ index ] = col;
+ }
if ( hasNormalCoords ) {
aiVector3D &normal = ( m_currentVertices.m_normals[ idx ] );
m_currentMesh->mNormals[ index ].Set( normal.x, normal.y, normal.z );
@@ -876,7 +935,7 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *
}
//------------------------------------------------------------------------------------------------
-static void getColorRGB( aiColor3D *pColor, DataArrayList *colList ) {
+static void getColorRGB3( aiColor3D *pColor, DataArrayList *colList ) {
if( nullptr == pColor || nullptr == colList ) {
return;
}
@@ -891,6 +950,23 @@ static void getColorRGB( aiColor3D *pColor, DataArrayList *colList ) {
}
//------------------------------------------------------------------------------------------------
+static void getColorRGB4( aiColor4D *pColor, DataArrayList *colList ) {
+ if ( nullptr == pColor || nullptr == colList ) {
+ return;
+ }
+
+ ai_assert( 4 == 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();
+ val = val->getNext();
+ pColor->a = val->getFloat();
+}
+
+//------------------------------------------------------------------------------------------------
enum ColorType {
NoneColor = 0,
DiffuseColor,
@@ -927,7 +1003,7 @@ void OpenGEXImporter::handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pS
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == node ) {
return;
}
@@ -940,7 +1016,17 @@ void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScen
return;
}
aiColor3D col;
- getColorRGB( &col, colList );
+ if ( 3 == colList->m_numItems ) {
+ aiColor3D col3;
+ getColorRGB3( &col3, colList );
+ col = col3;
+ } else {
+ aiColor4D col4;
+ getColorRGB4( &col4, colList );
+ col.r = col4.r;
+ col.g = col4.g;
+ col.b = col4.b;
+ }
const ColorType colType( getColorType( prop->m_key ) );
if( DiffuseColor == colType ) {
m_currentMaterial->AddProperty( &col, 1, AI_MATKEY_COLOR_DIFFUSE );
@@ -956,7 +1042,7 @@ void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScen
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if( nullptr == node ) {
return;
}
@@ -972,7 +1058,6 @@ void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pSc
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 ) {
@@ -991,7 +1076,7 @@ void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pSc
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if ( nullptr == node ) {
return;
}
@@ -1020,7 +1105,7 @@ void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene *pScen
}
//------------------------------------------------------------------------------------------------
-void OpenGEXImporter::handleAttenNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+void OpenGEXImporter::handleAttenNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {
if ( nullptr == node ) {
return;
}
@@ -1045,7 +1130,7 @@ void OpenGEXImporter::copyMeshes( aiScene *pScene ) {
return;
}
- pScene->mNumMeshes = m_meshCache.size();
+ pScene->mNumMeshes = static_cast<unsigned int>(m_meshCache.size());
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
std::copy( m_meshCache.begin(), m_meshCache.end(), pScene->mMeshes );
}
@@ -1058,7 +1143,7 @@ void OpenGEXImporter::copyCameras( aiScene *pScene ) {
return;
}
- pScene->mNumCameras = m_cameraCache.size();
+ pScene->mNumCameras = static_cast<unsigned int>(m_cameraCache.size());
pScene->mCameras = new aiCamera*[ pScene->mNumCameras ];
std::copy( m_cameraCache.begin(), m_cameraCache.end(), pScene->mCameras );
}
@@ -1071,33 +1156,61 @@ void OpenGEXImporter::copyLights( aiScene *pScene ) {
return;
}
- pScene->mNumLights = m_lightCache.size();
+ pScene->mNumLights = static_cast<unsigned int>(m_lightCache.size());
pScene->mLights = new aiLight*[ pScene->mNumLights ];
std::copy( m_lightCache.begin(), m_lightCache.end(), pScene->mLights );
}
//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::copyMaterials( aiScene *pScene ) {
+ ai_assert( nullptr != pScene );
+
+ if ( m_materialCache.empty() ) {
+ return;
+ }
+
+ pScene->mNumMaterials = static_cast<unsigned int>(m_materialCache.size());
+ pScene->mMaterials = new aiMaterial*[ pScene->mNumMaterials ];
+ std::copy( m_materialCache.begin(), m_materialCache.end(), pScene->mMaterials );
+}
+
+//------------------------------------------------------------------------------------------------
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 ) {
+ RefInfo *currentRefInfo( nullptr );
+ for( auto it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) {
+ currentRefInfo = it->get();
+ if( nullptr != currentRefInfo ) {
aiNode *node( currentRefInfo->m_node );
if( RefInfo::MeshRef == currentRefInfo->m_type ) {
- for( size_t i = 0; i < currentRefInfo->m_Names.size(); i++ ) {
+ 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 ];
+ unsigned int meshIdx = static_cast<unsigned int>(m_mesh2refMap[ name ]);
node->mMeshes[ i ] = meshIdx;
}
}
} else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
- // ToDo!
+ for ( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
+ const std::string name( currentRefInfo->m_Names[ i ] );
+ ReferenceMap::const_iterator it( m_material2refMap.find( name ) );
+ if ( m_material2refMap.end() != it ) {
+ if ( nullptr != m_currentMesh ) {
+ unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] );
+ if ( m_currentMesh->mMaterialIndex != 0 ) {
+ DefaultLogger::get()->warn( "Override of material reference in current mesh by material reference." );
+ }
+ m_currentMesh->mMaterialIndex = matIdx;
+ } else {
+ DefaultLogger::get()->warn( "Cannot resolve material reference, because no current mesh is there." );
+
+ }
+ }
+ }
} else {
throw DeadlyImportError( "Unknown reference info to resolve." );
}
@@ -1115,7 +1228,7 @@ void OpenGEXImporter::createNodeTree( aiScene *pScene ) {
return;
}
- pScene->mRootNode->mNumChildren = m_root->m_children.size();
+ pScene->mRootNode->mNumChildren = static_cast<unsigned int>(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 );
}
@@ -1124,10 +1237,10 @@ void OpenGEXImporter::createNodeTree( aiScene *pScene ) {
void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
ai_assert( nullptr != pScene );
- if ( NULL == node ) {
+ if ( nullptr == node ) {
return;
}
-
+
ChildInfo *info( nullptr );
if( m_nodeStack.empty() ) {
node->mParent = pScene->mRootNode;
@@ -1135,9 +1248,9 @@ void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
if( m_nodeChildMap.end() == it ) {
info = new ChildInfo;
m_root = info;
- m_nodeChildMap[ node->mParent ] = info;
+ m_nodeChildMap[ node->mParent ] = std::unique_ptr<ChildInfo>(info);
} else {
- info = it->second;
+ info = it->second.get();
}
info->m_children.push_back( node );
} else {
@@ -1147,9 +1260,9 @@ void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) );
if( m_nodeChildMap.end() == it ) {
info = new ChildInfo;
- m_nodeChildMap[ node->mParent ] = info;
+ m_nodeChildMap[ node->mParent ] = std::unique_ptr<ChildInfo>(info);
} else {
- info = it->second;
+ info = it->second.get();
}
info->m_children.push_back( node );
}
diff --git a/src/3rdparty/assimp/code/OpenGEXImporter.h b/src/3rdparty/assimp/code/OpenGEXImporter.h
index d655fb60b..c0cde579c 100644
--- a/src/3rdparty/assimp/code/OpenGEXImporter.h
+++ b/src/3rdparty/assimp/code/OpenGEXImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <list>
+#include <map>
+#include <memory>
namespace ODDLParser {
class DDLNode;
@@ -130,7 +133,7 @@ protected:
void copyMeshes( aiScene *pScene );
void copyCameras( aiScene *pScene );
void copyLights( aiScene *pScene );
-
+ void copyMaterials( aiScene *pScene );
void resolveReferences();
void pushNode( aiNode *node, aiScene *pScene );
aiNode *popNode();
@@ -142,6 +145,8 @@ private:
struct VertexContainer {
size_t m_numVerts;
aiVector3D *m_vertices;
+ size_t m_numColors;
+ aiColor4D *m_colors;
size_t m_numNormals;
aiVector3D *m_normals;
size_t m_numUVComps[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
@@ -150,9 +155,8 @@ private:
VertexContainer();
~VertexContainer();
- private:
- VertexContainer( const VertexContainer & );
- VertexContainer &operator = ( const VertexContainer & );
+ VertexContainer( const VertexContainer & ) = delete;
+ VertexContainer &operator = ( const VertexContainer & ) = delete;
};
struct RefInfo {
@@ -168,9 +172,8 @@ private:
RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
~RefInfo();
- private:
- RefInfo( const RefInfo & );
- RefInfo &operator = ( const RefInfo & );
+ RefInfo( const RefInfo & ) = delete;
+ RefInfo &operator = ( const RefInfo & ) = delete;
};
struct ChildInfo {
@@ -178,12 +181,13 @@ private:
std::list<aiNode*> m_children;
};
ChildInfo *m_root;
- typedef std::map<aiNode*, ChildInfo*> NodeChildMap;
+ typedef std::map<aiNode*, std::unique_ptr<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;
+ std::map<std::string, size_t> m_material2refMap;
ODDLParser::Context *m_ctx;
MetricInfo m_metrics[ MetricInfo::Max ];
@@ -198,7 +202,7 @@ private:
std::vector<aiCamera*> m_cameraCache;
std::vector<aiLight*> m_lightCache;
std::vector<aiNode*> m_nodeStack;
- std::vector<RefInfo*> m_unresolvedRefStack;
+ std::vector<std::unique_ptr<RefInfo> > m_unresolvedRefStack;
};
} // Namespace OpenGEX
diff --git a/src/3rdparty/assimp/code/OpenGEXStructs.h b/src/3rdparty/assimp/code/OpenGEXStructs.h
index 837597975..6144a10c5 100644
--- a/src/3rdparty/assimp/code/OpenGEXStructs.h
+++ b/src/3rdparty/assimp/code/OpenGEXStructs.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -113,7 +114,6 @@ struct LightObject {
bool shadowFlag;
};
-
struct CameraObject {
float focalLength;
float nearDepth;
@@ -146,7 +146,6 @@ struct Name {
std::string name;
};
-
struct ObjectRef {
Object *targetStructure;
};
@@ -173,7 +172,6 @@ struct BoneIndex {
unsigned short *arrayStorage;
};
-
struct BoneWeight {
int boneWeightCount;
const float *boneWeightArray;
diff --git a/src/3rdparty/assimp/code/OptimizeGraph.cpp b/src/3rdparty/assimp/code/OptimizeGraph.cpp
index ec37bd447..11a6fcf65 100644
--- a/src/3rdparty/assimp/code/OptimizeGraph.cpp
+++ b/src/3rdparty/assimp/code/OptimizeGraph.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -48,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OptimizeGraph.h"
#include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "Exceptional.h"
#include <stdio.h>
@@ -230,15 +231,17 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list<aiNode*>& no
else nd->mChildren = NULL;
}
- nd->mNumChildren = child_nodes.size();
+ nd->mNumChildren = static_cast<unsigned int>(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;
+ if (nd->mChildren) {
+ 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_out += static_cast<unsigned int>(child_nodes.size());
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/OptimizeGraph.h b/src/3rdparty/assimp/code/OptimizeGraph.h
index 7b3a1d0de..22d53afff 100644
--- a/src/3rdparty/assimp/code/OptimizeGraph.h
+++ b/src/3rdparty/assimp/code/OptimizeGraph.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/OptimizeMeshes.cpp b/src/3rdparty/assimp/code/OptimizeMeshes.cpp
index 8d830bb9b..f8183fc75 100644
--- a/src/3rdparty/assimp/code/OptimizeMeshes.cpp
+++ b/src/3rdparty/assimp/code/OptimizeMeshes.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OptimizeMeshes.h"
#include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "Exceptional.h"
using namespace Assimp;
@@ -145,7 +146,7 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene)
meshes.resize( 0 );
ai_assert(output.size() <= num_old);
- mScene->mNumMeshes = output.size();
+ mScene->mNumMeshes = static_cast<unsigned int>(output.size());
std::copy(output.begin(),output.end(),mScene->mMeshes);
if (output.size() != num_old) {
@@ -180,11 +181,8 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
verts += mScene->mMeshes[am]->mNumVertices;
faces += mScene->mMeshes[am]->mNumFaces;
+ pNode->mMeshes[a] = pNode->mMeshes[pNode->mNumMeshes - 1];
--pNode->mNumMeshes;
- for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) {
- pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ];
- }
-
--a;
}
}
@@ -199,7 +197,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
} else {
output.push_back(mScene->mMeshes[im]);
}
- im = output.size()-1;
+ im = static_cast<unsigned int>(output.size()-1);
}
}
diff --git a/src/3rdparty/assimp/code/OptimizeMeshes.h b/src/3rdparty/assimp/code/OptimizeMeshes.h
index fc8b6a10b..bcefe9247 100644
--- a/src/3rdparty/assimp/code/OptimizeMeshes.h
+++ b/src/3rdparty/assimp/code/OptimizeMeshes.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ParsingUtils.h b/src/3rdparty/assimp/code/ParsingUtils.h
index 2371ee606..7da664374 100644
--- a/src/3rdparty/assimp/code/ParsingUtils.h
+++ b/src/3rdparty/assimp/code/ParsingUtils.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/PlyExporter.cpp b/src/3rdparty/assimp/code/PlyExporter.cpp
index e69c5e386..b20c2b328 100644
--- a/src/3rdparty/assimp/code/PlyExporter.cpp
+++ b/src/3rdparty/assimp/code/PlyExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -56,13 +57,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//using namespace Assimp;
namespace Assimp {
+// make sure type_of returns consistent output across different platforms
+// also consider using: typeid(VAR).name()
+template <typename T> const char* type_of(T&) { return "unknown"; }
+template<> const char* type_of(float&) { return "float"; }
+template<> const char* type_of(double&) { return "double"; }
+
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
-void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
// invoke the exporter
PlyExporter exporter(pFile, pScene);
+ if (exporter.mOutput.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + 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) {
@@ -72,7 +83,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
}
-void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
// invoke the exporter
PlyExporter exporter(pFile, pScene, true);
@@ -136,15 +147,21 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina
<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
<< aiGetVersionRevision() << ")" << endl;
+ // TODO: probably want to check here rather than just assume something
+ // definitely not good to always write float even if we might have double precision
+
+ ai_real tmp = 0.0;
+ const char * typeName = type_of(tmp);
+
mOutput << "element vertex " << vertices << endl;
- mOutput << "property float x" << endl;
- mOutput << "property float y" << endl;
- mOutput << "property float z" << endl;
+ mOutput << "property " << typeName << " x" << endl;
+ mOutput << "property " << typeName << " y" << endl;
+ mOutput << "property " << typeName << " z" << endl;
if(components & PLY_EXPORT_HAS_NORMALS) {
- mOutput << "property float nx" << endl;
- mOutput << "property float ny" << endl;
- mOutput << "property float nz" << endl;
+ mOutput << "property " << typeName << " nx" << endl;
+ mOutput << "property " << typeName << " ny" << endl;
+ mOutput << "property " << typeName << " nz" << endl;
}
// write texcoords first, just in case an importer does not support tangents
@@ -154,37 +171,37 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina
// 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;
+ mOutput << "property " << typeName << " s" << endl;
+ mOutput << "property " << typeName << " t" << endl;
}
else {
- mOutput << "property float s" << c << endl;
- mOutput << "property float t" << c << endl;
+ mOutput << "property " << typeName << " s" << c << endl;
+ mOutput << "property " << typeName << " 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;
+ mOutput << "property " << typeName << " r" << endl;
+ mOutput << "property " << typeName << " g" << endl;
+ mOutput << "property " << typeName << " b" << endl;
+ mOutput << "property " << typeName << " 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;
+ mOutput << "property " << typeName << " r" << c << endl;
+ mOutput << "property " << typeName << " g" << c << endl;
+ mOutput << "property " << typeName << " b" << c << endl;
+ mOutput << "property " << typeName << " 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 << "property " << typeName << " tx" << endl;
+ mOutput << "property " << typeName << " ty" << endl;
+ mOutput << "property " << typeName << " tz" << endl;
+ mOutput << "property " << typeName << " bx" << endl;
+ mOutput << "property " << typeName << " by" << endl;
+ mOutput << "property " << typeName << " bz" << endl;
}
mOutput << "element face " << faces << endl;
@@ -223,7 +240,7 @@ PlyExporter::~PlyExporter() {
// ------------------------------------------------------------------------------------------------
void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components)
{
- static const float inf = std::numeric_limits<float>::infinity();
+ static const ai_real inf = std::numeric_limits<ai_real>::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.
diff --git a/src/3rdparty/assimp/code/PlyExporter.h b/src/3rdparty/assimp/code/PlyExporter.h
index be4fa466f..d1d4eafbb 100644
--- a/src/3rdparty/assimp/code/PlyExporter.h
+++ b/src/3rdparty/assimp/code/PlyExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -50,14 +51,12 @@ struct aiScene;
struct aiNode;
struct aiMesh;
-namespace Assimp
-{
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to a Stanford Ply file. */
// ------------------------------------------------------------------------------------------------
-class PlyExporter
-{
+class PlyExporter {
public:
/// The class constructor for a specific scene to export
PlyExporter(const char* filename, const aiScene* pScene, bool binary = false);
diff --git a/src/3rdparty/assimp/code/PlyLoader.cpp b/src/3rdparty/assimp/code/PlyLoader.cpp
index d4dc2f864..c6e862bf1 100644
--- a/src/3rdparty/assimp/code/PlyLoader.cpp
+++ b/src/3rdparty/assimp/code/PlyLoader.cpp
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
All rights reserved.
@@ -12,18 +12,18 @@ 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.
+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.
+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.
+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
@@ -47,25 +47,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers
#include "PlyLoader.h"
+#include "IOStreamBuffer.h"
#include "Macros.h"
#include <memory>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
-
+#include <assimp/importerdesc.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"
};
@@ -73,1040 +74,941 @@ static const aiImporterDesc desc = {
// 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];
+ // ------------------------------------------------------------------------------------------------
+ // 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()
-{}
+ : mBuffer()
+ , pcDOM()
+ , mGeneratedMesh(NULL){
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-PLYImporter::~PLYImporter()
-{}
+PLYImporter::~PLYImporter() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
-bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+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
+const aiImporterDesc* PLYImporter::GetInfo() const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-static bool isBigEndian( const char* szMe ) {
- ai_assert( NULL != szMe );
+static bool isBigEndian(const char* szMe) {
+ ai_assert(NULL != szMe);
- // binary_little_endian
- // binary_big_endian
- bool isBigEndian( false );
+ // binary_little_endian
+ // binary_big_endian
+ bool isBigEndian(false);
#if (defined AI_BUILD_BIG_ENDIAN)
- if ( 'l' == *szMe || 'L' == *szMe ) {
- isBigEndian = true;
-}
+ if ( 'l' == *szMe || 'L' == *szMe ) {
+ isBigEndian = true;
+ }
#else
- if ( 'b' == *szMe || 'B' == *szMe ) {
- isBigEndian = true;
- }
+ if ('b' == *szMe || 'B' == *szMe) {
+ isBigEndian = true;
+ }
#endif // ! AI_BUILD_BIG_ENDIAN
- return isBigEndian;
+ return isBigEndian;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
-void PLYImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+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 + ".");
+ static const std::string mode = "rb";
+ std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
+ if (!fileStream.get()) {
+ throw DeadlyImportError("Failed to open file " + pFile + ".");
+ }
+
+ // Get the file-size
+ size_t fileSize = fileStream->FileSize();
+ if ( 0 == fileSize ) {
+ throw DeadlyImportError("File " + pFile + " is empty.");
+ }
+
+ IOStreamBuffer<char> streamedBuffer(1024 * 1024);
+ streamedBuffer.open(fileStream.get());
+
+ // the beginning of the file must be PLY - magic, magic
+ std::vector<char> headerCheck;
+ streamedBuffer.getNextLine(headerCheck);
+
+ if ((headerCheck.size() < 3) ||
+ (headerCheck[0] != 'P' && headerCheck[0] != 'p') ||
+ (headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
+ (headerCheck[2] != 'Y' && headerCheck[2] != 'y') )
+ {
+ streamedBuffer.close();
+ throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there");
+ }
+
+ std::vector<char> mBuffer2;
+ streamedBuffer.getNextLine(mBuffer2);
+ mBuffer = (unsigned char*)&mBuffer2[0];
+
+ char* szMe = (char*)&this->mBuffer[0];
+ SkipSpacesAndLineEnd(szMe, (const char**)&szMe);
+
+ // determine the format of the file data and construct the aimesh
+ PLY::DOM sPlyDom;
+ this->pcDOM = &sPlyDom;
+
+ if (TokenMatch(szMe, "format", 6)) {
+ if (TokenMatch(szMe, "ascii", 5)) {
+ SkipLine(szMe, (const char**)&szMe);
+ if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this))
+ {
+ if (mGeneratedMesh != NULL)
+ delete(mGeneratedMesh);
+
+ streamedBuffer.close();
+ 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
+ if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE))
+ {
+ if (mGeneratedMesh != NULL)
+ delete(mGeneratedMesh);
+
+ streamedBuffer.close();
+ throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
+ }
+ }
+ else
+ {
+ if (mGeneratedMesh != NULL)
+ delete(mGeneratedMesh);
- // 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];
+ streamedBuffer.close();
+ throw DeadlyImportError("Invalid .ply file: Unknown file format");
+ }
+ }
+ else
+ {
+ AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+ if (mGeneratedMesh != NULL)
+ delete(mGeneratedMesh);
+
+ streamedBuffer.close();
+ throw DeadlyImportError("Invalid .ply file: Missing format specification");
+ }
+
+ //free the file buffer
+ streamedBuffer.close();
+
+ if (mGeneratedMesh == NULL)
+ {
+ throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data ");
+ }
+
+ // if no face list is existing we assume that the vertex
+ // list is containing a list of points
+ bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false;
+ if (pointsOnly)
+ {
+ if (mGeneratedMesh->mNumVertices < 3)
+ {
+ if (mGeneratedMesh != NULL)
+ delete(mGeneratedMesh);
- // 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");
+ streamedBuffer.close();
+ throw DeadlyImportError("Invalid .ply file: Not enough "
+ "vertices to build a proper face list. ");
}
- 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 ) );
+ const unsigned int iNum = (unsigned int)mGeneratedMesh->mNumVertices / 3;
+ mGeneratedMesh->mNumFaces = iNum;
+ mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
- // 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
+ for (unsigned int i = 0; i < iNum; ++i)
{
- AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
- throw DeadlyImportError( "Invalid .ply file: Missing format specification");
+ mGeneratedMesh->mFaces[i].mNumIndices = 3;
+ mGeneratedMesh->mFaces[i].mIndices = new unsigned int[3];
+ mGeneratedMesh->mFaces[i].mIndices[0] = (i * 3);
+ mGeneratedMesh->mFaces[i].mIndices[1] = (i * 3) + 1;
+ mGeneratedMesh->mFaces[i].mIndices[2] = (i * 3) + 2;
}
- this->pcDOM = &sPlyDom;
+ }
+
+ // now load a list of all materials
+ std::vector<aiMaterial*> avMaterials;
+ std::string defaultTexture;
+ LoadMaterial(&avMaterials, defaultTexture, pointsOnly);
+
+ // 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 = 1;
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ pScene->mMeshes[0] = mGeneratedMesh;
+
+ // 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;
+ }
+}
- // now load a list of vertices. This must be successfully in order to procedure
- std::vector<aiVector3D> avPositions;
- this->LoadVertices(&avPositions,false);
+void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) {
+ ai_assert(NULL != pcElement);
+ ai_assert(NULL != instElement);
- if ( avPositions.empty() ) {
- throw DeadlyImportError( "Invalid .ply file: No vertices found. "
- "Unable to parse the data format of the PLY file." );
- }
+ ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
- // now load a list of normals.
- std::vector<aiVector3D> avNormals;
- LoadVertices(&avNormals,true);
+ ai_uint aiNormal[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
- // load the face list
- std::vector<PLY::Face> avFaces;
- LoadFaces(&avFaces);
+ unsigned int aiColors[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char };
- // 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. ");
+ unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF };
+ PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
+
+ // now check whether which normal components are available
+ unsigned int _a( 0 ), cnt( 0 );
+ for ( std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+ a != pcElement->alProperties.end(); ++a, ++_a) {
+ if ((*a).bIsList) {
+ continue;
}
- 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);
+ // Positions
+ 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;
+ } else if (PLY::EST_XNormal == (*a).Semantic) {
+ // Normals
+ ++cnt;
+ aiNormal[0] = _a;
+ aiNormalTypes[0] = (*a).eType;
+ } else if (PLY::EST_YNormal == (*a).Semantic) {
+ ++cnt;
+ aiNormal[1] = _a;
+ aiNormalTypes[1] = (*a).eType;
+ } else if (PLY::EST_ZNormal == (*a).Semantic) {
+ ++cnt;
+ aiNormal[2] = _a;
+ aiNormalTypes[2] = (*a).eType;
+ } else if (PLY::EST_Red == (*a).Semantic) {
+ // Colors
+ ++cnt;
+ aiColors[0] = _a;
+ aiColorsTypes[0] = (*a).eType;
+ } else if (PLY::EST_Green == (*a).Semantic) {
+ ++cnt;
+ aiColors[1] = _a;
+ aiColorsTypes[1] = (*a).eType;
+ } else if (PLY::EST_Blue == (*a).Semantic) {
+ ++cnt;
+ aiColors[2] = _a;
+ aiColorsTypes[2] = (*a).eType;
+ } else if (PLY::EST_Alpha == (*a).Semantic) {
+ ++cnt;
+ aiColors[3] = _a;
+ aiColorsTypes[3] = (*a).eType;
+ } else if (PLY::EST_UTextureCoord == (*a).Semantic) {
+ // Texture coordinates
+ ++cnt;
+ aiTexcoord[0] = _a;
+ aiTexcoordTypes[0] = (*a).eType;
+ } else if (PLY::EST_VTextureCoord == (*a).Semantic) {
+ ++cnt;
+ aiTexcoord[1] = _a;
+ aiTexcoordTypes[1] = (*a).eType;
}
}
- // now load a list of all materials
- std::vector<aiMaterial*> avMaterials;
- LoadMaterial(&avMaterials);
+ // check whether we have a valid source for the vertex data
+ if (0 != cnt) {
+ // Position
+ aiVector3D vOut;
+ if (0xFFFFFFFF != aiPositions[0]) {
+ vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
+ }
- // now load a list of all vertex color channels
- std::vector<aiColor4D> avColors;
- avColors.reserve(avPositions.size());
- LoadVertexColor(&avColors);
+ if (0xFFFFFFFF != aiPositions[1]) {
+ vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
+ }
- // now try to load texture coordinates
- std::vector<aiVector2D> avTexCoords;
- avTexCoords.reserve(avPositions.size());
- LoadTextureCoordinates(&avTexCoords);
+ if (0xFFFFFFFF != aiPositions[2]) {
+ vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
+ }
- // now replace the default material in all faces and validate all material indices
- ReplaceDefaultMaterial(&avFaces,&avMaterials);
+ // Normals
+ aiVector3D nOut;
+ bool haveNormal = false;
+ if (0xFFFFFFFF != aiNormal[0]) {
+ nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
+ haveNormal = true;
+ }
- // 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 (0xFFFFFFFF != aiNormal[1]) {
+ nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
+ haveNormal = true;
+ }
- if ( avMeshes.empty() ) {
- throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data " );
- }
+ if (0xFFFFFFFF != aiNormal[2]) {
+ nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
+ haveNormal = true;
+ }
- // 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 ];
- }
+ //Colors
+ aiColor4D cOut;
+ bool haveColor = false;
+ if (0xFFFFFFFF != aiColors[0]) {
+ cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
+ aiColors[0]).avList.front(), aiColorsTypes[0]);
+ haveColor = true;
+ }
- // 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 ];
- }
+ if (0xFFFFFFFF != aiColors[1]) {
+ cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
+ aiColors[1]).avList.front(), aiColorsTypes[1]);
+ haveColor = true;
+ }
- // generate a simple node structure
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
- pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+ if (0xFFFFFFFF != aiColors[2]) {
+ cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
+ aiColors[2]).avList.front(), aiColorsTypes[2]);
+ haveColor = true;
+ }
- for ( unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i ) {
- pScene->mRootNode->mMeshes[ i ] = i;
- }
-}
+ // assume 1.0 for the alpha channel ifit is not set
+ if (0xFFFFFFFF == aiColors[3]) {
+ cOut.a = 1.0;
+ } else {
+ cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
+ aiColors[3]).avList.front(), aiColorsTypes[3]);
-// ------------------------------------------------------------------------------------------------
-// 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)
-{
- ai_assert(NULL != avFaces);
- ai_assert(NULL != avPositions);
- ai_assert(NULL != avMaterials);
+ haveColor = true;
+ }
- // split by materials
- std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()];
+ //Texture coordinates
+ aiVector3D tOut;
+ tOut.z = 0;
+ bool haveTextureCoords = false;
+ if (0xFFFFFFFF != aiTexcoord[0]) {
+ tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
+ haveTextureCoords = true;
+ }
- 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);
+ if (0xFFFFFFFF != aiTexcoord[1]) {
+ tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+ GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
+ haveTextureCoords = true;
+ }
- // 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;
+ //create aiMesh if needed
+ if ( nullptr == mGeneratedMesh ) {
+ mGeneratedMesh = new aiMesh();
+ mGeneratedMesh->mMaterialIndex = 0;
+ }
- p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
- p_pcOut->mFaces = new aiFace[aiSplit[p].size()];
+ if (nullptr == mGeneratedMesh->mVertices) {
+ mGeneratedMesh->mNumVertices = pcElement->NumOccur;
+ mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
+ }
- // 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];
+ mGeneratedMesh->mVertices[pos] = vOut;
- 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++;
- }
+ if (haveNormal) {
+ if (nullptr == mGeneratedMesh->mNormals)
+ mGeneratedMesh->mNormals = new aiVector3D[mGeneratedMesh->mNumVertices];
+ mGeneratedMesh->mNormals[pos] = nOut;
+ }
+ if (haveColor) {
+ if (nullptr == mGeneratedMesh->mColors[0])
+ mGeneratedMesh->mColors[0] = new aiColor4D[mGeneratedMesh->mNumVertices];
+ mGeneratedMesh->mColors[0][pos] = cOut;
+ }
+
+ if (haveTextureCoords) {
+ if (nullptr == mGeneratedMesh->mTextureCoords[0]) {
+ mGeneratedMesh->mNumUVComponents[0] = 2;
+ mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
}
- // add the mesh to the output list
- avOut->push_back(p_pcOut);
+ mGeneratedMesh->mTextureCoords[0][pos] = tOut;
}
}
- 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)
+// Convert a color component to [0...1]
+ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val,
+ PLY::EDataType eType)
{
- bool bNeedDefaultMat = false;
+ switch (eType)
+ {
+ case EDT_Float:
+ return val.fFloat;
+ case EDT_Double:
+ return (ai_real)val.fDouble;
+
+ case EDT_UChar:
+ return (ai_real)val.iUInt / (ai_real)0xFF;
+ case EDT_Char:
+ return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
+ case EDT_UShort:
+ return (ai_real)val.iUInt / (ai_real)0xFFFF;
+ case EDT_Short:
+ return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
+ case EDT_UInt:
+ return (ai_real)val.iUInt / (ai_real)0xFFFF;
+ case EDT_Int:
+ return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
+ default:;
+ };
+ return 0.0f;
+}
- 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;
- }
- }
+// ------------------------------------------------------------------------------------------------
+// Try to extract proper faces from the PLY DOM
+void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos)
+{
+ ai_assert(NULL != pcElement);
+ ai_assert(NULL != instElement);
- if (bNeedDefaultMat) {
- // generate a default material
- aiMaterial* pcHelper = new aiMaterial();
+ if (mGeneratedMesh == NULL)
+ throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces");
- // fill in a default material
- int iMode = (int)aiShadingMode_Gouraud;
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+ bool bOne = false;
- 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);
+ // index of the vertex index list
+ unsigned int iProperty = 0xFFFFFFFF;
+ PLY::EDataType eType = EDT_Char;
+ bool bIsTriStrip = false;
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+ // index of the material index property
+ //unsigned int iMaterialIndex = 0xFFFFFFFF;
+ //PLY::EDataType eType2 = EDT_Char;
- // 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);
+ // texture coordinates
+ unsigned int iTextureCoord = 0xFFFFFFFF;
+ PLY::EDataType eType3 = EDT_Char;
- avMaterials->push_back(pcHelper);
+ // face = unique number of vertex indices
+ if (PLY::EEST_Face == pcElement->eSemantic)
+ {
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+ a != pcElement->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;
+ }*/
+ else if (PLY::EST_TextureCoordinates == (*a).Semantic)
+ {
+ // must be a dynamic list!
+ if (!(*a).bIsList)
+ continue;
+ iTextureCoord = _a;
+ bOne = true;
+ eType3 = (*a).eType;
+ }
}
-}
-
-// ------------------------------------------------------------------------------------------------
-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)
+ }
+ // triangle strip
+ // TODO: triangle strip and material index support???
+ else if (PLY::EEST_TriStrip == pcElement->eSemantic)
+ {
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+ a != pcElement->alProperties.end(); ++a, ++_a)
{
- if (PLY::EEST_Vertex == (*i).eSemantic)
- {
- pcList = &this->pcDOM->alElementData[_i];
+ // must be a dynamic list!
+ if (!(*a).bIsList)
+ continue;
+ iProperty = _a;
+ bOne = true;
+ bIsTriStrip = true;
+ eType = (*a).eType;
+ break;
+ }
+ }
- // 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 at least one per-face information set
+ if (bOne)
+ {
+ if (mGeneratedMesh->mFaces == NULL)
+ {
+ mGeneratedMesh->mNumFaces = pcElement->NumOccur;
+ mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
}
- // check whether we have a valid source for the texture coordinates data
- if (NULL != pcList && 0 != cnt)
+
+ if (!bIsTriStrip)
{
- 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;
+ // parse the list of vertex indices
+ if (0xFFFFFFFF != iProperty)
+ {
+ const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
+ mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
+ mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
- if (0xFFFFFFFF != aiPositions[0])
- {
- vOut.x = PLY::PropertyInstance::ConvertTo<float>(
- GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
- }
+ std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+ GetProperty(instElement->alProperties, iProperty).avList.begin();
- 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);
+ for (unsigned int a = 0; a < iNum; ++a, ++p)
+ {
+ mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
}
- }
-}
+ }
-// ------------------------------------------------------------------------------------------------
-// Try to extract vertices from the PLY DOM
-void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
-{
- ai_assert(NULL != pvOut);
+ // parse the material index
+ // cannot be handled without processing the whole file first
+ /*if (0xFFFFFFFF != iMaterialIndex)
+ {
+ mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
+ GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
+ }*/
- 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;
+ if (0xFFFFFFFF != iTextureCoord)
+ {
+ const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
- // 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];
+ //should be 6 coords
+ std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+ GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
- // 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
+ if ((iNum / 3) == 2) // X Y coord
+ {
+ for (unsigned int a = 0; a < iNum; ++a, ++p)
+ {
+ unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
+ if (vindex < mGeneratedMesh->mNumVertices)
{
- // 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;
- }
+ if (mGeneratedMesh->mTextureCoords[0] == NULL)
+ {
+ mGeneratedMesh->mNumUVComponents[0] = 2;
+ mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
+ }
+
+ if (a % 2 == 0)
+ mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
+ else
+ mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
+
+ mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
}
- break;
+ }
}
+ }
}
- // check whether we have a valid source for the vertex data
- if (NULL != pcList && 0 != cnt)
+ else // triangle strips
{
- 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]);
- }
+ // normally we have only one triangle strip instance where
+ // a value of -1 indicates a restart of the strip
+ bool flip = false;
+ const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty(instElement->alProperties, iProperty).avList;
+ //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
+
+ 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;
+ }
- if (0xFFFFFFFF != aiPositions[1])
- {
- vOut.y = PLY::PropertyInstance::ConvertTo<float>(
- GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
- }
+ if (mGeneratedMesh->mFaces == NULL)
+ {
+ mGeneratedMesh->mNumFaces = pcElement->NumOccur;
+ mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
+ }
- if (0xFFFFFFFF != aiPositions[2])
- {
- vOut.z = PLY::PropertyInstance::ConvertTo<float>(
- GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
- }
+ mGeneratedMesh->mFaces[pos].mNumIndices = 3;
+ mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3];
+ mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0];
+ mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
+ mGeneratedMesh->mFaces[pos].mIndices[2] = p;
- // and add them to our nice list
- pvOut->push_back(vOut);
+ if ((flip = !flip)) {
+ std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
}
+
+ aiTable[0] = aiTable[1];
+ aiTable[1] = p;
+ }
}
+ }
}
// ------------------------------------------------------------------------------------------------
-// Convert a color component to [0...1]
-float PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,
- PLY::EDataType eType)
+// 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)
{
- 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;
+ 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]);
+ }
}
// ------------------------------------------------------------------------------------------------
-// Try to extract proper vertex colors from the PLY DOM
-void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
+// Extract a material from the PLY DOM
+void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly)
{
- 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)
+ 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;
+
+ // search 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)
{
- 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;
+
+ // pohng specularity -----------------------------------
+ if (PLY::EST_PhongPower == (*a).Semantic)
{
- 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;
+ iPhong = _a;
+ ePhong = (*a).eType;
}
- }
- // 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);
+ // general opacity -----------------------------------
+ if (PLY::EST_Opacity == (*a).Semantic)
+ {
+ iOpacity = _a;
+ eOpacity = (*a).eType;
}
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-// 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)
+ // diffuse color channels -----------------------------------
+ if (PLY::EST_DiffuseRed == (*a).Semantic)
{
- 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;
+ aaiPositions[0][0] = _a;
+ aaiTypes[0][0] = (*a).eType;
}
- // triangle strip
- // TODO: triangle strip and material index support???
- else if (PLY::EEST_TriStrip == (*i).eSemantic)
+ else if (PLY::EST_DiffuseGreen == (*a).Semantic)
{
- // 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;
+ aaiPositions[0][1] = _a;
+ aaiTypes[0][1] = (*a).eType;
}
- }
- // check whether we have at least one per-face information set
- if (pcList && bOne)
- {
- if (!bIsTristrip)
+ else if (PLY::EST_DiffuseBlue == (*a).Semantic)
{
- 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);
- }
+ aaiPositions[0][2] = _a;
+ aaiTypes[0][2] = (*a).eType;
}
- else // triangle strips
+ else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
{
- // 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;
- }
- }
+ 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;
}
-}
-
-// ------------------------------------------------------------------------------------------------
-// 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)
-{
- ai_assert(NULL != clrOut);
-
- if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
- else
+ else if (PLY::EEST_TextureFile == (*i).eSemantic)
{
- clrOut->r = NormalizeColorValue(GetProperty(avList,
- aiPositions[0]).avList.front(),aiTypes[0]);
+ defaultTexture = (*i).szName;
}
-
- if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
- else
- {
- clrOut->g = NormalizeColorValue(GetProperty(avList,
- aiPositions[1]).avList.front(),aiTypes[1]);
+ }
+ // 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 = (int)aiShadingMode_Gouraud;
+ if (0xFFFFFFFF != iPhong) {
+ ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(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<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
+
+ iMode = (int)aiShadingMode_Phong;
+ }
+ }
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ // handle opacity
+ if (0xFFFFFFFF != iOpacity) {
+ ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity);
+ pcHelper->AddProperty<ai_real>(&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);
+
+ //default texture
+ if (!defaultTexture.empty())
+ {
+ const aiString name(defaultTexture.c_str());
+ pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
+ }
+
+ if (!pointsOnly)
+ {
+ const int two_sided = 1;
+ pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
+ }
+
+ //set to wireframe, so when using this material info we can switch to points rendering
+ if (pointsOnly)
+ {
+ const int wireframe = 1;
+ pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
+ }
+
+ // add the newly created material instance to the list
+ pvOut->push_back(pcHelper);
}
-
- if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
- else
+ }
+ else
+ {
+ // 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);
+
+ //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
+ 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 = 1.0f;
+ 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.
+ if (!pointsOnly)
{
- clrOut->b = NormalizeColorValue(GetProperty(avList,
- aiPositions[2]).avList.front(),aiTypes[2]);
+ const int two_sided = 1;
+ pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
}
- // assume 1.0 for the alpha channel ifit is not set
- if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
- else
+ //default texture
+ if (!defaultTexture.empty())
{
- clrOut->a = NormalizeColorValue(GetProperty(avList,
- aiPositions[3]).avList.front(),aiTypes[3]);
+ const aiString name(defaultTexture.c_str());
+ pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
}
-}
-// ------------------------------------------------------------------------------------------------
-// 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)
+ //set to wireframe, so when using this material info we can switch to points rendering
+ if (pointsOnly)
{
- 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;
- }
+ const int wireframe = 1;
+ pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
- // 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);
- }
- }
+ 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 71b483c57..eb64a9036 100644
--- a/src/3rdparty/assimp/code/PlyLoader.h
+++ b/src/3rdparty/assimp/code/PlyLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,7 +54,7 @@ struct aiNode;
struct aiMaterial;
struct aiMesh;
-namespace Assimp {
+namespace Assimp {
using namespace PLY;
@@ -67,7 +68,6 @@ public:
PLYImporter();
~PLYImporter();
-
public:
// -------------------------------------------------------------------
@@ -77,6 +77,16 @@ public:
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Extract a vertex from the DOM
+ */
+ void LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
+
+ // -------------------------------------------------------------------
+ /** Extract a face from the DOM
+ */
+ void LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
+
protected:
// -------------------------------------------------------------------
@@ -93,53 +103,10 @@ protected:
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);
-
+ void LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly);
// -------------------------------------------------------------------
/** Static helper to parse a color from four single channels in
@@ -150,21 +117,22 @@ protected:
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 (
+ static ai_real 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;
+
+ /** Mesh generated by loader */
+ aiMesh* mGeneratedMesh;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/PlyParser.cpp b/src/3rdparty/assimp/code/PlyParser.cpp
index 06e4038f4..6321821d2 100644
--- a/src/3rdparty/assimp/code/PlyParser.cpp
+++ b/src/3rdparty/assimp/code/PlyParser.cpp
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
All rights reserved.
@@ -12,18 +12,18 @@ 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.
+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.
+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.
+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
@@ -44,885 +44,1078 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
-#include "PlyLoader.h"
#include "fast_atof.h"
#include <assimp/DefaultLogger.hpp>
#include "ByteSwapper.h"
-
+#include "PlyLoader.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;
+PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) {
+ ai_assert(!buffer.empty());
+
+ PLY::EDataType eOut = PLY::EDT_INVALID;
+
+ if (PLY::DOM::TokenMatch(buffer, "char", 4) ||
+ PLY::DOM::TokenMatch(buffer, "int8", 4))
+ {
+ eOut = PLY::EDT_Char;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) ||
+ PLY::DOM::TokenMatch(buffer, "uint8", 5))
+ {
+ eOut = PLY::EDT_UChar;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "short", 5) ||
+ PLY::DOM::TokenMatch(buffer, "int16", 5))
+ {
+ eOut = PLY::EDT_Short;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) ||
+ PLY::DOM::TokenMatch(buffer, "uint16", 6))
+ {
+ eOut = PLY::EDT_UShort;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3))
+ {
+ eOut = PLY::EDT_Int;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4))
+ {
+ eOut = PLY::EDT_UInt;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7))
+ {
+ eOut = PLY::EDT_Float;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) ||
+ PLY::DOM::TokenMatch(buffer, "float64", 7))
+ {
+ eOut = PLY::EDT_Double;
+ }
+ if (PLY::EDT_INVALID == eOut)
+ {
+ DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
+ }
+
+ 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",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;
+PLY::ESemantic PLY::Property::ParseSemantic(std::vector<char> &buffer) {
+ ai_assert(!buffer.empty());
+
+ PLY::ESemantic eOut = PLY::EST_INVALID;
+ if (PLY::DOM::TokenMatch(buffer, "red", 3)) {
+ eOut = PLY::EST_Red;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "green", 5)) {
+ eOut = PLY::EST_Green;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) {
+ eOut = PLY::EST_Blue;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) {
+ eOut = PLY::EST_Alpha;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) {
+ eOut = PLY::EST_VertexIndex;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces
+ {
+ eOut = PLY::EST_TextureCoordinates;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "material_index", 14))
+ {
+ eOut = PLY::EST_MaterialIndex;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11))
+ {
+ eOut = PLY::EST_AmbientRed;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13))
+ {
+ eOut = PLY::EST_AmbientGreen;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12))
+ {
+ eOut = PLY::EST_AmbientBlue;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13))
+ {
+ eOut = PLY::EST_AmbientAlpha;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11))
+ {
+ eOut = PLY::EST_DiffuseRed;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13))
+ {
+ eOut = PLY::EST_DiffuseGreen;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12))
+ {
+ eOut = PLY::EST_DiffuseBlue;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13))
+ {
+ eOut = PLY::EST_DiffuseAlpha;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12))
+ {
+ eOut = PLY::EST_SpecularRed;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14))
+ {
+ eOut = PLY::EST_SpecularGreen;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13))
+ {
+ eOut = PLY::EST_SpecularBlue;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14))
+ {
+ eOut = PLY::EST_SpecularAlpha;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "opacity", 7))
+ {
+ eOut = PLY::EST_Opacity;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14))
+ {
+ eOut = PLY::EST_PhongPower;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "r", 1))
+ {
+ eOut = PLY::EST_Red;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "g", 1))
+ {
+ eOut = PLY::EST_Green;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "b", 1))
+ {
+ eOut = PLY::EST_Blue;
+ }
+
+ // NOTE: Blender3D exports texture coordinates as s,t tuples
+ else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2) || PLY::DOM::TokenMatch(buffer, "texture_u", 9))
+ {
+ eOut = PLY::EST_UTextureCoord;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9))
+ {
+ eOut = PLY::EST_VTextureCoord;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "x", 1))
+ {
+ eOut = PLY::EST_XCoord;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "y", 1)) {
+ eOut = PLY::EST_YCoord;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "z", 1)) {
+ eOut = PLY::EST_ZCoord;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) {
+ eOut = PLY::EST_XNormal;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) {
+ eOut = PLY::EST_YNormal;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) {
+ eOut = PLY::EST_ZNormal;
+ }
+ else {
+ DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
+ PLY::DOM::SkipLine(buffer);
+ }
+ return eOut;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::Property::ParseProperty (const char* pCur,
- const char** pCurOut,
- PLY::Property* pOut)
+bool PLY::Property::ParseProperty(std::vector<char> &buffer, PLY::Property* pOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
+ ai_assert(!buffer.empty());
- // Forms supported:
- // "property float x"
- // "property list uchar int vertex_index"
- *pCurOut = pCur;
+ // Forms supported:
+ // "property float x"
+ // "property list uchar int vertex_index"
- // skip leading spaces
- if (!SkipSpaces(pCur,&pCur))return false;
+ // skip leading spaces
+ if (!PLY::DOM::SkipSpaces(buffer)) {
+ return false;
+ }
- // skip the "property" string at the beginning
- if (!TokenMatch(pCur,"property",8))
+ // skip the "property" string at the beginning
+ if (!PLY::DOM::TokenMatch(buffer, "property", 8))
+ {
+ // seems not to be a valid property entry
+ return false;
+ }
+ // get next word
+ if (!PLY::DOM::SkipSpaces(buffer)) {
+ return false;
+ }
+ if (PLY::DOM::TokenMatch(buffer, "list", 4))
+ {
+ pOut->bIsList = true;
+
+ // seems to be a list.
+ if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer)))
{
- // seems not to be a valid property entry
- return false;
+ // unable to parse list size data type
+ PLY::DOM::SkipLine(buffer);
+ return false;
}
- // get next word
- if (!SkipSpaces(pCur,&pCur))return false;
- if (TokenMatch(pCur,"list",4))
+ if (!PLY::DOM::SkipSpaces(buffer))return false;
+ if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer)))
{
- 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;
- }
+ // unable to parse list data type
+ PLY::DOM::SkipLine(buffer);
+ return false;
}
- else
+ }
+ else
+ {
+ if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer)))
{
- 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;
- }
+ // unable to parse data type. Skip the property
+ PLY::DOM::SkipLine(buffer);
+ return false;
}
+ }
- if (!SkipSpaces(pCur,&pCur))return false;
- const char* szCur = pCur;
- pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur);
+ if (!PLY::DOM::SkipSpaces(buffer))
+ return false;
- if (PLY::EST_INVALID == pOut->Semantic)
- {
- // store the name of the semantic
- uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+ pOut->Semantic = PLY::Property::ParseSemantic(buffer);
- DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
- pOut->szName = std::string(szCur,iDiff);
- }
+ if (PLY::EST_INVALID == pOut->Semantic)
+ {
+ DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
+ std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
+ }
- SkipSpacesAndLineEnd(pCur,&pCur);
- *pCurOut = pCur;
- return true;
+ PLY::DOM::SkipSpacesAndLineEnd(buffer);
+ return true;
}
// ------------------------------------------------------------------------------------------------
-PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur,
- const char** pCurOut)
+PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector<char> &buffer)
{
- 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(!buffer.empty());
+
+ PLY::EElementSemantic eOut = PLY::EEST_INVALID;
+ if (PLY::DOM::TokenMatch(buffer, "vertex", 6))
+ {
+ eOut = PLY::EEST_Vertex;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "face", 4))
+ {
+ eOut = PLY::EEST_Face;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9))
+ {
+ eOut = PLY::EEST_TriStrip;
+ }
#if 0
- // TODO: maybe implement this?
- else if (TokenMatch(pCur,"range_grid",10))
- {
- eOut = PLY::EEST_Face;
- }
+ // TODO: maybe implement this?
+ else if (PLY::DOM::TokenMatch(buffer,"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 (PLY::DOM::TokenMatch(buffer, "edge", 4))
+ {
+ eOut = PLY::EEST_Edge;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "material", 8))
+ {
+ eOut = PLY::EEST_Material;
+ }
+ else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11))
+ {
+ eOut = PLY::EEST_TextureFile;
+ }
+
+ return eOut;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::Element::ParseElement (const char* pCur,
- const char** pCurOut,
- PLY::Element* pOut)
+bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLY::Element* pOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pOut);
-
- // Example format: "element vertex 8"
- *pCurOut = pCur;
+ ai_assert(NULL != pOut);
+ // Example format: "element vertex 8"
- // skip leading spaces
- if (!SkipSpaces(&pCur))return false;
+ // skip leading spaces
+ if (!PLY::DOM::SkipSpaces(buffer))
+ {
+ 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;
+ // skip the "element" string at the beginning
+ if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7))
+ {
+ // seems not to be a valid property entry
+ return false;
+ }
+ // get next word
+ if (!PLY::DOM::SkipSpaces(buffer))
+ 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);
- }
+ // parse the semantic of the element
+ pOut->eSemantic = PLY::Element::ParseSemantic(buffer);
+ if (PLY::EEST_INVALID == pOut->eSemantic)
+ {
+ // if the exact semantic can't be determined, just store
+ // the original string identifier
+ pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
+ }
- if (!SkipSpaces(&pCur))return false;
+ if (!PLY::DOM::SkipSpaces(buffer))
+ return false;
- //parse the number of occurrences of this element
- pOut->NumOccur = strtoul10(pCur,&pCur);
+ if (PLY::EEST_TextureFile == pOut->eSemantic)
+ {
+ char* endPos = &buffer[0] + (strlen(&buffer[0]) - 1);
+ pOut->szName = std::string(&buffer[0], endPos);
// 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::DOM::SkipSpacesAndLineEnd(buffer);
- 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)
-{
- ai_assert(NULL != pCur && NULL != pCurOut);
- *pCurOut = pCur;
+ //parse the number of occurrences of this element
+ const char* pCur = (char*)&buffer[0];
+ pOut->NumOccur = strtoul10(pCur, &pCur);
- // skip spaces
- if (!SkipSpaces(pCur,&pCur))return false;
+ // go to the next line
+ PLY::DOM::SkipSpacesAndLineEnd(buffer);
- if (TokenMatch(pCur,"comment",7))
- {
- if ( !IsLineEnd(pCur[-1]) )
- {
- SkipLine(pCur,&pCur);
- }
- SkipComments(pCur,&pCur);
- *pCurOut = pCur;
- return true;
- }
- *pCurOut = pCur;
- return false;
+ // now parse all properties of the element
+ while (true)
+ {
+ streamBuffer.getNextLine(buffer);
+ pCur = (char*)&buffer[0];
+
+ // skip all comments
+ PLY::DOM::SkipComments(buffer);
+
+ PLY::Property prop;
+ if (!PLY::Property::ParseProperty(buffer, &prop))
+ break;
+
+ pOut->alProperties.push_back(prop);
+ }
+
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut,bool isBinary)
+bool PLY::DOM::SkipSpaces(std::vector<char> &buffer)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
- DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
+ const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+ bool ret = false;
+ if (pCur)
+ {
+ const char* szCur = pCur;
+ ret = Assimp::SkipSpaces(pCur, &pCur);
- // after ply and format line
- *pCurOut = pCur;
+ uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+ buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+ return ret;
+ }
- // parse all elements
- while ((*pCur) != '\0')
- {
- // skip all comments
- PLY::DOM::SkipComments(pCur,&pCur);
+ return ret;
+}
- 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;
+bool PLY::DOM::SkipLine(std::vector<char> &buffer)
+{
+ const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+ bool ret = false;
+ if (pCur)
+ {
+ const char* szCur = pCur;
+ ret = Assimp::SkipLine(pCur, &pCur);
- DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
- return true;
+ uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+ buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+ return ret;
+ }
+
+ return ret;
}
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceLists (
- const char* pCur,
- const char** pCurOut)
+bool PLY::DOM::TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
+ const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+ bool ret = false;
+ if (pCur)
+ {
+ const char* szCur = pCur;
+ ret = Assimp::TokenMatch(pCur, token, len);
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
- *pCurOut = pCur;
+ uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+ buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+ return ret;
+ }
- alElementData.resize(alElements.size());
+ return ret;
+}
- std::vector<PLY::Element>::const_iterator i = alElements.begin();
- std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+bool PLY::DOM::SkipSpacesAndLineEnd(std::vector<char> &buffer)
+{
+ const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+ bool ret = false;
+ if (pCur)
+ {
+ const char* szCur = pCur;
+ ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur);
- // parse all element instances
- for (;i != alElements.end();++i,++a)
- {
- (*a).alInstances.resize((*i).NumOccur);
- PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a));
- }
+ uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+ buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+ return ret;
+ }
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
- *pCurOut = pCur;
- return true;
+ return ret;
}
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceListsBinary (
- const char* pCur,
- const char** pCurOut,
- bool p_bBE)
+bool PLY::DOM::SkipComments(std::vector<char> &buffer)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
-
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
- *pCurOut = pCur;
+ ai_assert(!buffer.empty());
- alElementData.resize(alElements.size());
+ std::vector<char> nbuffer = buffer;
+ // skip spaces
+ if (!SkipSpaces(nbuffer)) {
+ return false;
+ }
- std::vector<PLY::Element>::const_iterator i = alElements.begin();
- std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+ if (TokenMatch(nbuffer, "comment", 7))
+ {
+ if (!SkipSpaces(nbuffer))
+ SkipLine(nbuffer);
- // parse all element instances
- for (;i != alElements.end();++i,++a)
+ if (!TokenMatch(nbuffer, "TextureFile", 11))
{
- (*a).alInstances.resize((*i).NumOccur);
- PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE);
+ SkipLine(nbuffer);
+ buffer = nbuffer;
+ return true;
}
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
- *pCurOut = pCur;
return true;
+ }
+
+ return false;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE)
-{
- ai_assert(NULL != pCur && NULL != p_pcOut);
+bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) {
+ DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
+ // parse all elements
+ while (!buffer.empty())
+ {
+ // skip all comments
+ PLY::DOM::SkipComments(buffer);
- if(!p_pcOut->ParseHeader(pCur,&pCur,true))
+ PLY::Element out;
+ if (PLY::Element::ParseElement(streamBuffer, buffer, &out))
{
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
- return false;
+ // add the element to the list of elements
+ alElements.push_back(out);
}
- if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE))
+ else if (TokenMatch(buffer, "end_header", 10))
{
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
- return false;
+ // we have reached the end of the header
+ break;
}
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
- return true;
+ else
+ {
+ // ignore unknown header elements
+ streamBuffer.getNextLine(buffer);
+ }
+ }
+
+ if (!isBinary) // it would occur an error, if binary data start with values as space or line end.
+ SkipSpacesAndLineEnd(buffer);
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut)
+bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader)
{
- ai_assert(NULL != pCur);
- ai_assert(NULL != p_pcOut);
-
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
+ alElementData.resize(alElements.size());
+ std::vector<PLY::Element>::const_iterator i = alElements.begin();
+ std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
- if(!p_pcOut->ParseHeader(pCur,&pCur,false))
+ // parse all element instances
+ //construct vertices and faces
+ for (; i != alElements.end(); ++i, ++a)
+ {
+ if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip)
{
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
- return false;
+ PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), NULL, loader);
}
- if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur))
+ else
{
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
- return false;
+ (*a).alInstances.resize((*i).NumOccur);
+ PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), NULL);
}
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
- return true;
+ }
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceList (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstanceList* p_pcOut)
+bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const char* &pCur,
+ unsigned int &bufferSize,
+ PLYImporter* loader,
+ bool p_bBE)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
+ alElementData.resize(alElements.size());
- if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
+ 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)
+ {
+ if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip)
{
- // 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);
- }
+ PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), NULL, loader, p_bBE);
}
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]);
- }
+ (*a).alInstances.resize((*i).NumOccur);
+ PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), NULL, p_bBE);
}
- *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 */)
-{
- 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;
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstance (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstance* p_pcOut)
+bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+ ai_assert(NULL != p_pcOut);
+ ai_assert(NULL != loader);
- if (!SkipSpaces(pCur, &pCur))return false;
+ std::vector<char> buffer;
+ streamBuffer.getNextLine(buffer);
- // allocate enough storage
- p_pcOut->alProperties.resize(pcElement->alProperties.size());
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
- 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;
+ if (!p_pcOut->ParseHeader(streamBuffer, buffer, true))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+ return false;
+ }
+
+ streamBuffer.getNextBlock(buffer);
+ unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
+ const char* pCur = (char*)&buffer[0];
+ if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+ return false;
+ }
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstanceBinary (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstance* p_pcOut,
- bool p_bBE /* = false */)
+bool PLY::DOM::ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+ ai_assert(NULL != p_pcOut);
+ ai_assert(NULL != loader);
- // allocate enough storage
- p_pcOut->alProperties.resize(pcElement->alProperties.size());
+ std::vector<char> buffer;
+ streamBuffer.getNextLine(buffer);
- 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");
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
- (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
- }
- }
- *pCurOut = pCur;
- return true;
+ if (!p_pcOut->ParseHeader(streamBuffer, buffer, false))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+ return false;
+ }
+
+ //get next line after header
+ streamBuffer.getNextLine(buffer);
+ if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+ return false;
+ }
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut,
- const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
+bool PLY::ElementInstanceList::ParseInstanceList(
+ IOStreamBuffer<char> &streamBuffer,
+ std::vector<char> &buffer,
+ const PLY::Element* pcElement,
+ PLY::ElementInstanceList* p_pcOut,
+ PLYImporter* loader)
{
- 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)
+ ai_assert(NULL != pcElement);
+
+ // parse all elements
+ 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(buffer);
+ PLY::DOM::SkipLine(buffer);
+ streamBuffer.getNextLine(buffer);
+ }
+ }
+ else
+ {
+ const char* pCur = (const char*)&buffer[0];
+ // be sure to have enough storage
+ for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
+ {
+ if (p_pcOut)
+ PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]);
+ else
+ {
+ ElementInstance elt;
+ PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt);
+
+ // Create vertex or face
+ if (pcElement->eSemantic == EEST_Vertex)
{
- if (!SkipSpaces(pCur, &pCur))return false;
- PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]);
+ //call loader instance from here
+ loader->LoadVertex(pcElement, &elt, i);
}
- }
- else
- {
- // parse the property
- PLY::PropertyInstance::ValueUnion v;
+ else if (pcElement->eSemantic == EEST_Face)
+ {
+ //call loader instance from here
+ loader->LoadFace(pcElement, &elt, i);
+ }
+ else if (pcElement->eSemantic == EEST_TriStrip)
+ {
+ //call loader instance from here
+ loader->LoadFace(pcElement, &elt, i);
+ }
+ }
- PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v);
- p_pcOut->avList.push_back(v);
+ streamBuffer.getNextLine(buffer);
+ pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0];
}
- SkipSpacesAndLineEnd(pCur, &pCur);
- *pCurOut = pCur;
- return true;
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseInstanceBinary (
- const char* pCur,
- const char** pCurOut,
- const PLY::Property* prop,
- PLY::PropertyInstance* p_pcOut,
- bool p_bBE)
+bool PLY::ElementInstanceList::ParseInstanceListBinary(
+ IOStreamBuffer<char> &streamBuffer,
+ std::vector<char> &buffer,
+ const char* &pCur,
+ unsigned int &bufferSize,
+ const PLY::Element* pcElement,
+ PLY::ElementInstanceList* p_pcOut,
+ PLYImporter* loader,
+ bool p_bBE /* = false */)
{
- 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);
- }
- }
+ ai_assert(NULL != pcElement);
+
+ // 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)
+ {
+ if (p_pcOut)
+ PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[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;
+ ElementInstance elt;
+ PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE);
+
+ // Create vertex or face
+ if (pcElement->eSemantic == EEST_Vertex)
+ {
+ //call loader instance from here
+ loader->LoadVertex(pcElement, &elt, i);
+ }
+ else if (pcElement->eSemantic == EEST_Face)
+ {
+ //call loader instance from here
+ loader->LoadFace(pcElement, &elt, i);
+ }
+ else if (pcElement->eSemantic == EEST_TriStrip)
+ {
+ //call loader instance from here
+ loader->LoadFace(pcElement, &elt, i);
+ }
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(
- PLY::EDataType eType)
+bool PLY::ElementInstance::ParseInstance(const char* &pCur,
+ const PLY::Element* pcElement,
+ PLY::ElementInstance* p_pcOut)
{
- PLY::PropertyInstance::ValueUnion out;
+ ai_assert(NULL != pcElement);
+ ai_assert(NULL != p_pcOut);
- switch (eType)
- {
- case EDT_Float:
- out.fFloat = 0.f;
- return out;
+ // allocate enough storage
+ p_pcOut->alProperties.resize(pcElement->alProperties.size());
- case EDT_Double:
- out.fDouble = 0.;
- return out;
+ 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, &(*a), &(*i))))
+ {
+ DefaultLogger::get()->warn("Unable to parse property instance. "
+ "Skipping this element instance");
- default: ;
- };
- out.iUInt = 0;
- return out;
+ PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
+ (*i).avList.push_back(v);
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValue(
- const char* pCur,
- const char** pCurOut,
- PLY::EDataType eType,
- PLY::PropertyInstance::ValueUnion* out)
+bool PLY::ElementInstance::ParseInstanceBinary(
+ IOStreamBuffer<char> &streamBuffer,
+ std::vector<char> &buffer,
+ const char* &pCur,
+ unsigned int &bufferSize,
+ const PLY::Element* pcElement,
+ PLY::ElementInstance* p_pcOut,
+ bool p_bBE /* = false */)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
-
- bool ret = true;
- *pCurOut = pCur;
- switch (eType)
- {
- case EDT_UInt:
- case EDT_UShort:
- case EDT_UChar:
-
- out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
- break;
-
- case EDT_Int:
- case EDT_Short:
- case EDT_Char:
-
- out->iInt = (int32_t)strtol10(pCur, &pCur);
- break;
-
- case EDT_Float:
+ ai_assert(NULL != pcElement);
+ ai_assert(NULL != p_pcOut);
- pCur = fast_atoreal_move<float>(pCur,out->fFloat);
- break;
+ // allocate enough storage
+ p_pcOut->alProperties.resize(pcElement->alProperties.size());
- case EDT_Double:
-
- float f;
- pCur = fast_atoreal_move<float>(pCur,f);
- out->fDouble = (double)f;
- break;
+ 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(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE)))
+ {
+ DefaultLogger::get()->warn("Unable to parse binary property instance. "
+ "Skipping this element instance");
- default:
- ret = false;
+ (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
}
- *pCurOut = pCur;
- return ret;
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValueBinary(
- const char* pCur,
- const char** pCurOut,
- PLY::EDataType eType,
- PLY::PropertyInstance::ValueUnion* out,
- bool p_bBE)
+bool PLY::PropertyInstance::ParseInstance(const char* &pCur,
+ const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
+ ai_assert(NULL != prop);
+ ai_assert(NULL != p_pcOut);
- bool ret = true;
- switch (eType)
- {
- case EDT_UInt:
- out->iUInt = (uint32_t)*((uint32_t*)pCur);
- pCur += 4;
+ // skip spaces at the beginning
+ if (!SkipSpaces(&pCur))
+ {
+ return false;
+ }
- // Swap endianness
- if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
- break;
+ if (prop->bIsList)
+ {
+ // parse the number of elements in the list
+ PLY::PropertyInstance::ValueUnion v;
+ PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v);
- case EDT_UShort:
- {
- uint16_t i = *((uint16_t*)pCur);
+ // convert to unsigned int
+ unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType);
- // Swap endianness
- if (p_bBE)ByteSwap::Swap(&i);
- out->iUInt = (uint32_t)i;
- pCur += 2;
- break;
- }
+ // parse all list elements
+ p_pcOut->avList.resize(iNum);
+ for (unsigned int i = 0; i < iNum; ++i)
+ {
+ if (!SkipSpaces(&pCur))
+ return false;
- case EDT_UChar:
- {
- out->iUInt = (uint32_t)(*((uint8_t*)pCur));
- pCur ++;
- break;
- }
+ PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]);
+ }
+ }
+ else
+ {
+ // parse the property
+ PLY::PropertyInstance::ValueUnion v;
- case EDT_Int:
- out->iInt = *((int32_t*)pCur);
- pCur += 4;
+ PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v);
+ p_pcOut->avList.push_back(v);
+ }
+ SkipSpacesAndLineEnd(&pCur);
+ return true;
+}
- // Swap endianness
- if (p_bBE)ByteSwap::Swap(&out->iInt);
- break;
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const char* &pCur,
+ unsigned int &bufferSize,
+ const PLY::Property* prop,
+ PLY::PropertyInstance* p_pcOut,
+ bool p_bBE)
+{
+ ai_assert(NULL != prop);
+ ai_assert(NULL != p_pcOut);
+
+ // parse all elements
+ if (prop->bIsList)
+ {
+ // parse the number of elements in the list
+ PLY::PropertyInstance::ValueUnion v;
+ PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, 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(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE);
+ }
+ }
+ else
+ {
+ // parse the property
+ PLY::PropertyInstance::ValueUnion v;
+ PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE);
+ p_pcOut->avList.push_back(v);
+ }
+ return true;
+}
- case EDT_Short:
- {
- int16_t i = *((int16_t*)pCur);
+// ------------------------------------------------------------------------------------------------
+PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType)
+{
+ PLY::PropertyInstance::ValueUnion out;
- // Swap endianness
- if (p_bBE)ByteSwap::Swap(&i);
- out->iInt = (int32_t)i;
- pCur += 2;
- break;
- }
+ switch (eType)
+ {
+ case EDT_Float:
+ out.fFloat = 0.f;
+ return out;
- case EDT_Char:
- out->iInt = (int32_t)*((int8_t*)pCur);
- pCur ++;
- break;
+ case EDT_Double:
+ out.fDouble = 0.;
+ return out;
- case EDT_Float:
- {
- out->fFloat = *((float*)pCur);
+ default:;
+ };
+ out.iUInt = 0;
+ return out;
+}
- // Swap endianness
- if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
- pCur += 4;
- break;
- }
- case EDT_Double:
- {
- out->fDouble = *((double*)pCur);
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseValue(const char* &pCur,
+ PLY::EDataType eType,
+ PLY::PropertyInstance::ValueUnion* out)
+{
+ ai_assert(NULL != pCur);
+ ai_assert(NULL != out);
+
+ //calc element size
+ bool ret = true;
+ switch (eType)
+ {
+ case EDT_UInt:
+ case EDT_UShort:
+ case EDT_UChar:
+
+ out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
+ break;
+
+ case EDT_Int:
+ case EDT_Short:
+ case EDT_Char:
+
+ out->iInt = (int32_t)strtol10(pCur, &pCur);
+ break;
+
+ case EDT_Float:
+ // technically this should cast to float, but people tend to use float descriptors for double data
+ // this is the best way to not risk losing precision on import and it doesn't hurt to do this
+ ai_real f;
+ pCur = fast_atoreal_move<ai_real>(pCur, f);
+ out->fFloat = (ai_real)f;
+ break;
+
+ case EDT_Double:
+ double d;
+ pCur = fast_atoreal_move<double>(pCur, d);
+ out->fDouble = (double)d;
+ break;
+
+ case EDT_INVALID:
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
- // Swap endianness
- if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
- pCur += 8;
- break;
- }
- default:
- ret = false;
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
+ std::vector<char> &buffer,
+ const char* &pCur,
+ unsigned int &bufferSize,
+ PLY::EDataType eType,
+ PLY::PropertyInstance::ValueUnion* out,
+ bool p_bBE)
+{
+ ai_assert(NULL != out);
+
+ //calc element size
+ unsigned int lsize = 0;
+ switch (eType)
+ {
+ case EDT_Char:
+ case EDT_UChar:
+ lsize = 1;
+ break;
+
+ case EDT_UShort:
+ case EDT_Short:
+ lsize = 2;
+ break;
+
+ case EDT_UInt:
+ case EDT_Int:
+ case EDT_Float:
+ lsize = 4;
+ break;
+
+ case EDT_Double:
+ lsize = 8;
+ break;
+
+ case EDT_INVALID:
+ default:
+ break;
+ }
+
+ //read the next file block if needed
+ if (bufferSize < lsize)
+ {
+ std::vector<char> nbuffer;
+ if (streamBuffer.getNextBlock(nbuffer))
+ {
+ //concat buffer contents
+ buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end());
+ buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end());
+ nbuffer.clear();
+ bufferSize = static_cast<unsigned int>(buffer.size());
+ pCur = (char*)&buffer[0];
}
- *pCurOut = pCur;
- return ret;
+ else
+ {
+ throw DeadlyImportError("Invalid .ply file: File corrupted");
+ }
+ }
+
+ 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;
+ }
+
+ bufferSize -= lsize;
+
+ 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 2753c1004..b17b07341 100644
--- a/src/3rdparty/assimp/code/PlyParser.h
+++ b/src/3rdparty/assimp/code/PlyParser.h
@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,19 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
+#include "IOStreamBuffer.h"
#include <vector>
-
namespace Assimp
{
+//pre-declaration
+class PLYImporter;
+
// http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
// http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
// http://www.okino.com/conv/exp_ply.htm
namespace PLY
{
-
// ---------------------------------------------------------------------------------
/*
name type number of bytes
@@ -196,6 +198,9 @@ enum EElementSemantic
//! The element is a material description
EEST_Material,
+ //! texture path
+ EEST_TextureFile,
+
//! Marks invalid entries
EEST_INVALID
};
@@ -234,19 +239,18 @@ public:
// -------------------------------------------------------------------
//! Parse a property from a string. The end of the
- //! string is either '\n', '\r' or '\0'. Return valie is false
+ //! string is either '\n', '\r' or '\0'. Return value 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);
+ static bool ParseProperty(std::vector<char> &buffer, Property* pOut);
// -------------------------------------------------------------------
//! Parse a data type from a string
- static EDataType ParseDataType(const char* pCur,const char** pCurOut);
+ static EDataType ParseDataType(std::vector<char> &buffer);
// -------------------------------------------------------------------
//! Parse a semantic from a string
- static ESemantic ParseSemantic(const char* pCur,const char** pCurOut);
+ static ESemantic ParseSemantic(std::vector<char> &buffer);
};
// ---------------------------------------------------------------------------------
@@ -284,13 +288,11 @@ public:
//! 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);
+ static bool ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, Element* pOut);
// -------------------------------------------------------------------
//! Parse a semantic from a string
- static EElementSemantic ParseSemantic(const char* pCur,
- const char** pCurOut);
+ static EElementSemantic ParseSemantic(std::vector<char> &buffer);
};
// ---------------------------------------------------------------------------------
@@ -330,13 +332,13 @@ public:
// -------------------------------------------------------------------
//! Parse a property instance
- static bool ParseInstance (const char* pCur,const char** pCurOut,
+ static bool ParseInstance(const char* &pCur,
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);
+ static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE);
// -------------------------------------------------------------------
//! Get the default value for a given data type
@@ -344,13 +346,12 @@ public:
// -------------------------------------------------------------------
//! Parse a value
- static bool ParseValue(const char* pCur,const char** pCurOut,
- EDataType eType,ValueUnion* out);
+ static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out);
// -------------------------------------------------------------------
//! Parse a binary value
- static bool ParseValueBinary(const char* pCur,const char** pCurOut,
- EDataType eType,ValueUnion* out,bool p_bBE);
+ static bool ParseValueBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE);
// -------------------------------------------------------------------
//! Convert a property value to a given type TYPE
@@ -374,13 +375,13 @@ public:
// -------------------------------------------------------------------
//! Parse an element instance
- static bool ParseInstance (const char* pCur,const char** pCurOut,
+ static bool ParseInstance(const char* &pCur,
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);
+ static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE);
};
// ---------------------------------------------------------------------------------
@@ -399,13 +400,13 @@ public:
// -------------------------------------------------------------------
//! Parse an element instance list
- static bool ParseInstanceList (const char* pCur,const char** pCurOut,
- const Element* pcElement, ElementInstanceList* p_pcOut);
+ static bool ParseInstanceList(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader);
// -------------------------------------------------------------------
//! Parse a binary element instance list
- static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut,
- const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
+ static bool ParseInstanceListBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+ const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE);
};
// ---------------------------------------------------------------------------------
/** \brief Class to represent the document object model of an ASCII or binary
@@ -427,50 +428,33 @@ public:
//! 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);
+ static bool ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader);
+ static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE);
//! Skip all comment lines after this
- static bool SkipComments (const char* pCur,const char** pCurOut);
+ static bool SkipComments(std::vector<char> &buffer);
+
+ static bool SkipSpaces(std::vector<char> &buffer);
+
+ static bool SkipLine(std::vector<char> &buffer);
+
+ static bool TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len);
+
+ static bool SkipSpacesAndLineEnd(std::vector<char> &buffer);
private:
// -------------------------------------------------------------------
//! Handle the file header and read all element descriptions
- bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE);
+ bool ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool p_bBE);
// -------------------------------------------------------------------
//! Read in all element instance lists
- bool ParseElementInstanceLists (const char* pCur,const char** pCurOut);
+ bool ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader);
// -------------------------------------------------------------------
//! Read in all element instance lists for a binary file format
- bool ParseElementInstanceListsBinary (const char* pCur,
- const char** pCurOut,bool p_bBE);
-};
-
-// ---------------------------------------------------------------------------------
-/** \brief Helper class to represent a loaded PLY face
- */
-class Face
-{
-public:
-
- Face()
- : iMaterialIndex(0xFFFFFFFF)
- {
- // set all indices to zero by default
- mIndices.resize(3,0);
- }
-
-public:
-
- //! List of vertex indices
- std::vector<unsigned int> mIndices;
-
- //! Material index
- unsigned int iMaterialIndex;
+ bool ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE);
};
// ---------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/PolyTools.h b/src/3rdparty/assimp/code/PolyTools.h
index 80e1dd173..1089327ae 100644
--- a/src/3rdparty/assimp/code/PolyTools.h
+++ b/src/3rdparty/assimp/code/PolyTools.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/PostStepRegistry.cpp b/src/3rdparty/assimp/code/PostStepRegistry.cpp
index 31518c132..c80c373e5 100644
--- a/src/3rdparty/assimp/code/PostStepRegistry.cpp
+++ b/src/3rdparty/assimp/code/PostStepRegistry.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/PretransformVertices.cpp b/src/3rdparty/assimp/code/PretransformVertices.cpp
index 8158bdd6f..0751c4556 100644
--- a/src/3rdparty/assimp/code/PretransformVertices.cpp
+++ b/src/3rdparty/assimp/code/PretransformVertices.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -46,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "PretransformVertices.h"
#include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "Exceptional.h"
using namespace Assimp;
@@ -103,7 +104,7 @@ unsigned int PretransformVertices::CountNodes( aiNode* pcNode )
// ------------------------------------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
-unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh)
+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
@@ -159,6 +160,11 @@ void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsign
unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
ai_assert(0 != num_ref);
--num_ref;
+ // Save the name of the last mesh
+ if (num_ref==0)
+ {
+ pcMeshOut->mName = pcMesh->mName;
+ }
if (identity) {
// copy positions without modifying them
@@ -397,7 +403,7 @@ void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in
out.push_back(ntz);
- node->mMeshes[i] = numIn + out.size() - 1;
+ node->mMeshes[i] = static_cast<unsigned int>(numIn + out.size() - 1);
}
}
}
@@ -483,7 +489,7 @@ void PretransformVertices::Execute( aiScene* pScene)
memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes);
memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size());
- pScene->mNumMeshes += apcOutMeshes.size();
+ pScene->mNumMeshes += static_cast<unsigned int>(apcOutMeshes.size());
delete[] pScene->mMeshes; pScene->mMeshes = npp;
}
@@ -625,9 +631,10 @@ void PretransformVertices::Execute( aiScene* pScene)
// now delete all nodes in the scene and build a new
// flat node graph with a root node and some level 1 children
+ aiNode* newRoot = new aiNode();
+ newRoot->mName = pScene->mRootNode->mName;
delete pScene->mRootNode;
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<dummy_root>");
+ pScene->mRootNode = newRoot;
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
{
@@ -645,7 +652,7 @@ void PretransformVertices::Execute( aiScene* pScene)
{
aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode;
- pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"mesh_%u",i);
+ pcNode->mName = pScene->mMeshes[i]->mName;
// setup mesh indices
pcNode->mNumMeshes = 1;
@@ -690,9 +697,9 @@ void PretransformVertices::Execute( aiScene* pScene)
// find the dominant axis
aiVector3D d = max-min;
- const float div = std::max(d.x,std::max(d.y,d.z))*0.5f;
+ const ai_real div = std::max(d.x,std::max(d.y,d.z))*ai_real( 0.5);
- d = min+d*0.5f;
+ d = min + d * (ai_real)0.5;
for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
aiMesh* m = pScene->mMeshes[a];
for (unsigned int i = 0; i < m->mNumVertices;++i) {
@@ -721,4 +728,3 @@ void PretransformVertices::Execute( aiScene* pScene)
DefaultLogger::get()->info(buffer);
}
}
-
diff --git a/src/3rdparty/assimp/code/PretransformVertices.h b/src/3rdparty/assimp/code/PretransformVertices.h
index 28bd95a67..65b4938b0 100644
--- a/src/3rdparty/assimp/code/PretransformVertices.h
+++ b/src/3rdparty/assimp/code/PretransformVertices.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ProcessHelper.cpp b/src/3rdparty/assimp/code/ProcessHelper.cpp
index e18d54c30..c255979bd 100644
--- a/src/3rdparty/assimp/code/ProcessHelper.cpp
+++ b/src/3rdparty/assimp/code/ProcessHelper.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -77,8 +78,8 @@ void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
const aiMatrix4x4& m)
{
- min = aiVector3D (10e10f, 10e10f, 10e10f);
- max = aiVector3D (-10e10f,-10e10f,-10e10f);
+ min = aiVector3D ( ai_real( 10e10 ), ai_real( 10e10 ), ai_real( 10e10 ) );
+ max = aiVector3D ( ai_real( -10e10 ), ai_real( -10e10 ), ai_real( -10e10 ) );
for (unsigned int i = 0;i < mesh->mNumVertices;++i)
{
const aiVector3D v = m * mesh->mVertices[i];
@@ -91,7 +92,7 @@ void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max)
{
ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max);
- out = min + (max-min)*0.5f;
+ out = min + (max-min)*(ai_real)0.5;
}
// -------------------------------------------------------------------------------
@@ -114,7 +115,7 @@ void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector
if (max[1] < tmax[1]) max[1] = tmax[1];
if (max[2] < tmax[2]) max[2] = tmax[2];
}
- out = min + (max-min)*0.5f;
+ out = min + (max-min)*(ai_real)0.5;
}
@@ -123,7 +124,7 @@ void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,
aiVector3D& max, const aiMatrix4x4& m)
{
FindAABBTransformed(mesh,min,max,m);
- out = min + (max-min)*0.5f;
+ out = min + (max-min)*(ai_real)0.5;
}
// -------------------------------------------------------------------------------
@@ -142,9 +143,9 @@ void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,
}
// -------------------------------------------------------------------------------
-float ComputePositionEpsilon(const aiMesh* pMesh)
+ai_real ComputePositionEpsilon(const aiMesh* pMesh)
{
- const float epsilon = 1e-4f;
+ const ai_real epsilon = ai_real( 1e-4 );
// calculate the position bounds so we have a reliable epsilon to check position differences against
aiVector3D minVec, maxVec;
@@ -153,11 +154,11 @@ float ComputePositionEpsilon(const aiMesh* pMesh)
}
// -------------------------------------------------------------------------------
-float ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num)
+ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num)
{
ai_assert( NULL != pMeshes );
- const float epsilon = 1e-4f;
+ const ai_real epsilon = ai_real( 1e-4 );
// calculate the position bounds so we have a reliable epsilon to check position differences against
aiVector3D minVec, maxVec, mi, ma;
@@ -308,7 +309,7 @@ aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMes
for(unsigned int j=0;j<f.mNumIndices;j++) {
if(vMap[f.mIndices[j]]==UINT_MAX) {
- vMap[f.mIndices[j]] = numSubVerts++;
+ vMap[f.mIndices[j]] = static_cast<unsigned int>(numSubVerts++);
}
}
}
@@ -320,8 +321,8 @@ aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMes
// create all the arrays for this mesh if the old mesh contained them
- oMesh->mNumFaces = subMeshFaces.size();
- oMesh->mNumVertices = numSubVerts;
+ oMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
+ oMesh->mNumVertices = static_cast<unsigned int>(numSubVerts);
oMesh->mVertices = new aiVector3D[numSubVerts];
if( pMesh->HasNormals() ) {
oMesh->mNormals = new aiVector3D[numSubVerts];
@@ -332,12 +333,12 @@ aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMes
oMesh->mBitangents = new aiVector3D[numSubVerts];
}
- for( size_t a = 0; pMesh->HasTextureCoords( a) ; ++a ) {
+ for( size_t a = 0; pMesh->HasTextureCoords(static_cast<unsigned int>(a)) ; ++a ) {
oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
}
- for( size_t a = 0; pMesh->HasVertexColors( a); ++a ) {
+ for( size_t a = 0; pMesh->HasVertexColors( static_cast<unsigned int>(a)); ++a ) {
oMesh->mColors[a] = new aiColor4D[numSubVerts];
}
diff --git a/src/3rdparty/assimp/code/ProcessHelper.h b/src/3rdparty/assimp/code/ProcessHelper.h
index 3f50a46c6..a49115936 100644
--- a/src/3rdparty/assimp/code/ProcessHelper.h
+++ b/src/3rdparty/assimp/code/ProcessHelper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -231,7 +232,7 @@ inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max)
* @param pColor1 First color
* @param pColor2 second color
* @return Quadratic color difference */
-inline float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2)
+inline ai_real 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;
@@ -293,12 +294,12 @@ void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,const aiMatrix4x4&
// -------------------------------------------------------------------------------
// Compute a good epsilon value for position comparisons on a mesh
-float ComputePositionEpsilon(const aiMesh* pMesh);
+ai_real ComputePositionEpsilon(const aiMesh* pMesh);
// -------------------------------------------------------------------------------
// Compute a good epsilon value for position comparisons on a array of meshes
-float ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num);
+ai_real ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num);
// -------------------------------------------------------------------------------
@@ -345,7 +346,7 @@ class ComputeSpatialSortProcess : public BaseProcess
void Execute( aiScene* pScene)
{
- typedef std::pair<SpatialSort, float> _Type;
+ typedef std::pair<SpatialSort, ai_real> _Type;
DefaultLogger::get()->debug("Generate spatially-sorted vertex cache");
std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes);
diff --git a/src/3rdparty/assimp/code/Profiler.h b/src/3rdparty/assimp/code/Profiler.h
index 9354339a2..1c9ca60b5 100644
--- a/src/3rdparty/assimp/code/Profiler.h
+++ b/src/3rdparty/assimp/code/Profiler.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -51,21 +52,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
namespace Assimp {
- namespace Profiling {
-
- using namespace Formatter;
+namespace Profiling {
+using namespace Formatter;
// ------------------------------------------------------------------------------------------------
/** Simple wrapper around boost::timer to simplify reporting. Timings are automatically
* dumped to the log file.
*/
-class Profiler
-{
-
+class Profiler {
public:
-
- Profiler() {}
+ Profiler() {
+ // empty
+ }
public:
@@ -83,17 +82,17 @@ public:
return;
}
- auto elapsedSeconds = std::chrono::system_clock::now() - regions[region];
+ std::chrono::duration<double> elapsedSeconds = std::chrono::system_clock::now() - regions[region];
DefaultLogger::get()->debug((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s"));
}
private:
-
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 42e2bf148..b836795f8 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileData.h
+++ b/src/3rdparty/assimp/code/Q3BSPFileData.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp b/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
index 47001d06f..9d6d8e870 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -40,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
-//#include <windows.h>
-#include "DefaultIOSystem.h"
#include "Q3BSPFileImporter.h"
#include "Q3BSPZipArchive.h"
#include "Q3BSPFileParser.h"
@@ -57,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
+#include <assimp/DefaultIOSystem.h>
+#include <assimp/importerdesc.h>
#include <vector>
#include <sstream>
#include "StringComparison.h"
@@ -76,14 +77,6 @@ static const aiImporterDesc desc = {
namespace Assimp {
-/*
-static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
- supportedExtensions.push_back( ".jpg" );
- supportedExtensions.push_back( ".png" );
- supportedExtensions.push_back( ".tga" );
-}
-*/
-
using namespace Q3BSP;
// ------------------------------------------------------------------------------------------------
@@ -175,7 +168,7 @@ Q3BSPFileImporter::~Q3BSPFileImporter() {
bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
{
if(!checkSig) {
- return SimpleExtensionCheck( rFile, "pk3" );
+ return SimpleExtensionCheck( rFile, "pk3", "bsp" );
}
// TODO perhaps add keyword based detection
return false;
@@ -339,14 +332,14 @@ void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* p
}
}
- pParent->mNumChildren = MeshArray.size();
+ pParent->mNumChildren = static_cast<unsigned int>(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;
+ pParent->mChildren[ i ]->mMeshes[ 0 ] = static_cast<unsigned int>(i);
}
}
@@ -373,9 +366,9 @@ aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel,
pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
pMesh->mFaces = new aiFace[ numTriangles ];
- pMesh->mNumFaces = numTriangles;
+ pMesh->mNumFaces = static_cast<unsigned int>(numTriangles);
- pMesh->mNumVertices = numVerts;
+ pMesh->mNumVertices = static_cast<unsigned int>(numVerts);
pMesh->mVertices = new aiVector3D[ numVerts ];
pMesh->mNormals = new aiVector3D[ numVerts ];
pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ];
@@ -524,7 +517,7 @@ void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScen
pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper;
pScene->mNumMaterials++;
}
- pScene->mNumTextures = mTextures.size();
+ pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
pScene->mTextures = new aiTexture*[ pScene->mNumTextures ];
std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures );
}
@@ -658,7 +651,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
size_t texSize = pTextureStream->FileSize();
aiTexture *pTexture = new aiTexture;
pTexture->mHeight = 0;
- pTexture->mWidth = texSize;
+ pTexture->mWidth = static_cast<unsigned int>(texSize);
unsigned char *pData = new unsigned char[ pTexture->mWidth ];
size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth );
(void)readSize;
@@ -672,7 +665,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
aiString name;
name.data[ 0 ] = '*';
- name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
+ name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(mTextures.size()) );
pArchive->Close( pTextureStream );
@@ -730,7 +723,7 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene
aiString name;
name.data[ 0 ] = '*';
- name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
+ name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(mTextures.size()) );
pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) );
mTextures.push_back( pTexture );
diff --git a/src/3rdparty/assimp/code/Q3BSPFileImporter.h b/src/3rdparty/assimp/code/Q3BSPFileImporter.h
index c995f82ab..cf53d4db0 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileImporter.h
+++ b/src/3rdparty/assimp/code/Q3BSPFileImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,30 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
+#include <map>
+
struct aiMesh;
struct aiNode;
struct aiFace;
struct aiMaterial;
struct aiTexture;
-namespace Assimp
-{
-namespace Q3BSP
-{
-
-class Q3BSPZipArchive;
-struct Q3BSPModel;
-struct sQ3BSPFace;
-
+namespace Assimp {
+namespace Q3BSP {
+ class Q3BSPZipArchive;
+ struct Q3BSPModel;
+ struct sQ3BSPFace;
}
+
// ------------------------------------------------------------------------------------------------
/** Loader to import BSP-levels from a PK3 archive or from a unpacked BSP-level.
*/
// ------------------------------------------------------------------------------------------------
-class Q3BSPFileImporter : public BaseImporter
-{
+class Q3BSPFileImporter : public BaseImporter {
public:
-
/// @brief Default constructor.
Q3BSPFileImporter();
diff --git a/src/3rdparty/assimp/code/Q3BSPFileParser.cpp b/src/3rdparty/assimp/code/Q3BSPFileParser.cpp
index db2247b8a..69721fc2d 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileParser.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPFileParser.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#include "Q3BSPFileParser.h"
-#include "DefaultIOSystem.h"
#include "Q3BSPFileData.h"
#include "Q3BSPZipArchive.h"
#include <vector>
+#include <assimp/DefaultIOSystem.h>
#include <assimp/ai_assert.h>
namespace Assimp {
diff --git a/src/3rdparty/assimp/code/Q3BSPFileParser.h b/src/3rdparty/assimp/code/Q3BSPFileParser.h
index 55de25491..1ee6d4aef 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileParser.h
+++ b/src/3rdparty/assimp/code/Q3BSPFileParser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp b/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
index 59e437836..86c966d8e 100644
--- a/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -38,14 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-
-
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#include "Q3BSPZipArchive.h"
-#include <algorithm>
#include <cassert>
-#include <cstdlib>
#include <assimp/ai_assert.h>
namespace Assimp {
@@ -73,19 +70,19 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
IOStream* io_stream = (IOStream*) stream;
- return io_stream->Read(buf, 1, size);
+ return static_cast<uLong>(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);
+ return static_cast<uLong>(io_stream->Write(buf, 1, size));
}
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream* io_stream = (IOStream*) stream;
- return io_stream->Tell();
+ return static_cast<long>(io_stream->Tell());
}
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
@@ -136,7 +133,6 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
return mapping;
}
-// ------------------------------------------------------------------------------------------------
ZipFile::ZipFile(size_t size) : m_Size(size) {
ai_assert(m_Size != 0);
@@ -259,6 +255,7 @@ IOStream *Q3BSPZipArchive::Open(const char* pFile, const char* /*pMode*/) {
// ------------------------------------------------------------------------------------------------
// Close a filestream.
void Q3BSPZipArchive::Close(IOStream *pFile) {
+ (void)(pFile);
ai_assert(pFile != NULL);
// We don't do anything in case the file would be opened again in the future
diff --git a/src/3rdparty/assimp/code/Q3BSPZipArchive.h b/src/3rdparty/assimp/code/Q3BSPZipArchive.h
index e46a11b4c..5430bac6f 100644
--- a/src/3rdparty/assimp/code/Q3BSPZipArchive.h
+++ b/src/3rdparty/assimp/code/Q3BSPZipArchive.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <contrib/unzip/unzip.h>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
-#include <string>
#include <vector>
#include <map>
#include <cassert>
@@ -58,24 +58,15 @@ namespace Q3BSP {
/// \brief
// ------------------------------------------------------------------------------------------------
class IOSystem2Unzip {
-
- public:
-
- static voidpf open(voidpf opaque, const char* filename, int mode);
-
- static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
-
- static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
-
- static long tell(voidpf opaque, voidpf stream);
-
- static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
-
- static int close(voidpf opaque, voidpf stream);
-
- static int testerror(voidpf opaque, voidpf stream);
-
- static zlib_filefunc_def get(IOSystem* pIOHandler);
+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);
};
// ------------------------------------------------------------------------------------------------
@@ -85,32 +76,21 @@ class IOSystem2Unzip {
/// \brief
// ------------------------------------------------------------------------------------------------
class ZipFile : public IOStream {
-
friend class Q3BSPZipArchive;
- 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;
+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;
};
// ------------------------------------------------------------------------------------------------
@@ -121,39 +101,25 @@ class ZipFile : public IOStream {
/// from a P3K archive ( Quake level format ).
// ------------------------------------------------------------------------------------------------
class Q3BSPZipArchive : public Assimp::IOSystem {
-
- public:
-
- static const unsigned int FileNameSize = 256;
-
- public:
-
- Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
-
- ~Q3BSPZipArchive();
-
- bool Exists(const char* pFile) const;
-
- char getOsSeparator() const;
-
- IOStream* Open(const char* pFile, const char* pMode = "rb");
-
- void Close(IOStream* pFile);
-
- bool isOpen() const;
-
- void getFileList(std::vector<std::string> &rFileList);
-
- private:
-
- bool mapArchive();
-
- private:
-
- unzFile m_ZipFileHandle;
-
- std::map<std::string, ZipFile*> m_ArchiveMap;
-
+public:
+ static const unsigned int FileNameSize = 256;
+
+public:
+ Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
+ ~Q3BSPZipArchive();
+ bool Exists(const char* pFile) const;
+ char getOsSeparator() const;
+ IOStream* Open(const char* pFile, const char* pMode = "rb");
+ void Close(IOStream* pFile);
+ bool isOpen() const;
+ void getFileList(std::vector<std::string> &rFileList);
+
+private:
+ bool mapArchive();
+
+private:
+ unzFile m_ZipFileHandle;
+ std::map<std::string, ZipFile*> m_ArchiveMap;
};
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/Q3DLoader.cpp b/src/3rdparty/assimp/code/Q3DLoader.cpp
index d9dc29672..5aa639d09 100644
--- a/src/3rdparty/assimp/code/Q3DLoader.cpp
+++ b/src/3rdparty/assimp/code/Q3DLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -53,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
using namespace Assimp;
diff --git a/src/3rdparty/assimp/code/Q3DLoader.h b/src/3rdparty/assimp/code/Q3DLoader.h
index fb1dd1818..97184a5ff 100644
--- a/src/3rdparty/assimp/code/Q3DLoader.h
+++ b/src/3rdparty/assimp/code/Q3DLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/RawLoader.cpp b/src/3rdparty/assimp/code/RawLoader.cpp
index 57e0fc119..2b76455d7 100644
--- a/src/3rdparty/assimp/code/RawLoader.cpp
+++ b/src/3rdparty/assimp/code/RawLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
@@ -259,7 +260,7 @@ void RAWImporter::InternReadFile( const std::string& pFile,
node = *cc = new aiNode();
node->mParent = pScene->mRootNode;
}
- else node = *cc;++cc;
+ else node = *cc;
node->mName.Set(outGroup.name);
// add all meshes
diff --git a/src/3rdparty/assimp/code/RawLoader.h b/src/3rdparty/assimp/code/RawLoader.h
index 984141a04..0a1a35815 100644
--- a/src/3rdparty/assimp/code/RawLoader.h
+++ b/src/3rdparty/assimp/code/RawLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/RemoveComments.cpp b/src/3rdparty/assimp/code/RemoveComments.cpp
index 8290d2217..37d74124d 100644
--- a/src/3rdparty/assimp/code/RemoveComments.cpp
+++ b/src/3rdparty/assimp/code/RemoveComments.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/RemoveComments.h b/src/3rdparty/assimp/code/RemoveComments.h
index 856ed74bf..0a00a8f0f 100644
--- a/src/3rdparty/assimp/code/RemoveComments.h
+++ b/src/3rdparty/assimp/code/RemoveComments.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,7 +45,7 @@ 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 <assimp/ai_assert.h>
+
#include <assimp/defs.h>
namespace Assimp {
diff --git a/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp b/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp
index a3e61ae8d..c6319f892 100644
--- a/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp
+++ b/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -144,6 +145,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
if (!abReferenced[i]) {
++unreferencedRemoved;
delete pScene->mMaterials[i];
+ pScene->mMaterials[i] = nullptr;
continue;
}
@@ -157,6 +159,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
me = 0;
aiMappingTable[i] = aiMappingTable[a];
delete pScene->mMaterials[i];
+ pScene->mMaterials[i] = nullptr;
break;
}
}
@@ -168,6 +171,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
// 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) {
+ ai_assert(iNewNum > 0);
aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
@@ -177,12 +181,14 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
continue;
}
- // generate new names for all modified materials
+ // generate new names for modified materials that had no names
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);
+ if( ppcMaterials[idx]->Get(AI_MATKEY_NAME, sz) != AI_SUCCESS ) {
+ sz.length = ::ai_snprintf(sz.data,MAXLEN,"JoinedMaterial_#%u",p);
+ ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
+ }
} else {
ppcMaterials[idx] = pScene->mMaterials[p];
}
diff --git a/src/3rdparty/assimp/code/RemoveRedundantMaterials.h b/src/3rdparty/assimp/code/RemoveRedundantMaterials.h
index 60efad9a4..cb4ec02bb 100644
--- a/src/3rdparty/assimp/code/RemoveRedundantMaterials.h
+++ b/src/3rdparty/assimp/code/RemoveRedundantMaterials.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/RemoveVCProcess.cpp b/src/3rdparty/assimp/code/RemoveVCProcess.cpp
index 473460452..016757dbb 100644
--- a/src/3rdparty/assimp/code/RemoveVCProcess.cpp
+++ b/src/3rdparty/assimp/code/RemoveVCProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -305,7 +306,7 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
if (!pMesh->mColors[i])break;
if (configDeleteFlags & aiComponent_COLORSn(i) || b)
{
- delete pMesh->mColors[i];
+ delete [] pMesh->mColors[i];
pMesh->mColors[i] = NULL;
ret = true;
diff --git a/src/3rdparty/assimp/code/RemoveVCProcess.h b/src/3rdparty/assimp/code/RemoveVCProcess.h
index a9173a815..d7d45e73e 100644
--- a/src/3rdparty/assimp/code/RemoveVCProcess.h
+++ b/src/3rdparty/assimp/code/RemoveVCProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,8 +54,7 @@ namespace Assimp {
/** RemoveVCProcess: Class to exclude specific parts of the data structure
* from further processing by removing them,
*/
-class ASSIMP_API RemoveVCProcess : public BaseProcess
-{
+class ASSIMP_API RemoveVCProcess : public BaseProcess {
public:
/// The default class constructor.
RemoveVCProcess();
@@ -62,7 +62,6 @@ public:
/// The class destructor.
~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
diff --git a/src/3rdparty/assimp/code/SGSpatialSort.cpp b/src/3rdparty/assimp/code/SGSpatialSort.cpp
index 84061888e..7a80381e2 100644
--- a/src/3rdparty/assimp/code/SGSpatialSort.cpp
+++ b/src/3rdparty/assimp/code/SGSpatialSort.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -47,7 +48,6 @@ the 3ds loader handling smooth groups correctly */
using namespace Assimp;
-
// ------------------------------------------------------------------------------------------------
SGSpatialSort::SGSpatialSort()
{
@@ -88,12 +88,11 @@ void SGSpatialSort::FindPositions( const aiVector3D& pPosition,
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());
+ // clear the array
+ poResults.clear();
// quick check for positions outside the range
- if( mPositions.size() == 0)
+ if( mPositions.empty() )
return;
if( maxDist < mPositions.front().mDistance)
return;
diff --git a/src/3rdparty/assimp/code/SGSpatialSort.h b/src/3rdparty/assimp/code/SGSpatialSort.h
index 59a5c37d6..e7cd38724 100644
--- a/src/3rdparty/assimp/code/SGSpatialSort.h
+++ b/src/3rdparty/assimp/code/SGSpatialSort.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SIBImporter.cpp b/src/3rdparty/assimp/code/SIBImporter.cpp
index b972f28d6..2127e2e0c 100644
--- a/src/3rdparty/assimp/code/SIBImporter.cpp
+++ b/src/3rdparty/assimp/code/SIBImporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -57,11 +58,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ByteSwapper.h"
#include "StreamReader.h"
#include "TinyFormatter.h"
-#include "../contrib/ConvertUTF/ConvertUTF.h"
+//#include "../contrib/ConvertUTF/ConvertUTF.h"
+#include "../contrib/utf8cpp/source/utf8.h"
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
+#include <map>
using namespace Assimp;
@@ -76,25 +80,26 @@ static const aiImporterDesc desc = {
"sib"
};
-struct SIBChunk
-{
+struct SIBChunk {
uint32_t Tag;
uint32_t Size;
} PACK_STRUCT;
-enum { POS, NRM, UV, N };
+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
-{
+struct SIBEdge {
uint32_t faceA, faceB;
bool creased;
};
-struct SIBMesh
-{
+struct SIBMesh {
aiMatrix4x4 axis;
uint32_t numPts;
std::vector<aiVector3D> pos, nrm, uv;
@@ -105,15 +110,13 @@ struct SIBMesh
std::map<SIBPair, uint32_t> edgeMap;
};
-struct SIBObject
-{
+struct SIBObject {
aiString name;
aiMatrix4x4 axis;
size_t meshIdx, meshCount;
};
-struct SIB
-{
+struct SIB {
std::vector<aiMaterial*> mtls;
std::vector<aiMesh*> meshes;
std::vector<aiLight*> lights;
@@ -121,8 +124,7 @@ struct SIB
};
// ------------------------------------------------------------------------------------------------
-static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB)
-{
+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())
@@ -131,7 +133,7 @@ static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB)
SIBEdge edge;
edge.creased = false;
edge.faceA = edge.faceB = 0xffffffff;
- mesh->edgeMap[pair] = mesh->edges.size();
+ mesh->edgeMap[pair] = static_cast<uint32_t>(mesh->edges.size());
mesh->edges.push_back(edge);
return mesh->edges.back();
}
@@ -161,72 +163,79 @@ static aiColor3D ReadColor(StreamReaderLE* stream)
return aiColor3D(r, g, b);
}
-static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk)
+static void UnknownChunk(StreamReaderLE* /*stream*/, const SIBChunk& chunk)
{
- char temp[5] = {
+ 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)
-{
+static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) {
+ if ( nullptr == stream || 0 == numWChars ) {
+ static const aiString empty;
+ return empty;
+ }
+
// 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();
+ std::vector<unsigned char> str;
+ str.reserve( numWChars * 4 + 1 );
+ uint16_t *temp = new uint16_t[ numWChars ];
+ 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';
+ const uint16_t *start( temp ), *end( temp + numWChars );
+ utf8::utf16to8( start, end, back_inserter( str ) );
+ str[ str.size() - 1 ] = '\0';
// Return the final string.
- aiString result = aiString((const char *)str);
- delete[] str;
+ aiString result = aiString((const char *)&str[0]);
delete[] temp;
+
return result;
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
-SIBImporter::SIBImporter()
-{}
+SIBImporter::SIBImporter() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-SIBImporter::~SIBImporter()
-{}
+SIBImporter::~SIBImporter() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
-bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
-{
+bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(pFile, "sib");
}
// ------------------------------------------------------------------------------------------------
-const aiImporterDesc* SIBImporter::GetInfo () const
-{
+const aiImporterDesc* SIBImporter::GetInfo () const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
-static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count)
-{
- mesh->pos.resize(count);
+static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) {
+ if ( nullptr == mesh || nullptr == stream ) {
+ return;
+ }
- 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();
+ 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();
}
}
@@ -244,7 +253,7 @@ static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream)
mesh->idx[pos-1] = numPoints;
uint32_t *idx = &mesh->idx[pos];
- mesh->faceStart.push_back(pos-1);
+ mesh->faceStart.push_back(static_cast<uint32_t>(pos-1));
mesh->mtls.push_back(0);
// Read all the position data.
@@ -373,7 +382,7 @@ static void ConnectFaces(SIBMesh* mesh)
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];
@@ -385,9 +394,9 @@ static void ConnectFaces(SIBMesh* mesh)
// 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;
+ edge.faceA = static_cast<uint32_t>(faceIdx);
+ else if (edge.faceB == 0xffffffff)
+ edge.faceB = static_cast<uint32_t>(faceIdx);
prev = next;
}
@@ -398,7 +407,7 @@ static void ConnectFaces(SIBMesh* mesh)
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
+ // 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.
@@ -430,12 +439,17 @@ static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_
{
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;
+ // Non-manifold meshes can produce faces which share
+ // positions but have no edge entry, so check it.
+ if (edge.faceA == faceIdx || edge.faceB == faceIdx)
+ {
+ // Move to whichever side we didn't just come from.
+ if (!edge.creased) {
+ if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx && edge.faceA != 0xffffffff)
+ nextFaceIdx = edge.faceA;
+ else if (edge.faceB != prevFaceIdx && edge.faceB != faceIdx && edge.faceB != 0xffffffff)
+ nextFaceIdx = edge.faceB;
+ }
}
}
@@ -449,7 +463,7 @@ static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_
prevFaceIdx = faceIdx;
faceIdx = nextFaceIdx;
- }
+ }
}
// Normalize it.
@@ -496,7 +510,7 @@ static void CalculateNormals(SIBMesh* mesh)
{
uint32_t pos = idx[i*N+POS];
uint32_t nrm = idx[i*N+NRM];
- aiVector3D vtxNorm = CalculateVertexNormal(mesh, faceIdx, pos, faceNormals);
+ aiVector3D vtxNorm = CalculateVertexNormal(mesh, static_cast<uint32_t>(faceIdx), pos, faceNormals);
mesh->nrm[nrm] = vtxNorm;
}
}
@@ -508,7 +522,7 @@ struct TempMesh
std::vector<aiVector3D> vtx;
std::vector<aiVector3D> nrm;
std::vector<aiVector3D> uv;
- std::vector<aiFace> faces;
+ std::vector<aiFace> faces;
};
static void ReadShape(SIB* sib, StreamReaderLE* stream)
@@ -546,7 +560,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
stream->SetReadLimit(oldLimit);
}
- assert(smesh.faceStart.size() == smesh.mtls.size()); // sanity check
+ ai_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
@@ -586,7 +600,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
for (unsigned pt=0;pt<face.mNumIndices;pt++,idx+=N)
{
size_t vtxIdx = dest.vtx.size();
- face.mIndices[pt] = vtxIdx;
+ face.mIndices[pt] = static_cast<unsigned int>(vtxIdx);
// De-index it. We don't need to validate here as
// we did it when creating the data.
@@ -610,7 +624,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
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++)
@@ -621,14 +635,14 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream)
aiMesh* mesh = new aiMesh;
mesh->mName = name;
- mesh->mNumFaces = src.faces.size();
+ mesh->mNumFaces = static_cast<unsigned int>(src.faces.size());
mesh->mFaces = new aiFace[mesh->mNumFaces];
- mesh->mNumVertices = src.vtx.size();
+ mesh->mNumVertices = static_cast<unsigned int>(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;
+ mesh->mMaterialIndex = static_cast<unsigned int>(n);
for (unsigned i=0;i<mesh->mNumVertices;i++)
{
@@ -697,8 +711,8 @@ static void ReadLightInfo(aiLight* light, StreamReaderLE* stream)
light->mColorDiffuse = ReadColor(stream);
light->mColorAmbient = ReadColor(stream);
light->mColorSpecular = ReadColor(stream);
- float spotExponent = stream->GetF4();
- float spotCutoff = stream->GetF4();
+ ai_real spotExponent = stream->GetF4();
+ ai_real spotCutoff = stream->GetF4();
light->mAttenuationConstant = stream->GetF4();
light->mAttenuationLinear = stream->GetF4();
light->mAttenuationQuadratic = stream->GetF4();
@@ -709,9 +723,9 @@ static void ReadLightInfo(aiLight* light, StreamReaderLE* stream)
// 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));
+ ai_real E = ai_real( 1.0 ) / std::max(spotExponent, (ai_real)0.00001);
+ ai_real inner = std::acos(std::pow((ai_real)0.99, E));
+ ai_real outer = std::acos(std::pow((ai_real)0.01, E));
// Apply the cutoff.
outer = std::min(outer, AI_DEG_TO_RAD(spotCutoff));
@@ -792,8 +806,9 @@ static void ReadInstance(SIB* sib, StreamReaderLE* stream)
stream->SetReadLimit(oldLimit);
}
- if (shapeIndex >= sib->objs.size())
- throw DeadlyImportError("SIB: Invalid shape index.");
+ if ( shapeIndex >= sib->objs.size() ) {
+ throw DeadlyImportError( "SIB: Invalid shape index." );
+ }
const SIBObject& src = sib->objs[shapeIndex];
inst.meshIdx = src.meshIdx;
@@ -805,8 +820,9 @@ static void ReadInstance(SIB* sib, StreamReaderLE* stream)
static void CheckVersion(StreamReaderLE* stream)
{
uint32_t version = stream->GetU4();
- if (version != 1)
- throw DeadlyImportError("SIB: Unsupported file version.");
+ if ( version < 1 || version > 2 ) {
+ throw DeadlyImportError( "SIB: Unsupported file version." );
+ }
}
static void ReadScene(SIB* sib, StreamReaderLE* stream)
@@ -862,9 +878,9 @@ void SIBImporter::InternReadFile(const std::string& pFile,
sib.insts.clear();
// Transfer to the aiScene.
- pScene->mNumMaterials = sib.mtls.size();
- pScene->mNumMeshes = sib.meshes.size();
- pScene->mNumLights = sib.lights.size();
+ pScene->mNumMaterials = static_cast<unsigned int>(sib.mtls.size());
+ pScene->mNumMeshes = static_cast<unsigned int>(sib.meshes.size());
+ pScene->mNumLights = static_cast<unsigned int>(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;
@@ -879,13 +895,14 @@ void SIBImporter::InternReadFile(const std::string& pFile,
size_t childIdx = 0;
aiNode *root = new aiNode();
root->mName.Set("<SIBRoot>");
- root->mNumChildren = sib.objs.size() + sib.lights.size();
+ root->mNumChildren = static_cast<unsigned int>(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++)
{
+ ai_assert(root->mChildren);
SIBObject& obj = sib.objs[n];
aiNode* node = new aiNode;
root->mChildren[childIdx++] = node;
@@ -893,19 +910,16 @@ void SIBImporter::InternReadFile(const std::string& pFile,
node->mParent = root;
node->mTransformation = obj.axis;
- node->mNumMeshes = obj.meshCount;
+ node->mNumMeshes = static_cast<unsigned int>(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;
+ node->mMeshes[i] = static_cast<unsigned int>(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);
+ node->mMetaData = aiMetadata::Alloc( 1 );
+ node->mMetaData->Set( 0, "IsInstance", true );
}
}
@@ -913,6 +927,7 @@ void SIBImporter::InternReadFile(const std::string& pFile,
// (no transformation as the light is already in world space)
for (size_t n=0;n<sib.lights.size();n++)
{
+ ai_assert(root->mChildren);
aiLight* light = sib.lights[n];
if ( nullptr != light ) {
aiNode* node = new aiNode;
diff --git a/src/3rdparty/assimp/code/SIBImporter.h b/src/3rdparty/assimp/code/SIBImporter.h
index d82a40da0..e7e2ec0b9 100644
--- a/src/3rdparty/assimp/code/SIBImporter.h
+++ b/src/3rdparty/assimp/code/SIBImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -53,15 +54,13 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the Nevercenter Silo SIB scene format
*/
-class SIBImporter : public BaseImporter
+class ASSIMP_API SIBImporter : public BaseImporter
{
public:
SIBImporter();
~SIBImporter();
-
public:
-
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
@@ -70,7 +69,6 @@ public:
bool checkSig) const;
protected:
-
// -------------------------------------------------------------------
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
@@ -85,7 +83,6 @@ protected:
IOSystem* pIOHandler);
private:
-
struct MeshInformation
{
explicit MeshInformation(const std::string& _name)
diff --git a/src/3rdparty/assimp/code/SMDLoader.cpp b/src/3rdparty/assimp/code/SMDLoader.cpp
index 7aef7bc56..60e3f63c8 100644
--- a/src/3rdparty/assimp/code/SMDLoader.cpp
+++ b/src/3rdparty/assimp/code/SMDLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
#include <memory>
using namespace Assimp;
@@ -74,20 +76,22 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
SMDImporter::SMDImporter()
- : configFrameID(),
- mBuffer(),
- pScene(),
- iFileSize(),
- iSmallestFrame(),
- dLengthOfAnim(),
- bHasUVs(),
- iLineNumber()
-{}
+: configFrameID(),
+mBuffer(),
+pScene( nullptr ),
+iFileSize( 0 ),
+iSmallestFrame( -1 ),
+dLengthOfAnim( 0.0 ),
+bHasUVs(false ),
+iLineNumber(-1) {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-SMDImporter::~SMDImporter()
-{}
+SMDImporter::~SMDImporter() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@@ -133,9 +137,8 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// 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];
+ mBuffer.resize( iFileSize + 1 );
+ TextFileToBuffer(file.get(), mBuffer );
iSmallestFrame = (1 << 31);
bHasUVs = true;
@@ -447,7 +450,9 @@ void SMDImporter::CreateOutputMeshes()
// add bone child nodes
void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
{
- ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren);
+ ai_assert( NULL != pcNode );
+ ai_assert( 0 == pcNode->mNumChildren );
+ ai_assert( NULL == pcNode->mChildren);
// first count ...
for (unsigned int i = 0; i < asBones.size();++i)
@@ -640,17 +645,19 @@ void SMDImporter::ComputeAbsoluteBoneTransformations()
bone.mOffsetMatrix.Inverse();
}
}
-
+\
// ------------------------------------------------------------------------------------------------
// create output materials
void SMDImporter::CreateOutputMaterials()
{
+ ai_assert( nullptr != pScene );
+
pScene->mNumMaterials = (unsigned int)aszTextures.size();
pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)];
- for (unsigned int iMat = 0; iMat < pScene->mNumMaterials;++iMat)
- {
+ for (unsigned int iMat = 0; iMat < pScene->mNumMaterials; ++iMat) {
aiMaterial* pcMat = new aiMaterial();
+ ai_assert( nullptr != pcMat );
pScene->mMaterials[iMat] = pcMat;
aiString szName;
@@ -659,7 +666,7 @@ void SMDImporter::CreateOutputMaterials()
if (aszTextures[iMat].length())
{
- ::strcpy(szName.data, aszTextures[iMat].c_str() );
+ ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
szName.length = aszTextures[iMat].length();
pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
}
@@ -694,14 +701,14 @@ void SMDImporter::CreateOutputMaterials()
// Parse the file
void SMDImporter::ParseFile()
{
- const char* szCurrent = mBuffer;
+ const char* szCurrent = &mBuffer[0];
// read line per line ...
for ( ;; )
{
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
- // "version <n> \n", <n> should be 1 for hl and hl� SMD files
+ // "version <n> \n", <n> should be 1 for hl and hl2 SMD files
if (TokenMatch(szCurrent,"version",7))
{
if(!SkipSpaces(szCurrent,&szCurrent)) break;
@@ -1019,7 +1026,7 @@ void SMDImporter::ParseTriangle(const char* szCurrent,
// read the texture file name
const char* szLast = szCurrent;
- while (!IsSpaceOrNewLine(*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));
diff --git a/src/3rdparty/assimp/code/SMDLoader.h b/src/3rdparty/assimp/code/SMDLoader.h
index 0b069cc25..c50b327e3 100644
--- a/src/3rdparty/assimp/code/SMDLoader.h
+++ b/src/3rdparty/assimp/code/SMDLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -171,7 +172,7 @@ struct Bone
// ---------------------------------------------------------------------------
/** Used to load Half-life 1 and 2 SMD models
*/
-class SMDImporter : public BaseImporter
+class ASSIMP_API SMDImporter : public BaseImporter
{
public:
SMDImporter();
@@ -372,7 +373,7 @@ private:
unsigned int configFrameID;
/** Buffer to hold the loaded file */
- const char* mBuffer;
+ std::vector<char> mBuffer;
/** Output scene to be filled
*/
diff --git a/src/3rdparty/assimp/code/STEPFile.h b/src/3rdparty/assimp/code/STEPFile.h
index e09add1eb..8a30beb3f 100644
--- a/src/3rdparty/assimp/code/STEPFile.h
+++ b/src/3rdparty/assimp/code/STEPFile.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -54,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
-# else
+#else
# define step_unordered_map map
# define step_unordered_multimap multimap
#endif
@@ -72,7 +73,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "LineSplitter.h"
-
// uncomment this to have the loader evaluate all entities upon loading.
// this is intended as stress test - by default, entities are evaluated
// lazily and therefore not unless needed.
@@ -118,15 +118,13 @@ namespace STEP {
// ********************************************************************************
-
namespace STEP {
// -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code. It is typically
* coupled with a line number. */
// -------------------------------------------------------------------------------
- struct SyntaxError : DeadlyImportError
- {
+ struct SyntaxError : DeadlyImportError {
enum {
LINE_NOT_SPECIFIED = 0xffffffffffffffffLL
};
@@ -253,7 +251,7 @@ namespace STEP {
{
public:
- // This is the type that will ultimatively be used to
+ // This is the type that will cd ultimatively be used to
// expose this data type to the user.
typedef T Out;
@@ -441,13 +439,17 @@ namespace STEP {
// ------------------------------------------------------------------------------
/** Base class for all concrete object instances */
// ------------------------------------------------------------------------------
- class Object
- {
+ class Object {
public:
-
- virtual ~Object() {}
Object(const char* classname = "unknown")
- : classname(classname) {}
+ : id( 0 )
+ , classname(classname) {
+ // empty
+ }
+
+ virtual ~Object() {
+ // empty
+ }
public:
@@ -462,7 +464,6 @@ namespace STEP {
return dynamic_cast<T&>(*this);
}
-
template <typename T>
const T* ToPtr() const {
return dynamic_cast<const T*>(this);
@@ -474,7 +475,6 @@ namespace STEP {
}
public:
-
uint64_t GetID() const {
return id;
}
@@ -492,7 +492,6 @@ namespace STEP {
const char* const classname;
};
-
template <typename T>
size_t GenericFill(const STEP::DB& db, const EXPRESS::LIST& params, T* in);
// (intentionally undefined)
@@ -1001,26 +1000,20 @@ namespace STEP {
refs.insert(std::make_pair(who,by_whom));
}
-
-
private:
-
HeaderInfo header;
ObjectMap objects;
ObjectMapByType objects_bytype;
RefMap refs;
InverseWhitelist inv_whitelist;
-
std::shared_ptr<StreamReaderLE> reader;
LineSplitter splitter;
-
uint64_t evaluated_count;
-
const EXPRESS::ConversionSchema* schema;
};
}
-
} // end Assimp
-#endif
+
+#endif // INCLUDED_AI_STEPFILE_H
diff --git a/src/3rdparty/assimp/code/STEPFileEncoding.cpp b/src/3rdparty/assimp/code/STEPFileEncoding.cpp
index aff0b618d..7204f802b 100644
--- a/src/3rdparty/assimp/code/STEPFileEncoding.cpp
+++ b/src/3rdparty/assimp/code/STEPFileEncoding.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -39,18 +40,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file STEPFileEncoding.cpp
- * @brief STEP character handling, string unescaping
+ * @brief STEP character handling, string un-escaping
*/
#include "STEPFileEncoding.h"
#include "fast_atof.h"
+#include <contrib/utf8cpp/source/utf8.h>
-#include "../contrib/ConvertUTF/ConvertUTF.h"
#include <memory>
using namespace Assimp;
// roman1 to utf16 table
-static const UTF16 mac_codetable[] = {
+static const uint16_t mac_codetable[] = {
// 0x20 unassig./nonprint. slots
0x0020 ,
0x0021 ,
@@ -308,14 +309,12 @@ bool STEP::StringToUTF8(std::string& s)
ai_assert(sizeof(mac_codetable) / sizeof(mac_codetable[0]) == 0x100-0x20);
- const UTF32 unival = mac_codetable[macval - 0x20], *univalp = &unival;
+ const uint32_t unival = mac_codetable[macval - 0x20], *univalp = &unival;
- UTF8 temp[5], *tempp = temp;
- ai_assert(sizeof(UTF8) == 1);
+ unsigned char temp[5], *tempp = temp;
+ ai_assert(sizeof( unsigned char ) == 1);
- if(ConvertUTF32toUTF8(&univalp, univalp+1, &tempp, tempp+sizeof(temp), lenientConversion) != conversionOK) {
- return false;
- }
+ utf8::utf32to8( univalp, univalp + 1, tempp );
const size_t outcount = static_cast<size_t>(tempp-temp);
@@ -335,7 +334,7 @@ bool STEP::StringToUTF8(std::string& s)
size_t j = basei, jend = s.size()-3;
for (; j < jend; ++j) {
- if (s[j] == '\\' && s[j] == 'X' && s[j] == '0' && s[j] == '\\') {
+ if (s[j] == '\\' && s[j+1] == 'X' && s[j+2] == '0' && s[j+3] == '\\') {
break;
}
}
@@ -354,28 +353,26 @@ bool STEP::StringToUTF8(std::string& s)
}
const size_t count = (j-basei)/4;
- std::unique_ptr<UTF16[]> src(new UTF16[count]);
+ std::unique_ptr<uint16_t[]> src(new uint16_t[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));
+ src[k] = (static_cast<uint16_t>(HexOctetToDecimal(cur)) << 8u) |
+ static_cast<uint16_t>(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]);
+ std::unique_ptr<unsigned char[]> dest(new unsigned char[dcount]);
- const UTF16* srct = src.get();
- UTF8* destt = dest.get();
- if(ConvertUTF16toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
- return false;
- }
+ const uint16_t* srct = src.get();
+ unsigned char* destt = dest.get();
+ utf8::utf16to8( srct, srct + count, destt );
const size_t outcount = static_cast<size_t>(destt-dest.get());
s.erase(i,(j+4-i));
- ai_assert(sizeof(UTF8) == 1);
+ ai_assert(sizeof(unsigned char) == 1);
s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
i += outcount;
@@ -387,37 +384,34 @@ bool STEP::StringToUTF8(std::string& s)
}
const size_t count = (j-basei)/8;
- std::unique_ptr<UTF32[]> src(new UTF32[count]);
+ std::unique_ptr<uint32_t[]> src(new uint32_t[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)));
+ src[k] = (static_cast<uint32_t>(HexOctetToDecimal(cur )) << 24u) |
+ (static_cast<uint32_t>(HexOctetToDecimal(cur+2)) << 16u) |
+ (static_cast<uint32_t>(HexOctetToDecimal(cur+4)) << 8u) |
+ (static_cast<uint32_t>(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]);
+ std::unique_ptr<unsigned char[]> dest(new unsigned char[dcount]);
- const UTF32* srct = src.get();
- UTF8* destt = dest.get();
- if(ConvertUTF32toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
- return false;
- }
+ const uint32_t* srct = src.get();
+ unsigned char* destt = dest.get();
+ utf8::utf32to8( srct, srct + count, destt );
const size_t outcount = static_cast<size_t>(destt-dest.get());
s.erase(i,(j+4-i));
- ai_assert(sizeof(UTF8) == 1);
+ ai_assert(sizeof(unsigned char) == 1);
s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
i += outcount;
continue;
}
}
-
break;
// TODO: other encoding patterns?
diff --git a/src/3rdparty/assimp/code/STEPFileEncoding.h b/src/3rdparty/assimp/code/STEPFileEncoding.h
index 3aec83056..56615c8f6 100644
--- a/src/3rdparty/assimp/code/STEPFileEncoding.h
+++ b/src/3rdparty/assimp/code/STEPFileEncoding.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/STEPFileReader.cpp b/src/3rdparty/assimp/code/STEPFileReader.cpp
index afaa53a45..d014c1a5d 100644
--- a/src/3rdparty/assimp/code/STEPFileReader.cpp
+++ b/src/3rdparty/assimp/code/STEPFileReader.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/STEPFileReader.h b/src/3rdparty/assimp/code/STEPFileReader.h
index c5bc88a5e..fb8c86f59 100644
--- a/src/3rdparty/assimp/code/STEPFileReader.h
+++ b/src/3rdparty/assimp/code/STEPFileReader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/STLExporter.cpp b/src/3rdparty/assimp/code/STLExporter.cpp
index 09e01626d..60b5d8bf3 100644
--- a/src/3rdparty/assimp/code/STLExporter.cpp
+++ b/src/3rdparty/assimp/code/STLExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -56,11 +57,15 @@ 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, const ExportProperties* pProperties)
+void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
// invoke the exporter
STLExporter exporter(pFile, pScene);
+ if (exporter.mOutput.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + 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) {
@@ -69,11 +74,15 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
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, const ExportProperties* pProperties)
+void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
// invoke the exporter
STLExporter exporter(pFile, pScene, true);
+ if (exporter.mOutput.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + 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) {
@@ -162,12 +171,12 @@ void STLExporter :: WriteMeshBinary(const aiMesh* m)
}
nor.Normalize();
}
- float nx = nor.x, ny = nor.y, nz = nor.z;
+ ai_real 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_real 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);
}
diff --git a/src/3rdparty/assimp/code/STLExporter.h b/src/3rdparty/assimp/code/STLExporter.h
index 44b12344f..7fb6a3e75 100644
--- a/src/3rdparty/assimp/code/STLExporter.h
+++ b/src/3rdparty/assimp/code/STLExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/STLLoader.cpp b/src/3rdparty/assimp/code/STLLoader.cpp
index 95fce47e2..be4c7584d 100644
--- a/src/3rdparty/assimp/code/STLLoader.cpp
+++ b/src/3rdparty/assimp/code/STLLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,10 +53,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
using namespace Assimp;
namespace {
+
static const aiImporterDesc desc = {
"Stereolithography (STL) Importer",
"",
@@ -78,7 +81,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
return false;
}
- const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
+ const char *facecount_pos = buffer + 80;
+ uint32_t faceCount( 0 );
+ ::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) );
const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
return expectedBinaryFileSize == fileSize;
@@ -144,7 +149,7 @@ bool STLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
const char* tokens[] = {"STL","solid"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
}
-
+
return false;
}
@@ -168,8 +173,7 @@ void addFacesToMesh(aiMesh* pMesh)
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
-void STLImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
{
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
@@ -189,7 +193,7 @@ void STLImporter::InternReadFile( const std::string& pFile,
this->mBuffer = &mBuffer2[0];
// the default vertex color is light gray.
- clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f;
+ clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = (ai_real) 0.6;
// allocate a single node
pScene->mRootNode = new aiNode();
@@ -199,42 +203,37 @@ void STLImporter::InternReadFile( const std::string& pFile,
if (IsBinarySTL(mBuffer, fileSize)) {
bMatClr = LoadBinaryFile();
} else if (IsAsciiSTL(mBuffer, fileSize)) {
- LoadASCIIFile();
+ LoadASCIIFile( pScene->mRootNode );
} 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
+ // create a single default material, using a white 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);
+ aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0));
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);
+ clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0));
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()
-{
+void STLImporter::LoadASCIIFile( aiNode *root ) {
std::vector<aiMesh*> meshes;
+ std::vector<aiNode*> nodes;
const char* sz = mBuffer;
const char* bufferEnd = mBuffer + fileSize;
std::vector<aiVector3D> positionBuffer;
@@ -246,12 +245,15 @@ void STLImporter::LoadASCIIFile()
positionBuffer.reserve(sizeEstimate);
normalBuffer.reserve(sizeEstimate);
- while (IsAsciiSTL(sz, bufferEnd - sz))
- {
+ while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz))) {
+ std::vector<unsigned int> meshIndices;
aiMesh* pMesh = new aiMesh();
pMesh->mMaterialIndex = 0;
+ meshIndices.push_back((unsigned int) meshes.size() );
meshes.push_back(pMesh);
-
+ aiNode *node = new aiNode;
+ node->mParent = root;
+ nodes.push_back( node );
SkipSpaces(&sz);
ai_assert(!IsLineEnd(sz));
@@ -264,20 +266,21 @@ void STLImporter::LoadASCIIFile()
size_t temp;
// setup the name of the node
- if ((temp = (size_t)(sz-szMe))) {
+ 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';
+ std::string name( szMe, temp );
+ node->mName.Set( name.c_str() );
+ //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>");
}
- else pScene->mRootNode->mName.Set("<STL_ASCII>");
- unsigned int faceVertexCounter = 0;
- for ( ;; )
- {
+ unsigned int faceVertexCounter = 3;
+ for ( ;; ) {
// go to the next token
if(!SkipSpacesAndLineEnd(&sz))
{
@@ -299,32 +302,25 @@ void STLImporter::LoadASCIIFile()
SkipSpaces(&sz);
if (strncmp(sz,"normal",6)) {
DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
- }
- else
- {
+ } 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 );
+ sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->x );
SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->y );
+ sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->y );
SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->z );
+ sz = fast_atoreal_move<ai_real>(sz, (ai_real&)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)))
- {
+ } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000
if (faceVertexCounter >= 3) {
DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
++sz;
- }
- else
- {
+ } else {
if (sz[6] == '\0') {
throw DeadlyImportError("STL: unexpected EOF while parsing facet");
}
@@ -332,24 +328,21 @@ void STLImporter::LoadASCIIFile()
SkipSpaces(&sz);
positionBuffer.push_back(aiVector3D());
aiVector3D* vn = &positionBuffer.back();
- sz = fast_atoreal_move<float>(sz, (float&)vn->x );
+ sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->x );
SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->y );
+ sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->y );
SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->z );
+ sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z );
faceVertexCounter++;
}
- }
- else if (!::strncmp(sz,"endsolid",8)) {
+ } else if (!::strncmp(sz,"endsolid",8)) {
do {
++sz;
} while (!::IsLineEnd(*sz));
SkipSpacesAndLineEnd(&sz);
// finished!
break;
- }
- // else skip the whole identifier
- else {
+ } else { // else skip the whole identifier
do {
++sz;
} while (!::IsSpaceOrNewLine(*sz));
@@ -368,8 +361,8 @@ void STLImporter::LoadASCIIFile()
pMesh->mNumFaces = 0;
throw DeadlyImportError("Normal buffer size does not match position buffer size");
}
- pMesh->mNumFaces = positionBuffer.size() / 3;
- pMesh->mNumVertices = positionBuffer.size();
+ pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
+ pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
positionBuffer.clear();
@@ -379,13 +372,22 @@ void STLImporter::LoadASCIIFile()
// now copy faces
addFacesToMesh(pMesh);
+
+ // assign the meshes to the current node
+ pushMeshesToNode( meshIndices, node );
}
+
// 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];
+ for (size_t i = 0; i < meshes.size(); i++) {
+ pScene->mMeshes[ i ] = meshes[i];
+ }
+
+ root->mNumChildren = (unsigned int) nodes.size();
+ root->mChildren = new aiNode*[ root->mNumChildren ];
+ for ( size_t i=0; i<nodes.size(); ++i ) {
+ root->mChildren[ i ] = nodes[ i ];
}
}
@@ -416,10 +418,11 @@ bool STLImporter::LoadBinaryFile()
// 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;
+ const ai_real invByte = (ai_real)1.0 / ( ai_real )255.0;
+ clrColorDefault.r = (*sz2++) * invByte;
+ clrColorDefault.g = (*sz2++) * invByte;
+ clrColorDefault.b = (*sz2++) * invByte;
+ clrColorDefault.a = (*sz2++) * invByte;
break;
}
}
@@ -480,18 +483,19 @@ bool STLImporter::LoadBinaryFile()
DefaultLogger::get()->info("STL: Mesh has vertex colors");
}
aiColor4D* clr = &pMesh->mColors[0][i*3];
- clr->a = 1.0f;
+ clr->a = 1.0;
+ const ai_real invVal( (ai_real)1.0 / ( ai_real )31.0 );
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;
+ clr->r = (color & 0x31u) *invVal;
+ clr->g = ((color & (0x31u<<5))>>5u) *invVal;
+ clr->b = ((color & (0x31u<<10))>>10u) *invVal;
}
else
{
- clr->b = (color & 0x31u) / 31.0f;
- clr->g = ((color & (0x31u<<5))>>5u) / 31.0f;
- clr->r = ((color & (0x31u<<10))>>10u) / 31.0f;
+ clr->b = (color & 0x31u) *invVal;
+ clr->g = ((color & (0x31u<<5))>>5u) *invVal;
+ clr->r = ((color & (0x31u<<10))>>10u) *invVal;
}
// assign the color to all vertices of the face
*(clr+1) = *clr;
@@ -502,6 +506,12 @@ bool STLImporter::LoadBinaryFile()
// now copy faces
addFacesToMesh(pMesh);
+ // 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;
+
if (bIsMaterialise && !pMesh->mColors[0])
{
// use the color as diffuse material color
@@ -510,4 +520,18 @@ bool STLImporter::LoadBinaryFile()
return false;
}
+void STLImporter::pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node ) {
+ ai_assert( nullptr != node );
+ if ( meshIndices.empty() ) {
+ return;
+ }
+
+ node->mNumMeshes = static_cast<unsigned int>( meshIndices.size() );
+ node->mMeshes = new unsigned int[ meshIndices.size() ];
+ for ( size_t i=0; i<meshIndices.size(); ++i ) {
+ node->mMeshes[ i ] = meshIndices[ i ];
+ }
+ meshIndices.clear();
+}
+
#endif // !! ASSIMP_BUILD_NO_STL_IMPORTER
diff --git a/src/3rdparty/assimp/code/STLLoader.h b/src/3rdparty/assimp/code/STLLoader.h
index a0d82dbe8..c51604861 100644
--- a/src/3rdparty/assimp/code/STLLoader.h
+++ b/src/3rdparty/assimp/code/STLLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,53 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include <assimp/types.h>
-namespace Assimp {
+// Forward declarations
+struct aiNode;
+
+namespace Assimp {
+
// ---------------------------------------------------------------------------
-/** Importer class for the sterolithography STL file format
-*/
-class STLImporter : public BaseImporter
-{
+/**
+ * @brief Importer class for the sterolithography STL file format.
+ */
+class STLImporter : public BaseImporter {
public:
+ /**
+ * @brief STLImporter, the class default constructor.
+ */
STLImporter();
- ~STLImporter();
+ /**
+ * @brief The class destructor.
+ */
+ ~STLImporter();
-public:
-
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
+ /**
+ * @brief 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;
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
+ /**
+ * @brief Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
*/
const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
+ /**
+ * @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);
-
- // -------------------------------------------------------------------
- /** Loads a binary .stl file
+ /**
+ * @brief 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();
+ /**
+ * @brief Loads a ASCII text .stl file
+ */
+ void LoadASCIIFile( aiNode *root );
+
+ void pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node );
protected:
diff --git a/src/3rdparty/assimp/code/ScaleProcess.cpp b/src/3rdparty/assimp/code/ScaleProcess.cpp
new file mode 100644
index 000000000..ada978e82
--- /dev/null
+++ b/src/3rdparty/assimp/code/ScaleProcess.cpp
@@ -0,0 +1,105 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 "ScaleProcess.h"
+
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+
+namespace Assimp {
+
+ScaleProcess::ScaleProcess()
+: BaseProcess()
+, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) {
+ // empty
+}
+
+ScaleProcess::~ScaleProcess() {
+ // empty
+}
+
+void ScaleProcess::setScale( ai_real scale ) {
+ mScale = scale;
+}
+
+ai_real ScaleProcess::getScale() const {
+ return mScale;
+}
+
+bool ScaleProcess::IsActive( unsigned int pFlags ) const {
+ return ( pFlags & aiProcess_GlobalScale ) != 0;
+}
+
+void ScaleProcess::SetupProperties( const Importer* pImp ) {
+ mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 0 );
+}
+
+void ScaleProcess::Execute( aiScene* pScene ) {
+ if ( nullptr == pScene ) {
+ return;
+ }
+
+ if ( nullptr == pScene->mRootNode ) {
+ return;
+ }
+
+ traverseNodes( pScene->mRootNode );
+}
+
+void ScaleProcess::traverseNodes( aiNode *node ) {
+ applyScaling( node );
+
+ /*for ( unsigned int i = 0; i < node->mNumChildren; ++i ) {
+ aiNode *currentNode = currentNode->mChildren[ i ];
+ if ( nullptr != currentNode ) {
+ traverseNodes( currentNode );
+ }
+ }*/
+}
+
+void ScaleProcess::applyScaling( aiNode *currentNode ) {
+ if ( nullptr != currentNode ) {
+ currentNode->mTransformation.a1 = currentNode->mTransformation.a1 * mScale;
+ currentNode->mTransformation.b2 = currentNode->mTransformation.b2 * mScale;
+ currentNode->mTransformation.c3 = currentNode->mTransformation.c3 * mScale;
+ }
+}
+
+} // Namespace Assimp
diff --git a/src/3rdparty/assimp/code/ScaleProcess.h b/src/3rdparty/assimp/code/ScaleProcess.h
new file mode 100644
index 000000000..7eb91fd5c
--- /dev/null
+++ b/src/3rdparty/assimp/code/ScaleProcess.h
@@ -0,0 +1,87 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include "BaseProcess.h"
+
+struct aiNode;
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** ScaleProcess: Class to rescale the whole model.
+*/
+class ASSIMP_API ScaleProcess : public BaseProcess {
+public:
+ /// The default class constructor.
+ ScaleProcess();
+
+ /// The class destructor.
+ virtual ~ScaleProcess();
+
+ /// Will set the scale manually.
+ void setScale( ai_real scale );
+
+ /// Returns the current scaling value.
+ ai_real getScale() const;
+
+ /// Overwritten, @see BaseProcess
+ virtual bool IsActive( unsigned int pFlags ) const;
+
+ /// Overwritten, @see BaseProcess
+ virtual void SetupProperties( const Importer* pImp );
+
+ /// Overwritten, @see BaseProcess
+ virtual void Execute( aiScene* pScene );
+
+private:
+ void traverseNodes( aiNode *currentNode );
+ void applyScaling( aiNode *currentNode );
+
+private:
+ ai_real mScale;
+};
+
+} // Namespace Assimp
diff --git a/src/3rdparty/assimp/code/SceneCombiner.cpp b/src/3rdparty/assimp/code/SceneCombiner.cpp
index b39adbf78..4b77bb2db 100644
--- a/src/3rdparty/assimp/code/SceneCombiner.cpp
+++ b/src/3rdparty/assimp/code/SceneCombiner.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,28 +44,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// possible as new fields are added to assimp structures.
// ----------------------------------------------------------------------------
-/** @file Implements Assimp::SceneCombiner. This is a smart utility
- * class that combines multiple scenes, meshes, ... into one. Currently
- * these utilities are used by the IRR and LWS loaders and the
- * OptimizeGraph step.
- */
+/**
+ * @file Implements Assimp::SceneCombiner. This is a smart utility
+ * class that combines multiple scenes, meshes, ... into one. Currently
+ * these utilities are used by the IRR and LWS loaders and the
+ * OptimizeGraph step.
+ */
// ----------------------------------------------------------------------------
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "StringUtils.h"
#include "fast_atof.h"
#include "Hash.h"
#include "time.h"
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
+#include <assimp/mesh.h>
#include <stdio.h>
#include "ScenePrivate.h"
-namespace Assimp {
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Add a prefix to a string
-inline void PrefixString(aiString& string,const char* prefix, unsigned int len)
-{
+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;
@@ -85,12 +88,11 @@ inline void PrefixString(aiString& string,const char* prefix, unsigned int len)
// ------------------------------------------------------------------------------------------------
// Add node identifiers to a hashing set
-void SceneCombiner::AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes)
-{
+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) );
+ hashes.insert( SuperFastHash(node->mName.data, static_cast<uint32_t>(node->mName.length)) );
}
// Process all children recursively
@@ -100,25 +102,23 @@ void SceneCombiner::AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes)
// ------------------------------------------------------------------------------------------------
// Add a name prefix to all nodes in a hierarchy
-void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len)
-{
+void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) {
ai_assert(NULL != prefix);
PrefixString(node->mName,prefix,len);
// Process all children recursively
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- AddNodePrefixes(node->mChildren[i],prefix,len);
+ 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);
+bool SceneCombiner::FindNameMatch(const aiString& name, std::vector<SceneHelper>& input, unsigned int cur) {
+ const unsigned int hash = SuperFastHash(name.data, static_cast<uint32_t>(name.length));
// Check whether we find a positive match in one of the given sets
for (unsigned int i = 0; i < input.size(); ++i) {
-
if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) {
return true;
}
@@ -129,14 +129,12 @@ bool SceneCombiner::FindNameMatch(const aiString& name, std::vector<SceneHelper>
// ------------------------------------------------------------------------------------------------
// 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);
+ const unsigned int hash = SuperFastHash(node->mName.data, static_cast<uint32_t>(node->mName.length));
// Check whether we find a positive match in one of the given sets
for (unsigned int i = 0; i < input.size(); ++i) {
-
if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) {
PrefixString(node->mName,prefix,len);
break;
@@ -150,27 +148,25 @@ void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, uns
// ------------------------------------------------------------------------------------------------
// Add an offset to all mesh indices in a node graph
-void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset)
-{
+void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) {
for (unsigned int i = 0; i < node->mNumMeshes;++i)
node->mMeshes[i] += offset;
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- OffsetNodeMeshIndices(node->mChildren[i],offset);
+ 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)
-{
- ai_assert(NULL != _dest);
+void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src, unsigned int flags) {
+ if ( nullptr == _dest ) {
+ return;
+ }
// if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it
- if (src.empty())
- {
- if (*_dest)
- {
+ if (src.empty()) {
+ if (*_dest) {
(*_dest)->~aiScene();
SceneCombiner::CopySceneFlat(_dest,src[0]);
}
@@ -195,11 +191,11 @@ void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src,
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList)
-{
+void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList) {
unsigned int cnt;
- for (cnt = 0; cnt < attach->mNumChildren;++cnt)
- AttachToGraph(attach->mChildren[cnt],srcList);
+ for ( cnt = 0; cnt < attach->mNumChildren; ++cnt ) {
+ AttachToGraph( attach->mChildren[ cnt ], srcList );
+ }
cnt = 0;
for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin();
@@ -235,19 +231,16 @@ void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInf
}
// ------------------------------------------------------------------------------------------------
-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);
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master,
- std::vector<AttachmentInfo>& srcList,
- unsigned int flags)
-{
- ai_assert(NULL != _dest);
+void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector<AttachmentInfo>& srcList, unsigned int flags) {
+ if ( nullptr == _dest ) {
+ return;
+ }
// if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it
if (srcList.empty()) {
@@ -323,7 +316,7 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master,
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));
+ src[i].hashes.insert(SuperFastHash(anim->mName.data,static_cast<uint32_t>(anim->mName.length)));
}
}
}
@@ -485,7 +478,7 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master,
aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations
? new aiAnimation*[dest->mNumAnimations] : NULL);
- for ( int n = src.size()-1; n >= 0 ;--n ) /* !!! important !!! */
+ for ( int n = static_cast<int>(src.size()-1); n >= 0 ;--n ) /* !!! important !!! */
{
SceneHelper* cur = &src[n];
aiNode* node;
@@ -704,7 +697,9 @@ void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash>& asBones,
void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
std::vector<aiMesh*>::const_iterator end)
{
- ai_assert(NULL != out && !out->mNumBones);
+ if ( nullptr == out || out->mNumBones == 0 ) {
+ return;
+ }
// find we need to build an unique list of all bones.
// we work with hashes to make the comparisons MUCH faster,
@@ -740,7 +735,7 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator
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.
+ // face index offset of the corresponding 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) {
@@ -754,11 +749,13 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator
// ------------------------------------------------------------------------------------------------
// Merge a list of meshes
-void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
+void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
std::vector<aiMesh*>::const_iterator begin,
std::vector<aiMesh*>::const_iterator end)
{
- ai_assert(NULL != _out);
+ if ( nullptr == _out ) {
+ return;
+ }
if (begin == end) {
*_out = NULL; // no meshes ...
@@ -769,8 +766,14 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
aiMesh* out = *_out = new aiMesh();
out->mMaterialIndex = (*begin)->mMaterialIndex;
+ std::string name;
// Find out how much output storage we'll need
- for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
+ const char *meshName( (*it)->mName.C_Str() );
+ name += std::string( meshName );
+ if ( it != end - 1 ) {
+ name += ".";
+ }
out->mNumVertices += (*it)->mNumVertices;
out->mNumFaces += (*it)->mNumFaces;
out->mNumBones += (*it)->mNumBones;
@@ -778,6 +781,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
// combine primitive type flags
out->mPrimitiveTypes |= (*it)->mPrimitiveTypes;
}
+ out->mName.Set( name.c_str() );
if (out->mNumVertices) {
aiVector3D* pv2;
@@ -786,7 +790,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
if ((**begin).HasPositions()) {
pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
- for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
if ((*it)->mVertices) {
::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D));
}
@@ -806,7 +810,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
pv2 += (*it)->mNumVertices;
}
}
- // copy tangents and bitangents
+ // copy tangents and bi-tangents
if ((**begin).HasTangentsAndBitangents()) {
pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
@@ -892,7 +896,9 @@ void SceneCombiner::MergeMaterials(aiMaterial** dest,
std::vector<aiMaterial*>::const_iterator begin,
std::vector<aiMaterial*>::const_iterator end)
{
- ai_assert(NULL != dest);
+ if ( nullptr == dest ) {
+ return;
+ }
if (begin == end) {
*dest = NULL; // no materials ...
@@ -942,24 +948,25 @@ void SceneCombiner::MergeMaterials(aiMaterial** dest,
// ------------------------------------------------------------------------------------------------
template <typename Type>
-inline void CopyPtrArray (Type**& dest, const Type* const * src, unsigned int num)
-{
- if (!num)
- {
+inline
+void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) {
+ if (!num) {
dest = NULL;
return;
}
dest = new Type*[num];
- for (unsigned int i = 0; i < num;++i) {
+ for (ai_uint 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;
+inline
+void GetArrayCopy(Type*& dest, ai_uint num ) {
+ if ( !dest ) {
+ return;
+ }
Type* old = dest;
dest = new Type[num];
@@ -967,22 +974,27 @@ inline void GetArrayCopy (Type*& dest, unsigned int num )
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src)
-{
+void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
// reuse the old scene or allocate a new?
if (*_dest) {
(*_dest)->~aiScene();
new (*_dest) aiScene();
+ } else {
+ *_dest = new aiScene();
}
- 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);
+void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
if (allocate) {
*_dest = new aiScene();
@@ -1033,9 +1045,10 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiMesh** _dest, const aiMesh* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiMesh* dest = *_dest = new aiMesh();
@@ -1061,17 +1074,17 @@ void SceneCombiner::Copy (aiMesh** _dest, const aiMesh* src)
// make a deep copy of all faces
GetArrayCopy(dest->mFaces,dest->mNumFaces);
- for (unsigned int i = 0; i < dest->mNumFaces;++i)
- {
+ 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);
+void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() );
@@ -1099,9 +1112,10 @@ void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiTexture* dest = *_dest = new aiTexture();
@@ -1128,11 +1142,11 @@ void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src )
-{
- ai_assert( NULL != _dest );
- ai_assert( NULL != src );
-
+void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
+
aiAnimation* dest = *_dest = new aiAnimation();
// get a flat copy
@@ -1143,9 +1157,10 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src )
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiNodeAnim* dest = *_dest = new aiNodeAnim();
@@ -1159,9 +1174,10 @@ void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiCamera* dest = *_dest = new aiCamera();
@@ -1170,9 +1186,10 @@ void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiLight** _dest, const aiLight* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiLight* dest = *_dest = new aiLight();
@@ -1181,9 +1198,10 @@ void SceneCombiner::Copy (aiLight** _dest, const aiLight* src)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiBone** _dest, const aiBone* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
aiBone* dest = *_dest = new aiBone();
@@ -1219,13 +1237,16 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
-{
- ai_assert(NULL != _dest && NULL != src);
+void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) {
+ if ( nullptr == _dest || nullptr == src ) {
+ return;
+ }
- aiMetadata* dest = *_dest = new aiMetadata();
- dest->mNumProperties = src->mNumProperties;
- dest->mKeys = new aiString[src->mNumProperties];
+ if ( 0 == src->mNumProperties ) {
+ return;
+ }
+
+ aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties );
std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
dest->mValues = new aiMetadataEntry[src->mNumProperties];
@@ -1237,8 +1258,8 @@ void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
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));
+ case AI_INT32:
+ out.mData = new int32_t(*static_cast<int32_t*>(in.mData));
break;
case AI_UINT64:
out.mData = new uint64_t(*static_cast<uint64_t*>(in.mData));
@@ -1246,6 +1267,9 @@ void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
case AI_FLOAT:
out.mData = new float(*static_cast<float*>(in.mData));
break;
+ case AI_DOUBLE:
+ out.mData = new double(*static_cast<double*>(in.mData));
+ break;
case AI_AISTRING:
out.mData = new aiString(*static_cast<aiString*>(in.mData));
break;
@@ -1258,4 +1282,5 @@ void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
}
}
-}
+} // Namespace Assimp
+
diff --git a/src/3rdparty/assimp/code/ScenePreprocessor.cpp b/src/3rdparty/assimp/code/ScenePreprocessor.cpp
index a38a9430e..0a6366b7d 100644
--- a/src/3rdparty/assimp/code/ScenePreprocessor.cpp
+++ b/src/3rdparty/assimp/code/ScenePreprocessor.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -176,22 +177,22 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
if (anim->mDuration == -1.) {
// Position keys
- for (unsigned int i = 0; i < channel->mNumPositionKeys;++i) {
- aiVectorKey& key = channel->mPositionKeys[i];
+ for (unsigned int j = 0; j < channel->mNumPositionKeys;++j) {
+ aiVectorKey& key = channel->mPositionKeys[j];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
// Scaling keys
- for (unsigned int i = 0; i < channel->mNumScalingKeys;++i) {
- aiVectorKey& key = channel->mScalingKeys[i];
+ for (unsigned int j = 0; j < channel->mNumScalingKeys;++j ) {
+ aiVectorKey& key = channel->mScalingKeys[j];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
// Rotation keys
- for (unsigned int i = 0; i < channel->mNumRotationKeys;++i) {
- aiQuatKey& key = channel->mRotationKeys[i];
+ for (unsigned int j = 0; j < channel->mNumRotationKeys;++j ) {
+ aiQuatKey& key = channel->mRotationKeys[ j ];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
diff --git a/src/3rdparty/assimp/code/ScenePreprocessor.h b/src/3rdparty/assimp/code/ScenePreprocessor.h
index 9c4b422a2..3311036c3 100644
--- a/src/3rdparty/assimp/code/ScenePreprocessor.h
+++ b/src/3rdparty/assimp/code/ScenePreprocessor.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ScenePrivate.h b/src/3rdparty/assimp/code/ScenePrivate.h
index dd4d0a5e1..90d34bade 100644
--- a/src/3rdparty/assimp/code/ScenePrivate.h
+++ b/src/3rdparty/assimp/code/ScenePrivate.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp b/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
index ec7aa8985..e9f427113 100644
--- a/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
+++ b/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -85,7 +86,7 @@ SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bK
void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
{
// add a joint entry for the node.
- const unsigned int vertexStartIndex = mVertices.size();
+ const unsigned int vertexStartIndex = static_cast<unsigned int>(mVertices.size());
// now build the geometry.
if( pNode->mNumChildren > 0 && !mKnobsOnly)
@@ -96,31 +97,31 @@ void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
// 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)
+ ai_real distanceToChild = childpos.Length();
+ if( distanceToChild < 0.0001)
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 orth( 1.0, 0.0, 0.0);
+ if( std::fabs( orth * up) > 0.99)
+ orth.Set( 0.0, 1.0, 0.0);
aiVector3D front = (up ^ orth).Normalize();
aiVector3D side = (front ^ up).Normalize();
- unsigned int localVertexStart = mVertices.size();
- mVertices.push_back( -front * distanceToChild * 0.1f);
+ unsigned int localVertexStart = static_cast<unsigned int>(mVertices.size());
+ mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
mVertices.push_back( childpos);
- mVertices.push_back( -side * distanceToChild * 0.1f);
- mVertices.push_back( -side * distanceToChild * 0.1f);
+ mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
mVertices.push_back( childpos);
- mVertices.push_back( front * distanceToChild * 0.1f);
- mVertices.push_back( front * distanceToChild * 0.1f);
+ mVertices.push_back( front * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( front * distanceToChild * (ai_real)0.1);
mVertices.push_back( childpos);
- mVertices.push_back( side * distanceToChild * 0.1f);
- mVertices.push_back( side * distanceToChild * 0.1f);
+ mVertices.push_back( side * distanceToChild * (ai_real)0.1);
+ mVertices.push_back( side * distanceToChild * (ai_real)0.1);
mVertices.push_back( childpos);
- mVertices.push_back( -front * distanceToChild * 0.1f);
+ mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
@@ -132,33 +133,33 @@ void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
{
// 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));
+ ai_real sizeEstimate = ownpos.Length() * ai_real( 0.18 );
+
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
+
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
+ mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
@@ -170,7 +171,7 @@ void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
}
- unsigned int numVertices = mVertices.size() - vertexStartIndex;
+ unsigned int numVertices = static_cast<unsigned int>(mVertices.size() - vertexStartIndex);
if( numVertices > 0)
{
// create a bone affecting all the newly created vertices
@@ -187,7 +188,7 @@ void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
bone->mNumWeights = numVertices;
bone->mWeights = new aiVertexWeight[numVertices];
for( unsigned int a = 0; a < numVertices; a++)
- bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0f);
+ bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0);
// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
// them to the array, but I'm tired now and I'm annoyed.
@@ -208,14 +209,14 @@ aiMesh* SkeletonMeshBuilder::CreateMesh()
aiMesh* mesh = new aiMesh();
// add points
- mesh->mNumVertices = mVertices.size();
+ mesh->mNumVertices = static_cast<unsigned int>(mVertices.size());
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices);
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
// add faces
- mesh->mNumFaces = mFaces.size();
+ mesh->mNumFaces = static_cast<unsigned int>(mFaces.size());
mesh->mFaces = new aiFace[mesh->mNumFaces];
for( unsigned int a = 0; a < mesh->mNumFaces; a++)
{
@@ -232,15 +233,15 @@ aiMesh* SkeletonMeshBuilder::CreateMesh()
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);
+ if (nor.Length() < 1e-5) /* ensure that FindInvalidData won't remove us ...*/
+ nor = aiVector3D(1.0,0.0,0.0);
for (unsigned int n = 0; n < 3; ++n)
mesh->mNormals[inface.mIndices[n]] = nor;
}
// add the bones
- mesh->mNumBones = mBones.size();
+ mesh->mNumBones = static_cast<unsigned int>(mBones.size());
mesh->mBones = new aiBone*[mesh->mNumBones];
std::copy( mBones.begin(), mBones.end(), mesh->mBones);
diff --git a/src/3rdparty/assimp/code/SkeletonMeshBuilder.h b/src/3rdparty/assimp/code/SkeletonMeshBuilder.h
index 3c518e8cd..7a7e7b8ff 100644
--- a/src/3rdparty/assimp/code/SkeletonMeshBuilder.h
+++ b/src/3rdparty/assimp/code/SkeletonMeshBuilder.h
@@ -4,7 +4,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SmoothingGroups.h b/src/3rdparty/assimp/code/SmoothingGroups.h
index 75c59d1cb..7a7e2e429 100644
--- a/src/3rdparty/assimp/code/SmoothingGroups.h
+++ b/src/3rdparty/assimp/code/SmoothingGroups.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SortByPTypeProcess.cpp b/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
index 74867184a..e4b314e02 100644
--- a/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
+++ b/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/SortByPTypeProcess.h b/src/3rdparty/assimp/code/SortByPTypeProcess.h
index f96985cb3..0be7925ff 100644
--- a/src/3rdparty/assimp/code/SortByPTypeProcess.h
+++ b/src/3rdparty/assimp/code/SortByPTypeProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SpatialSort.cpp b/src/3rdparty/assimp/code/SpatialSort.cpp
index c4e4ef2d5..35724c2cd 100644
--- a/src/3rdparty/assimp/code/SpatialSort.cpp
+++ b/src/3rdparty/assimp/code/SpatialSort.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -107,8 +108,8 @@ void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositio
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));
+ ai_real distance = *vec * mPlaneNormal;
+ mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
}
if (pFinalize) {
@@ -120,14 +121,13 @@ void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositio
// ------------------------------------------------------------------------------------------------
// 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
+ ai_real pRadius, std::vector<unsigned int>& poResults) const
{
- const float dist = pPosition * mPlaneNormal;
- const float minDist = dist - pRadius, maxDist = dist + pRadius;
+ const ai_real dist = pPosition * mPlaneNormal;
+ const ai_real 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());
+ // clear the array
+ poResults.clear();
// quick check for positions outside the range
if( mPositions.size() == 0)
@@ -160,7 +160,7 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
// 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;
+ const ai_real pSquared = pRadius*pRadius;
while( it->mDistance < maxDist)
{
if( (it->mPosition - pPosition).SquareLength() < pSquared)
@@ -182,23 +182,23 @@ namespace {
// 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;
+ typedef ai_int BinFloat;
// --------------------------------------------------------------------------------------------
// Converts the bit pattern of a floating-point number to its signed integer representation.
- BinFloat ToBinary( const float & pValue) {
+ BinFloat ToBinary( const ai_real & pValue) {
// If this assertion fails, signed int is not big enough to store a float on your platform.
// Please correct the declaration of BinFloat a few lines above - but do it in a portable,
// #ifdef'd manner!
- static_assert( sizeof(BinFloat) >= sizeof(float), "sizeof(BinFloat) >= sizeof(float)");
+ static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
#if defined( _MSC_VER)
// If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
// code has just become legacy code! Find out the current value of _MSC_VER and modify
// the #if above so it evaluates false on the current and all upcoming VC versions (or
// on the current platform, if LP64 or LLP64 are still used on other platforms).
- static_assert( sizeof(BinFloat) == sizeof(float), "sizeof(BinFloat) == sizeof(float)");
+ static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
// This works best on Visual C++, but other compilers have their problems with it.
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
@@ -206,7 +206,7 @@ namespace {
// 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;
+ ai_real asFloat;
BinFloat asBin;
} conversion;
conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
@@ -245,7 +245,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
// 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.
+ // 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
@@ -269,7 +269,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
// 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());
+ poResults.resize( 0 );
// do a binary search for the minimal distance to start the iteration there
unsigned int index = (unsigned int)mPositions.size() / 2;
@@ -308,13 +308,13 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
}
// ------------------------------------------------------------------------------------------------
-unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,float pRadius) const
+unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
{
fill.resize(mPositions.size(),UINT_MAX);
- float dist, maxDist;
+ ai_real dist, maxDist;
unsigned int t=0;
- const float pSquared = pRadius*pRadius;
+ const ai_real pSquared = pRadius*pRadius;
for (size_t i = 0; i < mPositions.size();) {
dist = mPositions[i].mPosition * mPlaneNormal;
maxDist = dist + pRadius;
@@ -339,4 +339,3 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,f
#endif
return t;
}
-
diff --git a/src/3rdparty/assimp/code/SpatialSort.h b/src/3rdparty/assimp/code/SpatialSort.h
index b594fc6d1..36b7a2767 100644
--- a/src/3rdparty/assimp/code/SpatialSort.h
+++ b/src/3rdparty/assimp/code/SpatialSort.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -117,7 +118,7 @@ public:
* @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,
+ void FindPositions( const aiVector3D& pPosition, ai_real pRadius,
std::vector<unsigned int>& poResults) const;
// ------------------------------------------------------------------------------------
@@ -139,7 +140,7 @@ public:
* be counted in.
* @return Number of unique vertices (n). */
unsigned int GenerateMappingTable(std::vector<unsigned int>& fill,
- float pRadius) const;
+ ai_real pRadius) const;
protected:
/** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
@@ -151,10 +152,10 @@ protected:
{
unsigned int mIndex; ///< The vertex referred by this entry
aiVector3D mPosition; ///< Position
- float mDistance; ///< Distance of this vertex to the sorting plane
+ ai_real mDistance; ///< Distance of this vertex to the sorting plane
Entry() { /** intentionally not initialized.*/ }
- Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance)
+ Entry( unsigned int pIndex, const aiVector3D& pPosition, ai_real pDistance)
: mIndex( pIndex), mPosition( pPosition), mDistance( pDistance)
{ }
diff --git a/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp b/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp
index 58b14ff49..a73dfe81e 100644
--- a/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp
+++ b/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -57,7 +58,7 @@ using namespace Assimp::Formatter;
// Constructor
SplitByBoneCountProcess::SplitByBoneCountProcess()
{
- // set default, might be overriden by importer config
+ // set default, might be overridden by importer config
mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
}
diff --git a/src/3rdparty/assimp/code/SplitByBoneCountProcess.h b/src/3rdparty/assimp/code/SplitByBoneCountProcess.h
index 816d18357..434ef9866 100644
--- a/src/3rdparty/assimp/code/SplitByBoneCountProcess.h
+++ b/src/3rdparty/assimp/code/SplitByBoneCountProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SplitLargeMeshes.cpp b/src/3rdparty/assimp/code/SplitLargeMeshes.cpp
index 5e21ec6b8..2066f7989 100644
--- a/src/3rdparty/assimp/code/SplitLargeMeshes.cpp
+++ b/src/3rdparty/assimp/code/SplitLargeMeshes.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/SplitLargeMeshes.h b/src/3rdparty/assimp/code/SplitLargeMeshes.h
index 9be27a8f1..7556e9fe8 100644
--- a/src/3rdparty/assimp/code/SplitLargeMeshes.h
+++ b/src/3rdparty/assimp/code/SplitLargeMeshes.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/StandardShapes.cpp b/src/3rdparty/assimp/code/StandardShapes.cpp
index d547c04a7..4346a8d76 100644
--- a/src/3rdparty/assimp/code/StandardShapes.cpp
+++ b/src/3rdparty/assimp/code/StandardShapes.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -47,8 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StandardShapes.h"
#include "StringComparison.h"
-#include "Defines.h"
#include <stddef.h>
+#include <assimp/Defines.h>
#include <assimp/mesh.h>
namespace Assimp {
@@ -95,7 +96,7 @@ namespace Assimp {
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();
+ const ai_real fl1 = positions[0].Length();
unsigned int origSize = (unsigned int)positions.size();
for (unsigned int i = 0 ; i < origSize ; i+=3)
@@ -121,8 +122,7 @@ void Subdivide(std::vector<aiVector3D>& positions)
aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
unsigned int numIndices)
{
- if (positions.size() & numIndices || positions.empty() || !numIndices)
- return NULL;
+ if (positions.empty() || !numIndices) return NULL;
// Determine which kinds of primitives the mesh consists of
aiMesh* out = new aiMesh();
@@ -194,21 +194,21 @@ 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 = 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;
+ const ai_real t = ( ai_real( 1.0 )+ ai_real( 2.236067977 ) ) / ai_real( 2.0 );
+ const ai_real s = std::sqrt(ai_real(1.0) + t*t);
+
+ const aiVector3D v0 = aiVector3D(t,1.0, 0.0)/s;
+ const aiVector3D v1 = aiVector3D(-t,1.0, 0.0)/s;
+ const aiVector3D v2 = aiVector3D(t,-1.0, 0.0)/s;
+ const aiVector3D v3 = aiVector3D(-t,-1.0, 0.0)/s;
+ const aiVector3D v4 = aiVector3D(1.0, 0.0, t)/s;
+ const aiVector3D v5 = aiVector3D(1.0, 0.0,-t)/s;
+ const aiVector3D v6 = aiVector3D(-1.0, 0.0,t)/s;
+ const aiVector3D v7 = aiVector3D(-1.0, 0.0,-t)/s;
+ const aiVector3D v8 = aiVector3D(0.0, t, 1.0)/s;
+ const aiVector3D v9 = aiVector3D(0.0,-t, 1.0)/s;
+ const aiVector3D v10 = aiVector3D(0.0, t,-1.0)/s;
+ const aiVector3D v11 = aiVector3D(0.0,-t,-1.0)/s;
ADD_TRIANGLE(v0,v8,v4);
ADD_TRIANGLE(v0,v5,v10);
@@ -244,9 +244,9 @@ unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions
{
positions.reserve(positions.size()+108);
- 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 ai_real a = ai_real( 1.0 ) / ai_real(1.7320508);
+ const ai_real b = std::sqrt(( ai_real( 3.0 )- ai_real( 2.23606797))/ ai_real( 6.0) );
+ const ai_real c = std::sqrt(( ai_real( 3.0 )+ ai_real( 2.23606797f))/ ai_real( 6.0) );
const aiVector3D v0 = aiVector3D(a,a,a);
const aiVector3D v1 = aiVector3D(a,a,-a);
@@ -256,18 +256,18 @@ unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions
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);
+ const aiVector3D v8 = aiVector3D(b,c,0.0);
+ const aiVector3D v9 = aiVector3D(-b,c,0.0);
+ const aiVector3D v10 = aiVector3D(b,-c,0.0);
+ const aiVector3D v11 = aiVector3D(-b,-c,0.0);
+ const aiVector3D v12 = aiVector3D(c, 0.0, b);
+ const aiVector3D v13 = aiVector3D(c, 0.0, -b);
+ const aiVector3D v14 = aiVector3D(-c, 0.0, b);
+ const aiVector3D v15 = aiVector3D(-c, 0.0, -b);
+ const aiVector3D v16 = aiVector3D(0.0, b, c);
+ const aiVector3D v17 = aiVector3D(0.0, -b, c);
+ const aiVector3D v18 = aiVector3D(0.0, b, -c);
+ const aiVector3D v19 = aiVector3D(0.0, -b, -c);
ADD_PENTAGON(v0, v8, v9, v4, v16);
ADD_PENTAGON(v0, v12, v13, v1, v8);
@@ -291,12 +291,12 @@ 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);
+ const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0) ;
+ const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0);
+ const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0);
+ const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0);
+ const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0);
+ const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0);
ADD_TRIANGLE(v4,v0,v2);
ADD_TRIANGLE(v4,v2,v1);
@@ -316,13 +316,14 @@ unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
{
positions.reserve(positions.size()+9);
- const float a = 1.41421f/3.f;
- const float b = 2.4494f/3.f;
+ const ai_real invThree = ai_real( 1.0 ) / ai_real( 3.0 );
+ const ai_real a = ai_real( 1.41421 ) * invThree;
+ const ai_real b = ai_real( 2.4494 ) * invThree;
- const aiVector3D v0 = aiVector3D(0.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.0,0.0,1.0);
+ const aiVector3D v1 = aiVector3D(2*a,0,-invThree );
+ const aiVector3D v2 = aiVector3D(-a,b,-invThree );
+ const aiVector3D v3 = aiVector3D(-a,-b,-invThree );
ADD_TRIANGLE(v0,v1,v2);
ADD_TRIANGLE(v0,v2,v3);
@@ -337,16 +338,16 @@ unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
bool polygons /*= false*/)
{
positions.reserve(positions.size()+36);
- const float length = 1.f/1.73205080f;
+ const ai_real length = ai_real(1.0)/ai_real(1.73205080);
- 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;
+ const aiVector3D v0 = aiVector3D(-1.0,-1.0,-1.0)*length;
+ const aiVector3D v1 = aiVector3D(1.0,-1.0,-1.0)*length;
+ const aiVector3D v2 = aiVector3D(1.0,1.0,-1.0)*length;
+ const aiVector3D v3 = aiVector3D(-1.0,1.0,-1.0)*length;
+ const aiVector3D v4 = aiVector3D(-1.0,-1.0,1.0)*length;
+ const aiVector3D v5 = aiVector3D(1.0,-1.0,1.0)*length;
+ const aiVector3D v6 = aiVector3D(1.0,1.0,1.0)*length;
+ const aiVector3D v7 = aiVector3D(-1.0,1.0,1.0)*length;
ADD_QUAD(v0,v3,v2,v1);
ADD_QUAD(v0,v1,v5,v4);
@@ -382,8 +383,8 @@ void StandardShapes::MakeSphere(unsigned int tess,
// ------------------------------------------------------------------------------------------------
// Build a cone
-void StandardShapes::MakeCone(float height,float radius1,
- float radius2,unsigned int tess,
+void StandardShapes::MakeCone(ai_real height,ai_real radius1,
+ ai_real radius2,unsigned int tess,
std::vector<aiVector3D>& positions,bool bOpen /*= false */)
{
// Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE
@@ -396,7 +397,7 @@ void StandardShapes::MakeCone(float height,float radius1,
radius1 = std::fabs(radius1);
radius2 = std::fabs(radius2);
- float halfHeight = height / 2;
+ ai_real halfHeight = height / ai_real(2.0);
// radius1 is always the smaller one
if (radius2 > radius1)
@@ -407,7 +408,7 @@ void StandardShapes::MakeCone(float height,float radius1,
else old = SIZE_MAX;
// Use a large epsilon to check whether the cone is pointy
- if (radius1 < (radius2-radius1)*10e-3f)radius1 = 0.f;
+ if (radius1 < (radius2-radius1)*10e-3)radius1 = 0.0;
// We will need 3*2 verts per segment + 3*2 verts per segment
// if the cone is closed
@@ -415,20 +416,20 @@ void StandardShapes::MakeCone(float height,float radius1,
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;
+ const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
+ const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
- float s = 1.f; // std::cos(angle == 0);
- float t = 0.f; // std::sin(angle == 0);
+ ai_real s = 1.0; // std::cos(angle == 0);
+ ai_real t = 0.0; // std::sin(angle == 0);
- for (float angle = 0.f; angle < angle_max; )
+ for (ai_real angle = 0.0; angle < angle_max; )
{
const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
- const float next = angle + angle_delta;
- float s2 = std::cos(next);
- float t2 = std::sin(next);
+ const ai_real next = angle + angle_delta;
+ ai_real s2 = std::cos(next);
+ ai_real t2 = std::sin(next);
const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 );
const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 );
@@ -445,7 +446,7 @@ void StandardShapes::MakeCone(float height,float radius1,
// 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));
+ positions.push_back(aiVector3D(0.0, halfHeight, 0.0));
if (radius1)
@@ -453,7 +454,7 @@ void StandardShapes::MakeCone(float height,float 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));
+ positions.push_back(aiVector3D(0.0, -halfHeight, 0.0));
}
}
@@ -472,7 +473,7 @@ void StandardShapes::MakeCone(float height,float radius1,
// ------------------------------------------------------------------------------------------------
// Build a circle
-void StandardShapes::MakeCircle(float radius, unsigned int tess,
+void StandardShapes::MakeCircle(ai_real radius, unsigned int tess,
std::vector<aiVector3D>& positions)
{
// Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE
@@ -484,21 +485,21 @@ void StandardShapes::MakeCircle(float radius, unsigned int tess,
// 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 ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
+ const ai_real angle_max = (ai_real)AI_MATH_TWO_PI;
- float s = 1.f; // std::cos(angle == 0);
- float t = 0.f; // std::sin(angle == 0);
+ ai_real s = 1.0; // std::cos(angle == 0);
+ ai_real t = 0.0; // std::sin(angle == 0);
- for (float angle = 0.f; angle < angle_max; )
+ for (ai_real angle = 0.0; angle < angle_max; )
{
- positions.push_back(aiVector3D(s * radius,0.f,t * radius));
+ positions.push_back(aiVector3D(s * radius,0.0,t * radius));
angle += angle_delta;
s = std::cos(angle);
t = std::sin(angle);
- positions.push_back(aiVector3D(s * radius,0.f,t * radius));
+ positions.push_back(aiVector3D(s * radius,0.0,t * radius));
- positions.push_back(aiVector3D(0.f,0.f,0.f));
+ positions.push_back(aiVector3D(0.0,0.0,0.0));
}
}
diff --git a/src/3rdparty/assimp/code/StandardShapes.h b/src/3rdparty/assimp/code/StandardShapes.h
index ec53ca30d..a31de566c 100644
--- a/src/3rdparty/assimp/code/StandardShapes.h
+++ b/src/3rdparty/assimp/code/StandardShapes.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -174,8 +175,8 @@ public:
* no 'end caps'
* @param positions Receives output triangles
*/
- static void MakeCone(float height,float radius1,
- float radius2,unsigned int tess,
+ static void MakeCone(ai_real height,ai_real radius1,
+ ai_real radius2,unsigned int tess,
std::vector<aiVector3D>& positions,bool bOpen= false);
@@ -189,7 +190,7 @@ public:
* @param tess Number of segments.
* @param positions Receives output triangles.
*/
- static void MakeCircle(float radius, unsigned int tess,
+ static void MakeCircle(ai_real radius, unsigned int tess,
std::vector<aiVector3D>& positions);
};
diff --git a/src/3rdparty/assimp/code/StdOStreamLogStream.h b/src/3rdparty/assimp/code/StdOStreamLogStream.h
index 20482fef7..d9993b246 100644
--- a/src/3rdparty/assimp/code/StdOStreamLogStream.h
+++ b/src/3rdparty/assimp/code/StdOStreamLogStream.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -38,6 +39,11 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
+
+/** @file StdOStreamLogStream.h
+* @brief Implementation of StdOStreamLogStream
+*/
+
#ifndef AI_STROSTREAMLOGSTREAM_H_INC
#define AI_STROSTREAMLOGSTREAM_H_INC
@@ -50,8 +56,7 @@ namespace Assimp {
/** @class StdOStreamLogStream
* @brief Logs into a std::ostream
*/
-class StdOStreamLogStream : public LogStream
-{
+class StdOStreamLogStream : public LogStream {
public:
/** @brief Construction from an existing std::ostream
* @param _ostream Output stream to be used
@@ -63,30 +68,33 @@ public:
/** @brief Writer */
void write(const char* message);
+
private:
- std::ostream& ostream;
+ std::ostream& mOstream;
};
// ---------------------------------------------------------------------------
// Default constructor
inline StdOStreamLogStream::StdOStreamLogStream(std::ostream& _ostream)
- : ostream (_ostream)
-{}
+: mOstream (_ostream){
+ // empty
+}
// ---------------------------------------------------------------------------
// Default constructor
-inline StdOStreamLogStream::~StdOStreamLogStream()
-{}
+inline StdOStreamLogStream::~StdOStreamLogStream() {
+ // empty
+}
// ---------------------------------------------------------------------------
// Write method
-inline void StdOStreamLogStream::write(const char* message)
-{
- ostream << message;
- ostream.flush();
+inline void StdOStreamLogStream::write(const char* message) {
+ mOstream << message;
+ mOstream.flush();
}
// ---------------------------------------------------------------------------
+
} // Namespace Assimp
#endif // guard
diff --git a/src/3rdparty/assimp/code/StepExporter.cpp b/src/3rdparty/assimp/code/StepExporter.cpp
index eb84ac594..acf1b6dad 100644
--- a/src/3rdparty/assimp/code/StepExporter.cpp
+++ b/src/3rdparty/assimp/code/StepExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,13 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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 <assimp/SceneCombiner.h>
#include <iostream>
#include <ctime>
#include <set>
@@ -56,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <list>
#include <memory>
#include "Exceptional.h"
+#include <assimp/DefaultIOSystem.h>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/light.h>
diff --git a/src/3rdparty/assimp/code/StepExporter.h b/src/3rdparty/assimp/code/StepExporter.h
index b51280c6c..e5cdda7a1 100644
--- a/src/3rdparty/assimp/code/StepExporter.h
+++ b/src/3rdparty/assimp/code/StepExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/StreamReader.h b/src/3rdparty/assimp/code/StreamReader.h
index 244ad9784..6220de9a8 100644
--- a/src/3rdparty/assimp/code/StreamReader.h
+++ b/src/3rdparty/assimp/code/StreamReader.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -40,7 +41,8 @@ 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 endianness. */
+ * a binary stream with a well-defined endianness.
+ */
#ifndef AI_STREAMREADER_H_INCLUDED
#define AI_STREAMREADER_H_INCLUDED
@@ -49,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Exceptional.h"
#include <memory>
#include <assimp/IOStream.hpp>
-#include "Defines.h"
+#include <assimp/Defines.h>
namespace Assimp {
@@ -66,9 +68,7 @@ namespace Assimp {
template <bool SwapEndianess = false, bool RuntimeSwitch = false>
class StreamReader
{
-
public:
-
// FIXME: use these data types throughout the whole library,
// then change them to 64 bit values :-)
@@ -76,8 +76,6 @@ public:
typedef unsigned int pos;
public:
-
-
// ---------------------------------------------------------------------
/** Construction from a given stream with a well-defined endianness.
*
@@ -178,14 +176,12 @@ public:
}
public:
-
// ---------------------------------------------------------------------
- /** Get the remaining stream size (to the end of the srream) */
+ /** Get the remaining stream size (to the end of the stream) */
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
@@ -194,7 +190,6 @@ public:
return (unsigned int)(limit - current);
}
-
// ---------------------------------------------------------------------
/** Increase the file pointer (relative seeking) */
void IncPtr(size_t plus) {
@@ -210,7 +205,6 @@ public:
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
@@ -218,7 +212,6 @@ public:
* @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");
@@ -230,14 +223,12 @@ public:
* @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);
+ ::memcpy(out,ur,bytes);
}
-
// ---------------------------------------------------------------------
/** Get the current offset from the beginning of the file */
int GetCurrentPos() const {
@@ -253,7 +244,7 @@ public:
*
* @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.
+ * 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();
@@ -271,14 +262,14 @@ public:
// ---------------------------------------------------------------------
/** Get the current read limit in bytes. Reading over this limit
- * accidentially raises an exception. */
+ * accidentally 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. */
+ * accidentally raises an exception. */
void SkipToReadLimit() {
current = limit;
}
@@ -292,31 +283,26 @@ public:
}
private:
-
// ---------------------------------------------------------------------
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
template <typename T>
T Get() {
- if (current + sizeof(T) > limit) {
+ if ( current + sizeof(T) > limit) {
throw DeadlyImportError("End of file or stream limit was reached");
}
-#ifdef __arm__
T f;
- memcpy (&f, current, sizeof(T));
-#else
- T f = *((const T*)current);
-#endif
- Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
-
+ ::memcpy (&f, current, sizeof(T));
+ Intern::Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
current += sizeof(T);
+
return f;
}
// ---------------------------------------------------------------------
void InternBegin() {
if (!stream) {
- // incase someone wonders: StreamReader is frequently invoked with
+ // in case 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'
@@ -337,14 +323,11 @@ private:
}
private:
-
-
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
diff --git a/src/3rdparty/assimp/code/StreamWriter.h b/src/3rdparty/assimp/code/StreamWriter.h
index 12239bf7f..26873fb5b 100644
--- a/src/3rdparty/assimp/code/StreamWriter.h
+++ b/src/3rdparty/assimp/code/StreamWriter.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/StringComparison.h b/src/3rdparty/assimp/code/StringComparison.h
index 0e1dbe4b8..ed5f4bd6a 100644
--- a/src/3rdparty/assimp/code/StringComparison.h
+++ b/src/3rdparty/assimp/code/StringComparison.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -56,7 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include <stdint.h>
#include <string>
-#include <cctype>
namespace Assimp {
diff --git a/src/3rdparty/assimp/code/StringUtils.h b/src/3rdparty/assimp/code/StringUtils.h
index 99352ebfb..64f66e6b9 100644
--- a/src/3rdparty/assimp/code/StringUtils.h
+++ b/src/3rdparty/assimp/code/StringUtils.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -40,11 +41,9 @@ 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>
+#include <stdarg.h>
+#include <cstdlib>
/// @fn ai_snprintf
/// @brief The portable version of the function snprintf ( C99 standard ), which works on visual studio compilers 2013 and earlier.
@@ -103,7 +102,7 @@ float ai_strtof( const char *begin, const char *end ) {
std::string token( begin, len );
val = static_cast< float >( ::atof( token.c_str() ) );
}
-
+
return val;
}
diff --git a/src/3rdparty/assimp/code/Subdivision.cpp b/src/3rdparty/assimp/code/Subdivision.cpp
index 012c70047..bc5292dbe 100644
--- a/src/3rdparty/assimp/code/Subdivision.cpp
+++ b/src/3rdparty/assimp/code/Subdivision.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -39,10 +40,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Subdivision.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
#include "SpatialSort.h"
#include "ProcessHelper.h"
#include "Vertex.h"
+#include <assimp/ai_assert.h>
#include <stdio.h>
using namespace Assimp;
@@ -55,9 +57,7 @@ void mydummy() {}
// ------------------------------------------------------------------------------------------------
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);
@@ -74,8 +74,6 @@ public:
unsigned int ref;
};
-
-
typedef std::vector<unsigned int> UIntVector;
typedef std::map<uint64_t,Edge> EdgeMap;
@@ -99,7 +97,6 @@ public:
unsigned int eh_tmp0__, eh_tmp1__;
private:
-
void InternSubdivide (const aiMesh* const * smesh,
size_t nmesh,aiMesh** out, unsigned int num);
};
@@ -128,7 +125,8 @@ void CatmullClarkSubdivider::Subdivide (
bool discard_input
)
{
- assert(mesh != out);
+ ai_assert(mesh != out);
+
Subdivide(&mesh,1,&out,num,discard_input);
}
@@ -142,12 +140,12 @@ void CatmullClarkSubdivider::Subdivide (
bool discard_input
)
{
- ai_assert(NULL != smesh && NULL != out);
+ ai_assert( NULL != smesh );
+ ai_assert( NULL != out );
// course, both regions may not overlap
- assert(smesh<out || smesh+nmesh>out+nmesh);
+ ai_assert(smesh<out || smesh+nmesh>out+nmesh);
if (!num) {
-
// No subdivision at all. Need to copy all the meshes .. argh.
if (discard_input) {
for (size_t s = 0; s < nmesh; ++s) {
@@ -191,7 +189,7 @@ void CatmullClarkSubdivider::Subdivide (
}
outmeshes.push_back(NULL);inmeshes.push_back(i);
- maptbl.push_back(s);
+ maptbl.push_back(static_cast<unsigned int>(s));
}
// Do the actual subdivision on the preallocated storage. InternSubdivide
@@ -535,9 +533,7 @@ void CatmullClarkSubdivider::InternSubdivide (
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) {
@@ -558,15 +554,16 @@ void CatmullClarkSubdivider::InternSubdivide (
// 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);
+ if ( !haveit ) {
+ DefaultLogger::get()->warn( "OBJ: no name for material library specified." );
+ }
}
const float div = static_cast<float>(cnt), divsq = 1.f/(div*div);
diff --git a/src/3rdparty/assimp/code/Subdivision.h b/src/3rdparty/assimp/code/Subdivision.h
index 658640f55..d06bc09d6 100644
--- a/src/3rdparty/assimp/code/Subdivision.h
+++ b/src/3rdparty/assimp/code/Subdivision.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -39,10 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file Defines a helper class to evaluate subdivision surfaces.*/
+#pragma once
#ifndef AI_SUBDISIVION_H_INC
#define AI_SUBDISIVION_H_INC
#include <cstddef>
+#include <assimp/types.h>
+
struct aiMesh;
namespace Assimp {
@@ -51,8 +55,7 @@ namespace Assimp {
/** Helper class to evaluate subdivision surfaces. Different algorithms
* are provided for choice. */
// ------------------------------------------------------------------------------
-class Subdivider
-{
+class ASSIMP_API Subdivider {
public:
/** Enumerates all supported subvidision algorithms */
@@ -60,12 +63,7 @@ public:
CATMULL_CLARKE = 0x1
};
-public:
-
- virtual ~Subdivider() {
- }
-
-public:
+ virtual ~Subdivider();
// ---------------------------------------------------------------
/** Create a subdivider of a specific type
@@ -118,9 +116,13 @@ public:
unsigned int num,
bool discard_input = false) = 0;
-private:
};
+inline
+Subdivider::~Subdivider() {
+ // empty
+}
+
} // end namespace Assimp
diff --git a/src/3rdparty/assimp/code/TargetAnimation.cpp b/src/3rdparty/assimp/code/TargetAnimation.cpp
index a78f66bea..ab6b3d12f 100644
--- a/src/3rdparty/assimp/code/TargetAnimation.cpp
+++ b/src/3rdparty/assimp/code/TargetAnimation.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -83,7 +84,7 @@ KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos,
// ------------------------------------------------------------------------------------------------
template <class T>
-inline T Interpolate(const T& one, const T& two, float val)
+inline T Interpolate(const T& one, const T& two, ai_real val)
{
return one + (two-one)*val;
}
@@ -100,8 +101,8 @@ void KeyIterator::operator ++()
// 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;
+ d0 = objPos->at ( std::min ( nextObjPos, static_cast<unsigned int>(objPos->size()-1)) ).mTime;
+ d1 = targetObjPos->at( std::min ( nextTargetObjPos, static_cast<unsigned int>(targetObjPos->size()-1)) ).mTime;
// Easiest case - all are identical. In this
// case we don't need to interpolate so we can
@@ -134,7 +135,7 @@ void KeyIterator::operator ++()
const aiVectorKey& last = targetObjPos->at(nextTargetObjPos);
const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1);
- curTargetPosition = Interpolate(first.mValue, last.mValue, (float) (
+ curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
(curTime-first.mTime) / (last.mTime-first.mTime) ));
}
@@ -155,7 +156,7 @@ void KeyIterator::operator ++()
const aiVectorKey& last = objPos->at(nextObjPos);
const aiVectorKey& first = objPos->at(nextObjPos-1);
- curPosition = Interpolate(first.mValue, last.mValue, (float) (
+ curPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
(curTime-first.mTime) / (last.mTime-first.mTime)));
}
@@ -220,7 +221,7 @@ void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
// diff vector
aiVector3D diff = tposition - position;
- float f = diff.Length();
+ ai_real f = diff.Length();
// output distance vector
if (f)
diff --git a/src/3rdparty/assimp/code/TargetAnimation.h b/src/3rdparty/assimp/code/TargetAnimation.h
index 79cef599e..21b66e591 100644
--- a/src/3rdparty/assimp/code/TargetAnimation.h
+++ b/src/3rdparty/assimp/code/TargetAnimation.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/TerragenLoader.cpp b/src/3rdparty/assimp/code/TerragenLoader.cpp
index 854959f19..0126229ac 100644
--- a/src/3rdparty/assimp/code/TerragenLoader.cpp
+++ b/src/3rdparty/assimp/code/TerragenLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -51,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
-
+#include <assimp/importerdesc.h>
using namespace Assimp;
@@ -140,9 +141,6 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
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>");
@@ -186,7 +184,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
// mapping == 1: earth radius
else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4))
{
- rad = reader.GetF4();
+ reader.GetF4();
}
// mapping mode
else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4))
diff --git a/src/3rdparty/assimp/code/TerragenLoader.h b/src/3rdparty/assimp/code/TerragenLoader.h
index c216a2186..a95bd6bff 100644
--- a/src/3rdparty/assimp/code/TerragenLoader.h
+++ b/src/3rdparty/assimp/code/TerragenLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/TextureTransform.cpp b/src/3rdparty/assimp/code/TextureTransform.cpp
index 948ec013b..30953113e 100644
--- a/src/3rdparty/assimp/code/TextureTransform.cpp
+++ b/src/3rdparty/assimp/code/TextureTransform.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -316,7 +317,7 @@ void TextureTransformStep::Execute( aiScene* pScene)
info.lockedPos = AI_TT_UV_IDX_LOCK_TBD;
}
- // Get all coresponding meshes
+ // Get all corresponding meshes
for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
aiMesh* mesh = pScene->mMeshes[n];
if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0])
diff --git a/src/3rdparty/assimp/code/TextureTransform.h b/src/3rdparty/assimp/code/TextureTransform.h
index ccad3bdd9..7f1e4572f 100644
--- a/src/3rdparty/assimp/code/TextureTransform.h
+++ b/src/3rdparty/assimp/code/TextureTransform.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/TinyFormatter.h b/src/3rdparty/assimp/code/TinyFormatter.h
index 7a5e7d21f..1612282fb 100644
--- a/src/3rdparty/assimp/code/TinyFormatter.h
+++ b/src/3rdparty/assimp/code/TinyFormatter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
namespace Assimp {
- namespace Formatter {
+namespace Formatter {
// ------------------------------------------------------------------------------------------------
/** stringstream utility. Usage:
@@ -160,4 +161,5 @@ typedef basic_formatter< wchar_t > wformat;
} // ! namespace Formatter
} // ! namespace Assimp
+
#endif
diff --git a/src/3rdparty/assimp/code/TriangulateProcess.cpp b/src/3rdparty/assimp/code/TriangulateProcess.cpp
index f19f85037..e2d77a80f 100644
--- a/src/3rdparty/assimp/code/TriangulateProcess.cpp
+++ b/src/3rdparty/assimp/code/TriangulateProcess.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -57,9 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* - dump all polygons and their triangulation sequences to
* a file
*/
-
-
-
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
#include "TriangulateProcess.h"
#include "ProcessHelper.h"
@@ -106,11 +104,15 @@ void TriangulateProcess::Execute( aiScene* pScene)
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
{
- if( TriangulateMesh( pScene->mMeshes[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." );
}
- if (bHas)DefaultLogger::get()->info ("TriangulateProcess finished. All polygons have been triangulated.");
- else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to be done.");
}
@@ -155,7 +157,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
}
// Just another check whether aiMesh::mPrimitiveTypes is correct
- assert(numOut != pMesh->mNumFaces);
+ ai_assert(numOut != pMesh->mNumFaces);
aiVector3D* nor_out = NULL;
@@ -184,7 +186,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
aiColor4D* clr = pMesh->mColors[0];
#endif
-
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
#endif
@@ -276,7 +277,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
{
// 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
+ // triangulate by tri-fanning. 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.
@@ -325,7 +326,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
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;
@@ -404,14 +404,13 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
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.
+ // have 2 'ears'. Here's definitely something wrong ... but we don't give up yet.
//
- // Instead we're continuting with the standard trifanning algorithm which we'd
+ // Instead we're continuing with the standard tri-fanning 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! ");
#endif
diff --git a/src/3rdparty/assimp/code/TriangulateProcess.h b/src/3rdparty/assimp/code/TriangulateProcess.h
index 97b5004e1..6775eca7c 100644
--- a/src/3rdparty/assimp/code/TriangulateProcess.h
+++ b/src/3rdparty/assimp/code/TriangulateProcess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/UnrealLoader.cpp b/src/3rdparty/assimp/code/UnrealLoader.cpp
index ad839fb25..a79a2a5c5 100644
--- a/src/3rdparty/assimp/code/UnrealLoader.cpp
+++ b/src/3rdparty/assimp/code/UnrealLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -60,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include <memory>
@@ -155,7 +157,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
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);
+ std::unique_ptr<IOStream> p(pIOHandler->Open(d_path));
if (!p)
throw DeadlyImportError("UNREAL: Unable to open _d file");
StreamReaderLE d_reader(pIOHandler->Open(d_path));
@@ -201,7 +203,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
d_reader.IncPtr(1);
}
- p = pIOHandler->Open(a_path);
+ p.reset(pIOHandler->Open(a_path));
if (!p)
throw DeadlyImportError("UNREAL: Unable to open _a file");
StreamReaderLE a_reader(pIOHandler->Open(a_path));
@@ -333,7 +335,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
if (nt == materials.end()) {
// add material
- tri.matIndex = materials.size();
+ tri.matIndex = static_cast<unsigned int>(materials.size());
mat.numFaces = 1;
materials.push_back(mat);
diff --git a/src/3rdparty/assimp/code/UnrealLoader.h b/src/3rdparty/assimp/code/UnrealLoader.h
index 93648ca82..a2ceb3d54 100644
--- a/src/3rdparty/assimp/code/UnrealLoader.h
+++ b/src/3rdparty/assimp/code/UnrealLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/ValidateDataStructure.cpp b/src/3rdparty/assimp/code/ValidateDataStructure.cpp
index 48647f344..c036eac18 100644
--- a/src/3rdparty/assimp/code/ValidateDataStructure.cpp
+++ b/src/3rdparty/assimp/code/ValidateDataStructure.cpp
@@ -1,9 +1,10 @@
-/*
+/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -88,9 +89,7 @@ AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...)
ai_assert(iLen > 0);
va_end(args);
-#ifdef ASSIMP_BUILD_DEBUG
- ai_assert( false );
-#endif
+
throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen));
}
// ------------------------------------------------------------------------------------------------
@@ -335,28 +334,28 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
case 1:
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT))
{
- ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes "
+ ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes "
"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 "
+ ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes "
"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 "
+ ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes "
"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 "
+ this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes "
"does not report the POLYGON flag",i);
}
break;
@@ -408,11 +407,12 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
// 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]])
+ /*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) &&
+ 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;
}
}
@@ -719,7 +719,7 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
}
// make some more specific tests
- float fTemp;
+ ai_real fTemp;
int iShading;
if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) {
switch ((aiShadingMode)iShading)
@@ -741,7 +741,7 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
};
}
- if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01f)) {
+ if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) {
ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)");
}
diff --git a/src/3rdparty/assimp/code/ValidateDataStructure.h b/src/3rdparty/assimp/code/ValidateDataStructure.h
index 87f158b37..084a2b083 100644
--- a/src/3rdparty/assimp/code/ValidateDataStructure.h
+++ b/src/3rdparty/assimp/code/ValidateDataStructure.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -90,7 +91,7 @@ protected:
// -------------------------------------------------------------------
/** Report a validation warning. This won't throw an exception,
- * control will return to the callera.
+ * control will return to the caller.
* @param msg Format string for sprintf().*/
void ReportWarning(const char* msg,...);
@@ -164,7 +165,7 @@ private:
inline void DoValidation(T** array, unsigned int size,
const char* firstName, const char* secondName);
- // extended version: checks whethr T::mName occurs twice
+ // extended version: checks whether T::mName occurs twice
template <typename T>
inline void DoValidationEx(T** array, unsigned int size,
const char* firstName, const char* secondName);
diff --git a/src/3rdparty/assimp/code/Version.cpp b/src/3rdparty/assimp/code/Version.cpp
index 42862baac..fe9a2fdaa 100644
--- a/src/3rdparty/assimp/code/Version.cpp
+++ b/src/3rdparty/assimp/code/Version.cpp
@@ -2,22 +2,29 @@
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+
+Copyright (c) 2006-2017, assimp team
+
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
@@ -34,12 +41,12 @@ 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 <assimp/version.h>
+#include <assimp/scene.h>
#include "ScenePrivate.h"
-static const unsigned int MajorVersion = 3;
-static const unsigned int MinorVersion = 3;
+static const unsigned int MajorVersion = 4;
+static const unsigned int MinorVersion = 1;
// --------------------------------------------------------------------------------
// Legal information string - dont't remove this.
@@ -48,7 +55,7 @@ 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"
+"(c) 2008-2017, assimp team\n"
"License under the terms and conditions of the 3-clause BSD license\n"
"http://assimp.sourceforge.net\n"
;
@@ -100,34 +107,32 @@ ASSIMP_API unsigned int aiGetCompileFlags () {
#include "revision.h"
// ------------------------------------------------------------------------------------------------
-ASSIMP_API unsigned int aiGetVersionRevision ()
-{
+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())
- {
- }
+: 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()) {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiScene::~aiScene()
-{
+ASSIMP_API aiScene::~aiScene() {
// delete all sub-objects recursively
delete mRootNode;
diff --git a/src/3rdparty/assimp/code/Vertex.h b/src/3rdparty/assimp/code/Vertex.h
index 5e2cf6986..1f1685ae9 100644
--- a/src/3rdparty/assimp/code/Vertex.h
+++ b/src/3rdparty/assimp/code/Vertex.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -94,15 +95,15 @@ class 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&,ai_real);
+// friend Vertex operator - (const Vertex&,ai_real);
+ friend Vertex operator * (const Vertex&,ai_real);
+ friend Vertex operator / (const Vertex&,ai_real);
-// 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 + (ai_real, const Vertex&);
+// friend Vertex operator - (ai_real, const Vertex&);
+ friend Vertex operator * (ai_real, const Vertex&);
+// friend Vertex operator / (ai_real, const Vertex&);
public:
@@ -146,22 +147,22 @@ public:
/*
- Vertex& operator += (float v) {
+ Vertex& operator += (ai_real v) {
*this = *this+v;
return *this;
}
- Vertex& operator -= (float v) {
+ Vertex& operator -= (ai_real v) {
*this = *this-v;
return *this;
}
*/
- Vertex& operator *= (float v) {
+ Vertex& operator *= (ai_real v) {
*this = *this*v;
return *this;
}
- Vertex& operator /= (float v) {
+ Vertex& operator /= (ai_real v) {
*this = *this/v;
return *this;
}
@@ -217,40 +218,40 @@ private:
// ----------------------------------------------------------------------------
/** 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) {
+ template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, ai_real 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);
+ res.position = op<aiVector3D,ai_real,aiVector3D>()(v0.position,f);
+ res.normal = op<aiVector3D,ai_real,aiVector3D>()(v0.normal,f);
+ res.tangent = op<aiVector3D,ai_real,aiVector3D>()(v0.tangent,f);
+ res.bitangent = op<aiVector3D,ai_real,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);
+ res.texcoords[i] = op<aiVector3D,ai_real,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);
+ res.colors[i] = op<aiColor4D,ai_real,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) {
+ template <template <typename, typename, typename> class op> static Vertex BinaryOp(ai_real 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);
+ res.position = op<ai_real,aiVector3D,aiVector3D>()(f,v0.position);
+ res.normal = op<ai_real,aiVector3D,aiVector3D>()(f,v0.normal);
+ res.tangent = op<ai_real,aiVector3D,aiVector3D>()(f,v0.tangent);
+ res.bitangent = op<ai_real,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]);
+ res.texcoords[i] = op<ai_real,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]);
+ res.colors[i] = op<ai_real,aiColor4D,aiColor4D>()(f,v0.colors[i]);
}
return res;
}
@@ -279,41 +280,41 @@ AI_FORCE_INLINE Vertex operator - (const Vertex& v0,const Vertex& v1) {
// ------------------------------------------------------------------------------------------------
/*
-AI_FORCE_INLINE Vertex operator + (const Vertex& v0,float f) {
+AI_FORCE_INLINE Vertex operator + (const Vertex& v0,ai_real f) {
return Vertex::BinaryOp<Intern::plus>(v0,f);
}
-AI_FORCE_INLINE Vertex operator - (const Vertex& v0,float f) {
+AI_FORCE_INLINE Vertex operator - (const Vertex& v0,ai_real f) {
return Vertex::BinaryOp<Intern::minus>(v0,f);
}
*/
-AI_FORCE_INLINE Vertex operator * (const Vertex& v0,float f) {
+AI_FORCE_INLINE Vertex operator * (const Vertex& v0,ai_real f) {
return Vertex::BinaryOp<Intern::multiplies>(v0,f);
}
-AI_FORCE_INLINE Vertex operator / (const Vertex& v0,float f) {
+AI_FORCE_INLINE Vertex operator / (const Vertex& v0,ai_real f) {
return Vertex::BinaryOp<Intern::multiplies>(v0,1.f/f);
}
// ------------------------------------------------------------------------------------------------
/*
-AI_FORCE_INLINE Vertex operator + (float f,const Vertex& v0) {
+AI_FORCE_INLINE Vertex operator + (ai_real f,const Vertex& v0) {
return Vertex::BinaryOp<Intern::plus>(f,v0);
}
-AI_FORCE_INLINE Vertex operator - (float f,const Vertex& v0) {
+AI_FORCE_INLINE Vertex operator - (ai_real f,const Vertex& v0) {
return Vertex::BinaryOp<Intern::minus>(f,v0);
}
*/
-AI_FORCE_INLINE Vertex operator * (float f,const Vertex& v0) {
+AI_FORCE_INLINE Vertex operator * (ai_real f,const Vertex& v0) {
return Vertex::BinaryOp<Intern::multiplies>(f,v0);
}
/*
-AI_FORCE_INLINE Vertex operator / (float f,const Vertex& v0) {
+AI_FORCE_INLINE Vertex operator / (ai_real f,const Vertex& 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 6de55ab34..09c0a51a7 100644
--- a/src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp
+++ b/src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
diff --git a/src/3rdparty/assimp/code/VertexTriangleAdjacency.h b/src/3rdparty/assimp/code/VertexTriangleAdjacency.h
index 218607508..ed7b83a6b 100644
--- a/src/3rdparty/assimp/code/VertexTriangleAdjacency.h
+++ b/src/3rdparty/assimp/code/VertexTriangleAdjacency.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/Win32DebugLogStream.h b/src/3rdparty/assimp/code/Win32DebugLogStream.h
index c7bd8ca62..0833712f9 100644
--- a/src/3rdparty/assimp/code/Win32DebugLogStream.h
+++ b/src/3rdparty/assimp/code/Win32DebugLogStream.h
@@ -1,7 +1,52 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Win32DebugLogStream.h
+* @brief Implementation of Win32DebugLogStream
+*/
#ifndef AI_WIN32DEBUGLOGSTREAM_H_INC
#define AI_WIN32DEBUGLOGSTREAM_H_INC
-#ifdef WIN32
+#ifdef _WIN32
#include <assimp/LogStream.hpp>
#include "windows.h"
@@ -12,9 +57,7 @@ namespace Assimp {
/** @class Win32DebugLogStream
* @brief Logs into the debug stream from win32.
*/
-class Win32DebugLogStream :
- public LogStream
-{
+class Win32DebugLogStream : public LogStream {
public:
/** @brief Default constructor */
Win32DebugLogStream();
@@ -27,24 +70,25 @@ public:
};
// ---------------------------------------------------------------------------
-// Default constructor
-inline Win32DebugLogStream::Win32DebugLogStream()
-{}
+inline
+Win32DebugLogStream::Win32DebugLogStream(){
+ // empty
+}
// ---------------------------------------------------------------------------
-// Default constructor
-inline Win32DebugLogStream::~Win32DebugLogStream()
-{}
+inline
+Win32DebugLogStream::~Win32DebugLogStream(){
+ // empty
+}
// ---------------------------------------------------------------------------
-// Write method
-inline void Win32DebugLogStream::write(const char* message)
-{
- OutputDebugStringA( message);
+inline
+void Win32DebugLogStream::write(const char* message) {
+ ::OutputDebugStringA( message);
}
// ---------------------------------------------------------------------------
} // Namespace Assimp
-#endif // ! WIN32
+#endif // ! _WIN32
#endif // guard
diff --git a/src/3rdparty/assimp/code/X3DExporter.cpp b/src/3rdparty/assimp/code/X3DExporter.cpp
new file mode 100644
index 000000000..b560855fb
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DExporter.cpp
@@ -0,0 +1,735 @@
+/// \file X3DExporter.cpp
+/// \brief X3D-format files exporter for Assimp. Implementation.
+/// \date 2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
+
+#include "X3DExporter.hpp"
+
+// Header files, Assimp.
+#include "Exceptional.h"
+#include "StringUtils.h"
+#include <assimp/Exporter.hpp>
+#include <assimp/IOSystem.hpp>
+
+using namespace std;
+
+namespace Assimp
+{
+
+void ExportSceneX3D(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ X3DExporter exporter(pFile, pIOSystem, pScene, pProperties);
+}
+
+}// namespace Assimp
+
+namespace Assimp
+{
+
+void X3DExporter::IndentationStringSet(const size_t pNewLevel)
+{
+ if(pNewLevel > mIndentationString.size())
+ {
+ if(pNewLevel > mIndentationString.capacity()) mIndentationString.reserve(pNewLevel + 1);
+
+ for(size_t i = 0, i_e = pNewLevel - mIndentationString.size(); i < i_e; i++) mIndentationString.push_back('\t');
+ }
+ else if(pNewLevel < mIndentationString.size())
+ {
+ mIndentationString.resize(pNewLevel);
+ }
+}
+
+void X3DExporter::XML_Write(const string& pData)
+{
+ if(pData.size() == 0) return;
+ if(mOutFile->Write((void*)pData.data(), pData.length(), 1) != 1) throw DeadlyExportError("Failed to write scene data!");
+}
+
+aiMatrix4x4 X3DExporter::Matrix_GlobalToCurrent(const aiNode& pNode) const
+{
+aiNode* cur_node;
+std::list<aiMatrix4x4> matr;
+aiMatrix4x4 out_matr;
+
+ // starting walk from current element to root
+ matr.push_back(pNode.mTransformation);
+ cur_node = pNode.mParent;
+ if(cur_node != nullptr)
+ {
+ do
+ {
+ matr.push_back(cur_node->mTransformation);
+ cur_node = cur_node->mParent;
+ } while(cur_node != nullptr);
+ }
+
+ // multiplicate all matrices in reverse order
+ for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); rit++) out_matr = out_matr * (*rit);
+
+ return out_matr;
+}
+
+void X3DExporter::AttrHelper_FloatToString(const float pValue, std::string& pTargetString)
+{
+ pTargetString = to_string(pValue);
+ AttrHelper_CommaToPoint(pTargetString);
+}
+
+void X3DExporter::AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, string& pTargetString)
+{
+ pTargetString.clear();
+ pTargetString.reserve(pArray_Size * 6);// (Number + space) * 3.
+ for(size_t idx = 0; idx < pArray_Size; idx++)
+ pTargetString.append(to_string(pArray[idx].x) + " " + to_string(pArray[idx].y) + " " + to_string(pArray[idx].z) + " ");
+
+ // remove last space symbol.
+ pTargetString.resize(pTargetString.length() - 1);
+ AttrHelper_CommaToPoint(pTargetString);
+}
+
+void X3DExporter::AttrHelper_Vec2DArrToString(const aiVector2D* pArray, const size_t pArray_Size, std::string& pTargetString)
+{
+ pTargetString.clear();
+ pTargetString.reserve(pArray_Size * 4);// (Number + space) * 2.
+ for(size_t idx = 0; idx < pArray_Size; idx++)
+ pTargetString.append(to_string(pArray[idx].x) + " " + to_string(pArray[idx].y) + " ");
+
+ // remove last space symbol.
+ pTargetString.resize(pTargetString.length() - 1);
+ AttrHelper_CommaToPoint(pTargetString);
+}
+
+void X3DExporter::AttrHelper_Vec3DAsVec2fArrToString(const aiVector3D* pArray, const size_t pArray_Size, string& pTargetString)
+{
+ pTargetString.clear();
+ pTargetString.reserve(pArray_Size * 4);// (Number + space) * 2.
+ for(size_t idx = 0; idx < pArray_Size; idx++)
+ pTargetString.append(to_string(pArray[idx].x) + " " + to_string(pArray[idx].y) + " ");
+
+ // remove last space symbol.
+ pTargetString.resize(pTargetString.length() - 1);
+ AttrHelper_CommaToPoint(pTargetString);
+}
+
+void X3DExporter::AttrHelper_Col4DArrToString(const aiColor4D* pArray, const size_t pArray_Size, string& pTargetString)
+{
+ pTargetString.clear();
+ pTargetString.reserve(pArray_Size * 8);// (Number + space) * 4.
+ for(size_t idx = 0; idx < pArray_Size; idx++)
+ pTargetString.append(to_string(pArray[idx].r) + " " + to_string(pArray[idx].g) + " " + to_string(pArray[idx].b) + " " +
+ to_string(pArray[idx].a) + " ");
+
+ // remove last space symbol.
+ pTargetString.resize(pTargetString.length() - 1);
+ AttrHelper_CommaToPoint(pTargetString);
+}
+
+void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+{
+ pTargetString.clear();
+ pTargetString.reserve(pArray_Size * 6);// (Number + space) * 3.
+ for(size_t idx = 0; idx < pArray_Size; idx++)
+ pTargetString.append(to_string(pArray[idx].r) + " " + to_string(pArray[idx].g) + " " + to_string(pArray[idx].b) + " ");
+
+ // remove last space symbol.
+ pTargetString.resize(pTargetString.length() - 1);
+ AttrHelper_CommaToPoint(pTargetString);
+}
+
+void X3DExporter::AttrHelper_Color3ToAttrList(std::list<SAttribute>& pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
+{
+string tstr;
+
+ if(pValue == pDefaultValue) return;
+
+ AttrHelper_Col3DArrToString(&pValue, 1, tstr);
+ pList.push_back({pName, tstr});
+}
+
+void X3DExporter::AttrHelper_FloatToAttrList(std::list<SAttribute>& pList, const string& pName, const float pValue, const float pDefaultValue)
+{
+string tstr;
+
+ if(pValue == pDefaultValue) return;
+
+ AttrHelper_FloatToString(pValue, tstr);
+ pList.push_back({pName, tstr});
+}
+
+void X3DExporter::NodeHelper_OpenNode(const string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const list<SAttribute>& pAttrList)
+{
+ // Write indentation.
+ IndentationStringSet(pTabLevel);
+ XML_Write(mIndentationString);
+ // Begin of the element
+ XML_Write("<" + pNodeName);
+ // Write attributes
+ for(const SAttribute& attr: pAttrList) { XML_Write(" " + attr.Name + "='" + attr.Value + "'"); }
+
+ // End of the element
+ if(pEmptyElement)
+ {
+ XML_Write("/>\n");
+ }
+ else
+ {
+ XML_Write(">\n");
+ }
+}
+
+void X3DExporter::NodeHelper_OpenNode(const string& pNodeName, const size_t pTabLevel, const bool pEmptyElement)
+{
+const list<SAttribute> attr_list;
+
+ NodeHelper_OpenNode(pNodeName, pTabLevel, pEmptyElement, attr_list);
+}
+
+void X3DExporter::NodeHelper_CloseNode(const string& pNodeName, const size_t pTabLevel)
+{
+ // Write indentation.
+ IndentationStringSet(pTabLevel);
+ XML_Write(mIndentationString);
+ // Write element
+ XML_Write("</" + pNodeName + ">\n");
+}
+
+void X3DExporter::Export_Node(const aiNode *pNode, const size_t pTabLevel)
+{
+bool transform = false;
+list<SAttribute> attr_list;
+
+ // In Assimp lights is stored in next way: light source store in mScene->mLights and in node tree must present aiNode with name same as
+ // light source has. Considering it we must compare every aiNode name with light sources names. Why not to look where ligths is present
+ // and save them to fili? Because corresponding aiNode can be already written to file and we can only add information to file not to edit.
+ if(CheckAndExport_Light(*pNode, pTabLevel)) return;
+
+ // Check if need DEF.
+ if(pNode->mName.length) attr_list.push_back({"DEF", pNode->mName.C_Str()});
+
+ // Check if need <Transformation> node against <Group>.
+ if(!pNode->mTransformation.IsIdentity())
+ {
+ auto Vector2String = [this](const aiVector3D pVector) -> string
+ {
+ string tstr = to_string(pVector.x) + " " + to_string(pVector.y) + " " + to_string(pVector.z);
+
+ AttrHelper_CommaToPoint(tstr);
+
+ return tstr;
+ };
+
+ auto Rotation2String = [this](const aiVector3D pAxis, const ai_real pAngle) -> string
+ {
+ string tstr = to_string(pAxis.x) + " " + to_string(pAxis.y) + " " + to_string(pAxis.z) + " " + to_string(pAngle);
+
+ AttrHelper_CommaToPoint(tstr);
+
+ return tstr;
+ };
+
+ aiVector3D scale, translate, rotate_axis;
+ ai_real rotate_angle;
+
+ transform = true;
+ pNode->mTransformation.Decompose(scale, rotate_axis, rotate_angle, translate);
+ // Check if values different from default
+ if((rotate_angle != 0) && (rotate_axis.Length() > 0))
+ attr_list.push_back({"rotation", Rotation2String(rotate_axis, rotate_angle)});
+
+ if(!scale.Equal({1.0,1.0,1.0})) {
+ attr_list.push_back({"scale", Vector2String(scale)});
+ }
+ if(translate.Length() > 0) {
+ attr_list.push_back({"translation", Vector2String(translate)});
+ }
+ }
+
+ // Begin node if need.
+ if(transform)
+ NodeHelper_OpenNode("Transform", pTabLevel, false, attr_list);
+ else
+ NodeHelper_OpenNode("Group", pTabLevel);
+
+ // Export metadata
+ if(pNode->mMetaData != nullptr)
+ {
+ for(size_t idx_prop = 0; idx_prop < pNode->mMetaData->mNumProperties; idx_prop++)
+ {
+ const aiString* key;
+ const aiMetadataEntry* entry;
+
+ if(pNode->mMetaData->Get(idx_prop, key, entry))
+ {
+ switch(entry->mType)
+ {
+ case AI_BOOL:
+ Export_MetadataBoolean(*key, *static_cast<bool*>(entry->mData), pTabLevel + 1);
+ break;
+ case AI_DOUBLE:
+ Export_MetadataDouble(*key, *static_cast<double*>(entry->mData), pTabLevel + 1);
+ break;
+ case AI_FLOAT:
+ Export_MetadataFloat(*key, *static_cast<float*>(entry->mData), pTabLevel + 1);
+ break;
+ case AI_INT32:
+ Export_MetadataInteger(*key, *static_cast<int32_t*>(entry->mData), pTabLevel + 1);
+ break;
+ case AI_AISTRING:
+ Export_MetadataString(*key, *static_cast<aiString*>(entry->mData), pTabLevel + 1);
+ break;
+ default:
+ LogError("Unsupported metadata type: " + to_string(entry->mType));
+ break;
+ }// switch(entry->mType)
+ }
+ }
+ }// if(pNode->mMetaData != nullptr)
+
+ // Export meshes.
+ for(size_t idx_mesh = 0; idx_mesh < pNode->mNumMeshes; idx_mesh++) Export_Mesh(pNode->mMeshes[idx_mesh], pTabLevel + 1);
+ // Export children.
+ for(size_t idx_node = 0; idx_node < pNode->mNumChildren; idx_node++) Export_Node(pNode->mChildren[idx_node], pTabLevel + 1);
+
+ // End node if need.
+ if(transform)
+ NodeHelper_CloseNode("Transform", pTabLevel);
+ else
+ NodeHelper_CloseNode("Group", pTabLevel);
+}
+
+void X3DExporter::Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel)
+{
+const char* NodeName_IFS = "IndexedFaceSet";
+const char* NodeName_Shape = "Shape";
+
+list<SAttribute> attr_list;
+aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance.
+
+ // Check if mesh already defined early.
+ if(mDEF_Map_Mesh.find(pIdxMesh) != mDEF_Map_Mesh.end())
+ {
+ // Mesh already defined, just refer to it
+ attr_list.push_back({"USE", mDEF_Map_Mesh.at(pIdxMesh)});
+ NodeHelper_OpenNode(NodeName_Shape, pTabLevel, true, attr_list);
+
+ return;
+ }
+
+ string mesh_name(mesh.mName.C_Str() + string("_IDX_") + to_string(pIdxMesh));// Create mesh name
+
+ // Define mesh name.
+ attr_list.push_back({"DEF", mesh_name});
+ mDEF_Map_Mesh[pIdxMesh] = mesh_name;
+
+ //
+ // "Shape" node.
+ //
+ NodeHelper_OpenNode(NodeName_Shape, pTabLevel, false, attr_list);
+ attr_list.clear();
+
+ //
+ // "Appearance" node.
+ //
+ Export_Material(mesh.mMaterialIndex, pTabLevel + 1);
+
+ //
+ // "IndexedFaceSet" node.
+ //
+ // Fill attributes which differ from default. In Assimp for colors, vertices and normals used one indices set. So, only "coordIndex" must be set.
+ string coordIndex;
+
+ // fill coordinates index.
+ coordIndex.reserve(mesh.mNumVertices * 4);// Index + space + Face delimiter
+ for(size_t idx_face = 0; idx_face < mesh.mNumFaces; idx_face++)
+ {
+ const aiFace& face_cur = mesh.mFaces[idx_face];
+
+ for(size_t idx_vert = 0; idx_vert < face_cur.mNumIndices; idx_vert++)
+ {
+ coordIndex.append(to_string(face_cur.mIndices[idx_vert]) + " ");
+ }
+
+ coordIndex.append("-1 ");// face delimiter.
+ }
+
+ // remove last space symbol.
+ coordIndex.resize(coordIndex.length() - 1);
+ attr_list.push_back({"coordIndex", coordIndex});
+ // create node
+ NodeHelper_OpenNode(NodeName_IFS, pTabLevel + 1, false, attr_list);
+ attr_list.clear();
+ // Child nodes for "IndexedFaceSet" needed when used colors, textures or normals.
+ string attr_value;
+
+ // Export <Coordinate>
+ AttrHelper_Vec3DArrToString(mesh.mVertices, mesh.mNumVertices, attr_value);
+ attr_list.push_back({"point", attr_value});
+ NodeHelper_OpenNode("Coordinate", pTabLevel + 2, true, attr_list);
+ attr_list.clear();
+
+ // Export <ColorRGBA>
+ if(mesh.HasVertexColors(0))
+ {
+ AttrHelper_Col4DArrToString(mesh.mColors[0], mesh.mNumVertices, attr_value);
+ attr_list.push_back({"color", attr_value});
+ NodeHelper_OpenNode("ColorRGBA", pTabLevel + 2, true, attr_list);
+ attr_list.clear();
+ }
+
+ // Export <TextureCoordinate>
+ if(mesh.HasTextureCoords(0))
+ {
+ AttrHelper_Vec3DAsVec2fArrToString(mesh.mTextureCoords[0], mesh.mNumVertices, attr_value);
+ attr_list.push_back({"point", attr_value});
+ NodeHelper_OpenNode("TextureCoordinate", pTabLevel + 2, true, attr_list);
+ attr_list.clear();
+ }
+
+ // Export <Normal>
+ if(mesh.HasNormals())
+ {
+ AttrHelper_Vec3DArrToString(mesh.mNormals, mesh.mNumVertices, attr_value);
+ attr_list.push_back({"vector", attr_value});
+ NodeHelper_OpenNode("Normal", pTabLevel + 2, true, attr_list);
+ attr_list.clear();
+ }
+
+ //
+ // Close opened nodes.
+ //
+ NodeHelper_CloseNode(NodeName_IFS, pTabLevel + 1);
+ NodeHelper_CloseNode(NodeName_Shape, pTabLevel);
+}
+
+void X3DExporter::Export_Material(const size_t pIdxMaterial, const size_t pTabLevel)
+{
+const char* NodeName_A = "Appearance";
+
+list<SAttribute> attr_list;
+aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for conveniance.
+
+ // Check if material already defined early.
+ if(mDEF_Map_Material.find(pIdxMaterial) != mDEF_Map_Material.end())
+ {
+ // Material already defined, just refer to it
+ attr_list.push_back({"USE", mDEF_Map_Material.at(pIdxMaterial)});
+ NodeHelper_OpenNode(NodeName_A, pTabLevel, true, attr_list);
+
+ return;
+ }
+
+ string material_name(string("_IDX_") + to_string(pIdxMaterial));// Create material name
+ aiString ai_mat_name;
+
+ if(material.Get(AI_MATKEY_NAME, ai_mat_name) == AI_SUCCESS) material_name.insert(0, ai_mat_name.C_Str());
+
+ // Define material name.
+ attr_list.push_back({"DEF", material_name});
+ mDEF_Map_Material[pIdxMaterial] = material_name;
+
+ //
+ // "Appearance" node.
+ //
+ NodeHelper_OpenNode(NodeName_A, pTabLevel, false, attr_list);
+ attr_list.clear();
+
+ //
+ // "Material" node.
+ //
+ {
+ auto Color4ToAttrList = [&](const string& pAttrName, const aiColor4D& pAttrValue, const aiColor3D& pAttrDefaultValue)
+ {
+ string tstr;
+
+ if(aiColor3D(pAttrValue.r, pAttrValue.g, pAttrValue.b) != pAttrDefaultValue)
+ {
+ AttrHelper_Col4DArrToString(&pAttrValue, 1, tstr);
+ attr_list.push_back({pAttrName, tstr});
+ }
+ };
+
+ float tvalf;
+ aiColor3D color3;
+ aiColor4D color4;
+
+ // ambientIntensity="0.2" SFFloat [inputOutput]
+ if(material.Get(AI_MATKEY_COLOR_AMBIENT, color3) == AI_SUCCESS)
+ AttrHelper_FloatToAttrList(attr_list, "ambientIntensity", (color3.r + color3.g + color3.b) / 3.0f, 0.2f);
+ else if(material.Get(AI_MATKEY_COLOR_AMBIENT, color4) == AI_SUCCESS)
+ AttrHelper_FloatToAttrList(attr_list, "ambientIntensity", (color4.r + color4.g + color4.b) / 3.0f, 0.2f);
+
+ // diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
+ if(material.Get(AI_MATKEY_COLOR_DIFFUSE, color3) == AI_SUCCESS)
+ AttrHelper_Color3ToAttrList(attr_list, "diffuseColor", color3, aiColor3D(0.8f, 0.8f, 0.8f));
+ else if(material.Get(AI_MATKEY_COLOR_DIFFUSE, color4) == AI_SUCCESS)
+ Color4ToAttrList("diffuseColor", color4, aiColor3D(0.8f, 0.8f, 0.8f));
+
+ // emissiveColor="0 0 0" SFColor [inputOutput]
+ if(material.Get(AI_MATKEY_COLOR_EMISSIVE, color3) == AI_SUCCESS)
+ AttrHelper_Color3ToAttrList(attr_list, "emissiveColor", color3, aiColor3D(0, 0, 0));
+ else if(material.Get(AI_MATKEY_COLOR_EMISSIVE, color4) == AI_SUCCESS)
+ Color4ToAttrList("emissiveColor", color4, aiColor3D(0, 0, 0));
+
+ // shininess="0.2" SFFloat [inputOutput]
+ if(material.Get(AI_MATKEY_SHININESS, tvalf) == AI_SUCCESS) AttrHelper_FloatToAttrList(attr_list, "shininess", tvalf, 0.2f);
+
+ // specularColor="0 0 0" SFColor [inputOutput]
+ if(material.Get(AI_MATKEY_COLOR_SPECULAR, color3) == AI_SUCCESS)
+ AttrHelper_Color3ToAttrList(attr_list, "specularColor", color3, aiColor3D(0, 0, 0));
+ else if(material.Get(AI_MATKEY_COLOR_SPECULAR, color4) == AI_SUCCESS)
+ Color4ToAttrList("specularColor", color4, aiColor3D(0, 0, 0));
+
+ // transparency="0" SFFloat [inputOutput]
+ if(material.Get(AI_MATKEY_OPACITY, tvalf) == AI_SUCCESS)
+ {
+ if(tvalf > 1) tvalf = 1;
+
+ tvalf = 1.0f - tvalf;
+ AttrHelper_FloatToAttrList(attr_list, "transparency", tvalf, 0);
+ }
+
+ NodeHelper_OpenNode("Material", pTabLevel + 1, true, attr_list);
+ attr_list.clear();
+ }// "Material" node. END.
+
+ //
+ // "ImageTexture" node.
+ //
+ {
+ auto RepeatToAttrList = [&](const string& pAttrName, const bool pAttrValue)
+ {
+ if(!pAttrValue) attr_list.push_back({pAttrName, "false"});
+ };
+
+ bool tvalb;
+ aiString tstring;
+
+ // url="" MFString
+ if(material.Get(AI_MATKEY_TEXTURE_DIFFUSE(0), tstring) == AI_SUCCESS)
+ {
+ if(strncmp(tstring.C_Str(), AI_EMBEDDED_TEXNAME_PREFIX, strlen(AI_EMBEDDED_TEXNAME_PREFIX)) == 0)
+ LogError("Embedded texture is not supported");
+ else
+ attr_list.push_back({"url", string("\"") + tstring.C_Str() + "\""});
+ }
+
+ // repeatS="true" SFBool
+ if(material.Get(AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0), tvalb) == AI_SUCCESS) RepeatToAttrList("repeatS", tvalb);
+
+ // repeatT="true" SFBool
+ if(material.Get(AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0), tvalb) == AI_SUCCESS) RepeatToAttrList("repeatT", tvalb);
+
+ NodeHelper_OpenNode("ImageTexture", pTabLevel + 1, true, attr_list);
+ attr_list.clear();
+ }// "ImageTexture" node. END.
+
+ //
+ // "TextureTransform" node.
+ //
+ {
+ auto Vec2ToAttrList = [&](const string& pAttrName, const aiVector2D& pAttrValue, const aiVector2D& pAttrDefaultValue)
+ {
+ string tstr;
+
+ if(pAttrValue != pAttrDefaultValue)
+ {
+ AttrHelper_Vec2DArrToString(&pAttrValue, 1, tstr);
+ attr_list.push_back({pAttrName, tstr});
+ }
+ };
+
+ aiUVTransform transform;
+
+ if(material.Get(AI_MATKEY_UVTRANSFORM_DIFFUSE(0), transform) == AI_SUCCESS)
+ {
+ Vec2ToAttrList("translation", transform.mTranslation, aiVector2D(0, 0));
+ AttrHelper_FloatToAttrList(attr_list, "rotation", transform.mRotation, 0);
+ Vec2ToAttrList("scale", transform.mScaling, aiVector2D(1, 1));
+
+ NodeHelper_OpenNode("TextureTransform", pTabLevel + 1, true, attr_list);
+ attr_list.clear();
+ }
+ }// "TextureTransform" node. END.
+
+ //
+ // Close opened nodes.
+ //
+ NodeHelper_CloseNode(NodeName_A, pTabLevel);
+
+}
+
+void X3DExporter::Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
+{
+list<SAttribute> attr_list;
+
+ attr_list.push_back({"name", pKey.C_Str()});
+ attr_list.push_back({"value", pValue ? "true" : "false"});
+ NodeHelper_OpenNode("MetadataBoolean", pTabLevel, true, attr_list);
+}
+
+void X3DExporter::Export_MetadataDouble(const aiString& pKey, const double pValue, const size_t pTabLevel)
+{
+list<SAttribute> attr_list;
+
+ attr_list.push_back({"name", pKey.C_Str()});
+ attr_list.push_back({"value", to_string(pValue)});
+ NodeHelper_OpenNode("MetadataDouble", pTabLevel, true, attr_list);
+}
+
+void X3DExporter::Export_MetadataFloat(const aiString& pKey, const float pValue, const size_t pTabLevel)
+{
+list<SAttribute> attr_list;
+
+ attr_list.push_back({"name", pKey.C_Str()});
+ attr_list.push_back({"value", to_string(pValue)});
+ NodeHelper_OpenNode("MetadataFloat", pTabLevel, true, attr_list);
+}
+
+void X3DExporter::Export_MetadataInteger(const aiString& pKey, const int32_t pValue, const size_t pTabLevel)
+{
+list<SAttribute> attr_list;
+
+ attr_list.push_back({"name", pKey.C_Str()});
+ attr_list.push_back({"value", to_string(pValue)});
+ NodeHelper_OpenNode("MetadataInteger", pTabLevel, true, attr_list);
+}
+
+void X3DExporter::Export_MetadataString(const aiString& pKey, const aiString& pValue, const size_t pTabLevel)
+{
+list<SAttribute> attr_list;
+
+ attr_list.push_back({"name", pKey.C_Str()});
+ attr_list.push_back({"value", pValue.C_Str()});
+ NodeHelper_OpenNode("MetadataString", pTabLevel, true, attr_list);
+}
+
+bool X3DExporter::CheckAndExport_Light(const aiNode& pNode, const size_t pTabLevel)
+{
+list<SAttribute> attr_list;
+
+auto Vec3ToAttrList = [&](const string& pAttrName, const aiVector3D& pAttrValue, const aiVector3D& pAttrDefaultValue)
+{
+ string tstr;
+
+ if(pAttrValue != pAttrDefaultValue)
+ {
+ AttrHelper_Vec3DArrToString(&pAttrValue, 1, tstr);
+ attr_list.push_back({pAttrName, tstr});
+ }
+};
+
+size_t idx_light;
+bool found = false;
+
+ // Name of the light source can not be empty.
+ if(pNode.mName.length == 0) return false;
+
+ // search for light with name like node has.
+ for(idx_light = 0; mScene->mNumLights; idx_light++)
+ {
+ if(pNode.mName == mScene->mLights[idx_light]->mName)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found) return false;
+
+ // Light source is found.
+ const aiLight& light = *mScene->mLights[idx_light];// Alias for conveniance.
+
+ aiMatrix4x4 trafo_mat = Matrix_GlobalToCurrent(pNode).Inverse();
+
+ attr_list.push_back({"DEF", light.mName.C_Str()});
+ attr_list.push_back({"global", "true"});// "false" is not supported.
+ // ambientIntensity="0" SFFloat [inputOutput]
+ AttrHelper_FloatToAttrList(attr_list, "ambientIntensity", aiVector3D(light.mColorAmbient.r, light.mColorAmbient.g, light.mColorAmbient.b).Length(), 0);
+ // color="1 1 1" SFColor [inputOutput]
+ AttrHelper_Color3ToAttrList(attr_list, "color", light.mColorDiffuse, aiColor3D(1, 1, 1));
+
+ switch(light.mType)
+ {
+ case aiLightSource_DIRECTIONAL:
+ {
+ aiVector3D direction = trafo_mat * light.mDirection;
+
+ Vec3ToAttrList("direction", direction, aiVector3D(0, 0, -1));
+ NodeHelper_OpenNode("DirectionalLight", pTabLevel, true, attr_list);
+ }
+
+ break;
+ case aiLightSource_POINT:
+ {
+ aiVector3D attenuation(light.mAttenuationConstant, light.mAttenuationLinear, light.mAttenuationQuadratic);
+ aiVector3D location = trafo_mat * light.mPosition;
+
+ Vec3ToAttrList("attenuation", attenuation, aiVector3D(1, 0, 0));
+ Vec3ToAttrList("location", location, aiVector3D(0, 0, 0));
+ NodeHelper_OpenNode("PointLight", pTabLevel, true, attr_list);
+ }
+
+ break;
+ case aiLightSource_SPOT:
+ {
+ aiVector3D attenuation(light.mAttenuationConstant, light.mAttenuationLinear, light.mAttenuationQuadratic);
+ aiVector3D location = trafo_mat * light.mPosition;
+ aiVector3D direction = trafo_mat * light.mDirection;
+
+ Vec3ToAttrList("attenuation", attenuation, aiVector3D(1, 0, 0));
+ Vec3ToAttrList("location", location, aiVector3D(0, 0, 0));
+ Vec3ToAttrList("direction", direction, aiVector3D(0, 0, -1));
+ AttrHelper_FloatToAttrList(attr_list, "beamWidth", light.mAngleInnerCone, 0.7854f);
+ AttrHelper_FloatToAttrList(attr_list, "cutOffAngle", light.mAngleOuterCone, 1.570796f);
+ NodeHelper_OpenNode("SpotLight", pTabLevel, true, attr_list);
+ }
+
+ break;
+ default:
+ throw DeadlyExportError("Unknown light type: " + to_string(light.mType));
+ }// switch(light.mType)
+
+ return true;
+}
+
+X3DExporter::X3DExporter(const char* pFileName, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
+ : mScene(pScene)
+{
+list<SAttribute> attr_list;
+
+ mOutFile = pIOSystem->Open(pFileName, "wt");
+ if(mOutFile == nullptr) throw DeadlyExportError("Could not open output .x3d file: " + string(pFileName));
+
+ // Begin document
+ XML_Write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ XML_Write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.3//EN\" \"http://www.web3d.org/specifications/x3d-3.3.dtd\">\n");
+ // Root node
+ attr_list.push_back({"profile", "Interchange"});
+ attr_list.push_back({"version", "3.3"});
+ attr_list.push_back({"xmlns:xsd", "http://www.w3.org/2001/XMLSchema-instance"});
+ attr_list.push_back({"xsd:noNamespaceSchemaLocation", "http://www.web3d.org/specifications/x3d-3.3.xsd"});
+ NodeHelper_OpenNode("X3D", 0, false, attr_list);
+ attr_list.clear();
+ // <head>: meta data.
+ NodeHelper_OpenNode("head", 1);
+ XML_Write(mIndentationString + "<!-- All \"meta\" from this section tou will found in <Scene> node as MetadataString nodes. -->\n");
+ NodeHelper_CloseNode("head", 1);
+ // Scene node.
+ NodeHelper_OpenNode("Scene", 1);
+ Export_Node(mScene->mRootNode, 2);
+ NodeHelper_CloseNode("Scene", 1);
+ // Close Root node.
+ NodeHelper_CloseNode("X3D", 0);
+ // Cleanup
+ pIOSystem->Close(mOutFile);
+ mOutFile = nullptr;
+}
+
+}// namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_X3D_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/X3DExporter.hpp b/src/3rdparty/assimp/code/X3DExporter.hpp
new file mode 100644
index 000000000..45f302d8d
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DExporter.hpp
@@ -0,0 +1,235 @@
+/// \file X3DExporter.hpp
+/// \brief X3D-format files exporter for Assimp.
+/// \date 2016
+/// \author smal.root@gmail.com
+// Thanks to acorn89 for support.
+
+#ifndef INCLUDED_AI_X3D_EXPORTER_H
+#define INCLUDED_AI_X3D_EXPORTER_H
+
+// Header files, Assimp.
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+
+// Header files, stdlib.
+#include <list>
+#include <string>
+
+namespace Assimp
+{
+
+/// \class X3DExporter
+/// Class which export aiScene to X3D file.
+///
+/// Limitations.
+///
+/// Pay attention that X3D is format for interactive graphic and simulations for web browsers. aiScene can not contain all features of the X3D format.
+/// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tesselation:
+/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but that's not a good idea at all.
+///
+/// Supported nodes:
+/// Core component:
+/// "MetadataBoolean", "MetadataDouble", "MetadataFloat", "MetadataInteger", "MetadataSet", "MetadataString"
+/// Geometry3D component:
+/// "IndexedFaceSet"
+/// Grouping component:
+/// "Group", "Transform"
+/// Lighting component:
+/// "DirectionalLight", "PointLight", "SpotLight"
+/// Rendering component:
+/// "ColorRGBA", "Coordinate", "Normal"
+/// Shape component:
+/// "Shape", "Appearance", "Material"
+/// Texturing component:
+/// "ImageTexture", "TextureCoordinate", "TextureTransform"
+///
+class X3DExporter
+{
+ /***********************************************/
+ /******************** Types ********************/
+ /***********************************************/
+
+ struct SAttribute
+ {
+ const std::string Name;
+ const std::string Value;
+ };
+
+ /***********************************************/
+ /****************** Constants ******************/
+ /***********************************************/
+
+ const aiScene* const mScene;
+
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+ IOStream* mOutFile;
+ std::map<size_t, std::string> mDEF_Map_Mesh;
+ std::map<size_t, std::string> mDEF_Map_Material;
+
+private:
+
+ std::string mIndentationString;
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+ /// \fn void IndentationStringSet(const size_t pNewLevel)
+ /// Set value of the indentation string.
+ /// \param [in] pNewLevel - new level of the indentation.
+ void IndentationStringSet(const size_t pNewLevel);
+
+ /// \fn void XML_Write(const std::string& pData)
+ /// Write data to XML-file.
+ /// \param [in] pData - reference to string which must be written.
+ void XML_Write(const std::string& pData);
+
+ /// \fn aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode& pNode) const
+ /// Calculate transformation matrix for transformation from global coordinate system to pointed aiNode.
+ /// \param [in] pNode - reference to local node.
+ /// \return calculated matrix.
+ aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode& pNode) const;
+
+ /// \fn void AttrHelper_CommaToPoint(std::string& pStringWithComma)
+ /// Convert commas in string to points. That's needed because "std::to_string" result depends on locale (regional settings).
+ /// \param [in, out] pStringWithComma - reference to string, which must be modified.
+ void AttrHelper_CommaToPoint(std::string& pStringWithComma) { for(char& c: pStringWithComma) { if(c == ',') c = '.'; } }
+
+ /// \fn void AttrHelper_FloatToString(const float pValue, std::string& pTargetString)
+ /// Converts float to string.
+ /// \param [in] pValue - value for converting.
+ /// \param [out] pTargetString - reference to string where result will be placed. Will be cleared before using.
+ void AttrHelper_FloatToString(const float pValue, std::string& pTargetString);
+
+ /// \fn void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// Converts array of vectors to string.
+ /// \param [in] pArray - pointer to array of vectors.
+ /// \param [in] pArray_Size - count of elements in array.
+ /// \param [out] pTargetString - reference to string where result will be placed. Will be cleared before using.
+ void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString);
+
+ /// \fn void AttrHelper_Vec2DArrToString(const aiVector2D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// \overload void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ void AttrHelper_Vec2DArrToString(const aiVector2D* pArray, const size_t pArray_Size, std::string& pTargetString);
+
+ /// \fn void AttrHelper_Vec3DAsVec2fArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// \overload void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// Only x, y is used from aiVector3D.
+ void AttrHelper_Vec3DAsVec2fArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString);
+
+ /// \fn void AttrHelper_Col4DArrToString(const aiColor4D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// \overload void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// Converts array of colors to string.
+ void AttrHelper_Col4DArrToString(const aiColor4D* pArray, const size_t pArray_Size, std::string& pTargetString);
+
+ /// \fn void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// \overload void AttrHelper_Col4DArrToString(const aiColor4D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ /// Converts array of colors to string.
+ void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString);
+
+ /// \fn void AttrHelper_FloatToAttrList(std::list<SAttribute> pList, const std::string& pName, const float pValue, const float pDefaultValue)
+ /// \overload void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
+ void AttrHelper_FloatToAttrList(std::list<SAttribute> &pList, const std::string& pName, const float pValue, const float pDefaultValue);
+
+ /// \fn void AttrHelper_Color3ToAttrList(std::list<SAttribute> pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
+ /// Add attribute to list if value not equal to default.
+ /// \param [in] pList - target list of the attributes.
+ /// \param [in] pName - name of new attribute.
+ /// \param [in] pValue - value of the new attribute.
+ /// \param [in] pDefaultValue - default value for checking: if pValue is equal to pDefaultValue then attribute will not be added.
+ void AttrHelper_Color3ToAttrList(std::list<SAttribute> &pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue);
+
+ /// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList)
+ /// Begin new XML-node element.
+ /// \param [in] pNodeName - name of the element.
+ /// \param [in] pTabLevel - indentation level.
+ /// \param [in] pEmtyElement - if true then empty element will be created.
+ /// \param [in] pAttrList - list of the attributes for element.
+ void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList);
+
+ /// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement = false)
+ /// \overload void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList)
+ void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement = false);
+
+ /// \fn void NodeHelper_CloseNode(const std::string& pNodeName, const size_t pTabLevel)
+ /// End XML-node element.
+ /// \param [in] pNodeName - name of the element.
+ /// \param [in] pTabLevel - indentation level.
+ void NodeHelper_CloseNode(const std::string& pNodeName, const size_t pTabLevel);
+
+ /// \fn void Export_Node(const aiNode* pNode, const size_t pTabLevel)
+ /// Export data from scene to XML-file: aiNode.
+ /// \param [in] pNode - source aiNode.
+ /// \param [in] pTabLevel - indentation level.
+ void Export_Node(const aiNode* pNode, const size_t pTabLevel);
+
+ /// \fn void Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel)
+ /// Export data from scene to XML-file: aiMesh.
+ /// \param [in] pMesh - index of the source aiMesh.
+ /// \param [in] pTabLevel - indentation level.
+ void Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel);
+
+ /// \fn void Export_Material(const size_t pIdxMaterial, const size_t pTabLevel)
+ /// Export data from scene to XML-file: aiMaterial.
+ /// \param [in] pIdxMaterial - index of the source aiMaterial.
+ /// \param [in] pTabLevel - indentation level.
+ void Export_Material(const size_t pIdxMaterial, const size_t pTabLevel);
+
+ /// \fn void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
+ /// Export data from scene to XML-file: aiMetadata.
+ /// \param [in] pKey - source data: value of the metadata key.
+ /// \param [in] pValue - source data: value of the metadata value.
+ /// \param [in] pTabLevel - indentation level.
+ void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel);
+
+ /// \fn void Export_MetadataDouble(const aiString& pKey, const double pValue, const size_t pTabLevel)
+ /// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
+ void Export_MetadataDouble(const aiString& pKey, const double pValue, const size_t pTabLevel);
+
+ /// \fn void Export_MetadataFloat(const aiString& pKey, const float pValue, const size_t pTabLevel)
+ /// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
+ void Export_MetadataFloat(const aiString& pKey, const float pValue, const size_t pTabLevel);
+
+ /// \fn void Export_MetadataInteger(const aiString& pKey, const int32_t pValue, const size_t pTabLevel)
+ /// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
+ void Export_MetadataInteger(const aiString& pKey, const int32_t pValue, const size_t pTabLevel);
+
+ /// \fn void Export_MetadataString(const aiString& pKey, const aiString& pValue, const size_t pTabLevel)
+ /// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
+ void Export_MetadataString(const aiString& pKey, const aiString& pValue, const size_t pTabLevel);
+
+ /// \fn bool CheckAndExport_Light(const aiNode& pNode, const size_t pTabLevel)
+ /// Check if node point to light source. If yes then export light source.
+ /// \param [in] pNode - reference to node for checking.
+ /// \param [in] pTabLevel - indentation level.
+ /// \return true - if node assigned with light and it was exported, else - return false.
+ bool CheckAndExport_Light(const aiNode& pNode, const size_t pTabLevel);
+
+ /***********************************************/
+ /************** Functions: LOG set *************/
+ /***********************************************/
+
+ /// \fn void LogError(const std::string& pMessage)
+ /// Short variant for calling \ref DefaultLogger::get()->error()
+ void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
+
+public:
+
+ /// \fn X3DExporter()
+ /// Default constructor.
+ X3DExporter(const char* pFileName, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties);
+
+ /// \fn ~X3DExporter()
+ /// Default destructor.
+ ~X3DExporter() {}
+
+};// class X3DExporter
+
+}// namespace Assimp
+
+#endif // INCLUDED_AI_X3D_EXPORTER_H
diff --git a/src/3rdparty/assimp/code/X3DImporter.cpp b/src/3rdparty/assimp/code/X3DImporter.cpp
new file mode 100644
index 000000000..aaf99b309
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter.cpp
@@ -0,0 +1,1728 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter.cpp
+/// \brief X3D-format files importer for Assimp: main algorithm implementation.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+#include "StringUtils.h"
+
+// Header files, Assimp.
+#include <assimp/DefaultIOSystem.h>
+#include "fast_atof.h"
+#include "FIReader.hpp"
+
+// Header files, stdlib.
+#include <memory>
+#include <string>
+#include <iterator>
+
+namespace Assimp {
+
+/// \var aiImporterDesc X3DImporter::Description
+/// Constant which holds the importer description
+const aiImporterDesc X3DImporter::Description = {
+ "Extensible 3D(X3D) Importer",
+ "smalcom",
+ "",
+ "See documentation in source code. Chapter: Limitations.",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+ 0,
+ 0,
+ 0,
+ 0,
+ "x3d x3db"
+};
+
+//const std::regex X3DImporter::pattern_nws(R"([^, \t\r\n]+)");
+//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase);
+
+struct WordIterator: public std::iterator<std::input_iterator_tag, const char*> {
+ static const char *whitespace;
+ const char *start_, *end_;
+ WordIterator(const char *start, const char *end): start_(start), end_(end) {
+ start_ = start + strspn(start, whitespace);
+ if (start_ >= end_) {
+ start_ = 0;
+ }
+ }
+ WordIterator(): start_(0), end_(0) {}
+ WordIterator(const WordIterator &other): start_(other.start_), end_(other.end_) {}
+ WordIterator &operator=(const WordIterator &other) {
+ start_ = other.start_;
+ end_ = other.end_;
+ return *this;
+ }
+ bool operator==(const WordIterator &other) const { return start_ == other.start_; }
+ bool operator!=(const WordIterator &other) const { return start_ != other.start_; }
+ WordIterator &operator++() {
+ start_ += strcspn(start_, whitespace);
+ start_ += strspn(start_, whitespace);
+ if (start_ >= end_) {
+ start_ = 0;
+ }
+ return *this;
+ }
+ WordIterator operator++(int) {
+ WordIterator result(*this);
+ ++(*this);
+ return result;
+ }
+ const char *operator*() const { return start_; }
+};
+
+const char *WordIterator::whitespace = ", \t\r\n";
+
+X3DImporter::X3DImporter()
+: NodeElement_Cur( nullptr )
+, mReader( nullptr ) {
+ // empty
+}
+
+X3DImporter::~X3DImporter() {
+ // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
+ Clear();
+}
+
+void X3DImporter::Clear() {
+ NodeElement_Cur = nullptr;
+ // Delete all elements
+ if(NodeElement_List.size()) {
+ for ( std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++ ) {
+ delete *it;
+ }
+ NodeElement_List.clear();
+ }
+}
+
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: find set ************************************************************/
+/*********************************************************************************************************************************************/
+
+bool X3DImporter::FindNodeElement_FromRoot(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
+{
+ for(std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++)
+ {
+ if(((*it)->Type == pType) && ((*it)->ID == pID))
+ {
+ if(pElement != nullptr) *pElement = *it;
+
+ return true;
+ }
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++)
+
+ return false;
+}
+
+bool X3DImporter::FindNodeElement_FromNode(CX3DImporter_NodeElement* pStartNode, const std::string& pID,
+ const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
+{
+ bool found = false;// flag: true - if requested element is found.
+
+ // Check if pStartNode - this is the element, we are looking for.
+ if((pStartNode->Type == pType) && (pStartNode->ID == pID))
+ {
+ found = true;
+ if ( pElement != nullptr )
+ {
+ *pElement = pStartNode;
+ }
+
+ goto fne_fn_end;
+ }// if((pStartNode->Type() == pType) && (pStartNode->ID() == pID))
+
+ // Check childs of pStartNode.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = pStartNode->Child.begin(); ch_it != pStartNode->Child.end(); ch_it++)
+ {
+ found = FindNodeElement_FromNode(*ch_it, pID, pType, pElement);
+ if ( found )
+ {
+ break;
+ }
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = it->Child.begin(); ch_it != it->Child.end(); ch_it++)
+
+fne_fn_end:
+
+ return found;
+}
+
+bool X3DImporter::FindNodeElement(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
+{
+ CX3DImporter_NodeElement* tnd = NodeElement_Cur;// temporary pointer to node.
+ bool static_search = false;// flag: true if searching in static node.
+
+ // At first check if we have deal with static node. Go up through parent nodes and check flag.
+ while(tnd != nullptr)
+ {
+ if(tnd->Type == CX3DImporter_NodeElement::ENET_Group)
+ {
+ if(((CX3DImporter_NodeElement_Group*)tnd)->Static)
+ {
+ static_search = true;// Flag found, stop walking up. Node with static flag will holded in tnd variable.
+ break;
+ }
+ }
+
+ tnd = tnd->Parent;// go up in graph.
+ }// while(tnd != nullptr)
+
+ // at now call appropriate search function.
+ if ( static_search )
+ {
+ return FindNodeElement_FromNode( tnd, pID, pType, pElement );
+ }
+ else
+ {
+ return FindNodeElement_FromRoot( pID, pType, pElement );
+ }
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: throw set ***********************************************************/
+/*********************************************************************************************************************************************/
+
+void X3DImporter::Throw_ArgOutOfRange(const std::string& pArgument)
+{
+ throw DeadlyImportError("Argument value is out of range for: \"" + pArgument + "\".");
+}
+
+void X3DImporter::Throw_CloseNotFound(const std::string& pNode)
+{
+ throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
+}
+
+void X3DImporter::Throw_ConvertFail_Str2ArrF(const std::string& pAttrValue)
+{
+ throw DeadlyImportError("In <" + std::string(mReader->getNodeName()) + "> failed to convert attribute value \"" + pAttrValue +
+ "\" from string to array of floats.");
+}
+
+void X3DImporter::Throw_DEF_And_USE()
+{
+ throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + std::string(mReader->getNodeName()) + ">.");
+}
+
+void X3DImporter::Throw_IncorrectAttr(const std::string& pAttrName)
+{
+ throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
+}
+
+void X3DImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
+{
+ throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
+}
+
+void X3DImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
+{
+ throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
+}
+
+void X3DImporter::Throw_TagCountIncorrect(const std::string& pNode)
+{
+ throw DeadlyImportError("Count of open and close tags for node <" + pNode + "> are not equivalent. Seems file is corrupt.");
+}
+
+void X3DImporter::Throw_USE_NotFound(const std::string& pAttrValue)
+{
+ throw DeadlyImportError("Not found node with name \"" + pAttrValue + "\" in <" + std::string(mReader->getNodeName()) + ">.");
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************* Functions: XML set ************************************************************/
+/*********************************************************************************************************************************************/
+
+void X3DImporter::XML_CheckNode_MustBeEmpty()
+{
+ if(!mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must be empty.");
+}
+
+void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
+{
+ static const size_t Uns_Skip_Len = 192;
+ const char* Uns_Skip[ Uns_Skip_Len ] = {
+ // CAD geometry component
+ "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet",
+ // Core
+ "ROUTE", "ExternProtoDeclare", "ProtoDeclare", "ProtoInstance", "ProtoInterface", "WorldInfo",
+ // Distributed interactive simulation (DIS) component
+ "DISEntityManager", "DISEntityTypeMapping", "EspduTransform", "ReceiverPdu", "SignalPdu", "TransmitterPdu",
+ // Cube map environmental texturing component
+ "ComposedCubeMapTexture", "GeneratedCubeMapTexture", "ImageCubeMapTexture",
+ // Environmental effects component
+ "Background", "Fog", "FogCoordinate", "LocalFog", "TextureBackground",
+ // Environmental sensor component
+ "ProximitySensor", "TransformSensor", "VisibilitySensor",
+ // Followers component
+ "ColorChaser", "ColorDamper", "CoordinateChaser", "CoordinateDamper", "OrientationChaser", "OrientationDamper", "PositionChaser", "PositionChaser2D",
+ "PositionDamper", "PositionDamper2D", "ScalarChaser", "ScalarDamper", "TexCoordChaser2D", "TexCoordDamper2D",
+ // Geospatial component
+ "GeoCoordinate", "GeoElevationGrid", "GeoLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", "GeoProximitySensor",
+ "GeoTouchSensor", "GeoTransform", "GeoViewpoint",
+ // Humanoid Animation (H-Anim) component
+ "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", "HAnimSegment", "HAnimSite",
+ // Interpolation component
+ "ColorInterpolator", "CoordinateInterpolator", "CoordinateInterpolator2D", "EaseInEaseOut", "NormalInterpolator", "OrientationInterpolator",
+ "PositionInterpolator", "PositionInterpolator2D", "ScalarInterpolator", "SplinePositionInterpolator", "SplinePositionInterpolator2D",
+ "SplineScalarInterpolator", "SquadOrientationInterpolator",
+ // Key device sensor component
+ "KeySensor", "StringSensor",
+ // Layering component
+ "Layer", "LayerSet", "Viewport",
+ // Layout component
+ "Layout", "LayoutGroup", "LayoutLayer", "ScreenFontStyle", "ScreenGroup",
+ // Navigation component
+ "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup",
+ // Networking component
+ "EXPORT", "IMPORT", "Anchor", "LoadSensor",
+ // NURBS component
+ "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
+ "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
+ "NurbsTrimmedSurface",
+ // Particle systems component
+ "BoundedPhysicsModel", "ConeEmitter", "ExplosionEmitter", "ForcePhysicsModel", "ParticleSystem", "PointEmitter", "PolylineEmitter", "SurfaceEmitter",
+ "VolumeEmitter", "WindPhysicsModel",
+ // Picking component
+ "LinePickSensor", "PickableGroup", "PointPickSensor", "PrimitivePickSensor", "VolumePickSensor",
+ // Pointing device sensor component
+ "CylinderSensor", "PlaneSensor", "SphereSensor", "TouchSensor",
+ // Rendering component
+ "ClipPlane",
+ // Rigid body physics
+ "BallJoint", "CollidableOffset", "CollidableShape", "CollisionCollection", "CollisionSensor", "CollisionSpace", "Contact", "DoubleAxisHingeJoint",
+ "MotorJoint", "RigidBody", "RigidBodyCollection", "SingleAxisHingeJoint", "SliderJoint", "UniversalJoint",
+ // Scripting component
+ "Script",
+ // Programmable shaders component
+ "ComposedShader", "FloatVertexAttribute", "Matrix3VertexAttribute", "Matrix4VertexAttribute", "PackagedShader", "ProgramShader", "ShaderPart",
+ "ShaderProgram",
+ // Shape component
+ "FillProperties", "LineProperties", "TwoSidedMaterial",
+ // Sound component
+ "AudioClip", "Sound",
+ // Text component
+ "FontStyle", "Text",
+ // Texturing3D Component
+ "ComposedTexture3D", "ImageTexture3D", "PixelTexture3D", "TextureCoordinate3D", "TextureCoordinate4D", "TextureTransformMatrix3D", "TextureTransform3D",
+ // Texturing component
+ "MovieTexture", "MultiTexture", "MultiTextureCoordinate", "MultiTextureTransform", "PixelTexture", "TextureCoordinateGenerator", "TextureProperties",
+ // Time component
+ "TimeSensor",
+ // Event Utilities component
+ "BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "IntegerSequencer", "IntegerTrigger", "TimeTrigger",
+ // Volume rendering component
+ "BlendedVolumeStyle", "BoundaryEnhancementVolumeStyle", "CartoonVolumeStyle", "ComposedVolumeStyle", "EdgeEnhancementVolumeStyle", "IsoSurfaceVolumeData",
+ "OpacityMapVolumeStyle", "ProjectionVolumeStyle", "SegmentedVolumeData", "ShadedVolumeStyle", "SilhouetteEnhancementVolumeStyle", "ToneMappedVolumeStyle",
+ "VolumeData"
+ };
+
+ const std::string nn( mReader->getNodeName() );
+ bool found = false;
+ bool close_found = false;
+
+ for(size_t i = 0; i < Uns_Skip_Len; i++)
+ {
+ if(nn == Uns_Skip[i])
+ {
+ found = true;
+ if(mReader->isEmptyElement())
+ {
+ close_found = true;
+
+ goto casu_cres;
+ }
+
+ while(mReader->read())
+ {
+ if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName()))
+ {
+ close_found = true;
+
+ goto casu_cres;
+ }
+ }
+ }
+ }
+
+casu_cres:
+
+ if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
+
+ if(close_found)
+ LogInfo("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
+ else
+ Throw_CloseNotFound(nn);
+}
+
+bool X3DImporter::XML_SearchNode(const std::string& pNodeName)
+{
+ while(mReader->read())
+ {
+ if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
+ }
+
+ return false;
+}
+
+bool X3DImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
+{
+ auto boolValue = std::dynamic_pointer_cast<const FIBoolValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (boolValue) {
+ if (boolValue->value.size() == 1) {
+ return boolValue->value.front();
+ }
+ throw DeadlyImportError("Invalid bool value");
+ }
+ else {
+ std::string val(mReader->getAttributeValue(pAttrIdx));
+
+ if(val == "false")
+ return false;
+ else if(val == "true")
+ return true;
+ else
+ throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"" + val + "\"");
+ }
+}
+
+float X3DImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
+{
+ auto floatValue = std::dynamic_pointer_cast<const FIFloatValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (floatValue) {
+ if (floatValue->value.size() == 1) {
+ return floatValue->value.front();
+ }
+ throw DeadlyImportError("Invalid float value");
+ }
+ else {
+ std::string val;
+ float tvalf;
+
+ ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
+ fast_atoreal_move(val.c_str(), tvalf, false);
+
+ return tvalf;
+ }
+}
+
+int32_t X3DImporter::XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx)
+{
+ auto intValue = std::dynamic_pointer_cast<const FIIntValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (intValue) {
+ if (intValue->value.size() == 1) {
+ return intValue->value.front();
+ }
+ throw DeadlyImportError("Invalid int value");
+ }
+ else {
+ return strtol10(mReader->getAttributeValue(pAttrIdx));
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue)
+{
+ std::vector<float> tlist;
+ std::vector<float>::iterator it;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);
+ if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
+
+ it = tlist.begin();
+ pValue.r = *it++;
+ pValue.g = *it++;
+ pValue.b = *it;
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue)
+{
+ std::vector<float> tlist;
+ std::vector<float>::iterator it;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);
+ if(tlist.size() != 2) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
+
+ it = tlist.begin();
+ pValue.x = *it++;
+ pValue.y = *it;
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue)
+{
+ std::vector<float> tlist;
+ std::vector<float>::iterator it;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);
+ if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
+
+ it = tlist.begin();
+ pValue.x = *it++;
+ pValue.y = *it++;
+ pValue.z = *it;
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue)
+{
+ auto boolValue = std::dynamic_pointer_cast<const FIBoolValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (boolValue) {
+ pValue = boolValue->value;
+ }
+ else {
+ const char *val = mReader->getAttributeValue(pAttrIdx);
+ pValue.clear();
+
+ //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+ //const std::cregex_iterator wordItEnd;
+ //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::regex_match(match.str(), pattern_true); });
+
+ WordIterator wordItBegin(val, val + strlen(val));
+ WordIterator wordItEnd;
+ std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return (::tolower(match[0]) == 't') || (match[0] == '1'); });
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue)
+{
+ auto intValue = std::dynamic_pointer_cast<const FIIntValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (intValue) {
+ pValue = intValue->value;
+ }
+ else {
+ const char *val = mReader->getAttributeValue(pAttrIdx);
+ pValue.clear();
+
+ //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+ //const std::cregex_iterator wordItEnd;
+ //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stoi(match.str()); });
+
+ WordIterator wordItBegin(val, val + strlen(val));
+ WordIterator wordItEnd;
+ std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atoi(match); });
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue)
+{
+ auto floatValue = std::dynamic_pointer_cast<const FIFloatValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (floatValue) {
+ pValue = floatValue->value;
+ }
+ else {
+ const char *val = mReader->getAttributeValue(pAttrIdx);
+ pValue.clear();
+
+ //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+ //const std::cregex_iterator wordItEnd;
+ //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stof(match.str()); });
+
+ WordIterator wordItBegin(val, val + strlen(val));
+ WordIterator wordItEnd;
+ std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return static_cast<float>(atof(match)); });
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue)
+{
+ auto doubleValue = std::dynamic_pointer_cast<const FIDoubleValue>(mReader->getAttributeEncodedValue(pAttrIdx));
+ if (doubleValue) {
+ pValue = doubleValue->value;
+ }
+ else {
+ const char *val = mReader->getAttributeValue(pAttrIdx);
+ pValue.clear();
+
+ //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws);
+ //const std::cregex_iterator wordItEnd;
+ //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stod(match.str()); });
+
+ WordIterator wordItBegin(val, val + strlen(val));
+ WordIterator wordItEnd;
+ std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atof(match); });
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue)
+{
+ std::vector<float> tlist;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
+ if(tlist.size() % 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
+
+ // copy data to array
+ for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
+ {
+ aiColor3D tcol;
+
+ tcol.r = *it++;
+ tcol.g = *it++;
+ tcol.b = *it++;
+ pValue.push_back(tcol);
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue)
+{
+ std::list<aiColor3D> tlist;
+
+ XML_ReadNode_GetAttrVal_AsListCol3f(pAttrIdx, tlist);// read as list
+ // and copy to array
+ if(tlist.size() > 0)
+ {
+ pValue.reserve(tlist.size());
+ for(std::list<aiColor3D>::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it);
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
+{
+ std::vector<float> tlist;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
+ if(tlist.size() % 4) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx));
+
+ // copy data to array
+ for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
+ {
+ aiColor4D tcol;
+
+ tcol.r = *it++;
+ tcol.g = *it++;
+ tcol.b = *it++;
+ tcol.a = *it++;
+ pValue.push_back(tcol);
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::vector<aiColor4D>& pValue)
+{
+ std::list<aiColor4D> tlist;
+
+ XML_ReadNode_GetAttrVal_AsListCol4f(pAttrIdx, tlist);// read as list
+ // and copy to array
+ if(tlist.size() > 0)
+ {
+ pValue.reserve(tlist.size());
+ for ( std::list<aiColor4D>::iterator it = tlist.begin(); it != tlist.end(); it++ )
+ {
+ pValue.push_back( *it );
+ }
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
+{
+ std::vector<float> tlist;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
+ if ( tlist.size() % 2 )
+ {
+ Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) );
+ }
+
+ // copy data to array
+ for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
+ {
+ aiVector2D tvec;
+
+ tvec.x = *it++;
+ tvec.y = *it++;
+ pValue.push_back(tvec);
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::vector<aiVector2D>& pValue)
+{
+ std::list<aiVector2D> tlist;
+
+ XML_ReadNode_GetAttrVal_AsListVec2f(pAttrIdx, tlist);// read as list
+ // and copy to array
+ if(tlist.size() > 0)
+ {
+ pValue.reserve(tlist.size());
+ for ( std::list<aiVector2D>::iterator it = tlist.begin(); it != tlist.end(); it++ )
+ {
+ pValue.push_back( *it );
+ }
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
+{
+ std::vector<float> tlist;
+
+ XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list
+ if ( tlist.size() % 3 )
+ {
+ Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) );
+ }
+
+ // copy data to array
+ for(std::vector<float>::iterator it = tlist.begin(); it != tlist.end();)
+ {
+ aiVector3D tvec;
+
+ tvec.x = *it++;
+ tvec.y = *it++;
+ tvec.z = *it++;
+ pValue.push_back(tvec);
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::vector<aiVector3D>& pValue)
+{
+ std::list<aiVector3D> tlist;
+
+ XML_ReadNode_GetAttrVal_AsListVec3f(pAttrIdx, tlist);// read as list
+ // and copy to array
+ if(tlist.size() > 0)
+ {
+ pValue.reserve(tlist.size());
+ for ( std::list<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); it++ )
+ {
+ pValue.push_back( *it );
+ }
+ }
+}
+
+void X3DImporter::XML_ReadNode_GetAttrVal_AsListS(const int pAttrIdx, std::list<std::string>& pValue)
+{
+ // make copy of attribute value - strings list.
+ const size_t tok_str_len = strlen(mReader->getAttributeValue(pAttrIdx));
+ if ( 0 == tok_str_len )
+ {
+ Throw_IncorrectAttrValue( mReader->getAttributeName( pAttrIdx ) );
+ }
+
+ // get pointer to begin of value.
+ char *tok_str = const_cast<char*>(mReader->getAttributeValue(pAttrIdx));
+ char *tok_str_end = tok_str + tok_str_len;
+ // string list has following format: attr_name='"s1" "s2" "sn"'.
+ do
+ {
+ char* tbeg;
+ char* tend;
+ size_t tlen;
+ std::string tstr;
+
+ // find begin of string(element of string list): "sn".
+ tbeg = strstr(tok_str, "\"");
+ if(tbeg == nullptr) Throw_IncorrectAttrValue(mReader->getAttributeName(pAttrIdx));
+
+ tbeg++;// forward pointer from '\"' symbol to next after it.
+ tok_str = tbeg;
+ // find end of string(element of string list): "sn".
+ tend = strstr(tok_str, "\"");
+ if(tend == nullptr) Throw_IncorrectAttrValue(mReader->getAttributeName(pAttrIdx));
+
+ tok_str = tend + 1;
+ // create storage for new string
+ tlen = tend - tbeg;
+ tstr.resize(tlen);// reserve enough space and copy data
+ memcpy((void*)tstr.data(), tbeg, tlen);// not strcpy because end of copied string from tok_str has no terminator.
+ // and store string in output list.
+ pValue.push_back(tstr);
+ } while(tok_str < tok_str_end);
+}
+
+/*********************************************************************************************************************************************/
+/****************************************************** Functions: geometry helper set ******************************************************/
+/*********************************************************************************************************************************************/
+
+aiVector3D X3DImporter::GeometryHelper_Make_Point2D(const float pAngle, const float pRadius)
+{
+ return aiVector3D(pRadius * std::cos(pAngle), pRadius * std::sin(pAngle), 0);
+}
+
+void X3DImporter::GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments,
+ std::list<aiVector3D>& pVertices)
+{
+ // check argument values ranges.
+ if ( ( pStartAngle < -AI_MATH_TWO_PI_F ) || ( pStartAngle > AI_MATH_TWO_PI_F ) )
+ {
+ Throw_ArgOutOfRange( "GeometryHelper_Make_Arc2D.pStartAngle" );
+ }
+ if ( ( pEndAngle < -AI_MATH_TWO_PI_F ) || ( pEndAngle > AI_MATH_TWO_PI_F ) )
+ {
+ Throw_ArgOutOfRange( "GeometryHelper_Make_Arc2D.pEndAngle" );
+ }
+ if ( pRadius <= 0 )
+ {
+ Throw_ArgOutOfRange( "GeometryHelper_Make_Arc2D.pRadius" );
+ }
+
+ // calculate arc angle and check type of arc
+ float angle_full = std::fabs(pEndAngle - pStartAngle);
+ if ( ( angle_full > AI_MATH_TWO_PI_F ) || ( angle_full == 0.0f ) )
+ {
+ angle_full = AI_MATH_TWO_PI_F;
+ }
+
+ // calculate angle for one step - angle to next point of line.
+ float angle_step = angle_full / (float)pNumSegments;
+ // make points
+ for(size_t pi = 0; pi <= pNumSegments; pi++)
+ {
+ float tangle = pStartAngle + pi * angle_step;
+ pVertices.push_back(GeometryHelper_Make_Point2D(tangle, pRadius));
+ }// for(size_t pi = 0; pi <= pNumSegments; pi++)
+
+ // if we making full circle then add last vertex equal to first vertex
+ if(angle_full == AI_MATH_TWO_PI_F) pVertices.push_back(*pVertices.begin());
+}
+
+void X3DImporter::GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>& pPoint, std::list<aiVector3D>& pLine)
+{
+ std::list<aiVector3D>::const_iterator pit = pPoint.begin();
+ std::list<aiVector3D>::const_iterator pit_last = pPoint.end();
+
+ pit_last--;
+
+ if ( pPoint.size() < 2 )
+ {
+ Throw_ArgOutOfRange( "GeometryHelper_Extend_PointToLine.pPoint.size() can not be less than 2." );
+ }
+
+ // add first point of first line.
+ pLine.push_back(*pit++);
+ // add internal points
+ while(pit != pit_last)
+ {
+ pLine.push_back(*pit);// second point of previous line
+ pLine.push_back(*pit);// first point of next line
+ pit++;
+ }
+ // add last point of last line
+ pLine.push_back(*pit);
+}
+
+void X3DImporter::GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int32_t>& pPolylineCoordIdx, std::list<int32_t>& pLineCoordIdx)
+{
+ std::list<int32_t>::const_iterator plit = pPolylineCoordIdx.begin();
+
+ while(plit != pPolylineCoordIdx.end())
+ {
+ // add first point of polyline
+ pLineCoordIdx.push_back(*plit++);
+ while((*plit != (-1)) && (plit != pPolylineCoordIdx.end()))
+ {
+ std::list<int32_t>::const_iterator plit_next;
+
+ plit_next = plit, plit_next++;
+ pLineCoordIdx.push_back(*plit);// second point of previous line.
+ pLineCoordIdx.push_back(-1);// delimiter
+ if((*plit_next == (-1)) || (plit_next == pPolylineCoordIdx.end())) break;// current polyline is finished
+
+ pLineCoordIdx.push_back(*plit);// first point of next line.
+ plit = plit_next;
+ }// while((*plit != (-1)) && (plit != pPolylineCoordIdx.end()))
+ }// while(plit != pPolylineCoordIdx.end())
+}
+
+#define MESH_RectParallelepiped_CREATE_VERT \
+aiVector3D vert_set[8]; \
+float x1, x2, y1, y2, z1, z2, hs; \
+ \
+ hs = pSize.x / 2, x1 = -hs, x2 = hs; \
+ hs = pSize.y / 2, y1 = -hs, y2 = hs; \
+ hs = pSize.z / 2, z1 = -hs, z2 = hs; \
+ vert_set[0].Set(x2, y1, z2); \
+ vert_set[1].Set(x2, y2, z2); \
+ vert_set[2].Set(x2, y2, z1); \
+ vert_set[3].Set(x2, y1, z1); \
+ vert_set[4].Set(x1, y1, z2); \
+ vert_set[5].Set(x1, y2, z2); \
+ vert_set[6].Set(x1, y2, z1); \
+ vert_set[7].Set(x1, y1, z1)
+
+void X3DImporter::GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSize, std::list<aiVector3D>& pVertices)
+{
+ MESH_RectParallelepiped_CREATE_VERT;
+ MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 3, 2, 1, 0);// front
+ MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 6, 7, 4, 5);// back
+ MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 7, 3, 0, 4);// left
+ MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 2, 6, 5, 1);// right
+ MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 0, 1, 5, 4);// top
+ MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 7, 6, 2, 3);// bottom
+}
+
+#undef MESH_RectParallelepiped_CREATE_VERT
+
+void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const
+{
+ std::vector<int32_t> f_data(pCoordIdx);
+ std::vector<unsigned int> inds;
+ unsigned int prim_type = 0;
+
+ if ( f_data.back() != ( -1 ) )
+ {
+ f_data.push_back( -1 );
+ }
+
+ // reserve average size.
+ pFaces.reserve(f_data.size() / 3);
+ inds.reserve(4);
+ //PrintVectorSet("build. ci", pCoordIdx);
+ for(std::vector<int32_t>::iterator it = f_data.begin(); it != f_data.end(); it++)
+ {
+ // when face is got count how many indices in it.
+ if(*it == (-1))
+ {
+ aiFace tface;
+ size_t ts;
+
+ ts = inds.size();
+ switch(ts)
+ {
+ case 0: goto mg_m_err;
+ case 1: prim_type |= aiPrimitiveType_POINT; break;
+ case 2: prim_type |= aiPrimitiveType_LINE; break;
+ case 3: prim_type |= aiPrimitiveType_TRIANGLE; break;
+ default: prim_type |= aiPrimitiveType_POLYGON; break;
+ }
+
+ tface.mNumIndices = static_cast<unsigned int>(ts);
+ tface.mIndices = new unsigned int[ts];
+ memcpy(tface.mIndices, inds.data(), ts * sizeof(unsigned int));
+ pFaces.push_back(tface);
+ inds.clear();
+ }// if(*it == (-1))
+ else
+ {
+ inds.push_back(*it);
+ }// if(*it == (-1)) else
+ }// for(std::list<int32_t>::iterator it = f_data.begin(); it != f_data.end(); it++)
+//PrintVectorSet("build. faces", pCoordIdx);
+
+ pPrimitiveTypes = prim_type;
+
+ return;
+
+mg_m_err:
+
+ for(size_t i = 0, i_e = pFaces.size(); i < i_e; i++) delete [] pFaces.at(i).mIndices;
+
+ pFaces.clear();
+}
+
+void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const
+{
+std::list<aiColor4D> tcol;
+
+ // create RGBA array from RGB.
+ for(std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); it++) tcol.push_back(aiColor4D((*it).r, (*it).g, (*it).b, 1));
+
+ // call existing function for adding RGBA colors
+ MeshGeometry_AddColor(pMesh, tcol, pColorPerVertex);
+}
+
+void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
+{
+ std::list<aiColor4D>::const_iterator col_it = pColors.begin();
+
+ if(pColorPerVertex)
+ {
+ if(pColors.size() < pMesh.mNumVertices)
+ {
+ throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(" + to_string(pColors.size()) + ") can not be less than Vertices count(" +
+ to_string(pMesh.mNumVertices) + ").");
+ }
+
+ // copy colors to mesh
+ pMesh.mColors[0] = new aiColor4D[pMesh.mNumVertices];
+ for(size_t i = 0; i < pMesh.mNumVertices; i++) pMesh.mColors[0][i] = *col_it++;
+ }// if(pColorPerVertex)
+ else
+ {
+ if(pColors.size() < pMesh.mNumFaces)
+ {
+ throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(" + to_string(pColors.size()) + ") can not be less than Faces count(" +
+ to_string(pMesh.mNumFaces) + ").");
+ }
+
+ // copy colors to mesh
+ pMesh.mColors[0] = new aiColor4D[pMesh.mNumVertices];
+ for(size_t fi = 0; fi < pMesh.mNumFaces; fi++)
+ {
+ // apply color to all vertices of face
+ for ( size_t vi = 0, vi_e = pMesh.mFaces[ fi ].mNumIndices; vi < vi_e; vi++ )
+ {
+ pMesh.mColors[ 0 ][ pMesh.mFaces[ fi ].mIndices[ vi ] ] = *col_it;
+ }
+
+ col_it++;
+ }
+ }// if(pColorPerVertex) else
+}
+
+void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
+ const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const
+{
+ std::list<aiColor4D> tcol;
+
+ // create RGBA array from RGB.
+ for ( std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); it++ )
+ {
+ tcol.push_back( aiColor4D( ( *it ).r, ( *it ).g, ( *it ).b, 1 ) );
+ }
+
+ // call existing function for adding RGBA colors
+ MeshGeometry_AddColor(pMesh, pCoordIdx, pColorIdx, tcol, pColorPerVertex);
+}
+
+void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
+ const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
+{
+ std::vector<aiColor4D> col_tgt_arr;
+ std::list<aiColor4D> col_tgt_list;
+ std::vector<aiColor4D> col_arr_copy;
+
+ if ( pCoordIdx.size() == 0 )
+ {
+ throw DeadlyImportError( "MeshGeometry_AddColor2. pCoordIdx can not be empty." );
+ }
+
+ // copy list to array because we are need indexed access to colors.
+ col_arr_copy.reserve(pColors.size());
+ for ( std::list<aiColor4D>::const_iterator it = pColors.begin(); it != pColors.end(); it++ )
+ {
+ col_arr_copy.push_back( *it );
+ }
+
+ if(pColorPerVertex)
+ {
+ if(pColorIdx.size() > 0)
+ {
+ // check indices array count.
+ if(pColorIdx.size() < pCoordIdx.size())
+ {
+ throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(" + to_string(pColorIdx.size()) +
+ ") can not be less than Coords inidces count(" + to_string(pCoordIdx.size()) + ").");
+ }
+ // create list with colors for every vertex.
+ col_tgt_arr.resize(pMesh.mNumVertices);
+ for(std::vector<int32_t>::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); colidx_it++, coordidx_it++)
+ {
+ if ( *colidx_it == ( -1 ) )
+ {
+ continue;// skip faces delimiter
+ }
+ if ( ( unsigned int ) ( *coordidx_it ) > pMesh.mNumVertices )
+ {
+ throw DeadlyImportError( "MeshGeometry_AddColor2. Coordinate idx is out of range." );
+ }
+ if ( ( unsigned int ) *colidx_it > pMesh.mNumVertices )
+ {
+ throw DeadlyImportError( "MeshGeometry_AddColor2. Color idx is out of range." );
+ }
+
+ col_tgt_arr[*coordidx_it] = col_arr_copy[*colidx_it];
+ }
+ }// if(pColorIdx.size() > 0)
+ else
+ {
+ // when color indices list is absent use CoordIdx.
+ // check indices array count.
+ if(pColors.size() < pMesh.mNumVertices)
+ {
+ throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(" + to_string(pColors.size()) + ") can not be less than Vertices count(" +
+ to_string(pMesh.mNumVertices) + ").");
+ }
+ // create list with colors for every vertex.
+ col_tgt_arr.resize(pMesh.mNumVertices);
+ for ( size_t i = 0; i < pMesh.mNumVertices; i++ )
+ {
+ col_tgt_arr[ i ] = col_arr_copy[ i ];
+ }
+ }// if(pColorIdx.size() > 0) else
+ }// if(pColorPerVertex)
+ else
+ {
+ if(pColorIdx.size() > 0)
+ {
+ // check indices array count.
+ if(pColorIdx.size() < pMesh.mNumFaces)
+ {
+ throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(" + to_string(pColorIdx.size()) +
+ ") can not be less than Faces count(" + to_string(pMesh.mNumFaces) + ").");
+ }
+ // create list with colors for every vertex using faces indices.
+ col_tgt_arr.resize(pMesh.mNumFaces);
+
+ std::vector<int32_t>::const_iterator colidx_it = pColorIdx.begin();
+ for(size_t fi = 0; fi < pMesh.mNumFaces; fi++)
+ {
+ if((unsigned int)*colidx_it > pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddColor2. Face idx is out of range.");
+
+ col_tgt_arr[fi] = col_arr_copy[*colidx_it++];
+ }
+ }// if(pColorIdx.size() > 0)
+ else
+ {
+ // when color indices list is absent use CoordIdx.
+ // check indices array count.
+ if(pColors.size() < pMesh.mNumFaces)
+ {
+ throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(" + to_string(pColors.size()) + ") can not be less than Faces count(" +
+ to_string(pMesh.mNumFaces) + ").");
+ }
+ // create list with colors for every vertex using faces indices.
+ col_tgt_arr.resize(pMesh.mNumFaces);
+ for(size_t fi = 0; fi < pMesh.mNumFaces; fi++) col_tgt_arr[fi] = col_arr_copy[fi];
+
+ }// if(pColorIdx.size() > 0) else
+ }// if(pColorPerVertex) else
+
+ // copy array to list for calling function that add colors.
+ for(std::vector<aiColor4D>::const_iterator it = col_tgt_arr.begin(); it != col_tgt_arr.end(); it++) col_tgt_list.push_back(*it);
+ // add prepared colors list to mesh.
+ MeshGeometry_AddColor(pMesh, col_tgt_list, pColorPerVertex);
+}
+
+void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pNormalIdx,
+ const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const
+{
+ std::vector<size_t> tind;
+ std::vector<aiVector3D> norm_arr_copy;
+
+ // copy list to array because we are need indexed access to normals.
+ norm_arr_copy.reserve(pNormals.size());
+ for ( std::list<aiVector3D>::const_iterator it = pNormals.begin(); it != pNormals.end(); it++ )
+ {
+ norm_arr_copy.push_back( *it );
+ }
+
+ if(pNormalPerVertex)
+ {
+ if(pNormalIdx.size() > 0)
+ {
+ // check indices array count.
+ if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal.");
+
+ tind.reserve(pNormalIdx.size());
+ for(std::vector<int32_t>::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); it++)
+ {
+ if(*it != (-1)) tind.push_back(*it);
+ }
+
+ // copy normals to mesh
+ pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+ for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++)
+ {
+ if(tind[i] >= norm_arr_copy.size())
+ throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) +
+ ") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + ".");
+
+ pMesh.mNormals[i] = norm_arr_copy[tind[i]];
+ }
+ }
+ else
+ {
+ if(pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal.");
+
+ // copy normals to mesh
+ pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+ std::list<aiVector3D>::const_iterator norm_it = pNormals.begin();
+ for(size_t i = 0; i < pMesh.mNumVertices; i++) pMesh.mNormals[i] = *norm_it++;
+ }
+ }// if(pNormalPerVertex)
+ else
+ {
+ if(pNormalIdx.size() > 0)
+ {
+ if(pMesh.mNumFaces != pNormalIdx.size()) throw DeadlyImportError("Normals faces count must be equal to mesh faces count.");
+
+ std::vector<int32_t>::const_iterator normidx_it = pNormalIdx.begin();
+
+ tind.reserve(pNormalIdx.size());
+ for(size_t i = 0, i_e = pNormalIdx.size(); i < i_e; i++) tind.push_back(*normidx_it++);
+
+ }
+ else
+ {
+ tind.reserve(pMesh.mNumFaces);
+ for(size_t i = 0; i < pMesh.mNumFaces; i++) tind.push_back(i);
+
+ }
+
+ // copy normals to mesh
+ pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+ for(size_t fi = 0; fi < pMesh.mNumFaces; fi++)
+ {
+ aiVector3D tnorm;
+
+ tnorm = norm_arr_copy[tind[fi]];
+ for(size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++) pMesh.mNormals[pMesh.mFaces[fi].mIndices[vi]] = tnorm;
+ }
+ }// if(pNormalPerVertex) else
+}
+
+void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const
+{
+ std::list<aiVector3D>::const_iterator norm_it = pNormals.begin();
+
+ if(pNormalPerVertex)
+ {
+ if(pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal.");
+
+ // copy normals to mesh
+ pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+ for(size_t i = 0; i < pMesh.mNumVertices; i++) pMesh.mNormals[i] = *norm_it++;
+ }// if(pNormalPerVertex)
+ else
+ {
+ if(pNormals.size() != pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and faces count must be equal.");
+
+ // copy normals to mesh
+ pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
+ for(size_t fi = 0; fi < pMesh.mNumFaces; fi++)
+ {
+ // apply color to all vertices of face
+ for(size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++) pMesh.mNormals[pMesh.mFaces[fi].mIndices[vi]] = *norm_it;
+
+ norm_it++;
+ }
+ }// if(pNormalPerVertex) else
+}
+
+void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pTexCoordIdx,
+ const std::list<aiVector2D>& pTexCoords) const
+{
+ std::vector<aiVector3D> texcoord_arr_copy;
+ std::vector<aiFace> faces;
+ unsigned int prim_type;
+
+ // copy list to array because we are need indexed access to normals.
+ texcoord_arr_copy.reserve(pTexCoords.size());
+ for(std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); it++)
+ {
+ texcoord_arr_copy.push_back(aiVector3D((*it).x, (*it).y, 0));
+ }
+
+ if(pTexCoordIdx.size() > 0)
+ {
+ GeometryHelper_CoordIdxStr2FacesArr(pTexCoordIdx, faces, prim_type);
+ if ( faces.empty() )
+ {
+ throw DeadlyImportError( "Failed to add texture coordinates to mesh, faces list is empty." );
+ }
+ if ( faces.size() != pMesh.mNumFaces )
+ {
+ throw DeadlyImportError( "Texture coordinates faces count must be equal to mesh faces count." );
+ }
+ }
+ else
+ {
+ GeometryHelper_CoordIdxStr2FacesArr(pCoordIdx, faces, prim_type);
+ }
+
+ pMesh.mTextureCoords[0] = new aiVector3D[pMesh.mNumVertices];
+ pMesh.mNumUVComponents[0] = 2;
+ for(size_t fi = 0, fi_e = faces.size(); fi < fi_e; fi++)
+ {
+ if(pMesh.mFaces[fi].mNumIndices != faces.at(fi).mNumIndices)
+ throw DeadlyImportError("Number of indices in texture face and mesh face must be equal. Invalid face index: " + to_string(fi) + ".");
+
+ for(size_t ii = 0; ii < pMesh.mFaces[fi].mNumIndices; ii++)
+ {
+ size_t vert_idx = pMesh.mFaces[fi].mIndices[ii];
+ size_t tc_idx = faces.at(fi).mIndices[ii];
+
+ pMesh.mTextureCoords[0][vert_idx] = texcoord_arr_copy.at(tc_idx);
+ }
+ }// for(size_t fi = 0, fi_e = faces.size(); fi < fi_e; fi++)
+}
+
+void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVector2D>& pTexCoords) const
+{
+ std::vector<aiVector3D> tc_arr_copy;
+
+ if ( pTexCoords.size() != pMesh.mNumVertices )
+ {
+ throw DeadlyImportError( "MeshGeometry_AddTexCoord. Texture coordinates and vertices count must be equal." );
+ }
+
+ // copy list to array because we are need convert aiVector2D to aiVector3D and also get indexed access as a bonus.
+ tc_arr_copy.reserve(pTexCoords.size());
+ for ( std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); it++ )
+ {
+ tc_arr_copy.push_back( aiVector3D( ( *it ).x, ( *it ).y, 0 ) );
+ }
+
+ // copy texture coordinates to mesh
+ pMesh.mTextureCoords[0] = new aiVector3D[pMesh.mNumVertices];
+ pMesh.mNumUVComponents[0] = 2;
+ for ( size_t i = 0; i < pMesh.mNumVertices; i++ )
+ {
+ pMesh.mTextureCoords[ 0 ][ i ] = tc_arr_copy[ i ];
+ }
+}
+
+aiMesh* X3DImporter::GeometryHelper_MakeMesh(const std::vector<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const
+{
+ std::vector<aiFace> faces;
+ unsigned int prim_type = 0;
+
+ // create faces array from input string with vertices indices.
+ GeometryHelper_CoordIdxStr2FacesArr(pCoordIdx, faces, prim_type);
+ if ( !faces.size() )
+ {
+ throw DeadlyImportError( "Failed to create mesh, faces list is empty." );
+ }
+
+ //
+ // Create new mesh and copy geometry data.
+ //
+ aiMesh *tmesh = new aiMesh;
+ size_t ts = faces.size();
+ // faces
+ tmesh->mFaces = new aiFace[ts];
+ tmesh->mNumFaces = static_cast<unsigned int>(ts);
+ for(size_t i = 0; i < ts; i++) tmesh->mFaces[i] = faces.at(i);
+
+ // vertices
+ std::list<aiVector3D>::const_iterator vit = pVertices.begin();
+
+ ts = pVertices.size();
+ tmesh->mVertices = new aiVector3D[ts];
+ tmesh->mNumVertices = static_cast<unsigned int>(ts);
+ for ( size_t i = 0; i < ts; i++ )
+ {
+ tmesh->mVertices[ i ] = *vit++;
+ }
+
+ // set primitives type and return result.
+ tmesh->mPrimitiveTypes = prim_type;
+
+ return tmesh;
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: parse set ***********************************************************/
+/*********************************************************************************************************************************************/
+
+void X3DImporter::ParseHelper_Group_Begin(const bool pStatic)
+{
+ CX3DImporter_NodeElement_Group* new_group = new CX3DImporter_NodeElement_Group(NodeElement_Cur, pStatic);// create new node with current node as parent.
+
+ // if we are adding not the root element then add new element to current element child list.
+ if ( NodeElement_Cur != nullptr )
+ {
+ NodeElement_Cur->Child.push_back( new_group );
+ }
+
+ NodeElement_List.push_back(new_group);// it's a new element - add it to list.
+ NodeElement_Cur = new_group;// switch current element to new one.
+}
+
+void X3DImporter::ParseHelper_Node_Enter(CX3DImporter_NodeElement* pNode)
+{
+ NodeElement_Cur->Child.push_back(pNode);// add new element to current element child list.
+ NodeElement_Cur = pNode;// switch current element to new one.
+}
+
+void X3DImporter::ParseHelper_Node_Exit()
+{
+ // check if we can walk up.
+ if ( NodeElement_Cur != nullptr )
+ {
+ NodeElement_Cur = NodeElement_Cur->Parent;
+ }
+}
+
+void X3DImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
+{
+ pOutString.clear();
+ const size_t instr_len = strlen(pInStr);
+ if ( 0 == instr_len )
+ {
+ return;
+ }
+
+ pOutString.reserve(instr_len * 3 / 2);
+ // check and correct floats in format ".x". Must be "x.y".
+ if ( pInStr[ 0 ] == '.' )
+ {
+ pOutString.push_back( '0' );
+ }
+
+ pOutString.push_back(pInStr[0]);
+ for(size_t ci = 1; ci < instr_len; ci++)
+ {
+ if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t')))
+ {
+ pOutString.push_back('0');
+ pOutString.push_back('.');
+ }
+ else
+ {
+ pOutString.push_back(pInStr[ci]);
+ }
+ }
+}
+
+extern FIVocabulary X3D_vocabulary_3_2;
+extern FIVocabulary X3D_vocabulary_3_3;
+
+void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
+{
+ std::unique_ptr<FIReader> OldReader = std::move(mReader);// store current XMLreader.
+ std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
+
+ // Check whether we can read from the file
+ if ( file.get() == nullptr )
+ {
+ throw DeadlyImportError( "Failed to open X3D file " + pFile + "." );
+ }
+ mReader = FIReader::create(file.get());
+ if ( !mReader )
+ {
+ throw DeadlyImportError( "Failed to create XML reader for file" + pFile + "." );
+ }
+ mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.2", &X3D_vocabulary_3_2);
+ mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.3", &X3D_vocabulary_3_3);
+ // start reading
+ ParseNode_Root();
+
+ // restore old XMLreader
+ mReader = std::move(OldReader);
+}
+
+void X3DImporter::ParseNode_Root()
+{
+ // search for root tag <X3D>
+ if ( !XML_SearchNode( "X3D" ) )
+ {
+ throw DeadlyImportError( "Root node \"X3D\" not found." );
+ }
+
+ ParseHelper_Group_Begin();// create root node element.
+ // parse other contents
+ while(mReader->read())
+ {
+ if ( mReader->getNodeType() != irr::io::EXN_ELEMENT )
+ {
+ continue;
+ }
+
+ if(XML_CheckNode_NameEqual("head"))
+ ParseNode_Head();
+ else if(XML_CheckNode_NameEqual("Scene"))
+ ParseNode_Scene();
+ else
+ XML_CheckNode_SkipUnsupported("Root");
+ }
+
+ // exit from root node element.
+ ParseHelper_Node_Exit();
+}
+
+void X3DImporter::ParseNode_Head()
+{
+ bool close_found = false;// flag: true if close tag of node are found.
+
+ while(mReader->read())
+ {
+ if(mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if(XML_CheckNode_NameEqual("meta"))
+ {
+ XML_CheckNode_MustBeEmpty();
+
+ // adding metadata from <head> as MetaString from <Scene>
+ bool added( false );
+ CX3DImporter_NodeElement_MetaString* ms = new CX3DImporter_NodeElement_MetaString(NodeElement_Cur);
+
+ ms->Name = mReader->getAttributeValueSafe("name");
+ // name must not be empty
+ if(!ms->Name.empty())
+ {
+ ms->Value.push_back(mReader->getAttributeValueSafe("content"));
+ NodeElement_List.push_back(ms);
+ if ( NodeElement_Cur != nullptr )
+ {
+ NodeElement_Cur->Child.push_back( ms );
+ added = true;
+ }
+ }
+ // if an error has occurred, release instance
+ if ( !added ) {
+ delete ms;
+ }
+ }// if(XML_CheckNode_NameEqual("meta"))
+ }// if(mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if(XML_CheckNode_NameEqual("head"))
+ {
+ close_found = true;
+ break;
+ }
+ }// if(mReader->getNodeType() == irr::io::EXN_ELEMENT) else
+ }// while(mReader->read())
+
+ if ( !close_found )
+ {
+ Throw_CloseNotFound( "head" );
+ }
+}
+
+void X3DImporter::ParseNode_Scene()
+{
+ auto GroupCounter_Increase = [](size_t& pCounter, const char* pGroupName) -> void
+ {
+ pCounter++;
+ if(pCounter == 0) throw DeadlyImportError("Group counter overflow. Too much groups with type: " + std::string(pGroupName) + ".");
+};
+
+auto GroupCounter_Decrease = [&](size_t& pCounter, const char* pGroupName) -> void
+{
+ if(pCounter == 0) Throw_TagCountIncorrect(pGroupName);
+
+ pCounter--;
+};
+
+static const char* GroupName_Group = "Group";
+static const char* GroupName_StaticGroup = "StaticGroup";
+static const char* GroupName_Transform = "Transform";
+static const char* GroupName_Switch = "Switch";
+
+bool close_found = false;
+size_t counter_group = 0;
+size_t counter_transform = 0;
+size_t counter_switch = 0;
+
+ // while create static node? Because objects name used deeper in "USE" attribute can be equal to some meta in <head> node.
+ ParseHelper_Group_Begin(true);
+ while(mReader->read())
+ {
+ if(mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if(XML_CheckNode_NameEqual("Shape"))
+ {
+ ParseNode_Shape_Shape();
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_Group))
+ {
+ GroupCounter_Increase(counter_group, GroupName_Group);
+ ParseNode_Grouping_Group();
+ // if node is empty then decrease group counter at this place.
+ if(mReader->isEmptyElement()) GroupCounter_Decrease(counter_group, GroupName_Group);
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_StaticGroup))
+ {
+ GroupCounter_Increase(counter_group, GroupName_StaticGroup);
+ ParseNode_Grouping_StaticGroup();
+ // if node is empty then decrease group counter at this place.
+ if(mReader->isEmptyElement()) GroupCounter_Decrease(counter_group, GroupName_StaticGroup);
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_Transform))
+ {
+ GroupCounter_Increase(counter_transform, GroupName_Transform);
+ ParseNode_Grouping_Transform();
+ // if node is empty then decrease group counter at this place.
+ if(mReader->isEmptyElement()) GroupCounter_Decrease(counter_transform, GroupName_Transform);
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_Switch))
+ {
+ GroupCounter_Increase(counter_switch, GroupName_Switch);
+ ParseNode_Grouping_Switch();
+ // if node is empty then decrease group counter at this place.
+ if(mReader->isEmptyElement()) GroupCounter_Decrease(counter_switch, GroupName_Switch);
+ }
+ else if(XML_CheckNode_NameEqual("DirectionalLight"))
+ {
+ ParseNode_Lighting_DirectionalLight();
+ }
+ else if(XML_CheckNode_NameEqual("PointLight"))
+ {
+ ParseNode_Lighting_PointLight();
+ }
+ else if(XML_CheckNode_NameEqual("SpotLight"))
+ {
+ ParseNode_Lighting_SpotLight();
+ }
+ else if(XML_CheckNode_NameEqual("Inline"))
+ {
+ ParseNode_Networking_Inline();
+ }
+ else if(!ParseHelper_CheckRead_X3DMetadataObject())
+ {
+ XML_CheckNode_SkipUnsupported("Scene");
+ }
+ }// if(mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if(XML_CheckNode_NameEqual("Scene"))
+ {
+ close_found = true;
+
+ break;
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_Group))
+ {
+ GroupCounter_Decrease(counter_group, GroupName_Group);
+ ParseNode_Grouping_GroupEnd();
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_StaticGroup))
+ {
+ GroupCounter_Decrease(counter_group, GroupName_StaticGroup);
+ ParseNode_Grouping_StaticGroupEnd();
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_Transform))
+ {
+ GroupCounter_Decrease(counter_transform, GroupName_Transform);
+ ParseNode_Grouping_TransformEnd();
+ }
+ else if(XML_CheckNode_NameEqual(GroupName_Switch))
+ {
+ GroupCounter_Decrease(counter_switch, GroupName_Switch);
+ ParseNode_Grouping_SwitchEnd();
+ }
+ }// if(mReader->getNodeType() == irr::io::EXN_ELEMENT) else
+ }// while(mReader->read())
+
+ ParseHelper_Node_Exit();
+
+ if(counter_group) Throw_TagCountIncorrect("Group");
+ if(counter_transform) Throw_TagCountIncorrect("Transform");
+ if(counter_switch) Throw_TagCountIncorrect("Switch");
+ if(!close_found) Throw_CloseNotFound("Scene");
+
+}
+
+/*********************************************************************************************************************************************/
+/******************************************************** Functions: BaseImporter set ********************************************************/
+/*********************************************************************************************************************************************/
+
+bool X3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const
+{
+ const std::string extension = GetExtension(pFile);
+
+ if((extension == "x3d") || (extension == "x3db")) return true;
+
+ if(!extension.length() || pCheckSig)
+ {
+ const char* tokens[] = { "DOCTYPE X3D PUBLIC", "http://www.web3d.org/specifications/x3d" };
+
+ return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2);
+ }
+
+ return false;
+}
+
+void X3DImporter::GetExtensionList(std::set<std::string>& pExtensionList)
+{
+ pExtensionList.insert("x3d");
+ pExtensionList.insert("x3db");
+}
+
+const aiImporterDesc* X3DImporter::GetInfo () const
+{
+ return &Description;
+}
+
+void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+ mpIOHandler = pIOHandler;
+
+ Clear();// delete old graph.
+ std::string::size_type slashPos = pFile.find_last_of("\\/");
+ pIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : pFile.substr(0, slashPos + 1));
+ ParseFile(pFile, pIOHandler);
+ pIOHandler->PopDirectory();
+ //
+ // Assimp use static arrays of objects for fast speed of rendering. That's good, but need some additional operations/
+ // We know that geometry objects(meshes) are stored in <Shape>, also in <Shape>-><Appearance> materials(in Assimp logical view)
+ // are stored. So at first we need to count how meshes and materials are stored in scene graph.
+ //
+ // at first creating root node for aiScene.
+ pScene->mRootNode = new aiNode;
+ pScene->mRootNode->mParent = nullptr;
+ pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED;
+ //search for root node element
+ NodeElement_Cur = NodeElement_List.front();
+ while(NodeElement_Cur->Parent != nullptr) NodeElement_Cur = NodeElement_Cur->Parent;
+
+ {// fill aiScene with objects.
+ std::list<aiMesh*> mesh_list;
+ std::list<aiMaterial*> mat_list;
+ std::list<aiLight*> light_list;
+
+ // create nodes tree
+ Postprocess_BuildNode(*NodeElement_Cur, *pScene->mRootNode, mesh_list, mat_list, light_list);
+ // copy needed data to scene
+ if(mesh_list.size() > 0)
+ {
+ std::list<aiMesh*>::const_iterator it = mesh_list.begin();
+
+ pScene->mNumMeshes = static_cast<unsigned int>(mesh_list.size());
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for(size_t i = 0; i < pScene->mNumMeshes; i++) pScene->mMeshes[i] = *it++;
+ }
+
+ if(mat_list.size() > 0)
+ {
+ std::list<aiMaterial*>::const_iterator it = mat_list.begin();
+
+ pScene->mNumMaterials = static_cast<unsigned int>(mat_list.size());
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for(size_t i = 0; i < pScene->mNumMaterials; i++) pScene->mMaterials[i] = *it++;
+ }
+
+ if(light_list.size() > 0)
+ {
+ std::list<aiLight*>::const_iterator it = light_list.begin();
+
+ pScene->mNumLights = static_cast<unsigned int>(light_list.size());
+ pScene->mLights = new aiLight*[pScene->mNumLights];
+ for(size_t i = 0; i < pScene->mNumLights; i++) pScene->mLights[i] = *it++;
+ }
+ }// END: fill aiScene with objects.
+
+ ///TODO: IME optimize tree
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter.hpp b/src/3rdparty/assimp/code/X3DImporter.hpp
new file mode 100644
index 000000000..468db5f3e
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter.hpp
@@ -0,0 +1,833 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter.hpp
+/// \brief X3D-format files importer for Assimp.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+// Thanks to acorn89 for support.
+
+#ifndef INCLUDED_AI_X3D_IMPORTER_H
+#define INCLUDED_AI_X3D_IMPORTER_H
+
+#include "X3DImporter_Node.hpp"
+
+// Header files, Assimp.
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
+#include <assimp/ProgressHandler.hpp>
+#include <assimp/types.h>
+#include "BaseImporter.h"
+#include "irrXMLWrapper.h"
+#include "FIReader.hpp"
+//#include <regex>
+
+namespace Assimp {
+
+/// \class X3DImporter
+/// Class that holding scene graph which include: groups, geometry, metadata etc.
+///
+/// Limitations.
+///
+/// Pay attention that X3D is format for interactive graphic and simulations for web browsers.
+/// So not all features can be imported using Assimp.
+///
+/// Unsupported nodes:
+/// CAD geometry component:
+/// "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet"
+/// Core component:
+/// "ROUTE", "ExternProtoDeclare", "ProtoDeclare", "ProtoInstance", "ProtoInterface", "WorldInfo"
+/// Distributed interactive simulation (DIS) component:
+/// "DISEntityManager", "DISEntityTypeMapping", "EspduTransform", "ReceiverPdu", "SignalPdu", "TransmitterPdu"
+/// Cube map environmental texturing component:
+/// "ComposedCubeMapTexture", "GeneratedCubeMapTexture", "ImageCubeMapTexture"
+/// Environmental effects component:
+/// "Background", "Fog", "FogCoordinate", "LocalFog", "TextureBackground"
+/// Environmental sensor component:
+/// "ProximitySensor", "TransformSensor", "VisibilitySensor"
+/// Followers component:
+/// "ColorChaser", "ColorDamper", "CoordinateChaser", "CoordinateDamper", "OrientationChaser", "OrientationDamper", "PositionChaser",
+/// "PositionChaser2D", "PositionDamper", "PositionDamper2D", "ScalarChaser", "ScalarDamper", "TexCoordChaser2D", "TexCoordDamper2D"
+/// Geospatial component:
+/// "GeoCoordinate", "GeoElevationGrid", "GeoLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", "GeoProximitySensor",
+/// "GeoTouchSensor", "GeoTransform", "GeoViewpoint"
+/// Humanoid Animation (H-Anim) component:
+/// "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", "HAnimSegment", "HAnimSite"
+/// Interpolation component:
+/// "ColorInterpolator", "CoordinateInterpolator", "CoordinateInterpolator2D", "EaseInEaseOut", "NormalInterpolator", "OrientationInterpolator",
+/// "PositionInterpolator", "PositionInterpolator2D", "ScalarInterpolator", "SplinePositionInterpolator", "SplinePositionInterpolator2D",
+/// "SplineScalarInterpolator", "SquadOrientationInterpolator",
+/// Key device sensor component:
+/// "KeySensor", "StringSensor"
+/// Layering component:
+/// "Layer", "LayerSet", "Viewport"
+/// Layout component:
+/// "Layout", "LayoutGroup", "LayoutLayer", "ScreenFontStyle", "ScreenGroup"
+/// Navigation component:
+/// "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup"
+/// Networking component:
+/// "EXPORT", "IMPORT", "Anchor", "LoadSensor"
+/// NURBS component:
+/// "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
+/// "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
+/// "NurbsTrimmedSurface"
+/// Particle systems component:
+/// "BoundedPhysicsModel", "ConeEmitter", "ExplosionEmitter", "ForcePhysicsModel", "ParticleSystem", "PointEmitter", "PolylineEmitter",
+/// "SurfaceEmitter", "VolumeEmitter", "WindPhysicsModel"
+/// Picking component:
+/// "LinePickSensor", "PickableGroup", "PointPickSensor", "PrimitivePickSensor", "VolumePickSensor"
+/// Pointing device sensor component:
+/// "CylinderSensor", "PlaneSensor", "SphereSensor", "TouchSensor"
+/// Rendering component:
+/// "ClipPlane"
+/// Rigid body physics:
+/// "BallJoint", "CollidableOffset", "CollidableShape", "CollisionCollection", "CollisionSensor", "CollisionSpace", "Contact", "DoubleAxisHingeJoint",
+/// "MotorJoint", "RigidBody", "RigidBodyCollection", "SingleAxisHingeJoint", "SliderJoint", "UniversalJoint"
+/// Scripting component:
+/// "Script"
+/// Programmable shaders component:
+/// "ComposedShader", "FloatVertexAttribute", "Matrix3VertexAttribute", "Matrix4VertexAttribute", "PackagedShader", "ProgramShader", "ShaderPart",
+/// "ShaderProgram",
+/// Shape component:
+/// "FillProperties", "LineProperties", "TwoSidedMaterial"
+/// Sound component:
+/// "AudioClip", "Sound"
+/// Text component:
+/// "FontStyle", "Text"
+/// Texturing3D Component:
+/// "ComposedTexture3D", "ImageTexture3D", "PixelTexture3D", "TextureCoordinate3D", "TextureCoordinate4D", "TextureTransformMatrix3D",
+/// "TextureTransform3D"
+/// Texturing component:
+/// "MovieTexture", "MultiTexture", "MultiTextureCoordinate", "MultiTextureTransform", "PixelTexture", "TextureCoordinateGenerator",
+/// "TextureProperties",
+/// Time component:
+/// "TimeSensor"
+/// Event Utilities component:
+/// "BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "IntegerSequencer", "IntegerTrigger", "TimeTrigger",
+/// Volume rendering component:
+/// "BlendedVolumeStyle", "BoundaryEnhancementVolumeStyle", "CartoonVolumeStyle", "ComposedVolumeStyle", "EdgeEnhancementVolumeStyle",
+/// "IsoSurfaceVolumeData", "OpacityMapVolumeStyle", "ProjectionVolumeStyle", "SegmentedVolumeData", "ShadedVolumeStyle",
+/// "SilhouetteEnhancementVolumeStyle", "ToneMappedVolumeStyle", "VolumeData"
+///
+/// Supported nodes:
+/// Core component:
+/// "MetadataBoolean", "MetadataDouble", "MetadataFloat", "MetadataInteger", "MetadataSet", "MetadataString"
+/// Geometry2D component:
+/// "Arc2D", "ArcClose2D", "Circle2D", "Disk2D", "Polyline2D", "Polypoint2D", "Rectangle2D", "TriangleSet2D"
+/// Geometry3D component:
+/// "Box", "Cone", "Cylinder", "ElevationGrid", "Extrusion", "IndexedFaceSet", "Sphere"
+/// Grouping component:
+/// "Group", "StaticGroup", "Switch", "Transform"
+/// Lighting component:
+/// "DirectionalLight", "PointLight", "SpotLight"
+/// Networking component:
+/// "Inline"
+/// Rendering component:
+/// "Color", "ColorRGBA", "Coordinate", "IndexedLineSet", "IndexedTriangleFanSet", "IndexedTriangleSet", "IndexedTriangleStripSet", "LineSet",
+/// "PointSet", "TriangleFanSet", "TriangleSet", "TriangleStripSet", "Normal"
+/// Shape component:
+/// "Shape", "Appearance", "Material"
+/// Texturing component:
+/// "ImageTexture", "TextureCoordinate", "TextureTransform"
+///
+/// Limitations of attribute "USE".
+/// If "USE" is set then node must be empty, like that:
+/// <Node USE='name'/>
+/// not the
+/// <Node USE='name'><!-- something --> </Node>
+///
+/// Ignored attributes: "creaseAngle", "convex", "solid".
+///
+/// Texture coordinates generating: only for Sphere, Cone, Cylinder. In all other case used PLANE mapping.
+/// It's better that Assimp main code has powerful texture coordinates generator. Then is not needed to
+/// duplicate this code in every importer.
+///
+/// Lighting limitations.
+/// If light source placed in some group with "DEF" set. And after that some node is use it group with "USE" attribute then
+/// you will get error about duplicate light sources. That's happening because Assimp require names for lights but do not like
+/// duplicates of it )).
+///
+/// Color for faces.
+/// That's happening when attribute "colorPerVertex" is set to "false". But Assimp do not hold how many colors has mesh and require
+/// equal length for mVertices and mColors. You will see the colors but vertices will use call which last used in "colorIdx".
+///
+/// That's all for now. Enjoy
+///
+class X3DImporter : public BaseImporter
+{
+public:
+ std::list<CX3DImporter_NodeElement*> NodeElement_List;///< All elements of scene graph.
+
+public:
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+ /// Default constructor.
+ X3DImporter();
+
+ /// Default destructor.
+ ~X3DImporter();
+
+ /***********************************************/
+ /******** Functions: parse set, public *********/
+ /***********************************************/
+
+ /// Parse X3D file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
+ /// Also exception can be thrown if trouble will found.
+ /// \param [in] pFile - name of file to be parsed.
+ /// \param [in] pIOHandler - pointer to IO helper object.
+ void ParseFile( const std::string& pFile, IOSystem* pIOHandler );
+
+ /***********************************************/
+ /********* Functions: BaseImporter set *********/
+ /***********************************************/
+
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig ) const;
+ void GetExtensionList( std::set<std::string>& pExtensionList );
+ void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
+ const aiImporterDesc* GetInfo()const;
+
+
+private:
+ /// Disabled copy constructor.
+ X3DImporter(const X3DImporter& pScene);
+
+ /// Disabled assign operator.
+ X3DImporter& operator=(const X3DImporter& pScene);
+
+ /// Clear all temporary data.
+ void Clear();
+
+ /***********************************************/
+ /************* Functions: find set *************/
+ /***********************************************/
+
+ /// Find requested node element. Search will be made in all existing nodes.
+ /// \param [in] pID - ID of requested element.
+ /// \param [in] pType - type of requested element.
+ /// \param [out] pElement - pointer to pointer to item found.
+ /// \return true - if the element is found, else - false.
+ bool FindNodeElement_FromRoot(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement);
+
+ /// Find requested node element. Search will be made from pointed node down to childs.
+ /// \param [in] pStartNode - pointer to start node.
+ /// \param [in] pID - ID of requested element.
+ /// \param [in] pType - type of requested element.
+ /// \param [out] pElement - pointer to pointer to item found.
+ /// \return true - if the element is found, else - false.
+ bool FindNodeElement_FromNode(CX3DImporter_NodeElement* pStartNode, const std::string& pID, const CX3DImporter_NodeElement::EType pType,
+ CX3DImporter_NodeElement** pElement);
+
+ /// Find requested node element. For "Node"'s accounting flag "Static".
+ /// \param [in] pName - name of requested element.
+ /// \param [in] pType - type of requested element.
+ /// \param [out] pElement - pointer to pointer to item found.
+ /// \return true - if the element is found, else - false.
+ bool FindNodeElement(const std::string& pName, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement);
+
+ /***********************************************/
+ /********* Functions: postprocess set **********/
+ /***********************************************/
+
+ /// \return transformation matrix from global coordinate system to local.
+ aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const;
+
+ /// Check if child elements of node element is metadata and add it to temporary list.
+ /// \param [in] pNodeElement - node element where metadata is searching.
+ /// \param [out] pList - temporary list for collected metadata.
+ void PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const;
+
+ /// Check if type of node element is metadata. E.g. <MetadataSet>, <MetadataString>.
+ /// \param [in] pType - checked type.
+ /// \return true - if the type corresponds to the metadata.
+ bool PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const;
+
+ /// Check if type of node element is geometry object and can be used to build mesh. E.g. <Box>, <Arc2D>.
+ /// \param [in] pType - checked type.
+ /// \return true - if the type corresponds to the mesh.
+ bool PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const;
+
+ /// Read CX3DImporter_NodeElement_Light, create aiLight and add it to list of the lights.
+ /// \param [in] pNodeElement - reference to lisght element(<DirectionalLight>, <PointLight>, <SpotLight>).
+ /// \param [out] pSceneLightList - reference to list of the lights.
+ void Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const;
+
+ /// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
+ /// all needed data from scene graph.
+ /// \param [in] pNodeElement - reference to material element(<Appearance>).
+ /// \param [out] pMaterial - pointer to pointer to created material. *pMaterial must be nullptr.
+ void Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const;
+
+ /// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
+ /// all needed data from scene graph.
+ /// \param [in] pNodeElement - reference to geometry object.
+ /// \param [out] pMesh - pointer to pointer to created mesh. *pMesh must be nullptr.
+ void Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const;
+
+ /// Create aiNode from CX3DImporter_NodeElement. Also function check children and make recursive call.
+ /// \param [out] pNode - pointer to pointer to created node. *pNode must be nullptr.
+ /// \param [in] pNodeElement - CX3DImporter_NodeElement which read.
+ /// \param [out] pSceneNode - aiNode for filling.
+ /// \param [out] pSceneMeshList - list with aiMesh which belong to scene.
+ /// \param [out] pSceneMaterialList - list with aiMaterial which belong to scene.
+ /// \param [out] pSceneLightList - list with aiLight which belong to scene.
+ void Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
+ std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const;
+
+ /// To create mesh and material kept in <Schape>.
+ /// \param pShapeNodeElement - reference to node element which kept <Shape> data.
+ /// \param pNodeMeshInd - reference to list with mesh indices. When pShapeNodeElement will read new mesh index will be added to this list.
+ /// \param pSceneMeshList - reference to list with meshes. When pShapeNodeElement will read new mesh will be added to this list.
+ /// \param pSceneMaterialList - reference to list with materials. When pShapeNodeElement will read new material will be added to this list.
+ void Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
+ std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const;
+
+ /// Check if child elements of node element is metadata and add it to scene node.
+ /// \param [in] pNodeElement - node element where metadata is searching.
+ /// \param [out] pSceneNode - scene node in which metadata will be added.
+ void Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode) const;
+
+ /***********************************************/
+ /************* Functions: throw set ************/
+ /***********************************************/
+
+ /// Call that function when argument is out of range and exception must be raised.
+ /// \throw DeadlyImportError.
+ /// \param [in] pArgument - argument name.
+ void Throw_ArgOutOfRange(const std::string& pArgument);
+
+ /// Call that function when close tag of node not found and exception must be raised.
+ /// E.g.:
+ /// <Scene>
+ /// <Shape>
+ /// </Scene> <!--- shape not closed --->
+ /// \throw DeadlyImportError.
+ /// \param [in] pNode - node name in which exception happened.
+ void Throw_CloseNotFound(const std::string& pNode);
+
+ /// Call that function when string value can not be converted to floating point value and exception must be raised.
+ /// \param [in] pAttrValue - attribute value.
+ /// \throw DeadlyImportError.
+ void Throw_ConvertFail_Str2ArrF(const std::string& pAttrValue);
+
+ /// Call that function when in node defined attributes "DEF" and "USE" and exception must be raised.
+ /// E.g.: <Box DEF="BigBox" USE="MegaBox">
+ /// \throw DeadlyImportError.
+ void Throw_DEF_And_USE();
+
+ /// Call that function when attribute name is incorrect and exception must be raised.
+ /// \param [in] pAttrName - attribute name.
+ /// \throw DeadlyImportError.
+ void Throw_IncorrectAttr(const std::string& pAttrName);
+
+ /// Call that function when attribute value is incorrect and exception must be raised.
+ /// \param [in] pAttrName - attribute name.
+ /// \throw DeadlyImportError.
+ void Throw_IncorrectAttrValue(const std::string& pAttrName);
+
+ /// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised.
+ /// E.g.:
+ /// <Shape>
+ /// <Box/> <!--- first geometry node --->
+ /// <Sphere/> <!--- second geometry node. raise exception --->
+ /// </Shape>
+ /// \throw DeadlyImportError.
+ /// \param [in] pNodeType - type of node which defined one more time.
+ /// \param [in] pDescription - message about error. E.g. what the node defined while exception raised.
+ void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription);
+
+ /// Call that function when count of opening and closing tags which create group(e.g. <Group>) are not equal and exception must be raised.
+ /// E.g.:
+ /// <Scene>
+ /// <Transform> <!--- first grouping node begin --->
+ /// <Group> <!--- second grouping node begin --->
+ /// </Transform> <!--- first grouping node end --->
+ /// </Scene> <!--- one grouping node still not closed --->
+ /// \throw DeadlyImportError.
+ /// \param [in] pNode - node name in which exception happened.
+ void Throw_TagCountIncorrect(const std::string& pNode);
+
+ /// Call that function when defined in "USE" element are not found in graph and exception must be raised.
+ /// \param [in] pAttrValue - "USE" attribute value.
+ /// \throw DeadlyImportError.
+ void Throw_USE_NotFound(const std::string& pAttrValue);
+
+ /***********************************************/
+ /************** Functions: LOG set *************/
+ /***********************************************/
+
+ /// Short variant for calling \ref DefaultLogger::get()->info()
+ void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
+
+ /***********************************************/
+ /************** Functions: XML set *************/
+ /***********************************************/
+
+ /// Check if current node is empty: <node />. If not then exception will throwed.
+ void XML_CheckNode_MustBeEmpty();
+
+ /// Check if current node name is equal to pNodeName.
+ /// \param [in] pNodeName - name for checking.
+ /// return true if current node name is equal to pNodeName, else - false.
+ bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
+
+ /// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
+ /// \param [in] pParentNodeName - parent node name. Used for reporting.
+ void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName);
+
+ /// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
+ /// \param [in] pNodeName - requested node name.
+ /// return true - if node is found, else - false.
+ bool XML_SearchNode(const std::string& pNodeName);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \return read data.
+ bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \return read data.
+ float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \return read data.
+ int32_t XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue);
+
+ /// \overload void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue)
+ void XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue);
+
+ /// \overload void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
+ void XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::vector<aiColor4D>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue);
+
+ /// \overload void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
+ void XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::vector<aiVector2D>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue);
+
+ /// \overload void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
+ void XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::vector<aiVector3D>& pValue);
+
+ /// Read attribute value.
+ /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
+ /// \param [out] pValue - read data.
+ void XML_ReadNode_GetAttrVal_AsListS(const int pAttrIdx, std::list<std::string>& pValue);
+
+ /***********************************************/
+ /******* Functions: geometry helper set *******/
+ /***********************************************/
+
+ /// Make point on surface oXY.
+ /// \param [in] pAngle - angle in radians between radius-vector of point and oX axis. Angle extends from the oX axis counterclockwise to the radius-vector.
+ /// \param [in] pRadius - length of radius-vector.
+ /// \return made point coordinates.
+ aiVector3D GeometryHelper_Make_Point2D(const float pAngle, const float pRadius);
+
+ /// Make 2D figure - linear circular arc with center in (0, 0). The z-coordinate is 0. The arc extends from the pStartAngle counterclockwise
+ /// to the pEndAngle. If pStartAngle and pEndAngle have the same value, a circle is specified. If the absolute difference between pStartAngle
+ /// and pEndAngle is greater than or equal to 2pi, a circle is specified.
+ /// \param [in] pStartAngle - angle in radians of start of the arc.
+ /// \param [in] pEndAngle - angle in radians of end of the arc.
+ /// \param [in] pRadius - radius of the arc.
+ /// \param [out] pNumSegments - number of segments in arc. In other words - tesselation factor.
+ /// \param [out] pVertices - generated vertices.
+ void GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments, std::list<aiVector3D>& pVertices);
+
+ /// Create line set from point set.
+ /// \param [in] pPoint - input points list.
+ /// \param [out] pLine - made lines list.
+ void GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>& pPoint, std::list<aiVector3D>& pLine);
+
+ /// Create CoordIdx of line set from CoordIdx of polyline set.
+ /// \param [in] pPolylineCoordIdx - vertices indices divided by delimiter "-1". Must contain faces with two or more indices.
+ /// \param [out] pLineCoordIdx - made CoordIdx of line set.
+ void GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int32_t>& pPolylineCoordIdx, std::list<int32_t>& pLineCoordIdx);
+
+ /// Make 3D body - rectangular parallelepiped with center in (0, 0). QL mean quadlist (\sa pVertices).
+ /// \param [in] pSize - scale factor for body for every axis. E.g. (1, 2, 1) mean: X-size and Z-size - 1, Y-size - 2.
+ /// \param [out] pVertices - generated vertices. The list of vertices is grouped in quads.
+ void GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSize, std::list<aiVector3D>& pVertices);
+
+ /// Create faces array from vertices indices array.
+ /// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
+ /// \param [in] pFaces - created faces array.
+ /// \param [in] pPrimitiveTypes - type of primitives in faces.
+ void GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const;
+
+ /// Add colors to mesh.
+ /// a. If colorPerVertex is FALSE, colours are applied to each face, as follows:
+ /// If the colorIndex field is not empty, one colour is used for each face of the mesh. There shall be at least as many indices in the
+ /// colorIndex field as there are faces in the mesh. The colorIndex field shall not contain any negative entries.
+ /// If the colorIndex field is empty, the colours in the X3DColorNode node are applied to each face of the mesh in order.
+ /// There shall be at least as many colours in the X3DColorNode node as there are faces.
+ /// b. If colorPerVertex is TRUE, colours are applied to each vertex, as follows:
+ /// If the colorIndex field is not empty, colours are applied to each vertex of the mesh in exactly the same manner that the coordIndex
+ /// field is used to choose coordinates for each vertex from the <Coordinate> node. The colorIndex field shall contain end-of-face markers (-1)
+ /// in exactly the same places as the coordIndex field.
+ /// If the colorIndex field is empty, the coordIndex field is used to choose colours from the X3DColorNode node.
+ /// \param [in] pMesh - mesh for adding data.
+ /// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
+ /// \param [in] pColorIdx - color indices for every vertex divided by delimiter "-1" if \ref pColorPerVertex is true. if \ref pColorPerVertex is false
+ /// then pColorIdx contain color indices for every faces and must not contain delimiter "-1".
+ /// \param [in] pColors - defined colors.
+ /// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
+ void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
+ const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
+
+ /// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
+ void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
+ const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
+
+ /// Add colors to mesh.
+ /// \param [in] pMesh - mesh for adding data.
+ /// \param [in] pColors - defined colors.
+ /// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
+ void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
+
+ /// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
+ void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
+
+ /// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
+ void MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pNormalIdx,
+ const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
+
+ /// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
+ void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
+
+ /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
+ void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pTexCoordIdx,
+ const std::list<aiVector2D>& pTexCoords) const;
+
+ /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
+ void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVector2D>& pTexCoords) const;
+
+ /// Create mesh.
+ /// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
+ /// \param [in] pVertices - vertices of mesh.
+ /// \return created mesh.
+ aiMesh* GeometryHelper_MakeMesh(const std::vector<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const;
+
+ /***********************************************/
+ /******** Functions: parse set private *********/
+ /***********************************************/
+
+ /// Create node element with type "Node" in scene graph. That operation is needed when you enter to X3D group node
+ /// like <Group>, <Transform> etc. When exiting from X3D group node(e.g. </Group>) \ref ParseHelper_Node_Exit must
+ /// be called.
+ /// \param [in] pStatic - flag: if true then static node is created(e.g. <StaticGroup>).
+ void ParseHelper_Group_Begin(const bool pStatic = false);
+
+ /// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
+ /// \param [in] pNode - new current node.
+ void ParseHelper_Node_Enter(CX3DImporter_NodeElement* pNode);
+
+ /// This function must be called when exiting from X3D group node(e.g. </Group>). \ref ParseHelper_Group_Begin.
+ void ParseHelper_Node_Exit();
+
+ /// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
+ /// must be converted to right form - "0.xxx".
+ /// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
+ /// \param [out[ pOutString - output string with right form of values.
+ void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
+
+ /// Check if current node has nodes of type X3DMetadataObject. Why we must do it? Because X3DMetadataObject can be in any non-empty X3DNode.
+ /// Meaning that X3DMetadataObject can be in any non-empty node in <Scene>.
+ /// \return true - if metadata node are found and parsed, false - metadata not found.
+ bool ParseHelper_CheckRead_X3DMetadataObject();
+
+ /// Check if current node has nodes of type X3DGeometricPropertyNode. X3DGeometricPropertyNode
+ /// X3DGeometricPropertyNode inheritors:
+ /// <FogCoordinate>, <HAnimDisplacer>, <Color>, <ColorRGBA>, <Coordinate>, <CoordinateDouble>, <GeoCoordinate>, <Normal>,
+ /// <MultiTextureCoordinate>, <TextureCoordinate>, <TextureCoordinate3D>, <TextureCoordinate4D>, <TextureCoordinateGenerator>,
+ /// <FloatVertexAttribute>, <Matrix3VertexAttribute>, <Matrix4VertexAttribute>.
+ /// \return true - if nodes are found and parsed, false - nodes not found.
+ bool ParseHelper_CheckRead_X3DGeometricPropertyNode();
+
+ /// Parse <X3D> node of the file.
+ void ParseNode_Root();
+
+ /// Parse <head> node of the file.
+ void ParseNode_Head();
+
+ /// Parse <Scene> node of the file.
+ void ParseNode_Scene();
+
+ /// Parse child nodes of <Metadata*> node.
+ /// \param [in] pNodeName - parsed node name. Must be set because that function is general and name needed for checking the end
+ /// and error reporing.
+ /// \param [in] pParentElement - parent metadata element.
+ void ParseNode_Metadata(CX3DImporter_NodeElement* pParentElement, const std::string& pNodeName);
+
+ /// Parse <MetadataBoolean> node of the file.
+ void ParseNode_MetadataBoolean();
+
+ /// Parse <MetadataDouble> node of the file.
+ void ParseNode_MetadataDouble();
+
+ /// Parse <MetadataFloat> node of the file.
+ void ParseNode_MetadataFloat();
+
+ /// Parse <MetadataInteger> node of the file.
+ void ParseNode_MetadataInteger();
+
+ /// Parse <MetadataSet> node of the file.
+ void ParseNode_MetadataSet();
+
+ /// \fn void ParseNode_MetadataString()
+ /// Parse <MetadataString> node of the file.
+ void ParseNode_MetadataString();
+
+ /// Parse <Arc2D> node of the file.
+ void ParseNode_Geometry2D_Arc2D();
+
+ /// Parse <ArcClose2D> node of the file.
+ void ParseNode_Geometry2D_ArcClose2D();
+
+ /// Parse <Circle2D> node of the file.
+ void ParseNode_Geometry2D_Circle2D();
+
+ /// Parse <Disk2D> node of the file.
+ void ParseNode_Geometry2D_Disk2D();
+
+ /// Parse <Polyline2D> node of the file.
+ void ParseNode_Geometry2D_Polyline2D();
+
+ /// Parse <Polypoint2D> node of the file.
+ void ParseNode_Geometry2D_Polypoint2D();
+
+ /// Parse <Rectangle2D> node of the file.
+ void ParseNode_Geometry2D_Rectangle2D();
+
+ /// Parse <TriangleSet2D> node of the file.
+ void ParseNode_Geometry2D_TriangleSet2D();
+
+ /// Parse <Box> node of the file.
+ void ParseNode_Geometry3D_Box();
+
+ /// Parse <Cone> node of the file.
+ void ParseNode_Geometry3D_Cone();
+
+ /// Parse <Cylinder> node of the file.
+ void ParseNode_Geometry3D_Cylinder();
+
+ /// Parse <ElevationGrid> node of the file.
+ void ParseNode_Geometry3D_ElevationGrid();
+
+ /// Parse <Extrusion> node of the file.
+ void ParseNode_Geometry3D_Extrusion();
+
+ /// Parse <IndexedFaceSet> node of the file.
+ void ParseNode_Geometry3D_IndexedFaceSet();
+
+ /// Parse <Sphere> node of the file.
+ void ParseNode_Geometry3D_Sphere();
+
+ /// Parse <Group> node of the file. And create new node in scene graph.
+ void ParseNode_Grouping_Group();
+
+ /// Doing actions at an exit from <Group>. Walk up in scene graph.
+ void ParseNode_Grouping_GroupEnd();
+
+ /// Parse <StaticGroup> node of the file. And create new node in scene graph.
+ void ParseNode_Grouping_StaticGroup();
+
+ /// Doing actions at an exit from <StaticGroup>. Walk up in scene graph.
+ void ParseNode_Grouping_StaticGroupEnd();
+
+ /// Parse <Switch> node of the file. And create new node in scene graph.
+ void ParseNode_Grouping_Switch();
+
+ /// Doing actions at an exit from <Switch>. Walk up in scene graph.
+ void ParseNode_Grouping_SwitchEnd();
+
+ /// Parse <Transform> node of the file. And create new node in scene graph.
+ void ParseNode_Grouping_Transform();
+
+ /// Doing actions at an exit from <Transform>. Walk up in scene graph.
+ void ParseNode_Grouping_TransformEnd();
+
+ /// Parse <Color> node of the file.
+ void ParseNode_Rendering_Color();
+
+ /// Parse <ColorRGBA> node of the file.
+ void ParseNode_Rendering_ColorRGBA();
+
+ /// Parse <Coordinate> node of the file.
+ void ParseNode_Rendering_Coordinate();
+
+ /// Parse <Normal> node of the file.
+ void ParseNode_Rendering_Normal();
+
+ /// Parse <IndexedLineSet> node of the file.
+ void ParseNode_Rendering_IndexedLineSet();
+
+ /// Parse <IndexedTriangleFanSet> node of the file.
+ void ParseNode_Rendering_IndexedTriangleFanSet();
+
+ /// Parse <IndexedTriangleSet> node of the file.
+ void ParseNode_Rendering_IndexedTriangleSet();
+
+ /// Parse <IndexedTriangleStripSet> node of the file.
+ void ParseNode_Rendering_IndexedTriangleStripSet();
+
+ /// Parse <LineSet> node of the file.
+ void ParseNode_Rendering_LineSet();
+
+ /// Parse <PointSet> node of the file.
+ void ParseNode_Rendering_PointSet();
+
+ /// Parse <TriangleFanSet> node of the file.
+ void ParseNode_Rendering_TriangleFanSet();
+
+ /// Parse <TriangleSet> node of the file.
+ void ParseNode_Rendering_TriangleSet();
+
+ /// Parse <TriangleStripSet> node of the file.
+ void ParseNode_Rendering_TriangleStripSet();
+
+ /// Parse <ImageTexture> node of the file.
+ void ParseNode_Texturing_ImageTexture();
+
+ /// Parse <TextureCoordinate> node of the file.
+ void ParseNode_Texturing_TextureCoordinate();
+
+ /// Parse <TextureTransform> node of the file.
+ void ParseNode_Texturing_TextureTransform();
+
+ /// Parse <Shape> node of the file.
+ void ParseNode_Shape_Shape();
+
+ /// Parse <Appearance> node of the file.
+ void ParseNode_Shape_Appearance();
+
+ /// Parse <Material> node of the file.
+ void ParseNode_Shape_Material();
+
+ /// Parse <Inline> node of the file.
+ void ParseNode_Networking_Inline();
+
+ /// Parse <DirectionalLight> node of the file.
+ void ParseNode_Lighting_DirectionalLight();
+
+ /// Parse <PointLight> node of the file.
+ void ParseNode_Lighting_PointLight();
+
+ /// Parse <SpotLight> node of the file.
+ void ParseNode_Lighting_SpotLight();
+
+private:
+ /***********************************************/
+ /******************** Types ********************/
+ /***********************************************/
+
+ /***********************************************/
+ /****************** Constants ******************/
+ /***********************************************/
+ static const aiImporterDesc Description;
+ //static const std::regex pattern_nws;
+ //static const std::regex pattern_true;
+
+
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+ CX3DImporter_NodeElement* NodeElement_Cur;///< Current element.
+ std::unique_ptr<FIReader> mReader;///< Pointer to XML-reader object
+ IOSystem *mpIOHandler;
+};// class X3DImporter
+
+}// namespace Assimp
+
+#endif // INCLUDED_AI_X3D_IMPORTER_H
diff --git a/src/3rdparty/assimp/code/X3DImporter_Geometry2D.cpp b/src/3rdparty/assimp/code/X3DImporter_Geometry2D.cpp
new file mode 100644
index 000000000..895ba8798
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Geometry2D.cpp
@@ -0,0 +1,521 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Geometry2D.cpp
+/// \brief Parsing data from nodes of "Geometry2D" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Node.hpp"
+#include "X3DImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <Arc2D
+// DEF="" ID
+// USE="" IDREF
+// endAngle="1.570796" SFFloat [initializeOnly]
+// radius="1" SFFloat [initializeOnly]
+// startAngle="0" SFFloat [initializeOnly]
+// />
+// The Arc2D node specifies a linear circular arc whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
+// towards the positive y-axis. The radius field specifies the radius of the circle of which the arc is a portion. The arc extends from the startAngle
+// counterclockwise to the endAngle. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different
+// angle base unit has been specified). If startAngle and endAngle have the same value, a circle is specified.
+void X3DImporter::ParseNode_Geometry2D_Arc2D()
+{
+ std::string def, use;
+ float endAngle = AI_MATH_HALF_PI_F;
+ float radius = 1;
+ float startAngle = 0;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Arc2D, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Arc2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // create point list of geometry object and convert it to line set.
+ std::list<aiVector3D> tlist;
+
+ GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
+ GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Arc2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <ArcClose2D
+// DEF="" ID
+// USE="" IDREF
+// closureType="PIE" SFString [initializeOnly], {"PIE", "CHORD"}
+// endAngle="1.570796" SFFloat [initializeOnly]
+// radius="1" SFFloat [initializeOnly]
+// solid="false" SFBool [initializeOnly]
+// startAngle="0" SFFloat [initializeOnly]
+// />
+// The ArcClose node specifies a portion of a circle whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
+// towards the positive y-axis. The end points of the arc specified are connected as defined by the closureType field. The radius field specifies the radius
+// of the circle of which the arc is a portion. The arc extends from the startAngle counterclockwise to the endAngle. The value of radius shall be greater
+// than zero. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different default angle base unit has
+// been specified). If startAngle and endAngle have the same value, a circle is specified and closureType is ignored. If the absolute difference between
+// startAngle and endAngle is greater than or equal to 2pi, a complete circle is produced with no chord or radial line(s) drawn from the center.
+// A closureType of "PIE" connects the end point to the start point by defining two straight line segments first from the end point to the center and then
+// the center to the start point. A closureType of "CHORD" connects the end point to the start point by defining a straight line segment from the end point
+// to the start point. Textures are applied individually to each face of the ArcClose2D. On the front (+Z) and back (-Z) faces of the ArcClose2D, when
+// viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
+void X3DImporter::ParseNode_Geometry2D_ArcClose2D()
+{
+ std::string def, use;
+ std::string closureType("PIE");
+ float endAngle = AI_MATH_HALF_PI_F;
+ float radius = 1;
+ bool solid = false;
+ float startAngle = 0;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("closureType", closureType, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_ArcClose2D, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_ArcClose2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
+ // create point list of geometry object.
+ GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);///TODO: IME - AI_CONFIG for NumSeg
+ // add chord or two radiuses only if not a circle was defined
+ if(!((std::fabs(endAngle - startAngle) >= AI_MATH_TWO_PI_F) || (endAngle == startAngle)))
+ {
+ std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices;// just short alias.
+
+ if((closureType == "PIE") || (closureType == "\"PIE\""))
+ vlist.push_back(aiVector3D(0, 0, 0));// center point - first radial line
+ else if((closureType != "CHORD") && (closureType != "\"CHORD\""))
+ Throw_IncorrectAttrValue("closureType");
+
+ vlist.push_back(*vlist.begin());// arc first point - chord from first to last point of arc(if CHORD) or second radial line(if PIE).
+ }
+
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.size();
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "ArcClose2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Circle2D
+// DEF="" ID
+// USE="" IDREF
+// radius="1" SFFloat [initializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry2D_Circle2D()
+{
+ std::string def, use;
+ float radius = 1;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Circle2D, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Circle2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // create point list of geometry object and convert it to line set.
+ std::list<aiVector3D> tlist;
+
+ GeometryHelper_Make_Arc2D(0, 0, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
+ GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Circle2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Disk2D
+// DEF="" ID
+// USE="" IDREF
+// innerRadius="0" SFFloat [initializeOnly]
+// outerRadius="1" SFFloat [initializeOnly]
+// solid="false" SFBool [initializeOnly]
+// />
+// The Disk2D node specifies a circular disk which is centred at (0, 0) in the local coordinate system. The outerRadius field specifies the radius of the
+// outer dimension of the Disk2D. The innerRadius field specifies the inner dimension of the Disk2D. The value of outerRadius shall be greater than zero.
+// The value of innerRadius shall be greater than or equal to zero and less than or equal to outerRadius. If innerRadius is zero, the Disk2D is completely
+// filled. Otherwise, the area within the innerRadius forms a hole in the Disk2D. If innerRadius is equal to outerRadius, a solid circular line shall
+// be drawn using the current line properties. Textures are applied individually to each face of the Disk2D. On the front (+Z) and back (-Z) faces of
+// the Disk2D, when viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
+void X3DImporter::ParseNode_Geometry2D_Disk2D()
+{
+ std::string def, use;
+ float innerRadius = 0;
+ float outerRadius = 1;
+ bool solid = false;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("innerRadius", innerRadius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("outerRadius", outerRadius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Disk2D, ne);
+ }
+ else
+ {
+ std::list<aiVector3D> tlist_o, tlist_i;
+
+ if(innerRadius > outerRadius) Throw_IncorrectAttrValue("innerRadius");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Disk2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // create point list of geometry object.
+ ///TODO: IME - AI_CONFIG for NumSeg
+ GeometryHelper_Make_Arc2D(0, 0, outerRadius, 10, tlist_o);// outer circle
+ if(innerRadius == 0.0f)
+ {// make filled disk
+ // in tlist_o we already have points of circle. just copy it and sign as polygon.
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices = tlist_o;
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = tlist_o.size();
+ }
+ else if(innerRadius == outerRadius)
+ {// make circle
+ // in tlist_o we already have points of circle. convert it to line set.
+ GeometryHelper_Extend_PointToLine(tlist_o, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
+ }
+ else
+ {// make disk
+ std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices;// just short alias.
+
+ GeometryHelper_Make_Arc2D(0, 0, innerRadius, 10, tlist_i);// inner circle
+ //
+ // create quad list from two point lists
+ //
+ if(tlist_i.size() < 2) throw DeadlyImportError("Disk2D. Not enough points for creating quad list.");// tlist_i and tlist_o has equal size.
+
+ // add all quads except last
+ for(std::list<aiVector3D>::iterator it_i = tlist_i.begin(), it_o = tlist_o.begin(); it_i != tlist_i.end();)
+ {
+ // do not forget - CCW direction
+ vlist.push_back(*it_i++);// 1st point
+ vlist.push_back(*it_o++);// 2nd point
+ vlist.push_back(*it_o);// 3rd point
+ vlist.push_back(*it_i);// 4th point
+ }
+
+ // add last quad
+ vlist.push_back(*tlist_i.end());// 1st point
+ vlist.push_back(*tlist_o.end());// 2nd point
+ vlist.push_back(*tlist_o.begin());// 3rd point
+ vlist.push_back(*tlist_o.begin());// 4th point
+
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 4;
+ }
+
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Disk2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Polyline2D
+// DEF="" ID
+// USE="" IDREF
+// lineSegments="" MFVec2F [intializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry2D_Polyline2D()
+{
+ std::string def, use;
+ std::list<aiVector2D> lineSegments;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("lineSegments", lineSegments, XML_ReadNode_GetAttrVal_AsListVec2f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polyline2D, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Polyline2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ //
+ // convert read point list of geometry object to line set.
+ //
+ std::list<aiVector3D> tlist;
+
+ // convert vec2 to vec3
+ for(std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); it2++) tlist.push_back(aiVector3D(it2->x, it2->y, 0));
+
+ // convert point set to line set
+ GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Polyline2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Polypoint2D
+// DEF="" ID
+// USE="" IDREF
+// point="" MFVec2F [inputOutput]
+// />
+void X3DImporter::ParseNode_Geometry2D_Polypoint2D()
+{
+ std::string def, use;
+ std::list<aiVector2D> point;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polypoint2D, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Polypoint2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // convert vec2 to vec3
+ for(std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); it2++)
+ {
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
+ }
+
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 1;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Polypoint2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Rectangle2D
+// DEF="" ID
+// USE="" IDREF
+// size="2 2" SFVec2f [initializeOnly]
+// solid="false" SFBool [initializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry2D_Rectangle2D()
+{
+ std::string def, use;
+ aiVector2D size(2, 2);
+ bool solid = false;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec2f);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Rectangle2D, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Rectangle2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ float x1 = -size.x / 2.0f;
+ float x2 = size.x / 2.0f;
+ float y1 = -size.y / 2.0f;
+ float y2 = size.y / 2.0f;
+ std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices;// just short alias.
+
+ vlist.push_back(aiVector3D(x2, y1, 0));// 1st point
+ vlist.push_back(aiVector3D(x2, y2, 0));// 2nd point
+ vlist.push_back(aiVector3D(x1, y2, 0));// 3rd point
+ vlist.push_back(aiVector3D(x1, y1, 0));// 4th point
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 4;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Rectangle2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <TriangleSet2D
+// DEF="" ID
+// USE="" IDREF
+// solid="false" SFBool [initializeOnly]
+// vertices="" MFVec2F [inputOutput]
+// />
+void X3DImporter::ParseNode_Geometry2D_TriangleSet2D()
+{
+ std::string def, use;
+ bool solid = false;
+ std::list<aiVector2D> vertices;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("vertices", vertices, XML_ReadNode_GetAttrVal_AsListVec2f);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet2D, ne);
+ }
+ else
+ {
+ if(vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_TriangleSet2D, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // convert vec2 to vec3
+ for(std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); it2++)
+ {
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
+ }
+
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
+ ((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 3;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "TriangleSet2D");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Geometry3D.cpp b/src/3rdparty/assimp/code/X3DImporter_Geometry3D.cpp
new file mode 100644
index 000000000..b2e9a28f8
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Geometry3D.cpp
@@ -0,0 +1,998 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Geometry3D.cpp
+/// \brief Parsing data from nodes of "Geometry3D" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+// Header files, Assimp.
+#include "StandardShapes.h"
+
+namespace Assimp
+{
+
+// <Box
+// DEF="" ID
+// USE="" IDREF
+// size="2 2 2" SFVec3f [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// />
+// The Box node specifies a rectangular parallelepiped box centred at (0, 0, 0) in the local coordinate system and aligned with the local coordinate axes.
+// By default, the box measures 2 units in each dimension, from -1 to +1. The size field specifies the extents of the box along the X-, Y-, and Z-axes
+// respectively and each component value shall be greater than zero.
+void X3DImporter::ParseNode_Geometry3D_Box()
+{
+ std::string def, use;
+ bool solid = true;
+ aiVector3D size(2, 2, 2);
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Box, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Box, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ GeometryHelper_MakeQL_RectParallelepiped(size, ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices);// get quad list
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 4;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Box");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Cone
+// DEF="" ID
+// USE="" IDREF
+// bottom="true" SFBool [initializeOnly]
+// bottomRadius="1" SFloat [initializeOnly]
+// height="2" SFloat [initializeOnly]
+// side="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry3D_Cone()
+{
+ std::string use, def;
+ bool bottom = true;
+ float bottomRadius = 1;
+ float height = 2;
+ bool side = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("bottomRadius", bottomRadius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cone, ne);
+ }
+ else
+ {
+ const unsigned int tess = 30;///TODO: IME tesselation factor through ai_property
+
+ std::vector<aiVector3D> tvec;// temp array for vertices.
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Cone, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // make cone or parts according to flags.
+ if(side)
+ {
+ StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
+ }
+ else if(bottom)
+ {
+ StandardShapes::MakeCircle(bottomRadius, tess, tvec);
+ height = -(height / 2);
+ for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); it++) it->y = height;// y - because circle made in oXZ.
+ }
+
+ // copy data from temp array
+ for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); it++) ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it);
+
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Cone");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Cylinder
+// DEF="" ID
+// USE="" IDREF
+// bottom="true" SFBool [initializeOnly]
+// height="2" SFloat [initializeOnly]
+// radius="1" SFloat [initializeOnly]
+// side="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// top="true" SFBool [initializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry3D_Cylinder()
+{
+ std::string use, def;
+ bool bottom = true;
+ float height = 2;
+ float radius = 1;
+ bool side = true;
+ bool solid = true;
+ bool top = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("top", top, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cylinder, ne);
+ }
+ else
+ {
+ const unsigned int tess = 30;///TODO: IME tesselation factor through ai_property
+
+ std::vector<aiVector3D> tside;// temp array for vertices of side.
+ std::vector<aiVector3D> tcir;// temp array for vertices of circle.
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Cylinder, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // make cilynder or parts according to flags.
+ if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true);
+
+ height /= 2;// height defined for whole cylinder, when creating top and bottom circle we are using just half of height.
+ if(top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
+ // copy data from temp arrays
+ std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices;// just short alias.
+
+ for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); it++) vlist.push_back(*it);
+
+ if(top)
+ {
+ for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); it++)
+ {
+ (*it).y = height;// y - because circle made in oXZ.
+ vlist.push_back(*it);
+ }
+ }// if(top)
+
+ if(bottom)
+ {
+ for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); it++)
+ {
+ (*it).y = -height;// y - because circle made in oXZ.
+ vlist.push_back(*it);
+ }
+ }// if(top)
+
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Cylinder");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <ElevationGrid
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// creaseAngle="0" SFloat [initializeOnly]
+// height="" MFloat [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// xDimension="0" SFInt32 [initializeOnly]
+// xSpacing="1.0" SFloat [initializeOnly]
+// zDimension="0" SFInt32 [initializeOnly]
+// zSpacing="1.0" SFloat [initializeOnly]
+// >
+// <!-- ColorNormalTexCoordContentModel -->
+// ColorNormalTexCoordContentModel can contain Color (or ColorRGBA), Normal and TextureCoordinate, in any order. No more than one instance of any single
+// node type is allowed. A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </ElevationGrid>
+// The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described
+// by a scalar array of height values that specify the height of a surface above each point of the grid. The xDimension and zDimension fields indicate
+// the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension shall be greater than or equal to zero.
+// If either the xDimension or the zDimension is less than two, the ElevationGrid contains no quadrilaterals.
+void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ float creaseAngle = 0;
+ std::vector<float> height;
+ bool normalPerVertex = true;
+ bool solid = true;
+ int32_t xDimension = 0;
+ float xSpacing = 1;
+ int32_t zDimension = 0;
+ float zSpacing = 1;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsArrF);
+ MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
+ MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
+ MACRO_ATTRREAD_CHECK_RET("zSpacing", zSpacing, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_ElevationGrid, ne);
+ }
+ else
+ {
+ if((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
+ if((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
+ if((size_t)(xDimension * zDimension) != height.size()) Throw_IncorrectAttrValue("Heights count must be equal to \"xDimension * zDimension\"");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_ElevationGrid(CX3DImporter_NodeElement::ENET_ElevationGrid, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_ElevationGrid& grid_alias = *((CX3DImporter_NodeElement_ElevationGrid*)ne);// create alias for conveience
+
+ {// create grid vertices list
+ std::vector<float>::const_iterator he_it = height.begin();
+
+ for(int32_t zi = 0; zi < zDimension; zi++)// rows
+ {
+ for(int32_t xi = 0; xi < xDimension; xi++)// columns
+ {
+ aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
+
+ grid_alias.Vertices.push_back(tvec);
+ he_it++;
+ }
+ }
+ }// END: create grid vertices list
+ //
+ // create faces list. In "coordIdx" format
+ //
+ // check if we have quads
+ if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set.
+ {
+ ((CX3DImporter_NodeElement_ElevationGrid*)ne)->NumIndices = 2;// will be holded as line set.
+ for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++)
+ {
+ grid_alias.CoordIdx.push_back(static_cast<int32_t>(i));
+ grid_alias.CoordIdx.push_back(static_cast<int32_t>(i + 1));
+ grid_alias.CoordIdx.push_back(-1);
+ }
+ }
+ else// two or more elements in every dimension is set. create quad set.
+ {
+ ((CX3DImporter_NodeElement_ElevationGrid*)ne)->NumIndices = 4;
+ for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows
+ {
+ for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)// columns
+ {
+ // points direction in face.
+ if(ccw)
+ {
+ // CCW:
+ // 3 2
+ // 0 1
+ grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
+ grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
+ grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
+ grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
+ }
+ else
+ {
+ // CW:
+ // 0 1
+ // 3 2
+ grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
+ grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
+ grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
+ grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
+ }// if(ccw) else
+
+ grid_alias.CoordIdx.push_back(-1);
+ }// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)
+ }// for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
+ }// if((xDimension < 2) || (zDimension < 2)) else
+
+ grid_alias.ColorPerVertex = colorPerVertex;
+ grid_alias.NormalPerVertex = normalPerVertex;
+ grid_alias.CreaseAngle = creaseAngle;
+ grid_alias.Solid = solid;
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("ElevationGrid");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("ElevationGrid");
+
+ MACRO_NODECHECK_LOOPEND("ElevationGrid");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }// if(!mReader->isEmptyElement()) else
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+template<typename TVector>
+static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool& pCurveIsClosed)
+{
+ size_t cur_sz = pCurve.size();
+
+ pCurveIsClosed = false;
+ // for curve with less than four points checking is have no sense,
+ if(cur_sz < 4) return;
+
+ for(size_t s = 3, s_e = cur_sz; s < s_e; s++)
+ {
+ // search for first point of duplicated part.
+ if(pCurve[0] == pCurve[s])
+ {
+ bool found = true;
+
+ // check if tail(indexed by b2) is duplicate of head(indexed by b1).
+ for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
+ {
+ if(pCurve[b1] != pCurve[b2])
+ {// points not match: clear flag and break loop.
+ found = false;
+
+ break;
+ }
+ }// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
+
+ // if duplicate tail is found then drop or not it depending on flags.
+ if(found)
+ {
+ pCurveIsClosed = true;
+ if(pDropTail)
+ {
+ if(!pRemoveLastPoint) s++;// prepare value for iterator's arithmetics.
+
+ pCurve.erase(pCurve.begin() + s, pCurve.end());// remove tail
+ }
+
+ break;
+ }// if(found)
+ }// if(pCurve[0] == pCurve[s])
+ }// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++)
+}
+
+static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed)
+{
+ const size_t spine_idx_last = pSpine.size() - 1;
+ aiVector3D tvec;
+
+ if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases
+ {
+ if(pSpine_Closed)
+ {// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis.
+ // As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
+ // in tail are removed.
+ // So, last point in pSpine is a spine[n - 2]
+ tvec = pSpine[1] - pSpine[spine_idx_last];
+ }
+ else if(pSpine_PointIdx == 0)
+ {// The Y-axis used for the first point is the vector from spine[0] to spine[1]
+ tvec = pSpine[1] - pSpine[0];
+ }
+ else
+ {// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about droping tail) spine[n - 1] is
+ // the spine[0].
+ tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
+ }
+ }// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
+ else
+ {// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
+ tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
+ }// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else
+
+ return tvec.Normalize();
+}
+
+static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed,
+ const aiVector3D pVecZ_Prev)
+{
+ const aiVector3D zero_vec(0);
+ const size_t spine_idx_last = pSpine.size() - 1;
+
+ aiVector3D tvec;
+
+ // at first special cases
+ if(pSpine.size() < 3)// spine have not enough points for vector calculations.
+ {
+ tvec.Set(0, 0, 1);
+ }
+ else if(pSpine_PointIdx == 0)// special case: first point
+ {
+ if(pSpine_Closed)// for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
+ {
+ tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
+ }
+ else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
+ {
+ bool found = false;
+
+ // As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
+ // then the Z-axis for the first spine point with a defined Z-axis is used."
+ // Walk through spine and find Z.
+ for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++)
+ {
+ // (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
+ tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
+ found = !tvec.Equal(zero_vec);
+ }
+
+ // if entire spine are collinear then use OZ axis.
+ if(!found) tvec.Set(0, 0, 1);
+ }// if(pSpine_Closed) else
+ }// else if(pSpine_PointIdx == 0)
+ else if(pSpine_PointIdx == spine_idx_last)// special case: last point
+ {
+ if(pSpine_Closed)
+ {// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
+ tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
+ // if taken spine vectors are collinear then use previous vector Z.
+ if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
+ }
+ else
+ {// vector Z for last point of not closed curve is previous vector Z.
+ tvec = pVecZ_Prev;
+ }
+ }
+ else// regular point
+ {
+ tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
+ // if taken spine vectors are collinear then use previous vector Z.
+ if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
+ }
+
+ // After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis
+ // is flipped (multiplied by -1).
+ if((tvec * pVecZ_Prev) < 0) tvec = -tvec;
+
+ return tvec.Normalize();
+}
+
+// <Extrusion
+// DEF="" ID
+// USE="" IDREF
+// beginCap="true" SFBool [initializeOnly]
+// ccw="true" SFBool [initializeOnly]
+// convex="true" SFBool [initializeOnly]
+// creaseAngle="0.0" SFloat [initializeOnly]
+// crossSection="1 1 1 -1 -1 -1 -1 1 1 1" MFVec2f [initializeOnly]
+// endCap="true" SFBool [initializeOnly]
+// orientation="0 0 1 0" MFRotation [initializeOnly]
+// scale="1 1" MFVec2f [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// spine="0 0 0 0 1 0" MFVec3f [initializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry3D_Extrusion()
+{
+ std::string use, def;
+ bool beginCap = true;
+ bool ccw = true;
+ bool convex = true;
+ float creaseAngle = 0;
+ std::vector<aiVector2D> crossSection;
+ bool endCap = true;
+ std::vector<float> orientation;
+ std::vector<aiVector2D> scale;
+ bool solid = true;
+ std::vector<aiVector3D> spine;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("beginCap", beginCap, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("crossSection", crossSection, XML_ReadNode_GetAttrVal_AsArrVec2f);
+ MACRO_ATTRREAD_CHECK_RET("endCap", endCap, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("orientation", orientation, XML_ReadNode_GetAttrVal_AsArrF);
+ MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsArrVec2f);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("spine", spine, XML_ReadNode_GetAttrVal_AsArrVec3f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Extrusion, ne);
+ }
+ else
+ {
+ //
+ // check if default values must be assigned
+ //
+ if(spine.size() == 0)
+ {
+ spine.resize(2);
+ spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
+ }
+ else if(spine.size() == 1)
+ {
+ throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
+ }
+
+ if(crossSection.size() == 0)
+ {
+ crossSection.resize(5);
+ crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
+ }
+
+ {// orientation
+ size_t ori_size = orientation.size() / 4;
+
+ if(ori_size < spine.size())
+ {
+ float add_ori[4];// values that will be added
+
+ if(ori_size == 1)// if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
+ {
+ add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
+ }
+ else// else - use default values
+ {
+ add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
+ }
+
+ orientation.reserve(spine.size() * 4);
+ for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++)
+ orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]);
+ }
+
+ if(orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
+ }// END: orientation
+
+ {// scale
+ if(scale.size() < spine.size())
+ {
+ aiVector2D add_sc;
+
+ if(scale.size() == 1)// if "scale" has one element then use it value for all spine points.
+ add_sc = scale[0];
+ else// else - use default values
+ add_sc.Set(1, 1);
+
+ scale.reserve(spine.size());
+ for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc);
+ }
+ }// END: scale
+ //
+ // create and if needed - define new geometry object.
+ //
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_Extrusion, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_IndexedSet& ext_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);// create alias for conveience
+ // assign part of input data
+ ext_alias.CCW = ccw;
+ ext_alias.Convex = convex;
+ ext_alias.CreaseAngle = creaseAngle;
+ ext_alias.Solid = solid;
+
+ //
+ // How we done it at all?
+ // 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector
+ // are applied vor every basis.
+ // 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position
+ // using relative spine point.
+ // 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if
+ // needed. While createing CootdIdx is taking in account CCW flag.
+ // 4. The last step: create Vertices list.
+ //
+ bool spine_closed;// flag: true if spine curve is closed.
+ bool cross_closed;// flag: true if cross curve is closed.
+ std::vector<aiMatrix3x3> basis_arr;// array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z.
+ std::vector<std::vector<aiVector3D> > pointset_arr;// array of point sets: cross curves.
+
+ // detect closed curves
+ GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed);// true - drop tail, true - remove duplicate end.
+ GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed);// true - drop tail, true - remove duplicate end.
+ // If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
+ if(spine_closed)
+ {
+ beginCap |= endCap;
+ endCap = false;
+ }
+
+ {// 1. Calculate array of basises.
+ aiMatrix4x4 rotmat;
+ aiVector3D vecX(0), vecY(0), vecZ(0);
+
+ basis_arr.resize(spine.size());
+ for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
+ {
+ aiVector3D tvec;
+
+ // get axises of basis.
+ vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed);
+ vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ);
+ vecX = (vecY ^ vecZ).Normalize();
+ // get rotation matrix and apply "orientation" to basis
+ aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat);
+ tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z;
+ tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z;
+ tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z;
+ }// for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
+ }// END: 1. Calculate array of basises
+
+ {// 2. Create array of point sets.
+ aiMatrix4x4 scmat;
+ std::vector<aiVector3D> tcross(crossSection.size());
+
+ pointset_arr.resize(spine.size());
+ for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
+ {
+ aiVector3D tc23vec;
+
+ tc23vec.Set(scale[spi].x, 0, scale[spi].y);
+ aiMatrix4x4::Scaling(tc23vec, scmat);
+ for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
+ {
+ aiVector3D tvecX, tvecY, tvecZ;
+
+ tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
+ // apply scaling to point
+ tcross[cri] = scmat * tc23vec;
+ //
+ // transfer point to new basis
+ // calculate coordinate in new basis
+ tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x;
+ tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y;
+ tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z;
+ // apply new coordinates and translate it to spine point.
+ tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
+ }// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)
+
+ pointset_arr[spi] = tcross;// store transferred point set
+ }// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
+ }// END: 2. Create array of point sets.
+
+ {// 3. Create CoordIdx.
+ // add caps if needed
+ if(beginCap)
+ {
+ // add cap as polygon. vertices of cap are places at begin, so just add numbers from zero.
+ for(size_t i = 0, i_e = crossSection.size(); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
+
+ // add delimiter
+ ext_alias.CoordIndex.push_back(-1);
+ }// if(beginCap)
+
+ if(endCap)
+ {
+ // add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset.
+ size_t beg = (pointset_arr.size() - 1) * crossSection.size();
+
+ for(size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
+
+ // add delimiter
+ ext_alias.CoordIndex.push_back(-1);
+ }// if(beginCap)
+
+ // add quads
+ for(size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++)
+ {
+ const size_t cr_sz = crossSection.size();
+ const size_t cr_last = crossSection.size() - 1;
+
+ size_t right_col;// hold index basis for points of quad placed in right column;
+
+ if(spi != spi_e)
+ right_col = spi + 1;
+ else if(spine_closed)// if spine curve is closed then one more quad is needed: between first and last points of curve.
+ right_col = 0;
+ else
+ break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine.
+
+ for(size_t cri = 0; cri < cr_sz; cri++)
+ {
+ if(cri != cr_last)
+ {
+ MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
+ static_cast<int32_t>(spi * cr_sz + cri),
+ static_cast<int32_t>(right_col * cr_sz + cri),
+ static_cast<int32_t>(right_col * cr_sz + cri + 1),
+ static_cast<int32_t>(spi * cr_sz + cri + 1));
+ // add delimiter
+ ext_alias.CoordIndex.push_back(-1);
+ }
+ else if(cross_closed)// if cross curve is closed then one more quad is needed: between first and last points of curve.
+ {
+ MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
+ static_cast<int32_t>(spi * cr_sz + cri),
+ static_cast<int32_t>(right_col * cr_sz + cri),
+ static_cast<int32_t>(right_col * cr_sz + 0),
+ static_cast<int32_t>(spi * cr_sz + 0));
+ // add delimiter
+ ext_alias.CoordIndex.push_back(-1);
+ }
+ }// for(size_t cri = 0; cri < cr_sz; cri++)
+ }// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
+ }// END: 3. Create CoordIdx.
+
+ {// 4. Create vertices list.
+ // just copy all vertices
+ for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
+ {
+ for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
+ {
+ ext_alias.Vertices.push_back(pointset_arr[spi][cri]);
+ }
+ }
+ }// END: 4. Create vertices list.
+//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
+//PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Extrusion");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <IndexedFaceSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorIndex="" MFInt32 [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// convex="true" SFBool [initializeOnly]
+// coordIndex="" MFInt32 [initializeOnly]
+// creaseAngle="0" SFFloat [initializeOnly]
+// normalIndex="" MFInt32 [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// texCoordIndex="" MFInt32 [initializeOnly]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </IndexedFaceSet>
+void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ std::vector<int32_t> colorIndex;
+ bool colorPerVertex = true;
+ bool convex = true;
+ std::vector<int32_t> coordIndex;
+ float creaseAngle = 0;
+ std::vector<int32_t> normalIndex;
+ bool normalPerVertex = true;
+ bool solid = true;
+ std::vector<int32_t> texCoordIndex;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedFaceSet, ne);
+ }
+ else
+ {
+ // check data
+ if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedFaceSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorIndex = colorIndex;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.Convex = convex;
+ ne_alias.CoordIndex = coordIndex;
+ ne_alias.CreaseAngle = creaseAngle;
+ ne_alias.NormalIndex = normalIndex;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+ ne_alias.TexCoordIndex = texCoordIndex;
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("IndexedFaceSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedFaceSet");
+
+ MACRO_NODECHECK_LOOPEND("IndexedFaceSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Sphere
+// DEF="" ID
+// USE="" IDREF
+// radius="1" SFloat [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// />
+void X3DImporter::ParseNode_Geometry3D_Sphere()
+{
+ std::string use, def;
+ ai_real radius = 1;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Sphere, ne);
+ }
+ else
+ {
+ const unsigned int tess = 3;///TODO: IME tesselation factor through ai_property
+
+ std::vector<aiVector3D> tlist;
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Sphere, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ StandardShapes::MakeSphere(tess, tlist);
+ // copy data from temp array and apply scale
+ for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); it++)
+ {
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it * radius);
+ }
+
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
+ ((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Sphere");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Group.cpp b/src/3rdparty/assimp/code/X3DImporter_Group.cpp
new file mode 100644
index 000000000..e7df97b4b
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Group.cpp
@@ -0,0 +1,317 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Group.cpp
+/// \brief Parsing data from nodes of "Grouping" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <Group
+// DEF="" ID
+// USE="" IDREF
+// bboxCenter="0 0 0" SFVec3f [initializeOnly]
+// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
+// >
+// <!-- ChildContentModel -->
+// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
+// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
+// precise palette of legal nodes that are available depends on assigned profile and components.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </Group>
+// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
+void X3DImporter::ParseNode_Grouping_Group()
+{
+ std::string def, use;
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ CX3DImporter_NodeElement* ne;
+
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
+ }
+ else
+ {
+ ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
+ // at this place new group mode created and made current, so we can name it.
+ if(!def.empty()) NodeElement_Cur->ID = def;
+ // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
+
+ // for empty element exit from node in that place
+ if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
+ }// if(!use.empty()) else
+}
+
+void X3DImporter::ParseNode_Grouping_GroupEnd()
+{
+ ParseHelper_Node_Exit();// go up in scene graph
+}
+
+// <StaticGroup
+// DEF="" ID
+// USE="" IDREF
+// bboxCenter="0 0 0" SFVec3f [initializeOnly]
+// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
+// >
+// <!-- ChildContentModel -->
+// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
+// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
+// precise palette of legal nodes that are available depends on assigned profile and components.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </StaticGroup>
+// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
+// contain any USE references outside the StaticGroup.
+void X3DImporter::ParseNode_Grouping_StaticGroup()
+{
+ std::string def, use;
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ CX3DImporter_NodeElement* ne;
+
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
+ }
+ else
+ {
+ ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
+ // at this place new group mode created and made current, so we can name it.
+ if(!def.empty()) NodeElement_Cur->ID = def;
+ // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
+
+ // for empty element exit from node in that place
+ if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
+ }// if(!use.empty()) else
+}
+
+void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
+{
+ ParseHelper_Node_Exit();// go up in scene graph
+}
+
+// <Switch
+// DEF="" ID
+// USE="" IDREF
+// bboxCenter="0 0 0" SFVec3f [initializeOnly]
+// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
+// whichChoice="-1" SFInt32 [inputOutput]
+// >
+// <!-- ChildContentModel -->
+// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
+// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
+// precise palette of legal nodes that are available depends on assigned profile and components.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </Switch>
+// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
+// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
+// is chosen.
+void X3DImporter::ParseNode_Grouping_Switch()
+{
+ std::string def, use;
+ int32_t whichChoice = -1;
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ CX3DImporter_NodeElement* ne;
+
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
+ }
+ else
+ {
+ ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
+ // at this place new group mode created and made current, so we can name it.
+ if(!def.empty()) NodeElement_Cur->ID = def;
+
+ // also set values specific to this type of group
+ ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->UseChoice = true;
+ ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->Choice = whichChoice;
+ // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
+
+ // for empty element exit from node in that place
+ if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
+ }// if(!use.empty()) else
+}
+
+void X3DImporter::ParseNode_Grouping_SwitchEnd()
+{
+ // just exit from node. Defined choice will be accepted at postprocessing stage.
+ ParseHelper_Node_Exit();// go up in scene graph
+}
+
+// <Transform
+// DEF="" ID
+// USE="" IDREF
+// bboxCenter="0 0 0" SFVec3f [initializeOnly]
+// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
+// center="0 0 0" SFVec3f [inputOutput]
+// rotation="0 0 1 0" SFRotation [inputOutput]
+// scale="1 1 1" SFVec3f [inputOutput]
+// scaleOrientation="0 0 1 0" SFRotation [inputOutput]
+// translation="0 0 0" SFVec3f [inputOutput]
+// >
+// <!-- ChildContentModel -->
+// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
+// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
+// precise palette of legal nodes that are available depends on assigned profile and components.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </Transform>
+// The Transform node is a grouping node that defines a coordinate system for its children that is relative to the coordinate systems of its ancestors.
+// Given a 3-dimensional point P and Transform node, P is transformed into point P' in its parent's coordinate system by a series of intermediate
+// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
+// equivalent transformation matrices,
+// P' = T * C * R * SR * S * -SR * -C * P
+void X3DImporter::ParseNode_Grouping_Transform()
+{
+ aiVector3D center(0, 0, 0);
+ float rotation[4] = {0, 0, 1, 0};
+ aiVector3D scale(1, 1, 1);// A value of zero indicates that any child geometry shall not be displayed
+ float scale_orientation[4] = {0, 0, 1, 0};
+ aiVector3D translation(0, 0, 0);
+ aiMatrix4x4 matr, tmatr;
+ std::string use, def;
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);
+ if(an == "rotation")
+ {
+ std::vector<float> tvec;
+
+ XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
+ if(tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
+
+ memcpy(rotation, tvec.data(), sizeof(rotation));
+
+ continue;
+ }
+
+ if(an == "scaleOrientation")
+ {
+ std::vector<float> tvec;
+ XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
+ if ( tvec.size() != 4 )
+ {
+ throw DeadlyImportError( "<Transform>: scaleOrientation vector must have 4 elements." );
+ }
+
+ ::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation) );
+
+ continue;
+ }
+
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
+ }
+ else
+ {
+ ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
+ // at this place new group mode created and made current, so we can name it.
+ if ( !def.empty() )
+ {
+ NodeElement_Cur->ID = def;
+ }
+
+ //
+ // also set values specific to this type of group
+ //
+ // calculate transformation matrix
+ aiMatrix4x4::Translation(translation, matr);// T
+ aiMatrix4x4::Translation(center, tmatr);// C
+ matr *= tmatr;
+ aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr);// R
+ matr *= tmatr;
+ aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// SR
+ matr *= tmatr;
+ aiMatrix4x4::Scaling(scale, tmatr);// S
+ matr *= tmatr;
+ aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// -SR
+ matr *= tmatr;
+ aiMatrix4x4::Translation(-center, tmatr);// -C
+ matr *= tmatr;
+ // and assign it
+ ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->Transformation = matr;
+ // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
+
+ // for empty element exit from node in that place
+ if ( mReader->isEmptyElement() )
+ {
+ ParseHelper_Node_Exit();
+ }
+ }// if(!use.empty()) else
+}
+
+void X3DImporter::ParseNode_Grouping_TransformEnd()
+{
+ ParseHelper_Node_Exit();// go up in scene graph
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Light.cpp b/src/3rdparty/assimp/code/X3DImporter_Light.cpp
new file mode 100644
index 000000000..ff450f7a9
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Light.cpp
@@ -0,0 +1,289 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Light.cpp
+/// \brief Parsing data from nodes of "Lighting" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+#include "StringUtils.h"
+
+namespace Assimp {
+
+// <DirectionalLight
+// DEF="" ID
+// USE="" IDREF
+// ambientIntensity="0" SFFloat [inputOutput]
+// color="1 1 1" SFColor [inputOutput]
+// direction="0 0 -1" SFVec3f [inputOutput]
+// global="false" SFBool [inputOutput]
+// intensity="1" SFFloat [inputOutput]
+// on="true" SFBool [inputOutput]
+// />
+void X3DImporter::ParseNode_Lighting_DirectionalLight()
+{
+ std::string def, use;
+ float ambientIntensity = 0;
+ aiColor3D color(1, 1, 1);
+ aiVector3D direction(0, 0, -1);
+ bool global = false;
+ float intensity = 1;
+ bool on = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
+ MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_DirectionalLight, ne);
+ }
+ else
+ {
+ if(on)
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Light(CX3DImporter_NodeElement::ENET_DirectionalLight, NodeElement_Cur);
+ if(!def.empty())
+ ne->ID = def;
+ else
+ ne->ID = "DirectionalLight_" + to_string((size_t)ne);// make random name
+
+ ((CX3DImporter_NodeElement_Light*)ne)->AmbientIntensity = ambientIntensity;
+ ((CX3DImporter_NodeElement_Light*)ne)->Color = color;
+ ((CX3DImporter_NodeElement_Light*)ne)->Direction = direction;
+ ((CX3DImporter_NodeElement_Light*)ne)->Global = global;
+ ((CX3DImporter_NodeElement_Light*)ne)->Intensity = intensity;
+ // Assimp want a node with name similar to a light. "Why? I don't no." )
+ ParseHelper_Group_Begin(false);
+
+ NodeElement_Cur->ID = ne->ID;// assign name to node and return to light element.
+ ParseHelper_Node_Exit();
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "DirectionalLight");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(on)
+ }// if(!use.empty()) else
+}
+
+// <PointLight
+// DEF="" ID
+// USE="" IDREF
+// ambientIntensity="0" SFFloat [inputOutput]
+// attenuation="1 0 0" SFVec3f [inputOutput]
+// color="1 1 1" SFColor [inputOutput]
+// global="true" SFBool [inputOutput]
+// intensity="1" SFFloat [inputOutput]
+// location="0 0 0" SFVec3f [inputOutput]
+// on="true" SFBool [inputOutput]
+// radius="100" SFFloat [inputOutput]
+// />
+void X3DImporter::ParseNode_Lighting_PointLight()
+{
+ std::string def, use;
+ float ambientIntensity = 0;
+ aiVector3D attenuation( 1, 0, 0 );
+ aiColor3D color( 1, 1, 1 );
+ bool global = true;
+ float intensity = 1;
+ aiVector3D location( 0, 0, 0 );
+ bool on = true;
+ float radius = 100;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
+ MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointLight, ne);
+ }
+ else
+ {
+ if(on)
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Light(CX3DImporter_NodeElement::ENET_PointLight, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_Light*)ne)->AmbientIntensity = ambientIntensity;
+ ((CX3DImporter_NodeElement_Light*)ne)->Attenuation = attenuation;
+ ((CX3DImporter_NodeElement_Light*)ne)->Color = color;
+ ((CX3DImporter_NodeElement_Light*)ne)->Global = global;
+ ((CX3DImporter_NodeElement_Light*)ne)->Intensity = intensity;
+ ((CX3DImporter_NodeElement_Light*)ne)->Location = location;
+ ((CX3DImporter_NodeElement_Light*)ne)->Radius = radius;
+ // Assimp want a node with name similar to a light. "Why? I don't no." )
+ ParseHelper_Group_Begin(false);
+ // make random name
+ if(ne->ID.empty()) ne->ID = "PointLight_" + to_string((size_t)ne);
+
+ NodeElement_Cur->ID = ne->ID;// assign name to node and return to light element.
+ ParseHelper_Node_Exit();
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "PointLight");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(on)
+ }// if(!use.empty()) else
+}
+
+// <SpotLight
+// DEF="" ID
+// USE="" IDREF
+// ambientIntensity="0" SFFloat [inputOutput]
+// attenuation="1 0 0" SFVec3f [inputOutput]
+// beamWidth="0.7854" SFFloat [inputOutput]
+// color="1 1 1" SFColor [inputOutput]
+// cutOffAngle="1.570796" SFFloat [inputOutput]
+// direction="0 0 -1" SFVec3f [inputOutput]
+// global="true" SFBool [inputOutput]
+// intensity="1" SFFloat [inputOutput]
+// location="0 0 0" SFVec3f [inputOutput]
+// on="true" SFBool [inputOutput]
+// radius="100" SFFloat [inputOutput]
+// />
+void X3DImporter::ParseNode_Lighting_SpotLight()
+{
+ std::string def, use;
+ float ambientIntensity = 0;
+ aiVector3D attenuation( 1, 0, 0 );
+ float beamWidth = 0.7854f;
+ aiColor3D color( 1, 1, 1 );
+ float cutOffAngle = 1.570796f;
+ aiVector3D direction( 0, 0, -1 );
+ bool global = true;
+ float intensity = 1;
+ aiVector3D location( 0, 0, 0 );
+ bool on = true;
+ float radius = 100;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_RET("beamWidth", beamWidth, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
+ MACRO_ATTRREAD_CHECK_RET("cutOffAngle", cutOffAngle, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
+ MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_SpotLight, ne);
+ }
+ else
+ {
+ if(on)
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Light(CX3DImporter_NodeElement::ENET_SpotLight, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ if(beamWidth > cutOffAngle) beamWidth = cutOffAngle;
+
+ ((CX3DImporter_NodeElement_Light*)ne)->AmbientIntensity = ambientIntensity;
+ ((CX3DImporter_NodeElement_Light*)ne)->Attenuation = attenuation;
+ ((CX3DImporter_NodeElement_Light*)ne)->BeamWidth = beamWidth;
+ ((CX3DImporter_NodeElement_Light*)ne)->Color = color;
+ ((CX3DImporter_NodeElement_Light*)ne)->CutOffAngle = cutOffAngle;
+ ((CX3DImporter_NodeElement_Light*)ne)->Direction = direction;
+ ((CX3DImporter_NodeElement_Light*)ne)->Global = global;
+ ((CX3DImporter_NodeElement_Light*)ne)->Intensity = intensity;
+ ((CX3DImporter_NodeElement_Light*)ne)->Location = location;
+ ((CX3DImporter_NodeElement_Light*)ne)->Radius = radius;
+
+ // Assimp want a node with name similar to a light. "Why? I don't no." )
+ ParseHelper_Group_Begin(false);
+ // make random name
+ if(ne->ID.empty()) ne->ID = "SpotLight_" + to_string((size_t)ne);
+
+ NodeElement_Cur->ID = ne->ID;// assign name to node and return to light element.
+ ParseHelper_Node_Exit();
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "SpotLight");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(on)
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Macro.hpp b/src/3rdparty/assimp/code/X3DImporter_Macro.hpp
new file mode 100644
index 000000000..6281efcd5
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Macro.hpp
@@ -0,0 +1,194 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Macro.hpp
+/// \brief Useful macrodefines.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef X3DIMPORTER_MACRO_HPP_INCLUDED
+#define X3DIMPORTER_MACRO_HPP_INCLUDED
+
+/// \def MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pNE)
+/// Used for regular checking while attribute "USE" is defined.
+/// \param [in] pDEF - string holding "DEF" value.
+/// \param [in] pUSE - string holding "USE" value.
+/// \param [in] pType - type of element to find.
+/// \param [out] pNE - pointer to found node element.
+#define MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pType, pNE) \
+ do { \
+ XML_CheckNode_MustBeEmpty(); \
+ if(!pDEF.empty()) Throw_DEF_And_USE(); \
+ if(!FindNodeElement(pUSE, CX3DImporter_NodeElement::pType, &pNE)) Throw_USE_NotFound(pUSE); \
+ \
+ NodeElement_Cur->Child.push_back(pNE);/* add found object as child to current element */ \
+ } while(false)
+
+/// \def MACRO_ATTRREAD_LOOPBEG
+/// Begin of loop that read attributes values.
+#define MACRO_ATTRREAD_LOOPBEG \
+ for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
+ { \
+ std::string an(mReader->getAttributeName(idx));
+
+/// \def MACRO_ATTRREAD_LOOPEND
+/// End of loop that read attributes values.
+#define MACRO_ATTRREAD_LOOPEND \
+ Throw_IncorrectAttr(an); \
+ }
+
+/// \def MACRO_ATTRREAD_CHECK_REF
+/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
+/// "continue" will called.
+/// \param [in] pAttrName - attribute name.
+/// \param [out] pVarName - output variable name.
+/// \param [in] pFunction - function which read attribute value and write it to pVarName.
+#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
+ if(an == pAttrName) \
+ { \
+ pFunction(idx, pVarName); \
+ continue; \
+ }
+
+/// \def MACRO_ATTRREAD_CHECK_RET
+/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
+/// If result was read then "continue" will called.
+/// \param [in] pAttrName - attribute name.
+/// \param [out] pVarName - output variable name.
+/// \param [in] pFunction - function which read attribute value and write it to pVarName.
+#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
+ if(an == pAttrName) \
+ { \
+ pVarName = pFunction(idx); \
+ continue; \
+ }
+
+/// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
+/// Compact variant for checking "USE" and "DEF". Also skip bbox attributes: "bboxCenter", "bboxSize".
+/// If result was read then "continue" will called.
+/// \param [out] pDEF_Var - output variable name for "DEF" value.
+/// \param [out] pUSE_Var - output variable name for "USE" value.
+#define MACRO_ATTRREAD_CHECKUSEDEF_RET(pDEF_Var, pUSE_Var) \
+ MACRO_ATTRREAD_CHECK_RET("DEF", pDEF_Var, mReader->getAttributeValue); \
+ MACRO_ATTRREAD_CHECK_RET("USE", pUSE_Var, mReader->getAttributeValue); \
+ if(an == "bboxCenter") continue; \
+ if(an == "bboxSize") continue; \
+ if(an == "containerField") continue; \
+ do {} while(false)
+
+/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
+/// Begin of loop of parsing child nodes. Do not add ';' at end.
+/// \param [in] pNodeName - current node name.
+#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
+ do { \
+ bool close_found = false; \
+ \
+ while(mReader->read()) \
+ { \
+ if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
+ {
+
+/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
+/// End of loop of parsing child nodes.
+/// \param [in] pNodeName - current node name.
+#define MACRO_NODECHECK_LOOPEND(pNodeName) \
+ }/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
+ else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
+ { \
+ if(XML_CheckNode_NameEqual(pNodeName)) \
+ { \
+ close_found = true; \
+ \
+ break; \
+ } \
+ }/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
+ }/* while(mReader->read()) */ \
+ \
+ if(!close_found) Throw_CloseNotFound(pNodeName); \
+ \
+ } while(false)
+
+#define MACRO_NODECHECK_METADATA(pNodeName) \
+ MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
+ /* and childs must be metadata nodes */ \
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported(pNodeName); \
+ MACRO_NODECHECK_LOOPEND(pNodeName)
+
+/// \def MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4)
+/// Add points as quad. Means that pP1..pP4 set in CCW order.
+#define MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4) \
+ do { \
+ if(pCCW) \
+ { \
+ pOut.push_back(pIn[pP1]); \
+ pOut.push_back(pIn[pP2]); \
+ pOut.push_back(pIn[pP3]); \
+ pOut.push_back(pIn[pP4]); \
+ } \
+ else \
+ { \
+ pOut.push_back(pIn[pP4]); \
+ pOut.push_back(pIn[pP3]); \
+ pOut.push_back(pIn[pP2]); \
+ pOut.push_back(pIn[pP1]); \
+ } \
+ } while(false)
+
+/// \def MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4)
+/// Add points as quad. Means that pP1..pP4 set in CCW order.
+#define MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4) \
+ do { \
+ if(pCCW) \
+ { \
+ pOut.push_back(pP1); \
+ pOut.push_back(pP2); \
+ pOut.push_back(pP3); \
+ pOut.push_back(pP4); \
+ } \
+ else \
+ { \
+ pOut.push_back(pP4); \
+ pOut.push_back(pP3); \
+ pOut.push_back(pP2); \
+ pOut.push_back(pP1); \
+ } \
+ } while(false)
+
+#endif // X3DIMPORTER_MACRO_HPP_INCLUDED
diff --git a/src/3rdparty/assimp/code/X3DImporter_Metadata.cpp b/src/3rdparty/assimp/code/X3DImporter_Metadata.cpp
new file mode 100644
index 000000000..0fa1b27b3
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Metadata.cpp
@@ -0,0 +1,276 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Metadata.cpp
+/// \brief Parsing data from nodes of "Metadata" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+/// \def MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaName)
+/// Find element by "USE" or create new one.
+/// \param [in] pDEF_Var - variable name with "DEF" value.
+/// \param [in] pUSE_Var - variable name with "USE" value.
+/// \param [in] pReference - variable name with "reference" value.
+/// \param [in] pValue - variable name with "value" value.
+/// \param [in, out] pNE - pointer to node element.
+/// \param [in] pMetaClass - Class of node.
+/// \param [in] pMetaName - Name of node.
+/// \param [in] pType - type of element to find.
+#define MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaClass, pMetaName, pType) \
+ /* if "USE" defined then find already defined element. */ \
+ if(!pUSE_Var.empty()) \
+ { \
+ MACRO_USE_CHECKANDAPPLY(pDEF_Var, pUSE_Var, pType, pNE); \
+ } \
+ else \
+ { \
+ pNE = new pMetaClass(NodeElement_Cur); \
+ if(!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
+ \
+ ((pMetaClass*)pNE)->Reference = pReference; \
+ ((pMetaClass*)pNE)->Value = pValue; \
+ /* also metadata node can contain childs */ \
+ if(!mReader->isEmptyElement()) \
+ ParseNode_Metadata(pNE, pMetaName);/* in that case node element will be added to child elements list of current node. */ \
+ else \
+ NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manualy */ \
+ \
+ NodeElement_List.push_back(pNE);/* add new element to elements list. */ \
+ }/* if(!pUSE_Var.empty()) else */ \
+ \
+ do {} while(false)
+
+bool X3DImporter::ParseHelper_CheckRead_X3DMetadataObject()
+{
+ if(XML_CheckNode_NameEqual("MetadataBoolean"))
+ ParseNode_MetadataBoolean();
+ else if(XML_CheckNode_NameEqual("MetadataDouble"))
+ ParseNode_MetadataDouble();
+ else if(XML_CheckNode_NameEqual("MetadataFloat"))
+ ParseNode_MetadataFloat();
+ else if(XML_CheckNode_NameEqual("MetadataInteger"))
+ ParseNode_MetadataInteger();
+ else if(XML_CheckNode_NameEqual("MetadataSet"))
+ ParseNode_MetadataSet();
+ else if(XML_CheckNode_NameEqual("MetadataString"))
+ ParseNode_MetadataString();
+ else
+ return false;
+
+ return true;
+}
+
+void X3DImporter::ParseNode_Metadata(CX3DImporter_NodeElement* pParentElement, const std::string& /*pNodeName*/)
+{
+ ParseHelper_Node_Enter(pParentElement);
+ MACRO_NODECHECK_METADATA(mReader->getNodeName());
+ ParseHelper_Node_Exit();
+}
+
+// <MetadataBoolean
+// DEF="" ID
+// USE="" IDREF
+// name="" SFString [inputOutput]
+// reference="" SFString [inputOutput]
+// value="" MFBool [inputOutput]
+// />
+void X3DImporter::ParseNode_MetadataBoolean()
+{
+ std::string def, use;
+ std::string name, reference;
+ std::vector<bool> value;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrB);
+ MACRO_ATTRREAD_LOOPEND;
+
+ MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
+}
+
+// <MetadataDouble
+// DEF="" ID
+// USE="" IDREF
+// name="" SFString [inputOutput]
+// reference="" SFString [inputOutput]
+// value="" MFDouble [inputOutput]
+// />
+void X3DImporter::ParseNode_MetadataDouble()
+{
+ std::string def, use;
+ std::string name, reference;
+ std::vector<double> value;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrD);
+ MACRO_ATTRREAD_LOOPEND;
+
+ MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaDouble, "MetadataDouble", ENET_MetaDouble);
+}
+
+// <MetadataFloat
+// DEF="" ID
+// USE="" IDREF
+// name="" SFString [inputOutput]
+// reference="" SFString [inputOutput]
+// value="" MFFloat [inputOutput]
+// />
+void X3DImporter::ParseNode_MetadataFloat()
+{
+ std::string def, use;
+ std::string name, reference;
+ std::vector<float> value;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrF);
+ MACRO_ATTRREAD_LOOPEND;
+
+ MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaFloat, "MetadataFloat", ENET_MetaFloat);
+}
+
+// <MetadataInteger
+// DEF="" ID
+// USE="" IDREF
+// name="" SFString [inputOutput]
+// reference="" SFString [inputOutput]
+// value="" MFInteger [inputOutput]
+// />
+void X3DImporter::ParseNode_MetadataInteger()
+{
+ std::string def, use;
+ std::string name, reference;
+ std::vector<int32_t> value;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_LOOPEND;
+
+ MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaInteger, "MetadataInteger", ENET_MetaInteger);
+}
+
+// <MetadataSet
+// DEF="" ID
+// USE="" IDREF
+// name="" SFString [inputOutput]
+// reference="" SFString [inputOutput]
+// />
+void X3DImporter::ParseNode_MetadataSet()
+{
+ std::string def, use;
+ std::string name, reference;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_MetaSet, ne);
+ }
+ else
+ {
+ ne = new CX3DImporter_NodeElement_MetaSet(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_MetaSet*)ne)->Reference = reference;
+ // also metadata node can contain childs
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "MetadataSet");
+ else
+ NodeElement_Cur->Child.push_back(ne);// made object as child to current element
+
+ NodeElement_List.push_back(ne);// add new element to elements list.
+ }// if(!use.empty()) else
+}
+
+// <MetadataString
+// DEF="" ID
+// USE="" IDREF
+// name="" SFString [inputOutput]
+// reference="" SFString [inputOutput]
+// value="" MFString [inputOutput]
+// />
+void X3DImporter::ParseNode_MetadataString()
+{
+ std::string def, use;
+ std::string name, reference;
+ std::list<std::string> value;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
+ MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListS);
+ MACRO_ATTRREAD_LOOPEND;
+
+ MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaString, "MetadataString", ENET_MetaString);
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Networking.cpp b/src/3rdparty/assimp/code/X3DImporter_Networking.cpp
new file mode 100644
index 000000000..269c58ba3
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Networking.cpp
@@ -0,0 +1,133 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Networking.cpp
+/// \brief Parsing data from nodes of "Networking" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+// Header files, Assimp.
+#include <assimp/DefaultIOSystem.h>
+
+//#include <regex>
+
+namespace Assimp
+{
+
+//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)");
+static std::string parentDir("/../");
+
+// <Inline
+// DEF="" ID
+// USE="" IDREF
+// bboxCenter="0 0 0" SFVec3f [initializeOnly]
+// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
+// load="true" SFBool [inputOutput]
+// url="" MFString [inputOutput]
+// />
+void X3DImporter::ParseNode_Networking_Inline()
+{
+ std::string def, use;
+ bool load = true;
+ std::list<std::string> url;
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("load", load, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ CX3DImporter_NodeElement* ne;
+
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
+ }
+ else
+ {
+ ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
+ // at this place new group mode created and made current, so we can name it.
+ if(!def.empty()) NodeElement_Cur->ID = def;
+
+ if(load && (url.size() > 0))
+ {
+ std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
+
+ //full_path = std::regex_replace(full_path, pattern_parentDir, "$1");
+ for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) {
+ if (pos > 0) {
+ std::string::size_type pos2 = full_path.rfind('/', pos - 1);
+ if (pos2 != std::string::npos) {
+ full_path.erase(pos2, pos - pos2 + 3);
+ pos = pos2;
+ }
+ else {
+ full_path.erase(0, pos + 4);
+ pos = 0;
+ }
+ }
+ else {
+ pos += 3;
+ }
+ }
+ // Attribute "url" can contain list of strings. But we need only one - first.
+ std::string::size_type slashPos = full_path.find_last_of("\\/");
+ mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1));
+ ParseFile(full_path, mpIOHandler);
+ mpIOHandler->PopDirectory();
+ }
+
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement()) ParseNode_Metadata(NodeElement_Cur, "Inline");
+
+ // exit from node in that place
+ ParseHelper_Node_Exit();
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Node.hpp b/src/3rdparty/assimp/code/X3DImporter_Node.hpp
new file mode 100644
index 000000000..6ed96c2f9
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Node.hpp
@@ -0,0 +1,779 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Node.hpp
+/// \brief Elements of scene graph.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef INCLUDED_AI_X3D_IMPORTER_NODE_H
+#define INCLUDED_AI_X3D_IMPORTER_NODE_H
+
+// Header files, Assimp.
+#include <assimp/scene.h>
+#include <assimp/types.h>
+
+// Header files, stdlib.
+#include <list>
+#include <vector>
+#include <string>
+
+/// \class CX3DImporter_NodeElement
+/// Base class for elements of nodes.
+class CX3DImporter_NodeElement
+{
+ /***********************************************/
+ /******************** Types ********************/
+ /***********************************************/
+
+public:
+
+ /// \enum EType
+ /// Define what data type contain node element.
+ enum EType
+ {
+ ENET_Group, ///< Element has type "Group".
+ ENET_MetaBoolean, ///< Element has type "Metadata boolean".
+ ENET_MetaDouble, ///< Element has type "Metadata double".
+ ENET_MetaFloat, ///< Element has type "Metadata float".
+ ENET_MetaInteger, ///< Element has type "Metadata integer".
+ ENET_MetaSet, ///< Element has type "Metadata set".
+ ENET_MetaString, ///< Element has type "Metadata string".
+ ENET_Arc2D, ///< Element has type "Arc2D".
+ ENET_ArcClose2D, ///< Element has type "ArcClose2D".
+ ENET_Circle2D, ///< Element has type "Circle2D".
+ ENET_Disk2D, ///< Element has type "Disk2D".
+ ENET_Polyline2D, ///< Element has type "Polyline2D".
+ ENET_Polypoint2D, ///< Element has type "Polypoint2D".
+ ENET_Rectangle2D, ///< Element has type "Rectangle2D".
+ ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
+ ENET_Box, ///< Element has type "Box".
+ ENET_Cone, ///< Element has type "Cone".
+ ENET_Cylinder, ///< Element has type "Cylinder".
+ ENET_Sphere, ///< Element has type "Sphere".
+ ENET_ElevationGrid, ///< Element has type "ElevationGrid".
+ ENET_Extrusion, ///< Element has type "Extrusion".
+ ENET_Coordinate, ///< Element has type "Coordinate".
+ ENET_Normal, ///< Element has type "Normal".
+ ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
+ ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
+ ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
+ ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
+ ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
+ ENET_IndexedTriangleStripSet,///< Element has type "IndexedTriangleStripSet".
+ ENET_LineSet, ///< Element has type "LineSet".
+ ENET_PointSet, ///< Element has type "PointSet".
+ ENET_TriangleSet, ///< Element has type "TriangleSet".
+ ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
+ ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
+ ENET_Color, ///< Element has type "Color".
+ ENET_ColorRGBA, ///< Element has type "ColorRGBA".
+ ENET_Shape, ///< Element has type "Shape".
+ ENET_Appearance, ///< Element has type "Appearance".
+ ENET_Material, ///< Element has type "Material".
+ ENET_ImageTexture, ///< Element has type "ImageTexture".
+ ENET_TextureTransform, ///< Element has type "TextureTransform".
+ ENET_DirectionalLight, ///< Element has type "DirectionalLight".
+ ENET_PointLight, ///< Element has type "PointLight".
+ ENET_SpotLight, ///< Element has type "SpotLight".
+
+ ENET_Invalid ///< Element has invalid type and possible contain invalid data.
+ };
+
+ /***********************************************/
+ /****************** Constants ******************/
+ /***********************************************/
+
+public:
+
+ const EType Type;
+
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ std::string ID;///< ID of the element. Can be empty. In X3D synonym for "ID" attribute.
+ CX3DImporter_NodeElement* Parent;///< Parent element. If nullptr then this node is root.
+ std::list<CX3DImporter_NodeElement*> Child;///< Child elements.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+ /// @brief The destructor, virtual.
+ virtual ~CX3DImporter_NodeElement() {
+ // empty
+ }
+
+private:
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement(const CX3DImporter_NodeElement& pNodeElement);
+
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement& operator=(const CX3DImporter_NodeElement& pNodeElement);
+
+ /// Disabled default constructor.
+ CX3DImporter_NodeElement();
+
+protected:
+ /// In constructor inheritor must set element type.
+ /// \param [in] pType - element type.
+ /// \param [in] pParent - parent element.
+ CX3DImporter_NodeElement(const EType pType, CX3DImporter_NodeElement* pParent)
+ : Type(pType), Parent(pParent)
+ {}
+};// class IX3DImporter_NodeElement
+
+/// \class CX3DImporter_NodeElement_Group
+/// Class that define grouping node. Define transformation matrix for children.
+/// Also can select which child will be kept and others are removed.
+class CX3DImporter_NodeElement_Group : public CX3DImporter_NodeElement
+{
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ aiMatrix4x4 Transformation;///< Transformation matrix.
+
+ /// \var bool Static
+ /// As you know node elements can use already defined node elements when attribute "USE" is defined.
+ /// Standard search when looking for an element in the whole scene graph, existing at this moment.
+ /// If a node is marked as static, the children(or lower) can not search for elements in the nodes upper then static.
+ bool Static;
+
+ bool UseChoice;///< Flag: if true then use number from \ref Choice to choose what the child will be kept.
+ int32_t Choice;///< Number of the child which will be kept.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn CX3DImporter_NodeElement_Group(const CX3DImporter_NodeElement_Group& pNode)
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_Group(const CX3DImporter_NodeElement_Group& pNode);
+
+ /// \fn CX3DImporter_NodeElement_Group& operator=(const CX3DImporter_NodeElement_Group& pNode)
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_Group& operator=(const CX3DImporter_NodeElement_Group& pNode);
+
+ /// \fn CX3DImporter_NodeElement_Group()
+ /// Disabled default constructor.
+ CX3DImporter_NodeElement_Group();
+
+public:
+
+ /// \fn CX3DImporter_NodeElement_Group(CX3DImporter_NodeElement_Group* pParent, const bool pStatic = false)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pStatic - static node flag.
+ CX3DImporter_NodeElement_Group(CX3DImporter_NodeElement* pParent, const bool pStatic = false)
+ : CX3DImporter_NodeElement(ENET_Group, pParent), Static(pStatic), UseChoice(false)
+ {}
+
+};// class CX3DImporter_NodeElement_Group
+
+/// \class CX3DImporter_NodeElement_Meta
+/// This struct describe metavalue.
+class CX3DImporter_NodeElement_Meta : public CX3DImporter_NodeElement
+{
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ std::string Name;///< Name of metadata object.
+ /// \var std::string Reference
+ /// If provided, it identifies the metadata standard or other specification that defines the name field. If the reference field is not provided or is
+ /// empty, the meaning of the name field is considered implicit to the characters in the string.
+ std::string Reference;
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn CX3DImporter_NodeElement_Meta(const CX3DImporter_NodeElement_Meta& pNode)
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_Meta(const CX3DImporter_NodeElement_Meta& pNode);
+
+ /// \fn CX3DImporter_NodeElement_Meta& operator=(const CX3DImporter_NodeElement_Meta& pNode)
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_Meta& operator=(const CX3DImporter_NodeElement_Meta& pNode);
+
+ /// \fn CX3DImporter_NodeElement_Meta()
+ /// Disabled default constructor.
+ CX3DImporter_NodeElement_Meta();
+
+public:
+
+ /// \fn CX3DImporter_NodeElement_Meta(const EType pType, CX3DImporter_NodeElement* pParent)
+ /// In constructor inheritor must set element type.
+ /// \param [in] pType - element type.
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_Meta(const EType pType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(pType, pParent)
+ {}
+
+};// class CX3DImporter_NodeElement_Meta
+
+/// \struct CX3DImporter_NodeElement_MetaBoolean
+/// This struct describe metavalue of type boolean.
+struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Meta
+{
+ std::vector<bool> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Meta(ENET_MetaBoolean, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_MetaBoolean
+
+/// \struct CX3DImporter_NodeElement_MetaDouble
+/// This struct describe metavalue of type double.
+struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Meta
+{
+ std::vector<double> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Meta(ENET_MetaDouble, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_MetaDouble
+
+/// \struct CX3DImporter_NodeElement_MetaFloat
+/// This struct describe metavalue of type float.
+struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta
+{
+ std::vector<float> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Meta(ENET_MetaFloat, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_MetaFloat
+
+/// \struct CX3DImporter_NodeElement_MetaInteger
+/// This struct describe metavalue of type integer.
+struct CX3DImporter_NodeElement_MetaInteger : public CX3DImporter_NodeElement_Meta
+{
+ std::vector<int32_t> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Meta(ENET_MetaInteger, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_MetaInteger
+
+/// \struct CX3DImporter_NodeElement_MetaSet
+/// This struct describe container for metaobjects.
+struct CX3DImporter_NodeElement_MetaSet : public CX3DImporter_NodeElement_Meta
+{
+ std::list<CX3DImporter_NodeElement_Meta> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_MetaSet(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_MetaSet(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Meta(ENET_MetaSet, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_MetaSet
+
+/// \struct CX3DImporter_NodeElement_MetaString
+/// This struct describe metavalue of type string.
+struct CX3DImporter_NodeElement_MetaString : public CX3DImporter_NodeElement_Meta
+{
+ std::list<std::string> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_MetaString(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_MetaString(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Meta(ENET_MetaString, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_MetaString
+
+/// \struct CX3DImporter_NodeElement_Color
+/// This struct hold <Color> value.
+struct CX3DImporter_NodeElement_Color : public CX3DImporter_NodeElement
+{
+ std::list<aiColor3D> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_Color(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_Color(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_Color, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_Color
+
+/// \struct CX3DImporter_NodeElement_ColorRGBA
+/// This struct hold <ColorRGBA> value.
+struct CX3DImporter_NodeElement_ColorRGBA : public CX3DImporter_NodeElement
+{
+ std::list<aiColor4D> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_ColorRGBA(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_ColorRGBA(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_ColorRGBA, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_ColorRGBA
+
+/// \struct CX3DImporter_NodeElement_Coordinate
+/// This struct hold <Coordinate> value.
+struct CX3DImporter_NodeElement_Coordinate : public CX3DImporter_NodeElement
+{
+ std::list<aiVector3D> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_Coordinate(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_Coordinate(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_Coordinate, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_Coordinate
+
+/// \struct CX3DImporter_NodeElement_Normal
+/// This struct hold <Normal> value.
+struct CX3DImporter_NodeElement_Normal : public CX3DImporter_NodeElement
+{
+ std::list<aiVector3D> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_Normal(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_Normal(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_Normal, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_Normal
+
+/// \struct CX3DImporter_NodeElement_TextureCoordinate
+/// This struct hold <TextureCoordinate> value.
+struct CX3DImporter_NodeElement_TextureCoordinate : public CX3DImporter_NodeElement
+{
+ std::list<aiVector2D> Value;///< Stored value.
+
+ /// \fn CX3DImporter_NodeElement_TextureCoordinate(CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_TextureCoordinate(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_TextureCoordinate, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_TextureCoordinate
+
+/// \class CX3DImporter_NodeElement_Geometry2D
+/// Two-dimensional figure.
+class CX3DImporter_NodeElement_Geometry2D : public CX3DImporter_NodeElement
+{
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ std::list<aiVector3D> Vertices;///< Vertices list.
+ size_t NumIndices;///< Number of indices in one face.
+ bool Solid;///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn CX3DImporter_NodeElement_Geometry2D(const CX3DImporter_NodeElement_Geometry2D& pNode)
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_Geometry2D(const CX3DImporter_NodeElement_Geometry2D& pNode);
+
+ /// \fn CX3DImporter_NodeElement_Geometry2D& operator=(const CX3DImporter_NodeElement_Geometry2D& pNode)
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_Geometry2D& operator=(const CX3DImporter_NodeElement_Geometry2D& pNode);
+
+public:
+
+ /// \fn CX3DImporter_NodeElement_Geometry2D(const EType pType, CX3DImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pType - type of geometry object.
+ CX3DImporter_NodeElement_Geometry2D(const EType pType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(pType, pParent), Solid(true)
+ {}
+
+};// class CX3DImporter_NodeElement_Geometry2D
+
+/// \class CX3DImporter_NodeElement_Geometry3D
+/// Three-dimensional body.
+class CX3DImporter_NodeElement_Geometry3D : public CX3DImporter_NodeElement {
+public:
+ std::list<aiVector3D> Vertices; ///< Vertices list.
+ size_t NumIndices;///< Number of indices in one face.
+ bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
+
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pType - type of geometry object.
+ CX3DImporter_NodeElement_Geometry3D(const EType pType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(pType, pParent)
+ , Vertices()
+ , NumIndices( 0 )
+ , Solid(true) {
+ // empty
+ }
+
+private:
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_Geometry3D(const CX3DImporter_NodeElement_Geometry3D& pNode);
+
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_Geometry3D& operator=(const CX3DImporter_NodeElement_Geometry3D& pNode);
+};// class CX3DImporter_NodeElement_Geometry3D
+
+/// \class CX3DImporter_NodeElement_ElevationGrid
+/// Uniform rectangular grid of varying height.
+class CX3DImporter_NodeElement_ElevationGrid : public CX3DImporter_NodeElement_Geometry3D
+{
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
+ bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
+ /// \var CreaseAngle
+ /// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
+ /// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
+ float CreaseAngle;
+ std::vector<int32_t> CoordIdx;///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn CX3DImporter_NodeElement_ElevationGrid(const CX3DImporter_NodeElement_ElevationGrid& pNode)
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_ElevationGrid(const CX3DImporter_NodeElement_ElevationGrid& pNode);
+
+ /// \fn CX3DImporter_NodeElement_ElevationGrid& operator=(const CX3DImporter_NodeElement_ElevationGrid& pNode)
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_ElevationGrid& operator=(const CX3DImporter_NodeElement_ElevationGrid& pNode);
+
+public:
+
+ /// \fn CX3DImporter_NodeElement_ElevationGrid(const EType pType, CX3DImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pType - type of geometry object.
+ CX3DImporter_NodeElement_ElevationGrid(const EType pType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Geometry3D(pType, pParent)
+ {}
+
+};// class CX3DImporter_NodeElement_IndexedSet
+
+/// \class CX3DImporter_NodeElement_IndexedSet
+/// Shape with indexed vertices.
+class CX3DImporter_NodeElement_IndexedSet : public CX3DImporter_NodeElement_Geometry3D
+{
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ /// \var CCW
+ /// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
+ /// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
+ /// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
+ /// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
+ /// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
+ /// ccw field, results are undefined.
+ bool CCW;
+ std::vector<int32_t> ColorIndex;///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
+ bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
+ /// \var Convex
+ /// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
+ /// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
+ /// even if the convex field is FALSE.
+ bool Convex;
+ std::vector<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
+ /// \var CreaseAngle
+ /// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
+ /// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
+ float CreaseAngle;
+ std::vector<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
+ bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
+ std::vector<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn CX3DImporter_NodeElement_IndexedSet(const CX3DImporter_NodeElement_IndexedSet& pNode)
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_IndexedSet(const CX3DImporter_NodeElement_IndexedSet& pNode);
+
+ /// \fn CX3DImporter_NodeElement_IndexedSet& operator=(const CX3DImporter_NodeElement_IndexedSet& pNode)
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_IndexedSet& operator=(const CX3DImporter_NodeElement_IndexedSet& pNode);
+
+public:
+
+ /// \fn CX3DImporter_NodeElement_IndexedSet(const EType pType, CX3DImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pType - type of geometry object.
+ CX3DImporter_NodeElement_IndexedSet(const EType pType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Geometry3D(pType, pParent)
+ {}
+
+};// class CX3DImporter_NodeElement_IndexedSet
+
+/// \class CX3DImporter_NodeElement_Set
+/// Shape with set of vertices.
+class CX3DImporter_NodeElement_Set : public CX3DImporter_NodeElement_Geometry3D
+{
+ /***********************************************/
+ /****************** Variables ******************/
+ /***********************************************/
+
+public:
+
+ /// \var CCW
+ /// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
+ /// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
+ /// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
+ /// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
+ /// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
+ /// ccw field, results are undefined.
+ bool CCW;
+ bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line).
+ bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line).
+ std::vector<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
+ std::vector<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
+ std::vector<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
+ std::vector<int32_t> VertexCount;///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
+
+ /***********************************************/
+ /****************** Functions ******************/
+ /***********************************************/
+
+private:
+
+ /// \fn CX3DImporter_NodeElement_Set(const CX3DImporter_NodeElement_Set& pNode)
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_Set(const CX3DImporter_NodeElement_Set& pNode);
+
+ /// \fn CX3DImporter_NodeElement_Set& operator=(const CX3DImporter_NodeElement_Set& pNode)
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_Set& operator=(const CX3DImporter_NodeElement_Set& pNode);
+
+public:
+
+ /// \fn CX3DImporter_NodeElement_Set(const EType pType, CX3DImporter_NodeElement* pParent)
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pType - type of geometry object.
+ CX3DImporter_NodeElement_Set(const EType pType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement_Geometry3D(pType, pParent)
+ {}
+
+};// class CX3DImporter_NodeElement_Set
+
+/// \struct CX3DImporter_NodeElement_Shape
+/// This struct hold <Shape> value.
+struct CX3DImporter_NodeElement_Shape : public CX3DImporter_NodeElement
+{
+ /// \fn CX3DImporter_NodeElement_Shape(CX3DImporter_NodeElement_Shape* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_Shape(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_Shape, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_Shape
+
+/// \struct CX3DImporter_NodeElement_Appearance
+/// This struct hold <Appearance> value.
+struct CX3DImporter_NodeElement_Appearance : public CX3DImporter_NodeElement
+{
+ /// \fn CX3DImporter_NodeElement_Appearance(CX3DImporter_NodeElement_Appearance* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_Appearance(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_Appearance, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_Appearance
+
+/// \class CX3DImporter_NodeElement_Material
+/// Material.
+class CX3DImporter_NodeElement_Material : public CX3DImporter_NodeElement {
+public:
+ float AmbientIntensity;///< Specifies how much ambient light from light sources this surface shall reflect.
+ aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source.
+ aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models.
+ float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights.
+ aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights.
+ float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque.
+
+ /// Constructor.
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pType - type of geometry object.
+ CX3DImporter_NodeElement_Material(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_Material, pParent)
+ , AmbientIntensity( 0.0f )
+ , DiffuseColor()
+ , EmissiveColor()
+ , Shininess( 0.0f )
+ , SpecularColor()
+ , Transparency( 1.0f ) {
+ // empty
+ }
+
+private:
+ /// Disabled copy constructor.
+ CX3DImporter_NodeElement_Material(const CX3DImporter_NodeElement_Material& pNode);
+
+ /// Disabled assign operator.
+ CX3DImporter_NodeElement_Material& operator=(const CX3DImporter_NodeElement_Material& pNode);
+};// class CX3DImporter_NodeElement_Material
+
+/// \struct CX3DImporter_NodeElement_ImageTexture
+/// This struct hold <ImageTexture> value.
+struct CX3DImporter_NodeElement_ImageTexture : public CX3DImporter_NodeElement
+{
+ /// \var RepeatS
+ /// RepeatS and RepeatT, that specify how the texture wraps in the S and T directions. If repeatS is TRUE (the default), the texture map is repeated
+ /// outside the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape. If repeatS is FALSE, the texture coordinates are
+ /// clamped in the S direction to lie within the [0.0, 1.0] range. The repeatT field is analogous to the repeatS field.
+ bool RepeatS;
+ bool RepeatT;///< See \ref RepeatS.
+ std::string URL;///< URL of the texture.
+ /// \fn CX3DImporter_NodeElement_ImageTexture(CX3DImporter_NodeElement_ImageTexture* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_ImageTexture(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_ImageTexture, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_ImageTexture
+
+/// \struct CX3DImporter_NodeElement_TextureTransform
+/// This struct hold <TextureTransform> value.
+struct CX3DImporter_NodeElement_TextureTransform : public CX3DImporter_NodeElement
+{
+ aiVector2D Center;///< Specifies a translation offset in texture coordinate space about which the rotation and scale fields are applied.
+ float Rotation;///< Specifies a rotation in angle base units of the texture coordinates about the center point after the scale has been applied.
+ aiVector2D Scale;///< Specifies a scaling factor in S and T of the texture coordinates about the center point.
+ aiVector2D Translation;///< Specifies a translation of the texture coordinates.
+
+ /// \fn CX3DImporter_NodeElement_TextureTransform(CX3DImporter_NodeElement_TextureTransform* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ CX3DImporter_NodeElement_TextureTransform(CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(ENET_TextureTransform, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_TextureTransform
+
+/// \struct CX3DImporter_NodeElement_Light
+/// This struct hold <TextureTransform> value.
+struct CX3DImporter_NodeElement_Light : public CX3DImporter_NodeElement
+{
+ float AmbientIntensity;///< Specifies the intensity of the ambient emission from the light.
+ aiColor3D Color;///< specifies the spectral colour properties of both the direct and ambient light emission as an RGB value.
+ aiVector3D Direction;///< Specifies the direction vector of the illumination emanating from the light source in the local coordinate system.
+ /// \var Global
+ /// Field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence.
+ /// Scoped lights only illuminate objects that are in the same transformation hierarchy as the light.
+ bool Global;
+ float Intensity;///< Specifies the brightness of the direct emission from the light.
+ /// \var Attenuation
+ /// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor
+ /// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated.
+ aiVector3D Attenuation;
+ aiVector3D Location;///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin.
+ float Radius;///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source.
+ float BeamWidth;///< Specifies an inner solid angle in which the light source emits light at uniform full intensity.
+ float CutOffAngle;///< The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle).
+
+ /// \fn CX3DImporter_NodeElement_Light(EType pLightType, CX3DImporter_NodeElement* pParent)
+ /// Constructor
+ /// \param [in] pParent - pointer to parent node.
+ /// \param [in] pLightType - type of the light source.
+ CX3DImporter_NodeElement_Light(EType pLightType, CX3DImporter_NodeElement* pParent)
+ : CX3DImporter_NodeElement(pLightType, pParent)
+ {}
+
+};// struct CX3DImporter_NodeElement_Light
+
+#endif // INCLUDED_AI_X3D_IMPORTER_NODE_H
diff --git a/src/3rdparty/assimp/code/X3DImporter_Postprocess.cpp b/src/3rdparty/assimp/code/X3DImporter_Postprocess.cpp
new file mode 100644
index 000000000..390ef8995
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Postprocess.cpp
@@ -0,0 +1,826 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Postprocess.cpp
+/// \brief Convert built scenegraph and objects to Assimp scenegraph.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+
+// Header files, Assimp.
+#include <assimp/ai_assert.h>
+#include "StandardShapes.h"
+#include "StringUtils.h"
+
+// Header files, stdlib.
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+namespace Assimp
+{
+
+aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const
+{
+ CX3DImporter_NodeElement* cur_node;
+ std::list<aiMatrix4x4> matr;
+ aiMatrix4x4 out_matr;
+
+ // starting walk from current element to root
+ cur_node = NodeElement_Cur;
+ if(cur_node != nullptr)
+ {
+ do
+ {
+ // if cur_node is group then store group transformation matrix in list.
+ if(cur_node->Type == CX3DImporter_NodeElement::ENET_Group) matr.push_back(((CX3DImporter_NodeElement_Group*)cur_node)->Transformation);
+
+ cur_node = cur_node->Parent;
+ } while(cur_node != nullptr);
+ }
+
+ // multiplicate all matrices in reverse order
+ for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); rit++) out_matr = out_matr * (*rit);
+
+ return out_matr;
+}
+
+void X3DImporter::PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const
+{
+ // walk through childs and find for metadata.
+ for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
+ {
+ if(((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) ||
+ ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) ||
+ ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaString))
+ {
+ pList.push_back(*el_it);
+ }
+ else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaSet)
+ {
+ PostprocessHelper_CollectMetadata(**el_it, pList);
+ }
+ }// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
+}
+
+bool X3DImporter::PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const
+{
+ if((pType == CX3DImporter_NodeElement::ENET_MetaBoolean) || (pType == CX3DImporter_NodeElement::ENET_MetaDouble) ||
+ (pType == CX3DImporter_NodeElement::ENET_MetaFloat) || (pType == CX3DImporter_NodeElement::ENET_MetaInteger) ||
+ (pType == CX3DImporter_NodeElement::ENET_MetaString) || (pType == CX3DImporter_NodeElement::ENET_MetaSet))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool X3DImporter::PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const
+{
+ if((pType == CX3DImporter_NodeElement::ENET_Arc2D) || (pType == CX3DImporter_NodeElement::ENET_ArcClose2D) ||
+ (pType == CX3DImporter_NodeElement::ENET_Box) || (pType == CX3DImporter_NodeElement::ENET_Circle2D) ||
+ (pType == CX3DImporter_NodeElement::ENET_Cone) || (pType == CX3DImporter_NodeElement::ENET_Cylinder) ||
+ (pType == CX3DImporter_NodeElement::ENET_Disk2D) || (pType == CX3DImporter_NodeElement::ENET_ElevationGrid) ||
+ (pType == CX3DImporter_NodeElement::ENET_Extrusion) || (pType == CX3DImporter_NodeElement::ENET_IndexedFaceSet) ||
+ (pType == CX3DImporter_NodeElement::ENET_IndexedLineSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) ||
+ (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet) ||
+ (pType == CX3DImporter_NodeElement::ENET_PointSet) || (pType == CX3DImporter_NodeElement::ENET_LineSet) ||
+ (pType == CX3DImporter_NodeElement::ENET_Polyline2D) || (pType == CX3DImporter_NodeElement::ENET_Polypoint2D) ||
+ (pType == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pType == CX3DImporter_NodeElement::ENET_Sphere) ||
+ (pType == CX3DImporter_NodeElement::ENET_TriangleFanSet) || (pType == CX3DImporter_NodeElement::ENET_TriangleSet) ||
+ (pType == CX3DImporter_NodeElement::ENET_TriangleSet2D) || (pType == CX3DImporter_NodeElement::ENET_TriangleStripSet))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void X3DImporter::Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const
+{
+ const CX3DImporter_NodeElement_Light& ne = *( ( CX3DImporter_NodeElement_Light* ) &pNodeElement );
+ aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
+ aiLight* new_light = new aiLight;
+
+ new_light->mName = ne.ID;
+ new_light->mColorAmbient = ne.Color * ne.AmbientIntensity;
+ new_light->mColorDiffuse = ne.Color * ne.Intensity;
+ new_light->mColorSpecular = ne.Color * ne.Intensity;
+ switch(pNodeElement.Type)
+ {
+ case CX3DImporter_NodeElement::ENET_DirectionalLight:
+ new_light->mType = aiLightSource_DIRECTIONAL;
+ new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
+
+ break;
+ case CX3DImporter_NodeElement::ENET_PointLight:
+ new_light->mType = aiLightSource_POINT;
+ new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
+ new_light->mAttenuationConstant = ne.Attenuation.x;
+ new_light->mAttenuationLinear = ne.Attenuation.y;
+ new_light->mAttenuationQuadratic = ne.Attenuation.z;
+
+ break;
+ case CX3DImporter_NodeElement::ENET_SpotLight:
+ new_light->mType = aiLightSource_SPOT;
+ new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
+ new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
+ new_light->mAttenuationConstant = ne.Attenuation.x;
+ new_light->mAttenuationLinear = ne.Attenuation.y;
+ new_light->mAttenuationQuadratic = ne.Attenuation.z;
+ new_light->mAngleInnerCone = ne.BeamWidth;
+ new_light->mAngleOuterCone = ne.CutOffAngle;
+
+ break;
+ default:
+ throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + to_string(pNodeElement.Type) + ".");
+ }
+
+ pSceneLightList.push_back(new_light);
+}
+
+void X3DImporter::Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const
+{
+ // check argument
+ if(pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr.");
+ if(*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr.");
+
+ *pMaterial = new aiMaterial;
+ aiMaterial& taimat = **pMaterial;// creating alias for convenience.
+
+ // at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
+ for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
+ {
+ if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
+ {
+ aiColor3D tcol3;
+ float tvalf;
+ CX3DImporter_NodeElement_Material& tnemat = *((CX3DImporter_NodeElement_Material*)*el_it);
+
+ tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity;
+ taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT);
+ taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE);
+ taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
+ taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR);
+ tvalf = 1;
+ taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH);
+ taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS);
+ tvalf = 1.0f - tnemat.Transparency;
+ taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
+ }// if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
+ else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture)
+ {
+ CX3DImporter_NodeElement_ImageTexture& tnetex = *((CX3DImporter_NodeElement_ImageTexture*)*el_it);
+ aiString url_str(tnetex.URL.c_str());
+ int mode = aiTextureOp_Multiply;
+
+ taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
+ taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
+ taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
+ }// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture)
+ else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform)
+ {
+ aiUVTransform trans;
+ CX3DImporter_NodeElement_TextureTransform& tnetextr = *((CX3DImporter_NodeElement_TextureTransform*)*el_it);
+
+ trans.mTranslation = tnetextr.Translation - tnetextr.Center;
+ trans.mScaling = tnetextr.Scale;
+ trans.mRotation = tnetextr.Rotation;
+ taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
+ }// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform)
+ }// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
+}
+
+void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const
+{
+ // check argument
+ if(pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr.");
+ if(*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr.");
+
+ /************************************************************************************************************************************/
+ /************************************************************ Geometry2D ************************************************************/
+ /************************************************************************************************************************************/
+ if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Arc2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_ArcClose2D) ||
+ (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Circle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Disk2D) ||
+ (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polyline2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polypoint2D) ||
+ (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet2D))
+ {
+ CX3DImporter_NodeElement_Geometry2D& tnemesh = *((CX3DImporter_NodeElement_Geometry2D*)&pNodeElement);// create alias for convenience
+ std::vector<aiVector3D> tarr;
+
+ tarr.reserve(tnemesh.Vertices.size());
+ for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it);
+ *pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
+
+ return;// mesh is build, nothing to do anymore.
+ }
+ /************************************************************************************************************************************/
+ /************************************************************ Geometry3D ************************************************************/
+ /************************************************************************************************************************************/
+ //
+ // Predefined figures
+ //
+ if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Box) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cone) ||
+ (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cylinder) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Sphere))
+ {
+ CX3DImporter_NodeElement_Geometry3D& tnemesh = *((CX3DImporter_NodeElement_Geometry3D*)&pNodeElement);// create alias for convenience
+ std::vector<aiVector3D> tarr;
+
+ tarr.reserve(tnemesh.Vertices.size());
+ for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it);
+
+ *pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
+
+ return;// mesh is build, nothing to do anymore.
+ }
+ //
+ // Parametric figures
+ //
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
+ {
+ CX3DImporter_NodeElement_ElevationGrid& tnemesh = *((CX3DImporter_NodeElement_ElevationGrid*)&pNodeElement);// create alias for convenience
+
+ // at first create mesh from existing vertices.
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
+ MeshGeometry_AddNormal(**pMesh, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, tnemesh.NormalPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
+ MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
+ //
+ // Indexed primitives sets
+ //
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
+ {
+ CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
+ tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
+ MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
+ MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
+
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
+ {
+ CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ ai_assert(*pMesh);
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
+ tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
+
+ if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) ||
+ (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) ||
+ (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
+ {
+ CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ ai_assert(*pMesh);
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
+ tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
+ MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
+ MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
+ IndexedTriangleStripSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
+
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
+ {
+ CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
+
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, tnemesh.Vertices);
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
+
+ //
+ // Primitives sets
+ //
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
+ {
+ CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ std::vector<aiVector3D> vec_copy;
+
+ vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
+ for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
+ it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
+ {
+ vec_copy.push_back(*it);
+ }
+
+ *pMesh = StandardShapes::MakeMesh(vec_copy, 1);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ ai_assert(*pMesh);
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
+
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
+ {
+ CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ ai_assert(*pMesh);
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
+
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
+ {
+ CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if ( nullptr == *pMesh ) {
+ break;
+ }
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value,tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
+ MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
+ MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
+
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
+ {
+ CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ std::vector<aiVector3D> vec_copy;
+
+ vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
+ for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
+ it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
+ {
+ vec_copy.push_back(*it);
+ }
+
+ *pMesh = StandardShapes::MakeMesh(vec_copy, 3);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ ai_assert(*pMesh);
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
+ MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
+ MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
+
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
+ {
+ CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {
+ *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+ {
+ ai_assert(*pMesh);
+ if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
+ MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
+ {} // skip because already read when mesh created.
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
+ MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
+ MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + ".");
+ }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+
+ return;// mesh is build, nothing to do anymore.
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
+
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + to_string(pNodeElement.Type) + ".");
+}
+
+void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
+ std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const
+{
+ std::list<CX3DImporter_NodeElement*>::const_iterator chit_begin = pNodeElement.Child.begin();
+ std::list<CX3DImporter_NodeElement*>::const_iterator chit_end = pNodeElement.Child.end();
+ std::list<aiNode*> SceneNode_Child;
+ std::list<unsigned int> SceneNode_Mesh;
+
+ // At first read all metadata
+ Postprocess_CollectMetadata(pNodeElement, pSceneNode);
+ // check if we have deal with grouping node. Which can contain transformation or switch
+ if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
+ {
+ const CX3DImporter_NodeElement_Group& tne_group = *((CX3DImporter_NodeElement_Group*)&pNodeElement);// create alias for convenience
+
+ pSceneNode.mTransformation = tne_group.Transformation;
+ if(tne_group.UseChoice)
+ {
+ // If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen.
+ if((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Child.size()))
+ {
+ chit_begin = pNodeElement.Child.end();
+ chit_end = pNodeElement.Child.end();
+ }
+ else
+ {
+ for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to chosen node.
+
+ chit_end = chit_begin;
+ chit_end++;// point end iterator to next element after chosen node.
+ }
+ }// if(tne_group.UseChoice)
+ }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
+
+ // Reserve memory for fast access and check children.
+ for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
+ {// in this loop we do not read metadata because it's already read at begin.
+ if((*it)->Type == CX3DImporter_NodeElement::ENET_Group)
+ {
+ // if child is group then create new node and do recursive call.
+ aiNode* new_node = new aiNode;
+
+ new_node->mName = (*it)->ID;
+ new_node->mParent = &pSceneNode;
+ SceneNode_Child.push_back(new_node);
+ Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList);
+ }
+ else if((*it)->Type == CX3DImporter_NodeElement::ENET_Shape)
+ {
+ // shape can contain only one geometry and one appearance nodes.
+ Postprocess_BuildShape(*((CX3DImporter_NodeElement_Shape*)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
+ }
+ else if(((*it)->Type == CX3DImporter_NodeElement::ENET_DirectionalLight) || ((*it)->Type == CX3DImporter_NodeElement::ENET_PointLight) ||
+ ((*it)->Type == CX3DImporter_NodeElement::ENET_SpotLight))
+ {
+ Postprocess_BuildLight(*((CX3DImporter_NodeElement_Light*)*it), pSceneLightList);
+ }
+ else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata
+ {
+ throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + to_string((*it)->Type) + ".");
+ }
+ }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
+
+ // copy data about children and meshes to aiNode.
+ if(SceneNode_Child.size() > 0)
+ {
+ std::list<aiNode*>::const_iterator it = SceneNode_Child.begin();
+
+ pSceneNode.mNumChildren = static_cast<unsigned int>(SceneNode_Child.size());
+ pSceneNode.mChildren = new aiNode*[pSceneNode.mNumChildren];
+ for(size_t i = 0; i < pSceneNode.mNumChildren; i++) pSceneNode.mChildren[i] = *it++;
+ }
+
+ if(SceneNode_Mesh.size() > 0)
+ {
+ std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
+
+ pSceneNode.mNumMeshes = static_cast<unsigned int>(SceneNode_Mesh.size());
+ pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
+ for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *it++;
+ }
+
+ // that's all. return to previous deals
+}
+
+void X3DImporter::Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
+ std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const
+{
+ aiMaterial* tmat = nullptr;
+ aiMesh* tmesh = nullptr;
+ CX3DImporter_NodeElement::EType mesh_type = CX3DImporter_NodeElement::ENET_Invalid;
+ unsigned int mat_ind = 0;
+
+ for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
+ {
+ if(PostprocessHelper_ElementIsMesh((*it)->Type))
+ {
+ Postprocess_BuildMesh(**it, &tmesh);
+ if(tmesh != nullptr)
+ {
+ // if mesh successfully built then add data about it to arrays
+ pNodeMeshInd.push_back(static_cast<unsigned int>(pSceneMeshList.size()));
+ pSceneMeshList.push_back(tmesh);
+ // keep mesh type. Need above for texture coordinate generation.
+ mesh_type = (*it)->Type;
+ }
+ }
+ else if((*it)->Type == CX3DImporter_NodeElement::ENET_Appearance)
+ {
+ Postprocess_BuildMaterial(**it, &tmat);
+ if(tmat != nullptr)
+ {
+ // if material successfully built then add data about it to array
+ mat_ind = static_cast<unsigned int>(pSceneMaterialList.size());
+ pSceneMaterialList.push_back(tmat);
+ }
+ }
+ }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
+
+ // associate read material with read mesh.
+ if((tmesh != nullptr) && (tmat != nullptr))
+ {
+ tmesh->mMaterialIndex = mat_ind;
+ // Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates.
+ if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
+ {
+ int32_t tm;
+ aiVector3D tvec3;
+
+ switch(mesh_type)
+ {
+ case CX3DImporter_NodeElement::ENET_Box:
+ tm = aiTextureMapping_BOX;
+ break;
+ case CX3DImporter_NodeElement::ENET_Cone:
+ case CX3DImporter_NodeElement::ENET_Cylinder:
+ tm = aiTextureMapping_CYLINDER;
+ break;
+ case CX3DImporter_NodeElement::ENET_Sphere:
+ tm = aiTextureMapping_SPHERE;
+ break;
+ default:
+ tm = aiTextureMapping_PLANE;
+ break;
+ }// switch(mesh_type)
+
+ tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0));
+ }// if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
+ }// if((tmesh != nullptr) && (tmat != nullptr))
+}
+
+void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode) const
+{
+ std::list<CX3DImporter_NodeElement*> meta_list;
+ size_t meta_idx;
+
+ PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element.
+ if ( !meta_list.empty() )
+ {
+ if ( pSceneNode.mMetaData != nullptr ) {
+ throw DeadlyImportError( "Postprocess. MetaData member in node are not nullptr. Something went wrong." );
+ }
+
+ // copy collected metadata to output node.
+ pSceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(meta_list.size()) );
+ meta_idx = 0;
+ for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++, meta_idx++)
+ {
+ CX3DImporter_NodeElement_Meta* cur_meta = (CX3DImporter_NodeElement_Meta*)*it;
+
+ // due to limitations we can add only first element of value list.
+ // Add an element according to its type.
+ if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean)
+ {
+ if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.begin()));
+ }
+ else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble)
+ {
+ if(((CX3DImporter_NodeElement_MetaDouble*)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((CX3DImporter_NodeElement_MetaDouble*)cur_meta)->Value.begin()));
+ }
+ else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat)
+ {
+ if(((CX3DImporter_NodeElement_MetaFloat*)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((CX3DImporter_NodeElement_MetaFloat*)cur_meta)->Value.begin()));
+ }
+ else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger)
+ {
+ if(((CX3DImporter_NodeElement_MetaInteger*)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((CX3DImporter_NodeElement_MetaInteger*)cur_meta)->Value.begin()));
+ }
+ else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaString)
+ {
+ if(((CX3DImporter_NodeElement_MetaString*)cur_meta)->Value.size() > 0)
+ {
+ aiString tstr(((CX3DImporter_NodeElement_MetaString*)cur_meta)->Value.begin()->data());
+
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, tstr);
+ }
+ }
+ else
+ {
+ throw DeadlyImportError("Postprocess. Unknown metadata type.");
+ }// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else
+ }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
+ }// if( !meta_list.empty() )
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Rendering.cpp b/src/3rdparty/assimp/code/X3DImporter_Rendering.cpp
new file mode 100644
index 000000000..1d4632f32
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Rendering.cpp
@@ -0,0 +1,1070 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Rendering.cpp
+/// \brief Parsing data from nodes of "Rendering" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <Color
+// DEF="" ID
+// USE="" IDREF
+// color="" MFColor [inputOutput]
+// />
+void X3DImporter::ParseNode_Rendering_Color()
+{
+ std::string use, def;
+ std::list<aiColor3D> color;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol3f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Color, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Color(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_Color*)ne)->Value = color;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Color");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <ColorRGBA
+// DEF="" ID
+// USE="" IDREF
+// color="" MFColorRGBA [inputOutput]
+// />
+void X3DImporter::ParseNode_Rendering_ColorRGBA()
+{
+ std::string use, def;
+ std::list<aiColor4D> color;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol4f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_ColorRGBA, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_ColorRGBA(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_ColorRGBA*)ne)->Value = color;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "ColorRGBA");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Coordinate
+// DEF="" ID
+// USE="" IDREF
+// point="" MFVec3f [inputOutput]
+// />
+void X3DImporter::ParseNode_Rendering_Coordinate()
+{
+ std::string use, def;
+ std::list<aiVector3D> point;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec3f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Coordinate, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Coordinate(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_Coordinate*)ne)->Value = point;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Coordinate");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <IndexedLineSet
+// DEF="" ID
+// USE="" IDREF
+// colorIndex="" MFInt32 [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// coordIndex="" MFInt32 [initializeOnly]
+// >
+// <!-- ColorCoordinateContentModel -->
+// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
+// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </IndexedLineSet>
+void X3DImporter::ParseNode_Rendering_IndexedLineSet()
+{
+ std::string use, def;
+ std::vector<int32_t> colorIndex;
+ bool colorPerVertex = true;
+ std::vector<int32_t> coordIndex;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedLineSet, ne);
+ }
+ else
+ {
+ // check data
+ if((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3)))
+ throw DeadlyImportError("IndexedLineSet must contain not empty \"coordIndex\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedLineSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
+
+ ne_alias.ColorIndex = colorIndex;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.CoordIndex = coordIndex;
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("IndexedLineSet");
+ // check for Color and Coordinate nodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedLineSet");
+
+ MACRO_NODECHECK_LOOPEND("IndexedLineSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <IndexedTriangleFanSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// index="" MFInt32 [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </IndexedTriangleFanSet>
+void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ std::vector<int32_t> index;
+ bool normalPerVertex = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleFanSet, ne);
+ }
+ else
+ {
+ // check data
+ if(index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+
+ ne_alias.CoordIndex.clear();
+ int counter = 0;
+ int32_t idx[3];
+ for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+ {
+ idx[2] = *idx_it;
+ if (idx[2] < 0)
+ {
+ counter = 0;
+ }
+ else
+ {
+ if (counter >= 2)
+ {
+ if(ccw)
+ {
+ ne_alias.CoordIndex.push_back(idx[0]);
+ ne_alias.CoordIndex.push_back(idx[1]);
+ ne_alias.CoordIndex.push_back(idx[2]);
+ }
+ else
+ {
+ ne_alias.CoordIndex.push_back(idx[0]);
+ ne_alias.CoordIndex.push_back(idx[2]);
+ ne_alias.CoordIndex.push_back(idx[1]);
+ }
+ ne_alias.CoordIndex.push_back(-1);
+ idx[1] = idx[2];
+ }
+ else
+ {
+ idx[counter] = idx[2];
+ }
+ ++counter;
+ }
+ }// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleFanSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleFanSet");
+
+ MACRO_NODECHECK_LOOPEND("IndexedTriangleFanSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <IndexedTriangleSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// index="" MFInt32 [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </IndexedTriangleSet>
+void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ std::vector<int32_t> index;
+ bool normalPerVertex = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleSet, ne);
+ }
+ else
+ {
+ // check data
+ if(index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+
+ ne_alias.CoordIndex.clear();
+ int counter = 0;
+ int32_t idx[3];
+ for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+ {
+ idx[counter++] = *idx_it;
+ if (counter > 2)
+ {
+ counter = 0;
+ if(ccw)
+ {
+ ne_alias.CoordIndex.push_back(idx[0]);
+ ne_alias.CoordIndex.push_back(idx[1]);
+ ne_alias.CoordIndex.push_back(idx[2]);
+ }
+ else
+ {
+ ne_alias.CoordIndex.push_back(idx[0]);
+ ne_alias.CoordIndex.push_back(idx[2]);
+ ne_alias.CoordIndex.push_back(idx[1]);
+ }
+ ne_alias.CoordIndex.push_back(-1);
+ }
+ }// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleSet");
+
+ MACRO_NODECHECK_LOOPEND("IndexedTriangleSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <IndexedTriangleStripSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// index="" MFInt32 [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </IndexedTriangleStripSet>
+void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ std::vector<int32_t> index;
+ bool normalPerVertex = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleStripSet, ne);
+ }
+ else
+ {
+ // check data
+ if(index.size() == 0) throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+
+ ne_alias.CoordIndex.clear();
+ int counter = 0;
+ int32_t idx[3];
+ for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+ {
+ idx[2] = *idx_it;
+ if (idx[2] < 0)
+ {
+ counter = 0;
+ }
+ else
+ {
+ if (counter >= 2)
+ {
+ if(ccw)
+ {
+ ne_alias.CoordIndex.push_back(idx[0]);
+ ne_alias.CoordIndex.push_back(idx[1]);
+ ne_alias.CoordIndex.push_back(idx[2]);
+ }
+ else
+ {
+ ne_alias.CoordIndex.push_back(idx[0]);
+ ne_alias.CoordIndex.push_back(idx[2]);
+ ne_alias.CoordIndex.push_back(idx[1]);
+ }
+ ne_alias.CoordIndex.push_back(-1);
+ }
+ idx[counter & 1] = idx[2];
+ ++counter;
+ }
+ }// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleStripSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleStripSet");
+
+ MACRO_NODECHECK_LOOPEND("IndexedTriangleStripSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <LineSet
+// DEF="" ID
+// USE="" IDREF
+// vertexCount="" MFInt32 [initializeOnly]
+// >
+// <!-- ColorCoordinateContentModel -->
+// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
+// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </LineSet>
+void X3DImporter::ParseNode_Rendering_LineSet()
+{
+ std::string use, def;
+ std::vector<int32_t> vertexCount;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_LineSet, ne);
+ }
+ else
+ {
+ // check data
+ if(vertexCount.size() == 0) throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_LineSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
+
+ ne_alias.VertexCount = vertexCount;
+ // create CoordIdx
+ size_t coord_num = 0;
+
+ ne_alias.CoordIndex.clear();
+ for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+ {
+ if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
+
+ for(int32_t i = 0; i < *vc_it; i++) ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num++));// add vertices indices
+
+ ne_alias.CoordIndex.push_back(-1);// add face delimiter.
+ }
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("LineSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("LineSet");
+
+ MACRO_NODECHECK_LOOPEND("LineSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <PointSet
+// DEF="" ID
+// USE="" IDREF
+// >
+// <!-- ColorCoordinateContentModel -->
+// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
+// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </PointSet>
+void X3DImporter::ParseNode_Rendering_PointSet()
+{
+ std::string use, def;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointSet, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_PointSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("PointSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("PointSet");
+
+ MACRO_NODECHECK_LOOPEND("PointSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <TriangleFanSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// fanCount="" MFInt32 [inputOutput]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </TriangleFanSet>
+void X3DImporter::ParseNode_Rendering_TriangleFanSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ std::vector<int32_t> fanCount;
+ bool normalPerVertex = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleFanSet, ne);
+ }
+ else
+ {
+ // check data
+ if(fanCount.size() == 0) throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_TriangleFanSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.VertexCount = fanCount;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+ // create CoordIdx
+ size_t coord_num_first, coord_num_prev;
+
+ ne_alias.CoordIndex.clear();
+ // assign indices for first triangle
+ coord_num_first = 0;
+ coord_num_prev = 1;
+ for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+ {
+ if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
+
+ for(int32_t vc = 2; vc < *vc_it; vc++)
+ {
+ if(ccw)
+ {
+ // 2 1
+ // 0
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first));// first vertex is a center and always is [0].
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev));
+ }
+ else
+ {
+ // 1 2
+ // 0
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first));// first vertex is a center and always is [0].
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev + 1));
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
+ }// if(ccw) else
+
+ ne_alias.CoordIndex.push_back(-1);// add face delimiter.
+ }// for(int32_t vc = 2; vc < *vc_it; vc++)
+
+ coord_num_prev++;// that index will be center of next fan
+ coord_num_first = coord_num_prev++;// forward to next point - second point of fan
+ }// for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("TriangleFanSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleFanSet");
+
+ MACRO_NODECHECK_LOOPEND("TriangleFanSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <TriangleSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </TriangleSet>
+void X3DImporter::ParseNode_Rendering_TriangleSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ bool normalPerVertex = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_TriangleSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("TriangleSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleSet");
+
+ MACRO_NODECHECK_LOOPEND("TriangleSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <TriangleStripSet
+// DEF="" ID
+// USE="" IDREF
+// ccw="true" SFBool [initializeOnly]
+// colorPerVertex="true" SFBool [initializeOnly]
+// normalPerVertex="true" SFBool [initializeOnly]
+// solid="true" SFBool [initializeOnly]
+// stripCount="" MFInt32 [inputOutput]
+// >
+// <!-- ComposedGeometryContentModel -->
+// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
+// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
+// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
+// </TriangleStripSet>
+void X3DImporter::ParseNode_Rendering_TriangleStripSet()
+{
+ std::string use, def;
+ bool ccw = true;
+ bool colorPerVertex = true;
+ std::vector<int32_t> stripCount;
+ bool normalPerVertex = true;
+ bool solid = true;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsArrI32);
+ MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleStripSet, ne);
+ }
+ else
+ {
+ // check data
+ if(stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute.");
+
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_TriangleStripSet, NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
+
+ ne_alias.CCW = ccw;
+ ne_alias.ColorPerVertex = colorPerVertex;
+ ne_alias.VertexCount = stripCount;
+ ne_alias.NormalPerVertex = normalPerVertex;
+ ne_alias.Solid = solid;
+ // create CoordIdx
+ size_t coord_num0, coord_num1, coord_num2;// indices of current triangle
+ bool odd_tri;// sequence of current triangle
+ size_t coord_num_sb;// index of first point of strip
+
+ ne_alias.CoordIndex.clear();
+ coord_num_sb = 0;
+ for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+ {
+ if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
+
+ // set initial values for first triangle
+ coord_num0 = coord_num_sb;
+ coord_num1 = coord_num_sb + 1;
+ coord_num2 = coord_num_sb + 2;
+ odd_tri = true;
+
+ for(int32_t vc = 2; vc < *vc_it; vc++)
+ {
+ if(ccw)
+ {
+ // 0 2
+ // 1
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
+ }
+ else
+ {
+ // 0 1
+ // 2
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
+ ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
+ }// if(ccw) else
+
+ ne_alias.CoordIndex.push_back(-1);// add face delimiter.
+ // prepare values for next triangle
+ if(odd_tri)
+ {
+ coord_num0 = coord_num2;
+ coord_num2++;
+ }
+ else
+ {
+ coord_num1 = coord_num2;
+ coord_num2 = coord_num1 + 1;
+ }
+
+ odd_tri = !odd_tri;
+ coord_num_sb = coord_num2;// that index will be start of next strip
+ }// for(int32_t vc = 2; vc < *vc_it; vc++)
+ }// for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("TriangleStripSet");
+ // check for X3DComposedGeometryNodes
+ if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
+ if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
+ if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
+ if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
+ if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleStripSet");
+
+ MACRO_NODECHECK_LOOPEND("TriangleStripSet");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Normal
+// DEF="" ID
+// USE="" IDREF
+// vector="" MFVec3f [inputOutput]
+// />
+void X3DImporter::ParseNode_Rendering_Normal()
+{
+std::string use, def;
+std::list<aiVector3D> vector;
+CX3DImporter_NodeElement* ne;
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("vector", vector, XML_ReadNode_GetAttrVal_AsListVec3f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Normal, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Normal(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_Normal*)ne)->Value = vector;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Normal");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Shape.cpp b/src/3rdparty/assimp/code/X3DImporter_Shape.cpp
new file mode 100644
index 000000000..55ce7fa99
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Shape.cpp
@@ -0,0 +1,249 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Shape.cpp
+/// \brief Parsing data from nodes of "Shape" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <Shape
+// DEF="" ID
+// USE="" IDREF
+// bboxCenter="0 0 0" SFVec3f [initializeOnly]
+// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
+// >
+// <!-- ShapeChildContentModel -->
+// "ShapeChildContentModel is the child-node content model corresponding to X3DShapeNode. ShapeChildContentModel can contain a single Appearance node and a
+// single geometry node, in any order.
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
+// </Shape>
+// A Shape node is unlit if either of the following is true:
+// The shape's appearance field is NULL (default).
+// The material field in the Appearance node is NULL (default).
+// NOTE Geometry nodes that represent lines or points do not support lighting.
+void X3DImporter::ParseNode_Shape_Shape()
+{
+ std::string use, def;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Shape, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Shape(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("Shape");
+ // check for appearance node
+ if(XML_CheckNode_NameEqual("Appearance")) { ParseNode_Shape_Appearance(); continue; }
+ // check for X3DGeometryNodes
+ if(XML_CheckNode_NameEqual("Arc2D")) { ParseNode_Geometry2D_Arc2D(); continue; }
+ if(XML_CheckNode_NameEqual("ArcClose2D")) { ParseNode_Geometry2D_ArcClose2D(); continue; }
+ if(XML_CheckNode_NameEqual("Circle2D")) { ParseNode_Geometry2D_Circle2D(); continue; }
+ if(XML_CheckNode_NameEqual("Disk2D")) { ParseNode_Geometry2D_Disk2D(); continue; }
+ if(XML_CheckNode_NameEqual("Polyline2D")) { ParseNode_Geometry2D_Polyline2D(); continue; }
+ if(XML_CheckNode_NameEqual("Polypoint2D")) { ParseNode_Geometry2D_Polypoint2D(); continue; }
+ if(XML_CheckNode_NameEqual("Rectangle2D")) { ParseNode_Geometry2D_Rectangle2D(); continue; }
+ if(XML_CheckNode_NameEqual("TriangleSet2D")) { ParseNode_Geometry2D_TriangleSet2D(); continue; }
+ if(XML_CheckNode_NameEqual("Box")) { ParseNode_Geometry3D_Box(); continue; }
+ if(XML_CheckNode_NameEqual("Cone")) { ParseNode_Geometry3D_Cone(); continue; }
+ if(XML_CheckNode_NameEqual("Cylinder")) { ParseNode_Geometry3D_Cylinder(); continue; }
+ if(XML_CheckNode_NameEqual("ElevationGrid")) { ParseNode_Geometry3D_ElevationGrid(); continue; }
+ if(XML_CheckNode_NameEqual("Extrusion")) { ParseNode_Geometry3D_Extrusion(); continue; }
+ if(XML_CheckNode_NameEqual("IndexedFaceSet")) { ParseNode_Geometry3D_IndexedFaceSet(); continue; }
+ if(XML_CheckNode_NameEqual("Sphere")) { ParseNode_Geometry3D_Sphere(); continue; }
+ if(XML_CheckNode_NameEqual("IndexedLineSet")) { ParseNode_Rendering_IndexedLineSet(); continue; }
+ if(XML_CheckNode_NameEqual("LineSet")) { ParseNode_Rendering_LineSet(); continue; }
+ if(XML_CheckNode_NameEqual("PointSet")) { ParseNode_Rendering_PointSet(); continue; }
+ if(XML_CheckNode_NameEqual("IndexedTriangleFanSet")) { ParseNode_Rendering_IndexedTriangleFanSet(); continue; }
+ if(XML_CheckNode_NameEqual("IndexedTriangleSet")) { ParseNode_Rendering_IndexedTriangleSet(); continue; }
+ if(XML_CheckNode_NameEqual("IndexedTriangleStripSet")) { ParseNode_Rendering_IndexedTriangleStripSet(); continue; }
+ if(XML_CheckNode_NameEqual("TriangleFanSet")) { ParseNode_Rendering_TriangleFanSet(); continue; }
+ if(XML_CheckNode_NameEqual("TriangleSet")) { ParseNode_Rendering_TriangleSet(); continue; }
+ if(XML_CheckNode_NameEqual("TriangleStripSet")) { ParseNode_Rendering_TriangleStripSet(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Shape");
+
+ MACRO_NODECHECK_LOOPEND("Shape");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Appearance
+// DEF="" ID
+// USE="" IDREF
+// >
+// <!-- AppearanceChildContentModel -->
+// "Child-node content model corresponding to X3DAppearanceChildNode. Appearance can contain FillProperties, LineProperties, Material, any Texture node and
+// any TextureTransform node, in any order. No more than one instance of these nodes is allowed. Appearance may also contain multiple shaders (ComposedShader,
+// PackagedShader, ProgramShader).
+// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
+// </Appearance>
+void X3DImporter::ParseNode_Shape_Appearance()
+{
+ std::string use, def;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Appearance, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Appearance(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ {
+ ParseHelper_Node_Enter(ne);
+ MACRO_NODECHECK_LOOPBEGIN("Appearance");
+ if(XML_CheckNode_NameEqual("Material")) { ParseNode_Shape_Material(); continue; }
+ if(XML_CheckNode_NameEqual("ImageTexture")) { ParseNode_Texturing_ImageTexture(); continue; }
+ if(XML_CheckNode_NameEqual("TextureTransform")) { ParseNode_Texturing_TextureTransform(); continue; }
+ // check for X3DMetadataObject
+ if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Appearance");
+
+ MACRO_NODECHECK_LOOPEND("Appearance");
+ ParseHelper_Node_Exit();
+ }// if(!mReader->isEmptyElement())
+ else
+ {
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+ }
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <Material
+// DEF="" ID
+// USE="" IDREF
+// ambientIntensity="0.2" SFFloat [inputOutput]
+// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
+// emissiveColor="0 0 0" SFColor [inputOutput]
+// shininess="0.2" SFFloat [inputOutput]
+// specularColor="0 0 0" SFColor [inputOutput]
+// transparency="0" SFFloat [inputOutput]
+// />
+void X3DImporter::ParseNode_Shape_Material()
+{
+ std::string use, def;
+ float ambientIntensity = 0.2f;
+ float shininess = 0.2f;
+ float transparency = 0;
+ aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
+ aiColor3D emissiveColor(0, 0, 0);
+ aiColor3D specularColor(0, 0, 0);
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("shininess", shininess, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_RET("transparency", transparency, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("diffuseColor", diffuseColor, XML_ReadNode_GetAttrVal_AsCol3f);
+ MACRO_ATTRREAD_CHECK_REF("emissiveColor", emissiveColor, XML_ReadNode_GetAttrVal_AsCol3f);
+ MACRO_ATTRREAD_CHECK_REF("specularColor", specularColor, XML_ReadNode_GetAttrVal_AsCol3f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_Material, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_Material(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_Material*)ne)->AmbientIntensity = ambientIntensity;
+ ((CX3DImporter_NodeElement_Material*)ne)->Shininess = shininess;
+ ((CX3DImporter_NodeElement_Material*)ne)->Transparency = transparency;
+ ((CX3DImporter_NodeElement_Material*)ne)->DiffuseColor = diffuseColor;
+ ((CX3DImporter_NodeElement_Material*)ne)->EmissiveColor = emissiveColor;
+ ((CX3DImporter_NodeElement_Material*)ne)->SpecularColor = specularColor;
+ // check for child nodes
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "Material");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DImporter_Texturing.cpp b/src/3rdparty/assimp/code/X3DImporter_Texturing.cpp
new file mode 100644
index 000000000..40ea47797
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DImporter_Texturing.cpp
@@ -0,0 +1,196 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DImporter_Texturing.cpp
+/// \brief Parsing data from nodes of "Texturing" set of X3D.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DImporter.hpp"
+#include "X3DImporter_Macro.hpp"
+
+namespace Assimp
+{
+
+// <ImageTexture
+// DEF="" ID
+// USE="" IDREF
+// repeatS="true" SFBool
+// repeatT="true" SFBool
+// url="" MFString
+// />
+// When the url field contains no values ([]), texturing is disabled.
+void X3DImporter::ParseNode_Texturing_ImageTexture()
+{
+ std::string use, def;
+ bool repeatS = true;
+ bool repeatT = true;
+ std::list<std::string> url;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_RET("repeatS", repeatS, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_RET("repeatT", repeatT, XML_ReadNode_GetAttrVal_AsBool);
+ MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_ImageTexture, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_ImageTexture(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatS = repeatS;
+ ((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatT = repeatT;
+ // Attribute "url" can contain list of strings. But we need only one - first.
+ if(url.size() > 0)
+ ((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = url.front();
+ else
+ ((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = "";
+
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "ImageTexture");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <TextureCoordinate
+// DEF="" ID
+// USE="" IDREF
+// point="" MFVec3f [inputOutput]
+// />
+void X3DImporter::ParseNode_Texturing_TextureCoordinate()
+{
+ std::string use, def;
+ std::list<aiVector2D> point;
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureCoordinate, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_TextureCoordinate(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_TextureCoordinate*)ne)->Value = point;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "TextureCoordinate");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+// <TextureTransform
+// DEF="" ID
+// USE="" IDREF
+// center="0 0" SFVec2f [inputOutput]
+// rotation="0" SFFloat [inputOutput]
+// scale="1 1" SFVec2f [inputOutput]
+// translation="0 0" SFVec2f [inputOutput]
+// />
+void X3DImporter::ParseNode_Texturing_TextureTransform()
+{
+ std::string use, def;
+ aiVector2D center(0, 0);
+ float rotation = 0;
+ aiVector2D scale(1, 1);
+ aiVector2D translation(0, 0);
+ CX3DImporter_NodeElement* ne( nullptr );
+
+ MACRO_ATTRREAD_LOOPBEG;
+ MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
+ MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec2f);
+ MACRO_ATTRREAD_CHECK_RET("rotation", rotation, XML_ReadNode_GetAttrVal_AsFloat);
+ MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec2f);
+ MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec2f);
+ MACRO_ATTRREAD_LOOPEND;
+
+ // if "USE" defined then find already defined element.
+ if(!use.empty())
+ {
+ MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureTransform, ne);
+ }
+ else
+ {
+ // create and if needed - define new geometry object.
+ ne = new CX3DImporter_NodeElement_TextureTransform(NodeElement_Cur);
+ if(!def.empty()) ne->ID = def;
+
+ ((CX3DImporter_NodeElement_TextureTransform*)ne)->Center = center;
+ ((CX3DImporter_NodeElement_TextureTransform*)ne)->Rotation = rotation;
+ ((CX3DImporter_NodeElement_TextureTransform*)ne)->Scale = scale;
+ ((CX3DImporter_NodeElement_TextureTransform*)ne)->Translation = translation;
+ // check for X3DMetadataObject childs.
+ if(!mReader->isEmptyElement())
+ ParseNode_Metadata(ne, "TextureTransform");
+ else
+ NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
+
+ NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
+ }// if(!use.empty()) else
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/X3DVocabulary.cpp b/src/3rdparty/assimp/code/X3DVocabulary.cpp
new file mode 100644
index 000000000..780c4ffc2
--- /dev/null
+++ b/src/3rdparty/assimp/code/X3DVocabulary.cpp
@@ -0,0 +1,1675 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 X3DVocabulary.cpp
+/// \brief Vocabulary for Fast Infoset encoded binary X3D files.
+/// \date 2017
+/// \author Patrick Daehne
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "FIReader.hpp"
+
+namespace Assimp {
+
+static const char *encodingAlgorithmTable_3_2[] = {
+ "encoder://web3d.org/QuantizedFloatArrayEncoder",
+ "encoder://web3d.org/DeltazlibIntArrayEncoder",
+ "encoder://web3d.org/QuantizedzlibFloatArrayEncoder",
+ "encoder://web3d.org/zlibFloatArrayEncoder",
+ "encoder://web3d.org/QuantizedDoubleArrayEncoder",
+ "encoder://web3d.org/zlibDoubleArrayEncoder",
+ "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder",
+ "encoder://web3d.org/RangeIntArrayEncoder"
+};
+
+static const std::shared_ptr<const FIValue> attributeValueTable_3_2[] = {
+ FIStringValue::create("false"),
+ FIStringValue::create("true")
+};
+
+static const FIQName elementNameTable_3_2[] = {
+ { "Shape", nullptr, nullptr },
+ { "Appearance", nullptr, nullptr },
+ { "Material", nullptr, nullptr },
+ { "IndexedFaceSet", nullptr, nullptr },
+ { "ProtoInstance", nullptr, nullptr },
+ { "Transform", nullptr, nullptr },
+ { "ImageTexture", nullptr, nullptr },
+ { "TextureTransform", nullptr, nullptr },
+ { "Coordinate", nullptr, nullptr },
+ { "Normal", nullptr, nullptr },
+ { "Color", nullptr, nullptr },
+ { "ColorRGBA", nullptr, nullptr },
+ { "TextureCoordinate", nullptr, nullptr },
+ { "ROUTE", nullptr, nullptr },
+ { "fieldValue", nullptr, nullptr },
+ { "Group", nullptr, nullptr },
+ { "LOD", nullptr, nullptr },
+ { "Switch", nullptr, nullptr },
+ { "Script", nullptr, nullptr },
+ { "IndexedTriangleFanSet", nullptr, nullptr },
+ { "IndexedTriangleSet", nullptr, nullptr },
+ { "IndexedTriangleStripSet", nullptr, nullptr },
+ { "MultiTexture", nullptr, nullptr },
+ { "MultiTextureCoordinate", nullptr, nullptr },
+ { "MultiTextureTransform", nullptr, nullptr },
+ { "IndexedLineSet", nullptr, nullptr },
+ { "PointSet", nullptr, nullptr },
+ { "StaticGroup", nullptr, nullptr },
+ { "Sphere", nullptr, nullptr },
+ { "Box", nullptr, nullptr },
+ { "Cone", nullptr, nullptr },
+ { "Anchor", nullptr, nullptr },
+ { "Arc2D", nullptr, nullptr },
+ { "ArcClose2D", nullptr, nullptr },
+ { "AudioClip", nullptr, nullptr },
+ { "Background", nullptr, nullptr },
+ { "Billboard", nullptr, nullptr },
+ { "BooleanFilter", nullptr, nullptr },
+ { "BooleanSequencer", nullptr, nullptr },
+ { "BooleanToggle", nullptr, nullptr },
+ { "BooleanTrigger", nullptr, nullptr },
+ { "Circle2D", nullptr, nullptr },
+ { "Collision", nullptr, nullptr },
+ { "ColorInterpolator", nullptr, nullptr },
+ { "Contour2D", nullptr, nullptr },
+ { "ContourPolyline2D", nullptr, nullptr },
+ { "CoordinateDouble", nullptr, nullptr },
+ { "CoordinateInterpolator", nullptr, nullptr },
+ { "CoordinateInterpolator2D", nullptr, nullptr },
+ { "Cylinder", nullptr, nullptr },
+ { "CylinderSensor", nullptr, nullptr },
+ { "DirectionalLight", nullptr, nullptr },
+ { "Disk2D", nullptr, nullptr },
+ { "EXPORT", nullptr, nullptr },
+ { "ElevationGrid", nullptr, nullptr },
+ { "EspduTransform", nullptr, nullptr },
+ { "ExternProtoDeclare", nullptr, nullptr },
+ { "Extrusion", nullptr, nullptr },
+ { "FillProperties", nullptr, nullptr },
+ { "Fog", nullptr, nullptr },
+ { "FontStyle", nullptr, nullptr },
+ { "GeoCoordinate", nullptr, nullptr },
+ { "GeoElevationGrid", nullptr, nullptr },
+ { "GeoLOD", nullptr, nullptr },
+ { "GeoLocation", nullptr, nullptr },
+ { "GeoMetadata", nullptr, nullptr },
+ { "GeoOrigin", nullptr, nullptr },
+ { "GeoPositionInterpolator", nullptr, nullptr },
+ { "GeoTouchSensor", nullptr, nullptr },
+ { "GeoViewpoint", nullptr, nullptr },
+ { "HAnimDisplacer", nullptr, nullptr },
+ { "HAnimHumanoid", nullptr, nullptr },
+ { "HAnimJoint", nullptr, nullptr },
+ { "HAnimSegment", nullptr, nullptr },
+ { "HAnimSite", nullptr, nullptr },
+ { "IMPORT", nullptr, nullptr },
+ { "IS", nullptr, nullptr },
+ { "Inline", nullptr, nullptr },
+ { "IntegerSequencer", nullptr, nullptr },
+ { "IntegerTrigger", nullptr, nullptr },
+ { "KeySensor", nullptr, nullptr },
+ { "LineProperties", nullptr, nullptr },
+ { "LineSet", nullptr, nullptr },
+ { "LoadSensor", nullptr, nullptr },
+ { "MetadataDouble", nullptr, nullptr },
+ { "MetadataFloat", nullptr, nullptr },
+ { "MetadataInteger", nullptr, nullptr },
+ { "MetadataSet", nullptr, nullptr },
+ { "MetadataString", nullptr, nullptr },
+ { "MovieTexture", nullptr, nullptr },
+ { "NavigationInfo", nullptr, nullptr },
+ { "NormalInterpolator", nullptr, nullptr },
+ { "NurbsCurve", nullptr, nullptr },
+ { "NurbsCurve2D", nullptr, nullptr },
+ { "NurbsOrientationInterpolator", nullptr, nullptr },
+ { "NurbsPatchSurface", nullptr, nullptr },
+ { "NurbsPositionInterpolator", nullptr, nullptr },
+ { "NurbsSet", nullptr, nullptr },
+ { "NurbsSurfaceInterpolator", nullptr, nullptr },
+ { "NurbsSweptSurface", nullptr, nullptr },
+ { "NurbsSwungSurface", nullptr, nullptr },
+ { "NurbsTextureCoordinate", nullptr, nullptr },
+ { "NurbsTrimmedSurface", nullptr, nullptr },
+ { "OrientationInterpolator", nullptr, nullptr },
+ { "PixelTexture", nullptr, nullptr },
+ { "PlaneSensor", nullptr, nullptr },
+ { "PointLight", nullptr, nullptr },
+ { "Polyline2D", nullptr, nullptr },
+ { "Polypoint2D", nullptr, nullptr },
+ { "PositionInterpolator", nullptr, nullptr },
+ { "PositionInterpolator2D", nullptr, nullptr },
+ { "ProtoBody", nullptr, nullptr },
+ { "ProtoDeclare", nullptr, nullptr },
+ { "ProtoInterface", nullptr, nullptr },
+ { "ProximitySensor", nullptr, nullptr },
+ { "ReceiverPdu", nullptr, nullptr },
+ { "Rectangle2D", nullptr, nullptr },
+ { "ScalarInterpolator", nullptr, nullptr },
+ { "Scene", nullptr, nullptr },
+ { "SignalPdu", nullptr, nullptr },
+ { "Sound", nullptr, nullptr },
+ { "SphereSensor", nullptr, nullptr },
+ { "SpotLight", nullptr, nullptr },
+ { "StringSensor", nullptr, nullptr },
+ { "Text", nullptr, nullptr },
+ { "TextureBackground", nullptr, nullptr },
+ { "TextureCoordinateGenerator", nullptr, nullptr },
+ { "TimeSensor", nullptr, nullptr },
+ { "TimeTrigger", nullptr, nullptr },
+ { "TouchSensor", nullptr, nullptr },
+ { "TransmitterPdu", nullptr, nullptr },
+ { "TriangleFanSet", nullptr, nullptr },
+ { "TriangleSet", nullptr, nullptr },
+ { "TriangleSet2D", nullptr, nullptr },
+ { "TriangleStripSet", nullptr, nullptr },
+ { "Viewpoint", nullptr, nullptr },
+ { "VisibilitySensor", nullptr, nullptr },
+ { "WorldInfo", nullptr, nullptr },
+ { "X3D", nullptr, nullptr },
+ { "component", nullptr, nullptr },
+ { "connect", nullptr, nullptr },
+ { "field", nullptr, nullptr },
+ { "head", nullptr, nullptr },
+ { "humanoidBodyType", nullptr, nullptr },
+ { "meta", nullptr, nullptr },
+ { "CADAssembly", nullptr, nullptr },
+ { "CADFace", nullptr, nullptr },
+ { "CADLayer", nullptr, nullptr },
+ { "CADPart", nullptr, nullptr },
+ { "ComposedCubeMapTexture", nullptr, nullptr },
+ { "ComposedShader", nullptr, nullptr },
+ { "ComposedTexture3D", nullptr, nullptr },
+ { "FloatVertexAttribute", nullptr, nullptr },
+ { "FogCoordinate", nullptr, nullptr },
+ { "GeneratedCubeMapTexture", nullptr, nullptr },
+ { "ImageCubeMapTexture", nullptr, nullptr },
+ { "ImageTexture3D", nullptr, nullptr },
+ { "IndexedQuadSet", nullptr, nullptr },
+ { "LocalFog", nullptr, nullptr },
+ { "Matrix3VertexAttribute", nullptr, nullptr },
+ { "Matrix4VertexAttribute", nullptr, nullptr },
+ { "PackagedShader", nullptr, nullptr },
+ { "PixelTexture3D", nullptr, nullptr },
+ { "ProgramShader", nullptr, nullptr },
+ { "QuadSet", nullptr, nullptr },
+ { "ShaderPart", nullptr, nullptr },
+ { "ShaderProgram", nullptr, nullptr },
+ { "TextureCoordinate3D", nullptr, nullptr },
+ { "TextureCoordinate4D", nullptr, nullptr },
+ { "TextureTransform3D", nullptr, nullptr },
+ { "TextureTransformMatrix3D", nullptr, nullptr },
+ { "BallJoint", nullptr, nullptr },
+ { "BoundedPhysicsModel", nullptr, nullptr },
+ { "ClipPlane", nullptr, nullptr },
+ { "CollidableOffset", nullptr, nullptr },
+ { "CollidableShape", nullptr, nullptr },
+ { "CollisionCollection", nullptr, nullptr },
+ { "CollisionSensor", nullptr, nullptr },
+ { "CollisionSpace", nullptr, nullptr },
+ { "ColorDamper", nullptr, nullptr },
+ { "ConeEmitter", nullptr, nullptr },
+ { "Contact", nullptr, nullptr },
+ { "CoordinateDamper", nullptr, nullptr },
+ { "DISEntityManager", nullptr, nullptr },
+ { "DISEntityTypeMapping", nullptr, nullptr },
+ { "DoubleAxisHingeJoint", nullptr, nullptr },
+ { "EaseInEaseOut", nullptr, nullptr },
+ { "ExplosionEmitter", nullptr, nullptr },
+ { "ForcePhysicsModel", nullptr, nullptr },
+ { "GeoProximitySensor", nullptr, nullptr },
+ { "GeoTransform", nullptr, nullptr },
+ { "Layer", nullptr, nullptr },
+ { "LayerSet", nullptr, nullptr },
+ { "Layout", nullptr, nullptr },
+ { "LayoutGroup", nullptr, nullptr },
+ { "LayoutLayer", nullptr, nullptr },
+ { "LinePickSensor", nullptr, nullptr },
+ { "MotorJoint", nullptr, nullptr },
+ { "OrientationChaser", nullptr, nullptr },
+ { "OrientationDamper", nullptr, nullptr },
+ { "OrthoViewpoint", nullptr, nullptr },
+ { "ParticleSystem", nullptr, nullptr },
+ { "PickableGroup", nullptr, nullptr },
+ { "PointEmitter", nullptr, nullptr },
+ { "PointPickSensor", nullptr, nullptr },
+ { "PolylineEmitter", nullptr, nullptr },
+ { "PositionChaser", nullptr, nullptr },
+ { "PositionChaser2D", nullptr, nullptr },
+ { "PositionDamper", nullptr, nullptr },
+ { "PositionDamper2D", nullptr, nullptr },
+ { "PrimitivePickSensor", nullptr, nullptr },
+ { "RigidBody", nullptr, nullptr },
+ { "RigidBodyCollection", nullptr, nullptr },
+ { "ScalarChaser", nullptr, nullptr },
+ { "ScreenFontStyle", nullptr, nullptr },
+ { "ScreenGroup", nullptr, nullptr },
+ { "SingleAxisHingeJoint", nullptr, nullptr },
+ { "SliderJoint", nullptr, nullptr },
+ { "SplinePositionInterpolator", nullptr, nullptr },
+ { "SplinePositionInterpolator2D", nullptr, nullptr },
+ { "SplineScalarInterpolator", nullptr, nullptr },
+ { "SquadOrientationInterpolator", nullptr, nullptr },
+ { "SurfaceEmitter", nullptr, nullptr },
+ { "TexCoordDamper", nullptr, nullptr },
+ { "TextureProperties", nullptr, nullptr },
+ { "TransformSensor", nullptr, nullptr },
+ { "TwoSidedMaterial", nullptr, nullptr },
+ { "UniversalJoint", nullptr, nullptr },
+ { "ViewpointGroup", nullptr, nullptr },
+ { "Viewport", nullptr, nullptr },
+ { "VolumeEmitter", nullptr, nullptr },
+ { "VolumePickSensor", nullptr, nullptr },
+ { "WindPhysicsModel", nullptr, nullptr }
+};
+
+static const FIQName attributeNameTable_3_2[] = {
+ { "DEF", nullptr, nullptr },
+ { "USE", nullptr, nullptr },
+ { "containerField", nullptr, nullptr },
+ { "fromNode", nullptr, nullptr },
+ { "fromField", nullptr, nullptr },
+ { "toNode", nullptr, nullptr },
+ { "toField", nullptr, nullptr },
+ { "name", nullptr, nullptr },
+ { "value", nullptr, nullptr },
+ { "color", nullptr, nullptr },
+ { "colorIndex", nullptr, nullptr },
+ { "coordIndex", nullptr, nullptr },
+ { "texCoordIndex", nullptr, nullptr },
+ { "normalIndex", nullptr, nullptr },
+ { "colorPerVertex", nullptr, nullptr },
+ { "normalPerVertex", nullptr, nullptr },
+ { "rotation", nullptr, nullptr },
+ { "scale", nullptr, nullptr },
+ { "center", nullptr, nullptr },
+ { "scaleOrientation", nullptr, nullptr },
+ { "translation", nullptr, nullptr },
+ { "url", nullptr, nullptr },
+ { "repeatS", nullptr, nullptr },
+ { "repeatT", nullptr, nullptr },
+ { "point", nullptr, nullptr },
+ { "vector", nullptr, nullptr },
+ { "range", nullptr, nullptr },
+ { "ambientIntensity", nullptr, nullptr },
+ { "diffuseColor", nullptr, nullptr },
+ { "emissiveColor", nullptr, nullptr },
+ { "shininess", nullptr, nullptr },
+ { "specularColor", nullptr, nullptr },
+ { "transparency", nullptr, nullptr },
+ { "whichChoice", nullptr, nullptr },
+ { "index", nullptr, nullptr },
+ { "mode", nullptr, nullptr },
+ { "source", nullptr, nullptr },
+ { "function", nullptr, nullptr },
+ { "alpha", nullptr, nullptr },
+ { "vertexCount", nullptr, nullptr },
+ { "radius", nullptr, nullptr },
+ { "size", nullptr, nullptr },
+ { "height", nullptr, nullptr },
+ { "solid", nullptr, nullptr },
+ { "ccw", nullptr, nullptr },
+ { "key", nullptr, nullptr },
+ { "keyValue", nullptr, nullptr },
+ { "enabled", nullptr, nullptr },
+ { "direction", nullptr, nullptr },
+ { "position", nullptr, nullptr },
+ { "orientation", nullptr, nullptr },
+ { "bboxCenter", nullptr, nullptr },
+ { "bboxSize", nullptr, nullptr },
+ { "AS", nullptr, nullptr },
+ { "InlineDEF", nullptr, nullptr },
+ { "accessType", nullptr, nullptr },
+ { "actionKeyPress", nullptr, nullptr },
+ { "actionKeyRelease", nullptr, nullptr },
+ { "address", nullptr, nullptr },
+ { "altKey", nullptr, nullptr },
+ { "antennaLocation", nullptr, nullptr },
+ { "antennaPatternLength", nullptr, nullptr },
+ { "antennaPatternType", nullptr, nullptr },
+ { "applicationID", nullptr, nullptr },
+ { "articulationParameterArray", nullptr, nullptr },
+ { "articulationParameterChangeIndicatorArray", nullptr, nullptr },
+ { "articulationParameterCount", nullptr, nullptr },
+ { "articulationParameterDesignatorArray", nullptr, nullptr },
+ { "articulationParameterIdPartAttachedArray", nullptr, nullptr },
+ { "articulationParameterTypeArray", nullptr, nullptr },
+ { "attenuation", nullptr, nullptr },
+ { "autoOffset", nullptr, nullptr },
+ { "avatarSize", nullptr, nullptr },
+ { "axisOfRotation", nullptr, nullptr },
+ { "backUrl", nullptr, nullptr },
+ { "beamWidth", nullptr, nullptr },
+ { "beginCap", nullptr, nullptr },
+ { "bindTime", nullptr, nullptr },
+ { "bottom", nullptr, nullptr },
+ { "bottomRadius", nullptr, nullptr },
+ { "bottomUrl", nullptr, nullptr },
+ { "centerOfMass", nullptr, nullptr },
+ { "centerOfRotation", nullptr, nullptr },
+ { "child1Url", nullptr, nullptr },
+ { "child2Url", nullptr, nullptr },
+ { "child3Url", nullptr, nullptr },
+ { "child4Url", nullptr, nullptr },
+ { "class", nullptr, nullptr },
+ { "closureType", nullptr, nullptr },
+ { "collideTime", nullptr, nullptr },
+ { "content", nullptr, nullptr },
+ { "controlKey", nullptr, nullptr },
+ { "controlPoint", nullptr, nullptr },
+ { "convex", nullptr, nullptr },
+ { "coordinateSystem", nullptr, nullptr },
+ { "copyright", nullptr, nullptr },
+ { "creaseAngle", nullptr, nullptr },
+ { "crossSection", nullptr, nullptr },
+ { "cryptoKeyID", nullptr, nullptr },
+ { "cryptoSystem", nullptr, nullptr },
+ { "cutOffAngle", nullptr, nullptr },
+ { "cycleInterval", nullptr, nullptr },
+ { "cycleTime", nullptr, nullptr },
+ { "data", nullptr, nullptr },
+ { "dataFormat", nullptr, nullptr },
+ { "dataLength", nullptr, nullptr },
+ { "dataUrl", nullptr, nullptr },
+ { "date", nullptr, nullptr },
+ { "deadReckoning", nullptr, nullptr },
+ { "deletionAllowed", nullptr, nullptr },
+ { "description", nullptr, nullptr },
+ { "detonateTime", nullptr, nullptr },
+ { "dir", nullptr, nullptr },
+ { "directOutput", nullptr, nullptr },
+ { "diskAngle", nullptr, nullptr },
+ { "displacements", nullptr, nullptr },
+ { "documentation", nullptr, nullptr },
+ { "elapsedTime", nullptr, nullptr },
+ { "ellipsoid", nullptr, nullptr },
+ { "encodingScheme", nullptr, nullptr },
+ { "endAngle", nullptr, nullptr },
+ { "endCap", nullptr, nullptr },
+ { "enterTime", nullptr, nullptr },
+ { "enteredText", nullptr, nullptr },
+ { "entityCategory", nullptr, nullptr },
+ { "entityCountry", nullptr, nullptr },
+ { "entityDomain", nullptr, nullptr },
+ { "entityExtra", nullptr, nullptr },
+ { "entityID", nullptr, nullptr },
+ { "entityKind", nullptr, nullptr },
+ { "entitySpecific", nullptr, nullptr },
+ { "entitySubCategory", nullptr, nullptr },
+ { "exitTime", nullptr, nullptr },
+ { "extent", nullptr, nullptr },
+ { "family", nullptr, nullptr },
+ { "fanCount", nullptr, nullptr },
+ { "fieldOfView", nullptr, nullptr },
+ { "filled", nullptr, nullptr },
+ { "finalText", nullptr, nullptr },
+ { "fireMissionIndex", nullptr, nullptr },
+ { "fired1", nullptr, nullptr },
+ { "fired2", nullptr, nullptr },
+ { "firedTime", nullptr, nullptr },
+ { "firingRange", nullptr, nullptr },
+ { "firingRate", nullptr, nullptr },
+ { "fogType", nullptr, nullptr },
+ { "forceID", nullptr, nullptr },
+ { "frequency", nullptr, nullptr },
+ { "frontUrl", nullptr, nullptr },
+ { "fuse", nullptr, nullptr },
+ { "geoCoords", nullptr, nullptr },
+ { "geoGridOrigin", nullptr, nullptr },
+ { "geoSystem", nullptr, nullptr },
+ { "groundAngle", nullptr, nullptr },
+ { "groundColor", nullptr, nullptr },
+ { "hatchColor", nullptr, nullptr },
+ { "hatchStyle", nullptr, nullptr },
+ { "hatched", nullptr, nullptr },
+ { "headlight", nullptr, nullptr },
+ { "horizontal", nullptr, nullptr },
+ { "horizontalDatum", nullptr, nullptr },
+ { "http-equiv", nullptr, nullptr },
+ { "image", nullptr, nullptr },
+ { "importedDEF", nullptr, nullptr },
+ { "info", nullptr, nullptr },
+ { "innerRadius", nullptr, nullptr },
+ { "inputFalse", nullptr, nullptr },
+ { "inputNegate", nullptr, nullptr },
+ { "inputSource", nullptr, nullptr },
+ { "inputTrue", nullptr, nullptr },
+ { "integerKey", nullptr, nullptr },
+ { "intensity", nullptr, nullptr },
+ { "jump", nullptr, nullptr },
+ { "justify", nullptr, nullptr },
+ { "keyPress", nullptr, nullptr },
+ { "keyRelease", nullptr, nullptr },
+ { "knot", nullptr, nullptr },
+ { "lang", nullptr, nullptr },
+ { "language", nullptr, nullptr },
+ { "leftToRight", nullptr, nullptr },
+ { "leftUrl", nullptr, nullptr },
+ { "length", nullptr, nullptr },
+ { "lengthOfModulationParameters", nullptr, nullptr },
+ { "level", nullptr, nullptr },
+ { "limitOrientation", nullptr, nullptr },
+ { "lineSegments", nullptr, nullptr },
+ { "linearAcceleration", nullptr, nullptr },
+ { "linearVelocity", nullptr, nullptr },
+ { "linetype", nullptr, nullptr },
+ { "linewidthScaleFactor", nullptr, nullptr },
+ { "llimit", nullptr, nullptr },
+ { "load", nullptr, nullptr },
+ { "loadTime", nullptr, nullptr },
+ { "localDEF", nullptr, nullptr },
+ { "location", nullptr, nullptr },
+ { "loop", nullptr, nullptr },
+ { "marking", nullptr, nullptr },
+ { "mass", nullptr, nullptr },
+ { "maxAngle", nullptr, nullptr },
+ { "maxBack", nullptr, nullptr },
+ { "maxExtent", nullptr, nullptr },
+ { "maxFront", nullptr, nullptr },
+ { "maxPosition", nullptr, nullptr },
+ { "metadataFormat", nullptr, nullptr },
+ { "minAngle", nullptr, nullptr },
+ { "minBack", nullptr, nullptr },
+ { "minFront", nullptr, nullptr },
+ { "minPosition", nullptr, nullptr },
+ { "modulationTypeDetail", nullptr, nullptr },
+ { "modulationTypeMajor", nullptr, nullptr },
+ { "modulationTypeSpreadSpectrum", nullptr, nullptr },
+ { "modulationTypeSystem", nullptr, nullptr },
+ { "momentsOfInertia", nullptr, nullptr },
+ { "multicastRelayHost", nullptr, nullptr },
+ { "multicastRelayPort", nullptr, nullptr },
+ { "munitionApplicationID", nullptr, nullptr },
+ { "munitionEndPoint", nullptr, nullptr },
+ { "munitionEntityID", nullptr, nullptr },
+ { "munitionQuantity", nullptr, nullptr },
+ { "munitionSiteID", nullptr, nullptr },
+ { "munitionStartPoint", nullptr, nullptr },
+ { "mustEvaluate", nullptr, nullptr },
+ { "navType", nullptr, nullptr },
+ { "networkMode", nullptr, nullptr },
+ { "next", nullptr, nullptr },
+ { "nodeField", nullptr, nullptr },
+ { "offset", nullptr, nullptr },
+ { "on", nullptr, nullptr },
+ { "order", nullptr, nullptr },
+ { "originator", nullptr, nullptr },
+ { "outerRadius", nullptr, nullptr },
+ { "parameter", nullptr, nullptr },
+ { "pauseTime", nullptr, nullptr },
+ { "pitch", nullptr, nullptr },
+ { "points", nullptr, nullptr },
+ { "port", nullptr, nullptr },
+ { "power", nullptr, nullptr },
+ { "previous", nullptr, nullptr },
+ { "priority", nullptr, nullptr },
+ { "profile", nullptr, nullptr },
+ { "progress", nullptr, nullptr },
+ { "protoField", nullptr, nullptr },
+ { "radioEntityTypeCategory", nullptr, nullptr },
+ { "radioEntityTypeCountry", nullptr, nullptr },
+ { "radioEntityTypeDomain", nullptr, nullptr },
+ { "radioEntityTypeKind", nullptr, nullptr },
+ { "radioEntityTypeNomenclature", nullptr, nullptr },
+ { "radioEntityTypeNomenclatureVersion", nullptr, nullptr },
+ { "radioID", nullptr, nullptr },
+ { "readInterval", nullptr, nullptr },
+ { "receivedPower", nullptr, nullptr },
+ { "receiverState", nullptr, nullptr },
+ { "reference", nullptr, nullptr },
+ { "relativeAntennaLocation", nullptr, nullptr },
+ { "resolution", nullptr, nullptr },
+ { "resumeTime", nullptr, nullptr },
+ { "rightUrl", nullptr, nullptr },
+ { "rootUrl", nullptr, nullptr },
+ { "rotateYUp", nullptr, nullptr },
+ { "rtpHeaderExpected", nullptr, nullptr },
+ { "sampleRate", nullptr, nullptr },
+ { "samples", nullptr, nullptr },
+ { "shiftKey", nullptr, nullptr },
+ { "side", nullptr, nullptr },
+ { "siteID", nullptr, nullptr },
+ { "skinCoordIndex", nullptr, nullptr },
+ { "skinCoordWeight", nullptr, nullptr },
+ { "skyAngle", nullptr, nullptr },
+ { "skyColor", nullptr, nullptr },
+ { "spacing", nullptr, nullptr },
+ { "spatialize", nullptr, nullptr },
+ { "speed", nullptr, nullptr },
+ { "speedFactor", nullptr, nullptr },
+ { "spine", nullptr, nullptr },
+ { "startAngle", nullptr, nullptr },
+ { "startTime", nullptr, nullptr },
+ { "stiffness", nullptr, nullptr },
+ { "stopTime", nullptr, nullptr },
+ { "string", nullptr, nullptr },
+ { "stripCount", nullptr, nullptr },
+ { "style", nullptr, nullptr },
+ { "summary", nullptr, nullptr },
+ { "tdlType", nullptr, nullptr },
+ { "tessellation", nullptr, nullptr },
+ { "tessellationScale", nullptr, nullptr },
+ { "time", nullptr, nullptr },
+ { "timeOut", nullptr, nullptr },
+ { "timestamp", nullptr, nullptr },
+ { "title", nullptr, nullptr },
+ { "toggle", nullptr, nullptr },
+ { "top", nullptr, nullptr },
+ { "topToBottom", nullptr, nullptr },
+ { "topUrl", nullptr, nullptr },
+ { "touchTime", nullptr, nullptr },
+ { "transmitFrequencyBandwidth", nullptr, nullptr },
+ { "transmitState", nullptr, nullptr },
+ { "transmitterApplicationID", nullptr, nullptr },
+ { "transmitterEntityID", nullptr, nullptr },
+ { "transmitterRadioID", nullptr, nullptr },
+ { "transmitterSiteID", nullptr, nullptr },
+ { "transparent", nullptr, nullptr },
+ { "triggerTime", nullptr, nullptr },
+ { "triggerTrue", nullptr, nullptr },
+ { "triggerValue", nullptr, nullptr },
+ { "type", nullptr, nullptr },
+ { "uDimension", nullptr, nullptr },
+ { "uKnot", nullptr, nullptr },
+ { "uOrder", nullptr, nullptr },
+ { "uTessellation", nullptr, nullptr },
+ { "ulimit", nullptr, nullptr },
+ { "vDimension", nullptr, nullptr },
+ { "vKnot", nullptr, nullptr },
+ { "vOrder", nullptr, nullptr },
+ { "vTessellation", nullptr, nullptr },
+ { "version", nullptr, nullptr },
+ { "verticalDatum", nullptr, nullptr },
+ { "vertices", nullptr, nullptr },
+ { "visibilityLimit", nullptr, nullptr },
+ { "visibilityRange", nullptr, nullptr },
+ { "warhead", nullptr, nullptr },
+ { "weight", nullptr, nullptr },
+ { "whichGeometry", nullptr, nullptr },
+ { "writeInterval", nullptr, nullptr },
+ { "xDimension", nullptr, nullptr },
+ { "xSpacing", nullptr, nullptr },
+ { "yScale", nullptr, nullptr },
+ { "zDimension", nullptr, nullptr },
+ { "zSpacing", nullptr, nullptr },
+ { "visible", nullptr, nullptr },
+ { "repeatR", nullptr, nullptr },
+ { "texture", nullptr, nullptr },
+ { "back", nullptr, nullptr },
+ { "front", nullptr, nullptr },
+ { "left", nullptr, nullptr },
+ { "right", nullptr, nullptr },
+ { "parts", nullptr, nullptr },
+ { "isSelected", nullptr, nullptr },
+ { "isValid", nullptr, nullptr },
+ { "numComponents", nullptr, nullptr },
+ { "depth", nullptr, nullptr },
+ { "update", nullptr, nullptr },
+ { "fogCoord", nullptr, nullptr },
+ { "texCoord", nullptr, nullptr },
+ { "activate", nullptr, nullptr },
+ { "programs", nullptr, nullptr },
+ { "matrix", nullptr, nullptr },
+ { "anchorPoint", nullptr, nullptr },
+ { "body1", nullptr, nullptr },
+ { "body2", nullptr, nullptr },
+ { "mustOutput", nullptr, nullptr },
+ { "body1AnchorPoint", nullptr, nullptr },
+ { "body2AnchorPoint", nullptr, nullptr },
+ { "plane", nullptr, nullptr },
+ { "appliedParameters", nullptr, nullptr },
+ { "bounce", nullptr, nullptr },
+ { "frictionCoefficients", nullptr, nullptr },
+ { "minBounceSpeed", nullptr, nullptr },
+ { "slipFactors", nullptr, nullptr },
+ { "softnessConstantForceMix", nullptr, nullptr },
+ { "softnessErrorCorrection", nullptr, nullptr },
+ { "surfaceSpeed", nullptr, nullptr },
+ { "isActive", nullptr, nullptr },
+ { "useGeometry", nullptr, nullptr },
+ { "set_destination", nullptr, nullptr },
+ { "set_value", nullptr, nullptr },
+ { "tau", nullptr, nullptr },
+ { "tolerance", nullptr, nullptr },
+ { "value_changed", nullptr, nullptr },
+ { "initialDestination", nullptr, nullptr },
+ { "initialValue", nullptr, nullptr },
+ { "angle", nullptr, nullptr },
+ { "variation", nullptr, nullptr },
+ { "surfaceArea", nullptr, nullptr },
+ { "frictionDirection", nullptr, nullptr },
+ { "slipCoefficients", nullptr, nullptr },
+ { "category", nullptr, nullptr },
+ { "country", nullptr, nullptr },
+ { "domain", nullptr, nullptr },
+ { "extra", nullptr, nullptr },
+ { "kind", nullptr, nullptr },
+ { "specific", nullptr, nullptr },
+ { "subcategory", nullptr, nullptr },
+ { "axis1", nullptr, nullptr },
+ { "axis2", nullptr, nullptr },
+ { "desiredAngularVelocity1", nullptr, nullptr },
+ { "desiredAngularVelocity2", nullptr, nullptr },
+ { "maxAngle1", nullptr, nullptr },
+ { "maxTorque1", nullptr, nullptr },
+ { "maxTorque2", nullptr, nullptr },
+ { "minAngle1", nullptr, nullptr },
+ { "stopBounce1", nullptr, nullptr },
+ { "stopConstantForceMix1", nullptr, nullptr },
+ { "stopErrorCorrection1", nullptr, nullptr },
+ { "suspensionErrorCorrection", nullptr, nullptr },
+ { "suspensionForce", nullptr, nullptr },
+ { "body1Axis", nullptr, nullptr },
+ { "body2Axis", nullptr, nullptr },
+ { "hinge1Angle", nullptr, nullptr },
+ { "hinge1AngleRate", nullptr, nullptr },
+ { "hinge2Angle", nullptr, nullptr },
+ { "hinge2AngleRate", nullptr, nullptr },
+ { "set_fraction", nullptr, nullptr },
+ { "easeInEaseOut", nullptr, nullptr },
+ { "modifiedFraction_changed", nullptr, nullptr },
+ { "force", nullptr, nullptr },
+ { "geoCenter", nullptr, nullptr },
+ { "centerOfRotation_changed", nullptr, nullptr },
+ { "geoCoord_changed", nullptr, nullptr },
+ { "orientation_changed", nullptr, nullptr },
+ { "position_changed", nullptr, nullptr },
+ { "isPickable", nullptr, nullptr },
+ { "viewport", nullptr, nullptr },
+ { "activeLayer", nullptr, nullptr },
+ { "align", nullptr, nullptr },
+ { "offsetUnits", nullptr, nullptr },
+ { "scaleMode", nullptr, nullptr },
+ { "sizeUnits", nullptr, nullptr },
+ { "layout", nullptr, nullptr },
+ { "objectType", nullptr, nullptr },
+ { "pickedNormal", nullptr, nullptr },
+ { "pickedPoint", nullptr, nullptr },
+ { "pickedTextureCoordinate", nullptr, nullptr },
+ { "intersectionType", nullptr, nullptr },
+ { "sortOrder", nullptr, nullptr },
+ { "axis1Angle", nullptr, nullptr },
+ { "axis1Torque", nullptr, nullptr },
+ { "axis2Angle", nullptr, nullptr },
+ { "axis2Torque", nullptr, nullptr },
+ { "axis3Angle", nullptr, nullptr },
+ { "axis3Torque", nullptr, nullptr },
+ { "enabledAxies", nullptr, nullptr },
+ { "motor1Axis", nullptr, nullptr },
+ { "motor2Axis", nullptr, nullptr },
+ { "motor3Axis", nullptr, nullptr },
+ { "stop1Bounce", nullptr, nullptr },
+ { "stop1ErrorCorrection", nullptr, nullptr },
+ { "stop2Bounce", nullptr, nullptr },
+ { "stop2ErrorCorrection", nullptr, nullptr },
+ { "stop3Bounce", nullptr, nullptr },
+ { "stop3ErrorCorrection", nullptr, nullptr },
+ { "motor1Angle", nullptr, nullptr },
+ { "motor1AngleRate", nullptr, nullptr },
+ { "motor2Angle", nullptr, nullptr },
+ { "motor2AngleRate", nullptr, nullptr },
+ { "motor3Angle", nullptr, nullptr },
+ { "motor3AngleRate", nullptr, nullptr },
+ { "autoCalc", nullptr, nullptr },
+ { "duration", nullptr, nullptr },
+ { "retainUserOffsets", nullptr, nullptr },
+ { "isBound", nullptr, nullptr },
+ { "appearance", nullptr, nullptr },
+ { "createParticles", nullptr, nullptr },
+ { "lifetimeVariation", nullptr, nullptr },
+ { "maxParticles", nullptr, nullptr },
+ { "particleLifetime", nullptr, nullptr },
+ { "particleSize", nullptr, nullptr },
+ { "colorKey", nullptr, nullptr },
+ { "geometryType", nullptr, nullptr },
+ { "texCoordKey", nullptr, nullptr },
+ { "pickable", nullptr, nullptr },
+ { "angularDampingFactor", nullptr, nullptr },
+ { "angularVelocity", nullptr, nullptr },
+ { "autoDamp", nullptr, nullptr },
+ { "autoDisable", nullptr, nullptr },
+ { "disableAngularSpeed", nullptr, nullptr },
+ { "disableLinearSpeed", nullptr, nullptr },
+ { "disableTime", nullptr, nullptr },
+ { "finiteRotationAxis", nullptr, nullptr },
+ { "fixed", nullptr, nullptr },
+ { "forces", nullptr, nullptr },
+ { "inertia", nullptr, nullptr },
+ { "linearDampingFactor", nullptr, nullptr },
+ { "torques", nullptr, nullptr },
+ { "useFiniteRotation", nullptr, nullptr },
+ { "useGlobalForce", nullptr, nullptr },
+ { "constantForceMix", nullptr, nullptr },
+ { "constantSurfaceThickness", nullptr, nullptr },
+ { "errorCorrection", nullptr, nullptr },
+ { "iterations", nullptr, nullptr },
+ { "maxCorrectionSpeed", nullptr, nullptr },
+ { "preferAccuracy", nullptr, nullptr },
+ { "pointSize", nullptr, nullptr },
+ { "stopBounce", nullptr, nullptr },
+ { "stopErrorCorrection", nullptr, nullptr },
+ { "angleRate", nullptr, nullptr },
+ { "maxSeparation", nullptr, nullptr },
+ { "minSeparation", nullptr, nullptr },
+ { "separation", nullptr, nullptr },
+ { "separationRate", nullptr, nullptr },
+ { "closed", nullptr, nullptr },
+ { "keyVelocity", nullptr, nullptr },
+ { "normalizeVelocity", nullptr, nullptr },
+ { "surface", nullptr, nullptr },
+ { "anisotropicDegree", nullptr, nullptr },
+ { "borderColor", nullptr, nullptr },
+ { "borderWidth", nullptr, nullptr },
+ { "boundaryModeS", nullptr, nullptr },
+ { "boundaryModeT", nullptr, nullptr },
+ { "boundaryModeR", nullptr, nullptr },
+ { "magnificationFilter", nullptr, nullptr },
+ { "minificationFilter", nullptr, nullptr },
+ { "textureCompression", nullptr, nullptr },
+ { "texturePriority", nullptr, nullptr },
+ { "generateMipMaps", nullptr, nullptr },
+ { "targetObject", nullptr, nullptr },
+ { "backAmbientIntensity", nullptr, nullptr },
+ { "backDiffuseColor", nullptr, nullptr },
+ { "backEmissiveColor", nullptr, nullptr },
+ { "backShininess", nullptr, nullptr },
+ { "backSpecularColor", nullptr, nullptr },
+ { "separateBackColor", nullptr, nullptr },
+ { "displayed", nullptr, nullptr },
+ { "clipBoundary", nullptr, nullptr },
+ { "internal", nullptr, nullptr },
+ { "gustiness", nullptr, nullptr },
+ { "turbulence", nullptr, nullptr }
+};
+
+FIVocabulary X3D_vocabulary_3_2 = {
+ nullptr, 0,
+ encodingAlgorithmTable_3_2, 8,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ attributeValueTable_3_2, 2,
+ nullptr, 0,
+ nullptr, 0,
+ elementNameTable_3_2, 233,
+ attributeNameTable_3_2, 516
+};
+
+static const char *encodingAlgorithmTable_3_3[] = {
+ "encoder://web3d.org/QuantizedFloatArrayEncoder",
+ "encoder://web3d.org/DeltazlibIntArrayEncoder",
+ "encoder://web3d.org/QuantizedzlibFloatArrayEncoder",
+ "encoder://web3d.org/zlibFloatArrayEncoder",
+ "encoder://web3d.org/QuantizedDoubleArrayEncoder",
+ "encoder://web3d.org/zlibDoubleArrayEncoder",
+ "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder",
+ "encoder://web3d.org/RangeIntArrayEncoder"
+};
+
+static const std::shared_ptr<const FIValue> attributeValueTable_3_3[] = {
+ FIStringValue::create("false"),
+ FIStringValue::create("true")
+};
+
+static const FIQName elementNameTable_3_3[] = {
+ { "Shape", nullptr, nullptr },
+ { "Appearance", nullptr, nullptr },
+ { "Material", nullptr, nullptr },
+ { "IndexedFaceSet", nullptr, nullptr },
+ { "ProtoInstance", nullptr, nullptr },
+ { "Transform", nullptr, nullptr },
+ { "ImageTexture", nullptr, nullptr },
+ { "TextureTransform", nullptr, nullptr },
+ { "Coordinate", nullptr, nullptr },
+ { "Normal", nullptr, nullptr },
+ { "Color", nullptr, nullptr },
+ { "ColorRGBA", nullptr, nullptr },
+ { "TextureCoordinate", nullptr, nullptr },
+ { "ROUTE", nullptr, nullptr },
+ { "fieldValue", nullptr, nullptr },
+ { "Group", nullptr, nullptr },
+ { "LOD", nullptr, nullptr },
+ { "Switch", nullptr, nullptr },
+ { "Script", nullptr, nullptr },
+ { "IndexedTriangleFanSet", nullptr, nullptr },
+ { "IndexedTriangleSet", nullptr, nullptr },
+ { "IndexedTriangleStripSet", nullptr, nullptr },
+ { "MultiTexture", nullptr, nullptr },
+ { "MultiTextureCoordinate", nullptr, nullptr },
+ { "MultiTextureTransform", nullptr, nullptr },
+ { "IndexedLineSet", nullptr, nullptr },
+ { "PointSet", nullptr, nullptr },
+ { "StaticGroup", nullptr, nullptr },
+ { "Sphere", nullptr, nullptr },
+ { "Box", nullptr, nullptr },
+ { "Cone", nullptr, nullptr },
+ { "Anchor", nullptr, nullptr },
+ { "Arc2D", nullptr, nullptr },
+ { "ArcClose2D", nullptr, nullptr },
+ { "AudioClip", nullptr, nullptr },
+ { "Background", nullptr, nullptr },
+ { "Billboard", nullptr, nullptr },
+ { "BooleanFilter", nullptr, nullptr },
+ { "BooleanSequencer", nullptr, nullptr },
+ { "BooleanToggle", nullptr, nullptr },
+ { "BooleanTrigger", nullptr, nullptr },
+ { "Circle2D", nullptr, nullptr },
+ { "Collision", nullptr, nullptr },
+ { "ColorInterpolator", nullptr, nullptr },
+ { "Contour2D", nullptr, nullptr },
+ { "ContourPolyline2D", nullptr, nullptr },
+ { "CoordinateDouble", nullptr, nullptr },
+ { "CoordinateInterpolator", nullptr, nullptr },
+ { "CoordinateInterpolator2D", nullptr, nullptr },
+ { "Cylinder", nullptr, nullptr },
+ { "CylinderSensor", nullptr, nullptr },
+ { "DirectionalLight", nullptr, nullptr },
+ { "Disk2D", nullptr, nullptr },
+ { "EXPORT", nullptr, nullptr },
+ { "ElevationGrid", nullptr, nullptr },
+ { "EspduTransform", nullptr, nullptr },
+ { "ExternProtoDeclare", nullptr, nullptr },
+ { "Extrusion", nullptr, nullptr },
+ { "FillProperties", nullptr, nullptr },
+ { "Fog", nullptr, nullptr },
+ { "FontStyle", nullptr, nullptr },
+ { "GeoCoordinate", nullptr, nullptr },
+ { "GeoElevationGrid", nullptr, nullptr },
+ { "GeoLOD", nullptr, nullptr },
+ { "GeoLocation", nullptr, nullptr },
+ { "GeoMetadata", nullptr, nullptr },
+ { "GeoOrigin", nullptr, nullptr },
+ { "GeoPositionInterpolator", nullptr, nullptr },
+ { "GeoTouchSensor", nullptr, nullptr },
+ { "GeoViewpoint", nullptr, nullptr },
+ { "HAnimDisplacer", nullptr, nullptr },
+ { "HAnimHumanoid", nullptr, nullptr },
+ { "HAnimJoint", nullptr, nullptr },
+ { "HAnimSegment", nullptr, nullptr },
+ { "HAnimSite", nullptr, nullptr },
+ { "IMPORT", nullptr, nullptr },
+ { "IS", nullptr, nullptr },
+ { "Inline", nullptr, nullptr },
+ { "IntegerSequencer", nullptr, nullptr },
+ { "IntegerTrigger", nullptr, nullptr },
+ { "KeySensor", nullptr, nullptr },
+ { "LineProperties", nullptr, nullptr },
+ { "LineSet", nullptr, nullptr },
+ { "LoadSensor", nullptr, nullptr },
+ { "MetadataDouble", nullptr, nullptr },
+ { "MetadataFloat", nullptr, nullptr },
+ { "MetadataInteger", nullptr, nullptr },
+ { "MetadataSet", nullptr, nullptr },
+ { "MetadataString", nullptr, nullptr },
+ { "MovieTexture", nullptr, nullptr },
+ { "NavigationInfo", nullptr, nullptr },
+ { "NormalInterpolator", nullptr, nullptr },
+ { "NurbsCurve", nullptr, nullptr },
+ { "NurbsCurve2D", nullptr, nullptr },
+ { "NurbsOrientationInterpolator", nullptr, nullptr },
+ { "NurbsPatchSurface", nullptr, nullptr },
+ { "NurbsPositionInterpolator", nullptr, nullptr },
+ { "NurbsSet", nullptr, nullptr },
+ { "NurbsSurfaceInterpolator", nullptr, nullptr },
+ { "NurbsSweptSurface", nullptr, nullptr },
+ { "NurbsSwungSurface", nullptr, nullptr },
+ { "NurbsTextureCoordinate", nullptr, nullptr },
+ { "NurbsTrimmedSurface", nullptr, nullptr },
+ { "OrientationInterpolator", nullptr, nullptr },
+ { "PixelTexture", nullptr, nullptr },
+ { "PlaneSensor", nullptr, nullptr },
+ { "PointLight", nullptr, nullptr },
+ { "Polyline2D", nullptr, nullptr },
+ { "Polypoint2D", nullptr, nullptr },
+ { "PositionInterpolator", nullptr, nullptr },
+ { "PositionInterpolator2D", nullptr, nullptr },
+ { "ProtoBody", nullptr, nullptr },
+ { "ProtoDeclare", nullptr, nullptr },
+ { "ProtoInterface", nullptr, nullptr },
+ { "ProximitySensor", nullptr, nullptr },
+ { "ReceiverPdu", nullptr, nullptr },
+ { "Rectangle2D", nullptr, nullptr },
+ { "ScalarInterpolator", nullptr, nullptr },
+ { "Scene", nullptr, nullptr },
+ { "SignalPdu", nullptr, nullptr },
+ { "Sound", nullptr, nullptr },
+ { "SphereSensor", nullptr, nullptr },
+ { "SpotLight", nullptr, nullptr },
+ { "StringSensor", nullptr, nullptr },
+ { "Text", nullptr, nullptr },
+ { "TextureBackground", nullptr, nullptr },
+ { "TextureCoordinateGenerator", nullptr, nullptr },
+ { "TimeSensor", nullptr, nullptr },
+ { "TimeTrigger", nullptr, nullptr },
+ { "TouchSensor", nullptr, nullptr },
+ { "TransmitterPdu", nullptr, nullptr },
+ { "TriangleFanSet", nullptr, nullptr },
+ { "TriangleSet", nullptr, nullptr },
+ { "TriangleSet2D", nullptr, nullptr },
+ { "TriangleStripSet", nullptr, nullptr },
+ { "Viewpoint", nullptr, nullptr },
+ { "VisibilitySensor", nullptr, nullptr },
+ { "WorldInfo", nullptr, nullptr },
+ { "X3D", nullptr, nullptr },
+ { "component", nullptr, nullptr },
+ { "connect", nullptr, nullptr },
+ { "field", nullptr, nullptr },
+ { "head", nullptr, nullptr },
+ { "humanoidBodyType", nullptr, nullptr },
+ { "meta", nullptr, nullptr },
+ { "CADAssembly", nullptr, nullptr },
+ { "CADFace", nullptr, nullptr },
+ { "CADLayer", nullptr, nullptr },
+ { "CADPart", nullptr, nullptr },
+ { "ComposedCubeMapTexture", nullptr, nullptr },
+ { "ComposedShader", nullptr, nullptr },
+ { "ComposedTexture3D", nullptr, nullptr },
+ { "FloatVertexAttribute", nullptr, nullptr },
+ { "FogCoordinate", nullptr, nullptr },
+ { "GeneratedCubeMapTexture", nullptr, nullptr },
+ { "ImageCubeMapTexture", nullptr, nullptr },
+ { "ImageTexture3D", nullptr, nullptr },
+ { "IndexedQuadSet", nullptr, nullptr },
+ { "LocalFog", nullptr, nullptr },
+ { "Matrix3VertexAttribute", nullptr, nullptr },
+ { "Matrix4VertexAttribute", nullptr, nullptr },
+ { "PackagedShader", nullptr, nullptr },
+ { "PixelTexture3D", nullptr, nullptr },
+ { "ProgramShader", nullptr, nullptr },
+ { "QuadSet", nullptr, nullptr },
+ { "ShaderPart", nullptr, nullptr },
+ { "ShaderProgram", nullptr, nullptr },
+ { "TextureCoordinate3D", nullptr, nullptr },
+ { "TextureCoordinate4D", nullptr, nullptr },
+ { "TextureTransform3D", nullptr, nullptr },
+ { "TextureTransformMatrix3D", nullptr, nullptr },
+ { "BallJoint", nullptr, nullptr },
+ { "BoundedPhysicsModel", nullptr, nullptr },
+ { "ClipPlane", nullptr, nullptr },
+ { "CollidableOffset", nullptr, nullptr },
+ { "CollidableShape", nullptr, nullptr },
+ { "CollisionCollection", nullptr, nullptr },
+ { "CollisionSensor", nullptr, nullptr },
+ { "CollisionSpace", nullptr, nullptr },
+ { "ColorDamper", nullptr, nullptr },
+ { "ConeEmitter", nullptr, nullptr },
+ { "Contact", nullptr, nullptr },
+ { "CoordinateDamper", nullptr, nullptr },
+ { "DISEntityManager", nullptr, nullptr },
+ { "DISEntityTypeMapping", nullptr, nullptr },
+ { "DoubleAxisHingeJoint", nullptr, nullptr },
+ { "EaseInEaseOut", nullptr, nullptr },
+ { "ExplosionEmitter", nullptr, nullptr },
+ { "ForcePhysicsModel", nullptr, nullptr },
+ { "GeoProximitySensor", nullptr, nullptr },
+ { "GeoTransform", nullptr, nullptr },
+ { "Layer", nullptr, nullptr },
+ { "LayerSet", nullptr, nullptr },
+ { "Layout", nullptr, nullptr },
+ { "LayoutGroup", nullptr, nullptr },
+ { "LayoutLayer", nullptr, nullptr },
+ { "LinePickSensor", nullptr, nullptr },
+ { "MotorJoint", nullptr, nullptr },
+ { "OrientationChaser", nullptr, nullptr },
+ { "OrientationDamper", nullptr, nullptr },
+ { "OrthoViewpoint", nullptr, nullptr },
+ { "ParticleSystem", nullptr, nullptr },
+ { "PickableGroup", nullptr, nullptr },
+ { "PointEmitter", nullptr, nullptr },
+ { "PointPickSensor", nullptr, nullptr },
+ { "PolylineEmitter", nullptr, nullptr },
+ { "PositionChaser", nullptr, nullptr },
+ { "PositionChaser2D", nullptr, nullptr },
+ { "PositionDamper", nullptr, nullptr },
+ { "PositionDamper2D", nullptr, nullptr },
+ { "PrimitivePickSensor", nullptr, nullptr },
+ { "RigidBody", nullptr, nullptr },
+ { "RigidBodyCollection", nullptr, nullptr },
+ { "ScalarChaser", nullptr, nullptr },
+ { "ScreenFontStyle", nullptr, nullptr },
+ { "ScreenGroup", nullptr, nullptr },
+ { "SingleAxisHingeJoint", nullptr, nullptr },
+ { "SliderJoint", nullptr, nullptr },
+ { "SplinePositionInterpolator", nullptr, nullptr },
+ { "SplinePositionInterpolator2D", nullptr, nullptr },
+ { "SplineScalarInterpolator", nullptr, nullptr },
+ { "SquadOrientationInterpolator", nullptr, nullptr },
+ { "SurfaceEmitter", nullptr, nullptr },
+ { "TexCoordDamper2D", nullptr, nullptr },
+ { "TextureProperties", nullptr, nullptr },
+ { "TransformSensor", nullptr, nullptr },
+ { "TwoSidedMaterial", nullptr, nullptr },
+ { "UniversalJoint", nullptr, nullptr },
+ { "ViewpointGroup", nullptr, nullptr },
+ { "Viewport", nullptr, nullptr },
+ { "VolumeEmitter", nullptr, nullptr },
+ { "VolumePickSensor", nullptr, nullptr },
+ { "WindPhysicsModel", nullptr, nullptr },
+ { "BlendedVolumeStyle", nullptr, nullptr },
+ { "BoundaryEnhancementVolumeStyle", nullptr, nullptr },
+ { "CartoonVolumeStyle", nullptr, nullptr },
+ { "ComposedVolumeStyle", nullptr, nullptr },
+ { "EdgeEnhancementVolumeStyle", nullptr, nullptr },
+ { "IsoSurfaceVolumeData", nullptr, nullptr },
+ { "MetadataBoolean", nullptr, nullptr },
+ { "OpacityMapVolumeStyle", nullptr, nullptr },
+ { "ProjectionVolumeStyle", nullptr, nullptr },
+ { "SegmentedVolumeData", nullptr, nullptr },
+ { "ShadedVolumeStyle", nullptr, nullptr },
+ { "SilhouetteEnhancementVolumeStyle", nullptr, nullptr },
+ { "ToneMappedVolumeStyle", nullptr, nullptr },
+ { "VolumeData", nullptr, nullptr },
+ { "ColorChaser", nullptr, nullptr },
+ { "CoordinateChaser", nullptr, nullptr },
+ { "ScalarDamper", nullptr, nullptr },
+ { "TexCoordChaser2D", nullptr, nullptr },
+ { "unit", nullptr, nullptr }
+};
+
+static const FIQName attributeNameTable_3_3[] = {
+ { "DEF", nullptr, nullptr },
+ { "USE", nullptr, nullptr },
+ { "containerField", nullptr, nullptr },
+ { "fromNode", nullptr, nullptr },
+ { "fromField", nullptr, nullptr },
+ { "toNode", nullptr, nullptr },
+ { "toField", nullptr, nullptr },
+ { "name", nullptr, nullptr },
+ { "value", nullptr, nullptr },
+ { "color", nullptr, nullptr },
+ { "colorIndex", nullptr, nullptr },
+ { "coordIndex", nullptr, nullptr },
+ { "texCoordIndex", nullptr, nullptr },
+ { "normalIndex", nullptr, nullptr },
+ { "colorPerVertex", nullptr, nullptr },
+ { "normalPerVertex", nullptr, nullptr },
+ { "rotation", nullptr, nullptr },
+ { "scale", nullptr, nullptr },
+ { "center", nullptr, nullptr },
+ { "scaleOrientation", nullptr, nullptr },
+ { "translation", nullptr, nullptr },
+ { "url", nullptr, nullptr },
+ { "repeatS", nullptr, nullptr },
+ { "repeatT", nullptr, nullptr },
+ { "point", nullptr, nullptr },
+ { "vector", nullptr, nullptr },
+ { "range", nullptr, nullptr },
+ { "ambientIntensity", nullptr, nullptr },
+ { "diffuseColor", nullptr, nullptr },
+ { "emissiveColor", nullptr, nullptr },
+ { "shininess", nullptr, nullptr },
+ { "specularColor", nullptr, nullptr },
+ { "transparency", nullptr, nullptr },
+ { "whichChoice", nullptr, nullptr },
+ { "index", nullptr, nullptr },
+ { "mode", nullptr, nullptr },
+ { "source", nullptr, nullptr },
+ { "function", nullptr, nullptr },
+ { "alpha", nullptr, nullptr },
+ { "vertexCount", nullptr, nullptr },
+ { "radius", nullptr, nullptr },
+ { "size", nullptr, nullptr },
+ { "height", nullptr, nullptr },
+ { "solid", nullptr, nullptr },
+ { "ccw", nullptr, nullptr },
+ { "key", nullptr, nullptr },
+ { "keyValue", nullptr, nullptr },
+ { "enabled", nullptr, nullptr },
+ { "direction", nullptr, nullptr },
+ { "position", nullptr, nullptr },
+ { "orientation", nullptr, nullptr },
+ { "bboxCenter", nullptr, nullptr },
+ { "bboxSize", nullptr, nullptr },
+ { "AS", nullptr, nullptr },
+ { "InlineDEF", nullptr, nullptr },
+ { "accessType", nullptr, nullptr },
+ { "actionKeyPress", nullptr, nullptr },
+ { "actionKeyRelease", nullptr, nullptr },
+ { "address", nullptr, nullptr },
+ { "altKey", nullptr, nullptr },
+ { "antennaLocation", nullptr, nullptr },
+ { "antennaPatternLength", nullptr, nullptr },
+ { "antennaPatternType", nullptr, nullptr },
+ { "applicationID", nullptr, nullptr },
+ { "articulationParameterArray", nullptr, nullptr },
+ { "articulationParameterChangeIndicatorArray", nullptr, nullptr },
+ { "articulationParameterCount", nullptr, nullptr },
+ { "articulationParameterDesignatorArray", nullptr, nullptr },
+ { "articulationParameterIdPartAttachedArray", nullptr, nullptr },
+ { "articulationParameterTypeArray", nullptr, nullptr },
+ { "attenuation", nullptr, nullptr },
+ { "autoOffset", nullptr, nullptr },
+ { "avatarSize", nullptr, nullptr },
+ { "axisOfRotation", nullptr, nullptr },
+ { "backUrl", nullptr, nullptr },
+ { "beamWidth", nullptr, nullptr },
+ { "beginCap", nullptr, nullptr },
+ { "bindTime", nullptr, nullptr },
+ { "bottom", nullptr, nullptr },
+ { "bottomRadius", nullptr, nullptr },
+ { "bottomUrl", nullptr, nullptr },
+ { "centerOfMass", nullptr, nullptr },
+ { "centerOfRotation", nullptr, nullptr },
+ { "child1Url", nullptr, nullptr },
+ { "child2Url", nullptr, nullptr },
+ { "child3Url", nullptr, nullptr },
+ { "child4Url", nullptr, nullptr },
+ { "class", nullptr, nullptr },
+ { "closureType", nullptr, nullptr },
+ { "collideTime", nullptr, nullptr },
+ { "content", nullptr, nullptr },
+ { "controlKey", nullptr, nullptr },
+ { "controlPoint", nullptr, nullptr },
+ { "convex", nullptr, nullptr },
+ { "coordinateSystem", nullptr, nullptr },
+ { "copyright", nullptr, nullptr },
+ { "creaseAngle", nullptr, nullptr },
+ { "crossSection", nullptr, nullptr },
+ { "cryptoKeyID", nullptr, nullptr },
+ { "cryptoSystem", nullptr, nullptr },
+ { "cutOffAngle", nullptr, nullptr },
+ { "cycleInterval", nullptr, nullptr },
+ { "cycleTime", nullptr, nullptr },
+ { "data", nullptr, nullptr },
+ { "dataFormat", nullptr, nullptr },
+ { "dataLength", nullptr, nullptr },
+ { "dataUrl", nullptr, nullptr },
+ { "date", nullptr, nullptr },
+ { "deadReckoning", nullptr, nullptr },
+ { "deletionAllowed", nullptr, nullptr },
+ { "description", nullptr, nullptr },
+ { "detonateTime", nullptr, nullptr },
+ { "dir", nullptr, nullptr },
+ { "directOutput", nullptr, nullptr },
+ { "diskAngle", nullptr, nullptr },
+ { "displacements", nullptr, nullptr },
+ { "documentation", nullptr, nullptr },
+ { "elapsedTime", nullptr, nullptr },
+ { "ellipsoid", nullptr, nullptr },
+ { "encodingScheme", nullptr, nullptr },
+ { "endAngle", nullptr, nullptr },
+ { "endCap", nullptr, nullptr },
+ { "enterTime", nullptr, nullptr },
+ { "enteredText", nullptr, nullptr },
+ { "entityCategory", nullptr, nullptr },
+ { "entityCountry", nullptr, nullptr },
+ { "entityDomain", nullptr, nullptr },
+ { "entityExtra", nullptr, nullptr },
+ { "entityID", nullptr, nullptr },
+ { "entityKind", nullptr, nullptr },
+ { "entitySpecific", nullptr, nullptr },
+ { "entitySubCategory", nullptr, nullptr },
+ { "exitTime", nullptr, nullptr },
+ { "extent", nullptr, nullptr },
+ { "family", nullptr, nullptr },
+ { "fanCount", nullptr, nullptr },
+ { "fieldOfView", nullptr, nullptr },
+ { "filled", nullptr, nullptr },
+ { "finalText", nullptr, nullptr },
+ { "fireMissionIndex", nullptr, nullptr },
+ { "fired1", nullptr, nullptr },
+ { "fired2", nullptr, nullptr },
+ { "firedTime", nullptr, nullptr },
+ { "firingRange", nullptr, nullptr },
+ { "firingRate", nullptr, nullptr },
+ { "fogType", nullptr, nullptr },
+ { "forceID", nullptr, nullptr },
+ { "frequency", nullptr, nullptr },
+ { "frontUrl", nullptr, nullptr },
+ { "fuse", nullptr, nullptr },
+ { "geoCoords", nullptr, nullptr },
+ { "geoGridOrigin", nullptr, nullptr },
+ { "geoSystem", nullptr, nullptr },
+ { "groundAngle", nullptr, nullptr },
+ { "groundColor", nullptr, nullptr },
+ { "hatchColor", nullptr, nullptr },
+ { "hatchStyle", nullptr, nullptr },
+ { "hatched", nullptr, nullptr },
+ { "headlight", nullptr, nullptr },
+ { "horizontal", nullptr, nullptr },
+ { "horizontalDatum", nullptr, nullptr },
+ { "http-equiv", nullptr, nullptr },
+ { "image", nullptr, nullptr },
+ { "importedDEF", nullptr, nullptr },
+ { "info", nullptr, nullptr },
+ { "innerRadius", nullptr, nullptr },
+ { "inputFalse", nullptr, nullptr },
+ { "inputNegate", nullptr, nullptr },
+ { "inputSource", nullptr, nullptr },
+ { "inputTrue", nullptr, nullptr },
+ { "integerKey", nullptr, nullptr },
+ { "intensity", nullptr, nullptr },
+ { "jump", nullptr, nullptr },
+ { "justify", nullptr, nullptr },
+ { "keyPress", nullptr, nullptr },
+ { "keyRelease", nullptr, nullptr },
+ { "knot", nullptr, nullptr },
+ { "lang", nullptr, nullptr },
+ { "language", nullptr, nullptr },
+ { "leftToRight", nullptr, nullptr },
+ { "leftUrl", nullptr, nullptr },
+ { "length", nullptr, nullptr },
+ { "lengthOfModulationParameters", nullptr, nullptr },
+ { "level", nullptr, nullptr },
+ { "limitOrientation", nullptr, nullptr },
+ { "lineSegments", nullptr, nullptr },
+ { "linearAcceleration", nullptr, nullptr },
+ { "linearVelocity", nullptr, nullptr },
+ { "linetype", nullptr, nullptr },
+ { "linewidthScaleFactor", nullptr, nullptr },
+ { "llimit", nullptr, nullptr },
+ { "load", nullptr, nullptr },
+ { "loadTime", nullptr, nullptr },
+ { "localDEF", nullptr, nullptr },
+ { "location", nullptr, nullptr },
+ { "loop", nullptr, nullptr },
+ { "marking", nullptr, nullptr },
+ { "mass", nullptr, nullptr },
+ { "maxAngle", nullptr, nullptr },
+ { "maxBack", nullptr, nullptr },
+ { "maxExtent", nullptr, nullptr },
+ { "maxFront", nullptr, nullptr },
+ { "maxPosition", nullptr, nullptr },
+ { "metadataFormat", nullptr, nullptr },
+ { "minAngle", nullptr, nullptr },
+ { "minBack", nullptr, nullptr },
+ { "minFront", nullptr, nullptr },
+ { "minPosition", nullptr, nullptr },
+ { "modulationTypeDetail", nullptr, nullptr },
+ { "modulationTypeMajor", nullptr, nullptr },
+ { "modulationTypeSpreadSpectrum", nullptr, nullptr },
+ { "modulationTypeSystem", nullptr, nullptr },
+ { "momentsOfInertia", nullptr, nullptr },
+ { "multicastRelayHost", nullptr, nullptr },
+ { "multicastRelayPort", nullptr, nullptr },
+ { "munitionApplicationID", nullptr, nullptr },
+ { "munitionEndPoint", nullptr, nullptr },
+ { "munitionEntityID", nullptr, nullptr },
+ { "munitionQuantity", nullptr, nullptr },
+ { "munitionSiteID", nullptr, nullptr },
+ { "munitionStartPoint", nullptr, nullptr },
+ { "mustEvaluate", nullptr, nullptr },
+ { "navType", nullptr, nullptr },
+ { "networkMode", nullptr, nullptr },
+ { "next", nullptr, nullptr },
+ { "nodeField", nullptr, nullptr },
+ { "offset", nullptr, nullptr },
+ { "on", nullptr, nullptr },
+ { "order", nullptr, nullptr },
+ { "originator", nullptr, nullptr },
+ { "outerRadius", nullptr, nullptr },
+ { "parameter", nullptr, nullptr },
+ { "pauseTime", nullptr, nullptr },
+ { "pitch", nullptr, nullptr },
+ { "points", nullptr, nullptr },
+ { "port", nullptr, nullptr },
+ { "power", nullptr, nullptr },
+ { "previous", nullptr, nullptr },
+ { "priority", nullptr, nullptr },
+ { "profile", nullptr, nullptr },
+ { "progress", nullptr, nullptr },
+ { "protoField", nullptr, nullptr },
+ { "radioEntityTypeCategory", nullptr, nullptr },
+ { "radioEntityTypeCountry", nullptr, nullptr },
+ { "radioEntityTypeDomain", nullptr, nullptr },
+ { "radioEntityTypeKind", nullptr, nullptr },
+ { "radioEntityTypeNomenclature", nullptr, nullptr },
+ { "radioEntityTypeNomenclatureVersion", nullptr, nullptr },
+ { "radioID", nullptr, nullptr },
+ { "readInterval", nullptr, nullptr },
+ { "receivedPower", nullptr, nullptr },
+ { "receiverState", nullptr, nullptr },
+ { "reference", nullptr, nullptr },
+ { "relativeAntennaLocation", nullptr, nullptr },
+ { "resolution", nullptr, nullptr },
+ { "resumeTime", nullptr, nullptr },
+ { "rightUrl", nullptr, nullptr },
+ { "rootUrl", nullptr, nullptr },
+ { "rotateYUp", nullptr, nullptr },
+ { "rtpHeaderExpected", nullptr, nullptr },
+ { "sampleRate", nullptr, nullptr },
+ { "samples", nullptr, nullptr },
+ { "shiftKey", nullptr, nullptr },
+ { "side", nullptr, nullptr },
+ { "siteID", nullptr, nullptr },
+ { "skinCoordIndex", nullptr, nullptr },
+ { "skinCoordWeight", nullptr, nullptr },
+ { "skyAngle", nullptr, nullptr },
+ { "skyColor", nullptr, nullptr },
+ { "spacing", nullptr, nullptr },
+ { "spatialize", nullptr, nullptr },
+ { "speed", nullptr, nullptr },
+ { "speedFactor", nullptr, nullptr },
+ { "spine", nullptr, nullptr },
+ { "startAngle", nullptr, nullptr },
+ { "startTime", nullptr, nullptr },
+ { "stiffness", nullptr, nullptr },
+ { "stopTime", nullptr, nullptr },
+ { "string", nullptr, nullptr },
+ { "stripCount", nullptr, nullptr },
+ { "style", nullptr, nullptr },
+ { "summary", nullptr, nullptr },
+ { "tdlType", nullptr, nullptr },
+ { "tessellation", nullptr, nullptr },
+ { "tessellationScale", nullptr, nullptr },
+ { "time", nullptr, nullptr },
+ { "timeOut", nullptr, nullptr },
+ { "timestamp", nullptr, nullptr },
+ { "title", nullptr, nullptr },
+ { "toggle", nullptr, nullptr },
+ { "top", nullptr, nullptr },
+ { "topToBottom", nullptr, nullptr },
+ { "topUrl", nullptr, nullptr },
+ { "touchTime", nullptr, nullptr },
+ { "transmitFrequencyBandwidth", nullptr, nullptr },
+ { "transmitState", nullptr, nullptr },
+ { "transmitterApplicationID", nullptr, nullptr },
+ { "transmitterEntityID", nullptr, nullptr },
+ { "transmitterRadioID", nullptr, nullptr },
+ { "transmitterSiteID", nullptr, nullptr },
+ { "transparent", nullptr, nullptr },
+ { "triggerTime", nullptr, nullptr },
+ { "triggerTrue", nullptr, nullptr },
+ { "triggerValue", nullptr, nullptr },
+ { "type", nullptr, nullptr },
+ { "uDimension", nullptr, nullptr },
+ { "uKnot", nullptr, nullptr },
+ { "uOrder", nullptr, nullptr },
+ { "uTessellation", nullptr, nullptr },
+ { "ulimit", nullptr, nullptr },
+ { "vDimension", nullptr, nullptr },
+ { "vKnot", nullptr, nullptr },
+ { "vOrder", nullptr, nullptr },
+ { "vTessellation", nullptr, nullptr },
+ { "version", nullptr, nullptr },
+ { "verticalDatum", nullptr, nullptr },
+ { "vertices", nullptr, nullptr },
+ { "visibilityLimit", nullptr, nullptr },
+ { "visibilityRange", nullptr, nullptr },
+ { "warhead", nullptr, nullptr },
+ { "weight", nullptr, nullptr },
+ { "whichGeometry", nullptr, nullptr },
+ { "writeInterval", nullptr, nullptr },
+ { "xDimension", nullptr, nullptr },
+ { "xSpacing", nullptr, nullptr },
+ { "yScale", nullptr, nullptr },
+ { "zDimension", nullptr, nullptr },
+ { "zSpacing", nullptr, nullptr },
+ { "visible", nullptr, nullptr },
+ { "repeatR", nullptr, nullptr },
+ { "texture", nullptr, nullptr },
+ { "back", nullptr, nullptr },
+ { "front", nullptr, nullptr },
+ { "left", nullptr, nullptr },
+ { "right", nullptr, nullptr },
+ { "parts", nullptr, nullptr },
+ { "isSelected", nullptr, nullptr },
+ { "isValid", nullptr, nullptr },
+ { "numComponents", nullptr, nullptr },
+ { "depth", nullptr, nullptr },
+ { "update", nullptr, nullptr },
+ { "fogCoord", nullptr, nullptr },
+ { "texCoord", nullptr, nullptr },
+ { "activate", nullptr, nullptr },
+ { "programs", nullptr, nullptr },
+ { "matrix", nullptr, nullptr },
+ { "anchorPoint", nullptr, nullptr },
+ { "body1", nullptr, nullptr },
+ { "body2", nullptr, nullptr },
+ { "forceOutput", nullptr, nullptr },
+ { "body1AnchorPoint", nullptr, nullptr },
+ { "body2AnchorPoint", nullptr, nullptr },
+ { "plane", nullptr, nullptr },
+ { "appliedParameters", nullptr, nullptr },
+ { "bounce", nullptr, nullptr },
+ { "frictionCoefficients", nullptr, nullptr },
+ { "minBounceSpeed", nullptr, nullptr },
+ { "slipFactors", nullptr, nullptr },
+ { "softnessConstantForceMix", nullptr, nullptr },
+ { "softnessErrorCorrection", nullptr, nullptr },
+ { "surfaceSpeed", nullptr, nullptr },
+ { "isActive", nullptr, nullptr },
+ { "useGeometry", nullptr, nullptr },
+ { "set_destination", nullptr, nullptr },
+ { "set_value", nullptr, nullptr },
+ { "tau", nullptr, nullptr },
+ { "tolerance", nullptr, nullptr },
+ { "value_changed", nullptr, nullptr },
+ { "initialDestination", nullptr, nullptr },
+ { "initialValue", nullptr, nullptr },
+ { "angle", nullptr, nullptr },
+ { "variation", nullptr, nullptr },
+ { "surfaceArea", nullptr, nullptr },
+ { "frictionDirection", nullptr, nullptr },
+ { "slipCoefficients", nullptr, nullptr },
+ { "category", nullptr, nullptr },
+ { "country", nullptr, nullptr },
+ { "domain", nullptr, nullptr },
+ { "extra", nullptr, nullptr },
+ { "kind", nullptr, nullptr },
+ { "specific", nullptr, nullptr },
+ { "subcategory", nullptr, nullptr },
+ { "axis1", nullptr, nullptr },
+ { "axis2", nullptr, nullptr },
+ { "desiredAngularVelocity1", nullptr, nullptr },
+ { "desiredAngularVelocity2", nullptr, nullptr },
+ { "maxAngle1", nullptr, nullptr },
+ { "maxTorque1", nullptr, nullptr },
+ { "maxTorque2", nullptr, nullptr },
+ { "minAngle1", nullptr, nullptr },
+ { "stopBounce1", nullptr, nullptr },
+ { "stopConstantForceMix1", nullptr, nullptr },
+ { "stopErrorCorrection1", nullptr, nullptr },
+ { "suspensionErrorCorrection", nullptr, nullptr },
+ { "suspensionForce", nullptr, nullptr },
+ { "body1Axis", nullptr, nullptr },
+ { "body2Axis", nullptr, nullptr },
+ { "hinge1Angle", nullptr, nullptr },
+ { "hinge1AngleRate", nullptr, nullptr },
+ { "hinge2Angle", nullptr, nullptr },
+ { "hinge2AngleRate", nullptr, nullptr },
+ { "set_fraction", nullptr, nullptr },
+ { "easeInEaseOut", nullptr, nullptr },
+ { "modifiedFraction_changed", nullptr, nullptr },
+ { "force", nullptr, nullptr },
+ { "geoCenter", nullptr, nullptr },
+ { "centerOfRotation_changed", nullptr, nullptr },
+ { "geoCoord_changed", nullptr, nullptr },
+ { "orientation_changed", nullptr, nullptr },
+ { "position_changed", nullptr, nullptr },
+ { "isPickable", nullptr, nullptr },
+ { "viewport", nullptr, nullptr },
+ { "activeLayer", nullptr, nullptr },
+ { "align", nullptr, nullptr },
+ { "offsetUnits", nullptr, nullptr },
+ { "scaleMode", nullptr, nullptr },
+ { "sizeUnits", nullptr, nullptr },
+ { "layout", nullptr, nullptr },
+ { "objectType", nullptr, nullptr },
+ { "pickedNormal", nullptr, nullptr },
+ { "pickedPoint", nullptr, nullptr },
+ { "pickedTextureCoordinate", nullptr, nullptr },
+ { "intersectionType", nullptr, nullptr },
+ { "sortOrder", nullptr, nullptr },
+ { "axis1Angle", nullptr, nullptr },
+ { "axis1Torque", nullptr, nullptr },
+ { "axis2Angle", nullptr, nullptr },
+ { "axis2Torque", nullptr, nullptr },
+ { "axis3Angle", nullptr, nullptr },
+ { "axis3Torque", nullptr, nullptr },
+ { "enabledAxies", nullptr, nullptr },
+ { "motor1Axis", nullptr, nullptr },
+ { "motor2Axis", nullptr, nullptr },
+ { "motor3Axis", nullptr, nullptr },
+ { "stop1Bounce", nullptr, nullptr },
+ { "stop1ErrorCorrection", nullptr, nullptr },
+ { "stop2Bounce", nullptr, nullptr },
+ { "stop2ErrorCorrection", nullptr, nullptr },
+ { "stop3Bounce", nullptr, nullptr },
+ { "stop3ErrorCorrection", nullptr, nullptr },
+ { "motor1Angle", nullptr, nullptr },
+ { "motor1AngleRate", nullptr, nullptr },
+ { "motor2Angle", nullptr, nullptr },
+ { "motor2AngleRate", nullptr, nullptr },
+ { "motor3Angle", nullptr, nullptr },
+ { "motor3AngleRate", nullptr, nullptr },
+ { "autoCalc", nullptr, nullptr },
+ { "duration", nullptr, nullptr },
+ { "retainUserOffsets", nullptr, nullptr },
+ { "isBound", nullptr, nullptr },
+ { "appearance", nullptr, nullptr },
+ { "createParticles", nullptr, nullptr },
+ { "lifetimeVariation", nullptr, nullptr },
+ { "maxParticles", nullptr, nullptr },
+ { "particleLifetime", nullptr, nullptr },
+ { "particleSize", nullptr, nullptr },
+ { "colorKey", nullptr, nullptr },
+ { "geometryType", nullptr, nullptr },
+ { "texCoordKey", nullptr, nullptr },
+ { "pickable", nullptr, nullptr },
+ { "angularDampingFactor", nullptr, nullptr },
+ { "angularVelocity", nullptr, nullptr },
+ { "autoDamp", nullptr, nullptr },
+ { "autoDisable", nullptr, nullptr },
+ { "disableAngularSpeed", nullptr, nullptr },
+ { "disableLinearSpeed", nullptr, nullptr },
+ { "disableTime", nullptr, nullptr },
+ { "finiteRotationAxis", nullptr, nullptr },
+ { "fixed", nullptr, nullptr },
+ { "forces", nullptr, nullptr },
+ { "inertia", nullptr, nullptr },
+ { "linearDampingFactor", nullptr, nullptr },
+ { "torques", nullptr, nullptr },
+ { "useFiniteRotation", nullptr, nullptr },
+ { "useGlobalForce", nullptr, nullptr },
+ { "constantForceMix", nullptr, nullptr },
+ { "constantSurfaceThickness", nullptr, nullptr },
+ { "errorCorrection", nullptr, nullptr },
+ { "iterations", nullptr, nullptr },
+ { "maxCorrectionSpeed", nullptr, nullptr },
+ { "preferAccuracy", nullptr, nullptr },
+ { "pointSize", nullptr, nullptr },
+ { "stopBounce", nullptr, nullptr },
+ { "stopErrorCorrection", nullptr, nullptr },
+ { "angleRate", nullptr, nullptr },
+ { "maxSeparation", nullptr, nullptr },
+ { "minSeparation", nullptr, nullptr },
+ { "separation", nullptr, nullptr },
+ { "separationRate", nullptr, nullptr },
+ { "closed", nullptr, nullptr },
+ { "keyVelocity", nullptr, nullptr },
+ { "normalizeVelocity", nullptr, nullptr },
+ { "surface", nullptr, nullptr },
+ { "anisotropicDegree", nullptr, nullptr },
+ { "borderColor", nullptr, nullptr },
+ { "borderWidth", nullptr, nullptr },
+ { "boundaryModeS", nullptr, nullptr },
+ { "boundaryModeT", nullptr, nullptr },
+ { "boundaryModeR", nullptr, nullptr },
+ { "magnificationFilter", nullptr, nullptr },
+ { "minificationFilter", nullptr, nullptr },
+ { "textureCompression", nullptr, nullptr },
+ { "texturePriority", nullptr, nullptr },
+ { "generateMipMaps", nullptr, nullptr },
+ { "targetObject", nullptr, nullptr },
+ { "backAmbientIntensity", nullptr, nullptr },
+ { "backDiffuseColor", nullptr, nullptr },
+ { "backEmissiveColor", nullptr, nullptr },
+ { "backShininess", nullptr, nullptr },
+ { "backSpecularColor", nullptr, nullptr },
+ { "separateBackColor", nullptr, nullptr },
+ { "displayed", nullptr, nullptr },
+ { "clipBoundary", nullptr, nullptr },
+ { "internal", nullptr, nullptr },
+ { "gustiness", nullptr, nullptr },
+ { "turbulence", nullptr, nullptr },
+ { "unitCategory", nullptr, nullptr },
+ { "unitName", nullptr, nullptr },
+ { "unitConversionFactor", nullptr, nullptr },
+ { "weightConstant1", nullptr, nullptr },
+ { "weightConstant2", nullptr, nullptr },
+ { "weightFunction1", nullptr, nullptr },
+ { "weightFunction2", nullptr, nullptr },
+ { "boundaryOpacity", nullptr, nullptr },
+ { "opacityFactor", nullptr, nullptr },
+ { "retainedOpacity", nullptr, nullptr },
+ { "colorSteps", nullptr, nullptr },
+ { "orthogonalColor", nullptr, nullptr },
+ { "parallelColor", nullptr, nullptr },
+ { "ordered", nullptr, nullptr },
+ { "edgeColor", nullptr, nullptr },
+ { "gradientThreshold", nullptr, nullptr },
+ { "contourStepSize", nullptr, nullptr },
+ { "dimensions", nullptr, nullptr },
+ { "surfaceTolerance", nullptr, nullptr },
+ { "surfaceValues", nullptr, nullptr },
+ { "intensityThreshold", nullptr, nullptr },
+ { "segmentEnabled", nullptr, nullptr },
+ { "lighting", nullptr, nullptr },
+ { "shadows", nullptr, nullptr },
+ { "phaseFunction", nullptr, nullptr },
+ { "silhouetteBoundaryOpacity", nullptr, nullptr },
+ { "silhouetteRetainedOpacity", nullptr, nullptr },
+ { "silhouetteSharpness", nullptr, nullptr },
+ { "coolColor", nullptr, nullptr },
+ { "warmColor", nullptr, nullptr }
+};
+
+FIVocabulary X3D_vocabulary_3_3 = {
+ nullptr, 0,
+ encodingAlgorithmTable_3_3, 8,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ nullptr, 0,
+ attributeValueTable_3_3, 2,
+ nullptr, 0,
+ nullptr, 0,
+ elementNameTable_3_3, 252,
+ attributeNameTable_3_3, 546
+};
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/XFileExporter.cpp b/src/3rdparty/assimp/code/XFileExporter.cpp
index 8d5e75d3e..6407bf738 100644
--- a/src/3rdparty/assimp/code/XFileExporter.cpp
+++ b/src/3rdparty/assimp/code/XFileExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,14 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_EXPORT
-#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
+#ifndef ASSIMP_BUILD_NO_X_EXPORTER
+
#include "XFileExporter.h"
#include "ConvertToLHProcess.h"
#include "Bitmap.h"
#include "BaseImporter.h"
#include "fast_atof.h"
-#include "SceneCombiner.h"
-#include "DefaultIOSystem.h"
+#include <assimp/SceneCombiner.h>
+#include <assimp/DefaultIOSystem.h>
#include <ctime>
#include <set>
#include <memory>
@@ -78,6 +80,10 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce
// invoke the exporter
XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props);
+ if (iDoTheExportThing.mOutput.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+ }
+
// 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) {
@@ -513,7 +519,7 @@ std::string XFileExporter::toXFileString(aiString &name)
return str;
}
-void XFileExporter::writePath(aiString path)
+void XFileExporter::writePath(const aiString &path)
{
std::string str = std::string(path.C_Str());
BaseImporter::ConvertUTF8toISO8859_1(str);
diff --git a/src/3rdparty/assimp/code/XFileExporter.h b/src/3rdparty/assimp/code/XFileExporter.h
index c33de3347..e45fd7983 100644
--- a/src/3rdparty/assimp/code/XFileExporter.h
+++ b/src/3rdparty/assimp/code/XFileExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -92,7 +93,10 @@ protected:
void PushTag() { startstr.append( " "); }
/// Leaves an element, decreasing the indentation
- void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); }
+ void PopTag() {
+ ai_assert( startstr.length() > 1);
+ startstr.erase( startstr.length() - 2);
+ }
public:
/// Stringstream to write all output into
@@ -107,7 +111,7 @@ protected:
const ExportProperties* mProperties;
/// write a path
- void writePath(aiString path);
+ void writePath(const aiString &path);
/// The IOSystem for output
IOSystem* mIOSystem;
diff --git a/src/3rdparty/assimp/code/XFileHelper.h b/src/3rdparty/assimp/code/XFileHelper.h
index 484952106..e7c02c7c6 100644
--- a/src/3rdparty/assimp/code/XFileHelper.h
+++ b/src/3rdparty/assimp/code/XFileHelper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -51,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/quaternion.h>
#include <assimp/mesh.h>
#include <assimp/anim.h>
-#include "Defines.h"
+#include <assimp/Defines.h>
namespace Assimp
{
@@ -82,7 +83,7 @@ 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;
+ ai_real mSpecularExponent;
aiColor3D mSpecular;
aiColor3D mEmissive;
std::vector<TexEntry> mTextures;
@@ -100,7 +101,7 @@ struct Material
struct BoneWeight
{
unsigned int mVertex;
- float mWeight;
+ ai_real mWeight;
};
/** Helper structure to represent a bone in a mesh */
diff --git a/src/3rdparty/assimp/code/XFileImporter.cpp b/src/3rdparty/assimp/code/XFileImporter.cpp
index 9510ab3de..00c32dcc2 100644
--- a/src/3rdparty/assimp/code/XFileImporter.cpp
+++ b/src/3rdparty/assimp/code/XFileImporter.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -47,17 +48,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XFileImporter.h"
#include "XFileParser.h"
-#include "Defines.h"
#include "TinyFormatter.h"
#include "ConvertToLHProcess.h"
+#include <assimp/Defines.h>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
+
#include <cctype>
#include <memory>
-
-
using namespace Assimp;
using namespace Assimp::Formatter;
@@ -236,8 +237,9 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil
// Creates the meshes for the given node.
void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes)
{
- if( pMeshes.size() == 0)
+ if (pMeshes.empty()) {
return;
+ }
// create a mesh for each mesh-material combination in the source node
std::vector<aiMesh*> meshes;
@@ -286,7 +288,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
// or referenced material, it should already have a valid index
if( sourceMesh->mFaceMaterials.size() > 0)
{
- mesh->mMaterialIndex = sourceMesh->mMaterials[b].sceneIndex;
+ mesh->mMaterialIndex = static_cast<unsigned int>(sourceMesh->mMaterials[b].sceneIndex);
} else
{
mesh->mMaterialIndex = 0;
@@ -373,7 +375,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
{
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);
+ std::vector<ai_real> oldWeights( sourceMesh->mPositions.size(), 0.0);
for( unsigned int d = 0; d < obone.mWeights.size(); d++)
oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight;
@@ -383,8 +385,8 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
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)
+ ai_real w = oldWeights[orgPoints[d]];
+ if( w > 0.0)
newWeights.push_back( aiVertexWeight( d, w));
}
@@ -713,4 +715,3 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
}
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
-
diff --git a/src/3rdparty/assimp/code/XFileImporter.h b/src/3rdparty/assimp/code/XFileImporter.h
index 1de56cbc5..0fa6b52eb 100644
--- a/src/3rdparty/assimp/code/XFileImporter.h
+++ b/src/3rdparty/assimp/code/XFileImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -64,14 +65,11 @@ struct Node;
/** The XFileImporter is a worker class capable of importing a scene from a
* DirectX file .x
*/
-class XFileImporter : public BaseImporter
-{
+class XFileImporter : public BaseImporter {
public:
XFileImporter();
~XFileImporter();
-
-public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
diff --git a/src/3rdparty/assimp/code/XFileParser.cpp b/src/3rdparty/assimp/code/XFileParser.cpp
index a820955a8..1f8b8cbd3 100644
--- a/src/3rdparty/assimp/code/XFileParser.cpp
+++ b/src/3rdparty/assimp/code/XFileParser.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -465,15 +466,12 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
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
+ unsigned int numIndices = ReadInt();
Face& face = pMesh->mPosFaces[a];
- 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();
}
@@ -731,7 +729,7 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial)
std::string matName;
readHeadOfDataObject( &matName);
if( matName.empty())
- matName = std::string( "material") + std::to_string( mLineNumber );
+ matName = std::string( "material") + to_string( mLineNumber );
pMaterial->mName = matName;
pMaterial->mIsReference = false;
@@ -1326,7 +1324,7 @@ unsigned int XFileParser::ReadInt()
}
// ------------------------------------------------------------------------------------------------
-float XFileParser::ReadFloat()
+ai_real XFileParser::ReadFloat()
{
if( mIsBinaryFormat)
{
@@ -1343,7 +1341,7 @@ float XFileParser::ReadFloat()
if( mBinaryFloatSize == 8)
{
if( End - P >= 8) {
- float result = (float) (*(double*) P);
+ ai_real result = (ai_real) (*(double*) P);
P += 8;
return result;
} else {
@@ -1353,7 +1351,7 @@ float XFileParser::ReadFloat()
} else
{
if( End - P >= 4) {
- float result = *(float*) P;
+ ai_real result = *(ai_real*) P;
P += 4;
return result;
} else {
@@ -1372,17 +1370,17 @@ float XFileParser::ReadFloat()
{
P += 9;
CheckForSeparator();
- return 0.0f;
+ return 0.0;
} else
if( strncmp( P, "1.#QNAN0", 8) == 0)
{
P += 8;
CheckForSeparator();
- return 0.0f;
+ return 0.0;
}
- float result = 0.0f;
- P = fast_atoreal_move<float>( P, result);
+ ai_real result = 0.0;
+ P = fast_atoreal_move<ai_real>( P, result);
CheckForSeparator();
diff --git a/src/3rdparty/assimp/code/XFileParser.h b/src/3rdparty/assimp/code/XFileParser.h
index 14c5ef1cf..ec823bac0 100644
--- a/src/3rdparty/assimp/code/XFileParser.h
+++ b/src/3rdparty/assimp/code/XFileParser.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -127,7 +128,7 @@ protected:
unsigned short ReadBinWord();
unsigned int ReadBinDWord();
unsigned int ReadInt();
- float ReadFloat();
+ ai_real ReadFloat();
aiVector2D ReadVector2();
aiVector3D ReadVector3();
aiColor3D ReadRGB();
diff --git a/src/3rdparty/assimp/code/XGLLoader.cpp b/src/3rdparty/assimp/code/XGLLoader.cpp
index fafad2f66..8ef91afac 100644
--- a/src/3rdparty/assimp/code/XGLLoader.cpp
+++ b/src/3rdparty/assimp/code/XGLLoader.cpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -52,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "MemoryIOWrapper.h"
#include <assimp/mesh.h>
#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
#include <cctype>
#include <memory>
@@ -81,8 +83,11 @@ struct free_it
};
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
-template<> const std::string LogFunctions<XGLImporter>::log_prefix = "XGL: ";
-
+ template<> const char* LogFunctions<XGLImporter>::Prefix()
+ {
+ static auto prefix = "XGL: ";
+ return prefix;
+ }
}
static const aiImporterDesc desc = {
@@ -102,12 +107,16 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
XGLImporter::XGLImporter()
-{}
+: m_reader( nullptr )
+, m_scene( nullptr ) {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-XGLImporter::~XGLImporter()
-{}
+XGLImporter::~XGLImporter() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
@@ -149,7 +158,7 @@ void XGLImporter::InternReadFile( const std::string& pFile,
free_it free_it_really(dest);
#endif
- scene = pScene;
+ m_scene = pScene;
std::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb"));
// check whether we can read from the file
@@ -211,14 +220,13 @@ void XGLImporter::InternReadFile( const std::string& pFile,
// construct the irrXML parser
CIrrXML_IOStreamReader st(stream.get());
- std::unique_ptr<IrrXMLReader> read( createIrrXMLReader((IFileReadCallBack*) &st) );
- reader = read.get();
+ m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );
// parse the XML file
TempScope scope;
while (ReadElement()) {
- if (!ASSIMP_stricmp(reader->getNodeName(),"world")) {
+ if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) {
ReadWorld(scope);
}
}
@@ -231,21 +239,21 @@ void XGLImporter::InternReadFile( const std::string& pFile,
}
// copy meshes
- scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
- scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
- std::copy(meshes.begin(),meshes.end(),scene->mMeshes);
+ m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ m_scene->mMeshes = new aiMesh*[m_scene->mNumMeshes]();
+ std::copy(meshes.begin(),meshes.end(),m_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);
+ m_scene->mNumMaterials = static_cast<unsigned int>(materials.size());
+ m_scene->mMaterials = new aiMaterial*[m_scene->mNumMaterials]();
+ std::copy(materials.begin(),materials.end(),m_scene->mMaterials);
if (scope.light) {
- scene->mNumLights = 1;
- scene->mLights = new aiLight*[1];
- scene->mLights[0] = scope.light;
+ m_scene->mNumLights = 1;
+ m_scene->mLights = new aiLight*[1];
+ m_scene->mLights[0] = scope.light;
- scope.light->mName = scene->mRootNode->mName;
+ scope.light->mName = m_scene->mRootNode->mName;
}
scope.dismiss();
@@ -254,8 +262,8 @@ void XGLImporter::InternReadFile( const std::string& pFile,
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElement()
{
- while(reader->read()) {
- if (reader->getNodeType() == EXN_ELEMENT) {
+ while(m_reader->read()) {
+ if (m_reader->getNodeType() == EXN_ELEMENT) {
return true;
}
}
@@ -265,11 +273,11 @@ bool XGLImporter::ReadElement()
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElementUpToClosing(const char* closetag)
{
- while(reader->read()) {
- if (reader->getNodeType() == EXN_ELEMENT) {
+ while(m_reader->read()) {
+ if (m_reader->getNodeType() == EXN_ELEMENT) {
return true;
}
- else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),closetag)) {
+ else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(),closetag)) {
return false;
}
}
@@ -280,11 +288,11 @@ bool XGLImporter::ReadElementUpToClosing(const char* closetag)
// ------------------------------------------------------------------------------------------------
bool XGLImporter::SkipToText()
{
- while(reader->read()) {
- if (reader->getNodeType() == EXN_TEXT) {
+ while(m_reader->read()) {
+ if (m_reader->getNodeType() == EXN_TEXT) {
return true;
}
- else if (reader->getNodeType() == EXN_ELEMENT || reader->getNodeType() == EXN_ELEMENT_END) {
+ else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) {
ThrowException("expected text contents but found another element (or element end)");
}
}
@@ -294,7 +302,7 @@ bool XGLImporter::SkipToText()
// ------------------------------------------------------------------------------------------------
std::string XGLImporter::GetElementName()
{
- const char* s = reader->getNodeName();
+ const char* s = m_reader->getNodeName();
size_t len = strlen(s);
std::string ret;
@@ -328,7 +336,7 @@ void XGLImporter::ReadWorld(TempScope& scope)
nd->mName.Set("WORLD");
}
- scene->mRootNode = nd;
+ m_scene->mRootNode = nd;
}
// ------------------------------------------------------------------------------------------------
@@ -351,7 +359,7 @@ void XGLImporter::ReadLighting(TempScope& scope)
// ------------------------------------------------------------------------------------------------
aiLight* XGLImporter::ReadDirectionalLight()
{
- ScopeGuard<aiLight> l(new aiLight());
+ std::unique_ptr<aiLight> l(new aiLight());
l->mType = aiLightSource_DIRECTIONAL;
while (ReadElementUpToClosing("directionallight")) {
@@ -366,13 +374,13 @@ aiLight* XGLImporter::ReadDirectionalLight()
l->mColorSpecular = ReadCol3();
}
}
- return l.dismiss();
+ return l.release();
}
// ------------------------------------------------------------------------------------------------
aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag)
{
- ScopeGuard<aiNode> nd(new aiNode());
+ std::unique_ptr<aiNode> nd(new aiNode());
std::vector<aiNode*> children;
std::vector<unsigned int> meshes;
@@ -455,11 +463,11 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl
nd->mChildren = new aiNode*[nd->mNumChildren]();
for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
nd->mChildren[i] = children[i];
- children[i]->mParent = nd;
+ children[i]->mParent = nd.get();
}
}
- return nd.dismiss();
+ return nd.release();
}
// ------------------------------------------------------------------------------------------------
@@ -498,9 +506,9 @@ 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 substitute identity transform.
+ // so subtitute identity transform.
LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
return m;
}
@@ -531,7 +539,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
// ------------------------------------------------------------------------------------------------
aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m)
{
- ScopeGuard<aiMesh> mesh(new aiMesh());
+ std::unique_ptr<aiMesh> mesh(new aiMesh());
mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
@@ -568,7 +576,7 @@ aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m)
mesh->mPrimitiveTypes = m.pflags;
mesh->mMaterialIndex = m.matid;
- return mesh.dismiss();
+ return mesh.release();
}
// ------------------------------------------------------------------------------------------------
@@ -586,29 +594,29 @@ bool XGLImporter::ReadMesh(TempScope& scope)
ReadMaterial(scope);
}
else if (s == "p") {
- if (!reader->getAttributeValue("ID")) {
+ if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <p>, ignoring");
}
else {
- int id = reader->getAttributeValueAsInt("ID");
+ int id = m_reader->getAttributeValueAsInt("ID");
t.points[id] = ReadVec3();
}
}
else if (s == "n") {
- if (!reader->getAttributeValue("ID")) {
+ if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <n>, ignoring");
}
else {
- int id = reader->getAttributeValueAsInt("ID");
+ int id = m_reader->getAttributeValueAsInt("ID");
t.normals[id] = ReadVec3();
}
}
else if (s == "tc") {
- if (!reader->getAttributeValue("ID")) {
+ if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <tc>, ignoring");
}
else {
- int id = reader->getAttributeValueAsInt("ID");
+ int id = m_reader->getAttributeValueAsInt("ID");
t.uvs[id] = ReadVec2();
}
}
@@ -708,7 +716,7 @@ unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope)
const std::string& s = GetElementName();
if (s == "mat") {
ReadMaterial(scope);
- return scope.materials_linear.size()-1;
+ return static_cast<unsigned int>(scope.materials_linear.size()-1);
}
const int id = ReadIndexFromText();
@@ -737,7 +745,7 @@ void XGLImporter::ReadMaterial(TempScope& scope)
{
const unsigned int mat_id = ReadIDAttr();
- ScopeGuard<aiMaterial> mat(new aiMaterial());
+ std::unique_ptr<aiMaterial> mat(new aiMaterial());
while (ReadElementUpToClosing("mat")) {
const std::string& s = GetElementName();
if (s == "amb") {
@@ -766,8 +774,8 @@ void XGLImporter::ReadMaterial(TempScope& scope)
}
}
- scope.materials[mat_id] = mat;
- scope.materials_linear.push_back(mat.dismiss());
+ scope.materials[mat_id] = mat.get();
+ scope.materials_linear.push_back(mat.release());
}
@@ -828,10 +836,10 @@ void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
// ------------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadIDAttr()
{
- for(int i = 0, e = reader->getAttributeCount(); i < e; ++i) {
+ for(int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) {
- if(!ASSIMP_stricmp(reader->getAttributeName(i),"id")) {
- return reader->getAttributeValueAsInt(i);
+ if(!ASSIMP_stricmp(m_reader->getAttributeName(i),"id")) {
+ return m_reader->getAttributeValueAsInt(i);
}
}
return ~0u;
@@ -844,7 +852,7 @@ float XGLImporter::ReadFloat()
LogError("unexpected EOF reading float element contents");
return 0.f;
}
- const char* s = reader->getNodeData(), *se;
+ const char* s = m_reader->getNodeData(), *se;
if(!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse float");
@@ -869,7 +877,7 @@ unsigned int XGLImporter::ReadIndexFromText()
LogError("unexpected EOF reading index element contents");
return ~0u;
}
- const char* s = reader->getNodeData(), *se;
+ const char* s = m_reader->getNodeData(), *se;
if(!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse index element");
return ~0u;
@@ -894,7 +902,7 @@ aiVector2D XGLImporter::ReadVec2()
LogError("unexpected EOF reading vec2 contents");
return vec;
}
- const char* s = reader->getNodeData();
+ const char* s = m_reader->getNodeData();
for(int i = 0; i < 2; ++i) {
if(!SkipSpaces(&s)) {
@@ -923,7 +931,7 @@ aiVector3D XGLImporter::ReadVec3()
LogError("unexpected EOF reading vec3 contents");
return vec;
}
- const char* s = reader->getNodeData();
+ const char* s = m_reader->getNodeData();
for(int i = 0; i < 3; ++i) {
if(!SkipSpaces(&s)) {
diff --git a/src/3rdparty/assimp/code/XGLLoader.h b/src/3rdparty/assimp/code/XGLLoader.h
index 757f9d564..97ae5f8a3 100644
--- a/src/3rdparty/assimp/code/XGLLoader.h
+++ b/src/3rdparty/assimp/code/XGLLoader.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -51,6 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/light.h>
+#include <memory>
+#include <map>
struct aiNode;
@@ -203,12 +206,8 @@ private:
unsigned int ResolveMaterialRef(TempScope& scope);
private:
-
-
-private:
-
- irr::io::IrrXMLReader* reader;
- aiScene* scene;
+ std::shared_ptr<irr::io::IrrXMLReader> m_reader;
+ aiScene* m_scene;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/XMLTools.h b/src/3rdparty/assimp/code/XMLTools.h
index 7339a2fc8..5d31f885e 100644
--- a/src/3rdparty/assimp/code/XMLTools.h
+++ b/src/3rdparty/assimp/code/XMLTools.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/fast_atof.h b/src/3rdparty/assimp/code/fast_atof.h
index f65d72ae0..058a7ff87 100644
--- a/src/3rdparty/assimp/code/fast_atof.h
+++ b/src/3rdparty/assimp/code/fast_atof.h
@@ -1,3 +1,5 @@
+#pragma once
+
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
@@ -19,8 +21,10 @@
#include <limits>
#include <stdint.h>
#include <stdexcept>
+#include <assimp/defs.h>
#include "StringComparison.h"
+#include <assimp/DefaultLogger.hpp>
#ifdef _MSC_VER
@@ -191,7 +195,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
uint64_t value = 0;
if ( *in < '0' || *in > '9' )
- throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
+ throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
bool running = true;
while ( running )
@@ -201,8 +205,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
- if (new_value < value) /* numeric overflow, we rely on you */
- throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow.");
+ // numeric overflow, we rely on you
+ if ( new_value < value ) {
+ DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." );
+ return 0;
+ }
+ //throw std::overflow_error();
value = new_value;
@@ -350,51 +358,26 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma
// ------------------------------------------------------------------------------------
// The same but more human.
-inline float fast_atof(const char* c)
+inline ai_real fast_atof(const char* c)
{
- float ret;
- fast_atoreal_move<float>(c, ret);
+ ai_real ret(0.0);
+ fast_atoreal_move<ai_real>(c, ret);
return ret;
}
-inline float fast_atof( const char* c, const char** cout)
+inline ai_real fast_atof( const char* c, const char** cout)
{
- float ret;
- *cout = fast_atoreal_move<float>(c, ret);
+ ai_real ret(0.0);
+ *cout = fast_atoreal_move<ai_real>(c, ret);
return ret;
}
-inline float fast_atof( const char** inout)
+inline ai_real fast_atof( const char** inout)
{
- float ret;
- *inout = fast_atoreal_move<float>(*inout, ret);
-
- return ret;
-}
-
-
-inline double fast_atod(const char* c)
-{
- 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);
-
- return ret;
-}
-
-inline double fast_atod( const char** inout)
-{
- double ret;
- *inout = fast_atoreal_move<double>(*inout, ret);
+ ai_real ret(0.0);
+ *inout = fast_atoreal_move<ai_real>(*inout, ret);
return ret;
}
@@ -402,4 +385,3 @@ inline double fast_atod( const char** inout)
} // end of namespace Assimp
#endif
-
diff --git a/src/3rdparty/assimp/code/glTF2Asset.h b/src/3rdparty/assimp/code/glTF2Asset.h
new file mode 100644
index 000000000..cece307d9
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2Asset.h
@@ -0,0 +1,1131 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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_materials_pbrSpecularGlossiness full
+ */
+#ifndef GLTF2ASSET_H_INC
+#define GLTF2ASSET_H_INC
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#include <map>
+#include <string>
+#include <list>
+#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 <assimp/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
+
+#include "StringUtils.h"
+
+namespace glTF2
+{
+#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 Skin;
+
+ // 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"
+
+ #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0
+ #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
+ #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
+ #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1
+ #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0
+ #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0
+ #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
+ #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
+ #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
+
+ #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
+ #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"
+ #define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid"
+ #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag"
+ #define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin"
+
+ #define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N
+ #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N
+ #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N
+ #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N
+ #define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N
+
+ #ifdef ASSIMP_API
+ #include "./../include/assimp/Compiler/pushpack1.h"
+ #endif
+
+ //! For binary .glb files
+ //! 12-byte header (+ the JSON + a "body" data section)
+ struct GLB_Header
+ {
+ uint8_t magic[4]; //!< Magic number: "glTF"
+ uint32_t version; //!< Version number (always 2 as of the last update)
+ uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
+ } PACK_STRUCT;
+
+ struct GLB_Chunk
+ {
+ uint32_t chunkLength;
+ uint32_t chunkType;
+ } PACK_STRUCT;
+
+ #ifdef ASSIMP_API
+ #include "./../include/assimp/Compiler/poppack1.h"
+ #endif
+
+
+ //! Values for the GLB_Chunk::chunkType field
+ enum ChunkType
+ {
+ ChunkType_JSON = 0x4E4F534A,
+ ChunkType_BIN = 0x004E4942
+ };
+
+ //! 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_UNSIGNED_INT = 5125,
+ ComponentType_FLOAT = 5126
+ };
+
+ inline unsigned int ComponentTypeSize(ComponentType t)
+ {
+ switch (t) {
+ case ComponentType_SHORT:
+ case ComponentType_UNSIGNED_SHORT:
+ return 2;
+
+ case ComponentType_UNSIGNED_INT:
+ case ComponentType_FLOAT:
+ return 4;
+
+ case ComponentType_BYTE:
+ case ComponentType_UNSIGNED_BYTE:
+ return 1;
+ default:
+ throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t));
+ }
+ }
+
+ //! Values for the BufferView::target field
+ enum BufferViewTarget
+ {
+ BufferViewTarget_ARRAY_BUFFER = 34962,
+ BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
+ };
+
+ //! Values for the Sampler::magFilter field
+ enum class SamplerMagFilter: unsigned int
+ {
+ UNSET = 0,
+ SamplerMagFilter_Nearest = 9728,
+ SamplerMagFilter_Linear = 9729
+ };
+
+ //! Values for the Sampler::minFilter field
+ enum class SamplerMinFilter: unsigned int
+ {
+ UNSET = 0,
+ SamplerMinFilter_Nearest = 9728,
+ SamplerMinFilter_Linear = 9729,
+ SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
+ SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
+ SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
+ SamplerMinFilter_Linear_Mipmap_Linear = 9987
+ };
+
+ //! Values for the Sampler::wrapS and Sampler::wrapT field
+ enum class SamplerWrap: unsigned int
+ {
+ UNSET = 0,
+ Clamp_To_Edge = 33071,
+ Mirrored_Repeat = 33648,
+ Repeat = 10497
+ };
+
+ //! 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
+ {
+ int index; //!< The index of this object within its property container
+ int oIndex; //!< The original index of this object defined in the JSON
+ 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)
+ 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);
+ };
+
+ //! A buffer points to binary geometry, animation, or skins.
+ struct Buffer : public Object
+ {
+ /********************* Types *********************/
+ public:
+
+ enum Type
+ {
+ Type_arraybuffer,
+ Type_text
+ };
+
+ /// \struct SEncodedRegion
+ /// Descriptor of encoded region in "bufferView".
+ struct SEncodedRegion
+ {
+ const size_t Offset;///< Offset from begin of "bufferView" to encoded region, in bytes.
+ const size_t EncodedData_Length;///< Size of encoded region, in bytes.
+ uint8_t* const DecodedData;///< Cached encoded data.
+ const size_t DecodedData_Length;///< Size of decoded region, in bytes.
+ const std::string ID;///< ID of the region.
+
+ /// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
+ /// Constructor.
+ /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
+ /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pDecodedData - pointer to decoded data array.
+ /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pID - ID of the region.
+ SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
+ : Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID)
+ {}
+
+ /// \fn ~SEncodedRegion()
+ /// Destructor.
+ ~SEncodedRegion() { delete[] DecodedData; }
+ };
+
+ /******************* Variables *******************/
+
+ //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;
+
+ /// \var EncodedRegion_Current
+ /// Pointer to currently active encoded region.
+ /// Why not decoding all regions at once and not to set one buffer with decoded data?
+ /// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded
+ /// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But
+ /// offset is counted for another regions is encoded.
+ /// Example. You have two meshes. For every of it you have 4 bytes of data. That data compressed to 2 bytes. So, you have buffer with encoded data:
+ /// M1_E0, M1_E1, M2_E0, M2_E1.
+ /// After decoding you'll get:
+ /// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3.
+ /// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like
+ /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4}
+ /// but in real life you'll get:
+ /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
+ /// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
+ /// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished
+ /// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
+ ///
+ /// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
+ /// exporter and importer. And, thanks to such way, there is no need to load whole file into memory.
+ SEncodedRegion* EncodedRegion_Current;
+
+ private:
+
+ shared_ptr<uint8_t> mData; //!< Pointer to the data
+ bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
+
+ /// \var EncodedRegion_List
+ /// List of encoded regions.
+ std::list<SEncodedRegion*> EncodedRegion_List;
+
+ /******************* Functions *******************/
+
+ public:
+
+ Buffer();
+ ~Buffer();
+
+ void Read(Value& obj, Asset& r);
+
+ bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0);
+
+ /// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
+ /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
+ /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
+ /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pDecodedData - pointer to decoded data array.
+ /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pID - ID of the region.
+ void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID);
+
+ /// \fn void EncodedRegion_SetCurrent(const std::string& pID)
+ /// Select current encoded region by ID. \sa EncodedRegion_Current.
+ /// \param [in] pID - ID of the region.
+ void EncodedRegion_SetCurrent(const std::string& pID);
+
+ /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
+ /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
+ /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
+ /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
+ /// \param [in] pReplace_Data - pointer to array with new data for buffer.
+ /// \param [in] pReplace_Count - count of bytes in new data.
+ /// \return true - if successfully replaced, false if input arguments is out of range.
+ bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count);
+
+ 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; }
+
+ std::string GetURI()
+ { return std::string(this->id) + ".bin"; }
+
+ 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)
+ unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
+
+ BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
+
+ 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;
+ } cameraProperties;
+
+ 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);
+ };
+
+ const vec4 defaultBaseColor = {1, 1, 1, 1};
+ const vec3 defaultEmissiveFactor = {0, 0, 0};
+ const vec4 defaultDiffuseFactor = {1, 1, 1, 1};
+ const vec3 defaultSpecularFactor = {1, 1, 1};
+
+ struct TextureInfo
+ {
+ Ref<Texture> texture;
+ unsigned int index;
+ unsigned int texCoord = 0;
+ };
+
+ struct NormalTextureInfo : TextureInfo
+ {
+ float scale = 1;
+ };
+
+ struct OcclusionTextureInfo : TextureInfo
+ {
+ float strength = 1;
+ };
+
+ struct PbrMetallicRoughness
+ {
+ vec4 baseColorFactor;
+ TextureInfo baseColorTexture;
+ TextureInfo metallicRoughnessTexture;
+ float metallicFactor;
+ float roughnessFactor;
+ };
+
+ struct PbrSpecularGlossiness
+ {
+ vec4 diffuseFactor;
+ vec3 specularFactor;
+ float glossinessFactor;
+ TextureInfo diffuseTexture;
+ TextureInfo specularGlossinessTexture;
+
+ PbrSpecularGlossiness() { SetDefaults(); }
+ void SetDefaults();
+ };
+
+ //! The material appearance of a primitive.
+ struct Material : public Object
+ {
+ //PBR metallic roughness properties
+ PbrMetallicRoughness pbrMetallicRoughness;
+
+ //other basic material properties
+ NormalTextureInfo normalTexture;
+ OcclusionTextureInfo occlusionTexture;
+ TextureInfo emissiveTexture;
+ vec3 emissiveFactor;
+ std::string alphaMode;
+ float alphaCutoff;
+ bool doubleSided;
+
+ //extension: KHR_materials_pbrSpecularGlossiness
+ Nullable<PbrSpecularGlossiness> pbrSpecularGlossiness;
+
+ 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, tangent, texcoord, color, joint, jointmatrix, weight;
+ } attributes;
+
+ Ref<Accessor> indices;
+
+ Ref<Material> material;
+ };
+
+ std::vector<Primitive> primitives;
+
+ Mesh() {}
+
+ /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
+ /// Get mesh data from JSON-object and place them to root asset.
+ /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
+ /// \param [out] pAsset_Root - reference to root assed where data will be stored.
+ void Read(Value& pJSON_Object, Asset& pAsset_Root);
+ };
+
+ 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;
+
+ std::vector< Ref<Node> > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
+ Ref<Skin> skin; //!< The ID of the skin referenced by this node.
+ std::string jointName; //!< Name used when this node is a joint in a skin.
+
+ Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
+
+ Node() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Program : public Object
+ {
+ Program() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
+ struct Sampler : public Object
+ {
+ SamplerMagFilter magFilter; //!< The texture magnification filter.
+ SamplerMinFilter minFilter; //!< The texture minification filter.
+ SamplerWrap wrapS; //!< The texture wrapping in the S direction.
+ SamplerWrap wrapT; //!< The texture wrapping in the T direction.
+
+ Sampler() { SetDefaults(); }
+ void Read(Value& obj, Asset& r);
+ void SetDefaults();
+ };
+
+ 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
+ {
+ Nullable<mat4> bindShapeMatrix; //!< Floating-point 4x4 transformation matrix stored in column-major order.
+ Ref<Accessor> inverseBindMatrices; //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
+ std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
+ std::string name; //!< The user-defined name of this object.
+
+ Skin() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ //! A texture and its sampler.
+ struct Texture : public Object
+ {
+ Ref<Sampler> sampler; //!< 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);
+ };
+
+ struct Animation : public Object
+ {
+ struct AnimSampler {
+ std::string id; //!< The ID of this sampler.
+ std::string input; //!< The ID of a parameter in this animation to use as key-frame input.
+ std::string interpolation; //!< Type of interpolation algorithm to use between key-frames.
+ std::string output; //!< The ID of a parameter in this animation to use as key-frame output.
+ };
+
+ struct AnimChannel {
+ int sampler; //!< The index of a sampler in the containing animation's samplers property.
+
+ struct AnimTarget {
+ Ref<Node> node; //!< The node to animate.
+ std::string path; //!< The name of property of the node to animate ("translation", "rotation", or "scale").
+ } target;
+ };
+
+ struct AnimParameters {
+ Ref<Accessor> TIME; //!< Accessor reference to a buffer storing a array of floating point scalar values.
+ Ref<Accessor> rotation; //!< Accessor reference to a buffer storing a array of four-component floating-point vectors.
+ Ref<Accessor> scale; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
+ Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
+ };
+
+ // AnimChannel Channels[3]; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
+ // AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
+ // AnimSampler Samplers[3]; //!< The parameterized inputs representing the key-frame data.
+
+ std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
+ AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
+ std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
+
+ Animation() {}
+ void Read(Value& obj, Asset& r);
+
+ //! Get accessor given an animation parameter name.
+ Ref<Accessor> GetAccessor(std::string name) {
+ if (name == "TIME") {
+ return Parameters.TIME;
+ } else if (name == "rotation") {
+ return Parameters.rotation;
+ } else if (name == "scale") {
+ return Parameters.scale;
+ } else if (name == "translation") {
+ return Parameters.translation;
+ }
+ return Ref<Accessor>();
+ }
+ };
+
+
+ //! 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< unsigned int, unsigned int > Dict;
+ typedef typename std::gltf_unordered_map< std::string, unsigned int > IdDict;
+
+ std::vector<T*> mObjs; //! The read objects
+ Dict mObjsByOIndex; //! The read objects accessible by original index
+ IdDict mObjsById; //! The read objects accessible 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> Retrieve(unsigned int i);
+
+ Ref<T> Get(unsigned int i);
+ Ref<T> Get(const char* id);
+
+ Ref<T> Create(const char* id);
+ Ref<T> Create(const std::string& id)
+ { return Create(id.c_str()); }
+
+ unsigned int Remove(const char* id);
+
+ 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.
+
+ 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: {})
+
+ std::string version; //!< The glTF format version
+
+ void Read(Document& doc);
+
+ AssetMetadata() : version("") {}
+ };
+
+ //
+ // 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_materials_pbrSpecularGlossiness;
+
+ } 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<Sampler> samplers;
+ LazyDict<Scene> scenes;
+ LazyDict<Skin> skins;
+ LazyDict<Texture> textures;
+
+ 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")
+ , samplers (*this, "samplers")
+ , scenes (*this, "scenes")
+ , skins (*this, "skins")
+ , textures (*this, "textures")
+ {
+ memset(&extensionsUsed, 0, sizeof(extensionsUsed));
+ }
+
+ //! Main function
+ void Load(const std::string& file, bool isBinary = false);
+
+ //! Enables binary encoding 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, std::vector<char>& sceneData);
+
+ void ReadExtensionsUsed(Document& doc);
+
+ IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
+ };
+
+}
+
+// Include the implementation of the methods
+#include "glTF2Asset.inl"
+
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // GLTF2ASSET_H_INC
diff --git a/src/3rdparty/assimp/code/glTF2Asset.inl b/src/3rdparty/assimp/code/glTF2Asset.inl
new file mode 100644
index 000000000..549df747e
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2Asset.inl
@@ -0,0 +1,1449 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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"
+
+// Header files, Assimp
+#include <assimp/DefaultLogger.hpp>
+
+using namespace Assimp;
+
+namespace glTF2 {
+
+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* FindNumber(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
+ }
+
+ inline Value* FindUInt(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd() && it->value.IsUint()) ? &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 = FindArray(*container, mDictId);
+ }
+}
+
+template<class T>
+inline void LazyDict<T>::DetachFromDocument()
+{
+ mDict = 0;
+}
+
+template<class T>
+unsigned int LazyDict<T>::Remove(const char* id)
+{
+ id = T::TranslateId(mAsset, id);
+
+ typename IdDict::iterator it = mObjsById.find(id);
+
+ if (it == mObjsById.end()) {
+ throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found");
+ }
+
+ const unsigned int index = it->second;
+
+ mAsset.mUsedIds[id] = false;
+ mObjsById.erase(id);
+ mObjsByOIndex.erase(index);
+ mObjs.erase(mObjs.begin() + index);
+
+ //update index of object in mObjs;
+ for (unsigned int i = index; i < mObjs.size(); ++i) {
+ T *obj = mObjs[i];
+
+ obj->index = i;
+ }
+
+ for (IdDict::iterator it = mObjsById.begin(); it != mObjsById.end(); ++it) {
+ if (it->second <= index) {
+ continue;
+ }
+
+ mObjsById[it->first] = it->second - 1;
+ }
+
+ for (Dict::iterator it = mObjsByOIndex.begin(); it != mObjsByOIndex.end(); ++it) {
+ if (it->second <= index) {
+ continue;
+ }
+
+ mObjsByOIndex[it->first] = it->second - 1;
+ }
+
+ return index;
+}
+
+template<class T>
+Ref<T> LazyDict<T>::Retrieve(unsigned int i)
+{
+
+ typename Dict::iterator it = mObjsByOIndex.find(i);
+ if (it != mObjsByOIndex.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) + "\"");
+ }
+
+ if (!mDict->IsArray()) {
+ throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\"");
+ }
+
+ Value &obj = (*mDict)[i];
+
+ if (!obj.IsObject()) {
+ throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object");
+ }
+
+ T* inst = new T();
+ inst->id = std::string(mDictId) + "_" + to_string(i);
+ inst->oIndex = i;
+ ReadMember(obj, "name", inst->name);
+ inst->Read(obj, mAsset);
+
+ return Add(inst);
+}
+
+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 IdDict::iterator it = mObjsById.find(id);
+ if (it != mObjsById.end()) { // already created?
+ return Ref<T>(mObjs, it->second);
+ }
+
+ return Ref<T>();
+}
+
+template<class T>
+Ref<T> LazyDict<T>::Add(T* obj)
+{
+ unsigned int idx = unsigned(mObjs.size());
+ mObjs.push_back(obj);
+ mObjsByOIndex[obj->oIndex] = idx;
+ 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();
+ unsigned int idx = unsigned(mObjs.size());
+ inst->id = id;
+ inst->index = idx;
+ inst->oIndex = idx;
+ return Add(inst);
+}
+
+
+//
+// glTF dictionary objects methods
+//
+
+
+inline Buffer::Buffer()
+ : byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false)
+{ }
+
+inline Buffer::~Buffer()
+{
+ for(SEncodedRegion* reg : EncodedRegion_List) delete reg;
+}
+
+inline const char* Buffer::TranslateId(Asset& /*r*/, const char* id)
+{
+ 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, std::default_delete<uint8_t[]>());
+
+ if (statedLength > 0 && this->byteLength != statedLength) {
+ throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) +
+ " bytes, but found " + to_string(dataURI.dataLength));
+ }
+ }
+ else { // assume raw data
+ if (statedLength != dataURI.dataLength) {
+ throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) +
+ " bytes, but found " + to_string(dataURI.dataLength));
+ }
+
+ this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
+ memcpy( this->mData.get(), dataURI.data, dataURI.dataLength );
+ }
+ }
+ else { // Local file
+ if (byteLength > 0) {
+ std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : "";
+
+ IOStream* file = r.OpenFile(dir + 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], std::default_delete<uint8_t[]>());
+
+ if (stream.Read(mData.get(), byteLength, 1) != 1) {
+ return false;
+ }
+ return true;
+}
+
+inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
+{
+ // Check pointer to data
+ if(pDecodedData == nullptr) throw DeadlyImportError("GLTF: for marking encoded region pointer to decoded data must be provided.");
+
+ // Check offset
+ if(pOffset > byteLength)
+ {
+ const uint8_t val_size = 32;
+
+ char val[val_size];
+
+ ai_snprintf(val, val_size, "%llu", (long long)pOffset);
+ throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region.");
+ }
+
+ // Check length
+ if((pOffset + pEncodedData_Length) > byteLength)
+ {
+ const uint8_t val_size = 64;
+
+ char val[val_size];
+
+ ai_snprintf(val, val_size, "%llu, %llu", (long long)pOffset, (long long)pEncodedData_Length);
+ throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range.");
+ }
+
+ // Add new region
+ EncodedRegion_List.push_back(new SEncodedRegion(pOffset, pEncodedData_Length, pDecodedData, pDecodedData_Length, pID));
+ // And set new value for "byteLength"
+ byteLength += (pDecodedData_Length - pEncodedData_Length);
+}
+
+inline void Buffer::EncodedRegion_SetCurrent(const std::string& pID)
+{
+ if((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return;
+
+ for(SEncodedRegion* reg : EncodedRegion_List)
+ {
+ if(reg->ID == pID)
+ {
+ EncodedRegion_Current = reg;
+
+ return;
+ }
+
+ }
+
+ throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found.");
+}
+
+inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
+{
+const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count;
+
+uint8_t* new_data;
+
+ if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false;
+
+ new_data = new uint8_t[new_data_size];
+ // Copy data which place before replacing part.
+ memcpy(new_data, mData.get(), pBufferData_Offset);
+ // Copy new data.
+ memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count);
+ // Copy data which place after replacing part.
+ memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset);
+ // Apply new data
+ mData.reset(new_data, std::default_delete<uint8_t[]>());
+ byteLength = new_data_size;
+
+ 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, std::default_delete<uint8_t[]>());
+ byteLength += amount;
+}
+
+//
+// struct BufferView
+//
+
+inline void BufferView::Read(Value& obj, Asset& r)
+{
+
+ if (Value* bufferVal = FindUInt(obj, "buffer")) {
+ buffer = r.buffers.Retrieve(bufferVal->GetUint());
+ }
+
+ byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
+ byteLength = MemberOrDefault(obj, "byteLength", 0u);
+ byteStride = MemberOrDefault(obj, "byteStride", 0u);
+}
+
+//
+// struct Accessor
+//
+
+inline void Accessor::Read(Value& obj, Asset& r)
+{
+
+ if (Value* bufferViewVal = FindUInt(obj, "bufferView")) {
+ bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
+ }
+
+ byteOffset = MemberOrDefault(obj, "byteOffset", 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;
+
+ // Check if region is encoded.
+ if(bufferView->buffer->EncodedRegion_Current != nullptr)
+ {
+ const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset;
+ const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length;
+
+ if((offset >= begin) && (offset < end))
+ return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin];
+ }
+
+ 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 = bufferView && bufferView->byteStride ? bufferView->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.bufferView && acc.bufferView->byteStride ? acc.bufferView->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*/)
+{
+ 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 Sampler::Read(Value& obj, Asset& /*r*/)
+{
+ SetDefaults();
+
+ ReadMember(obj, "name", name);
+ ReadMember(obj, "magFilter", magFilter);
+ ReadMember(obj, "minFilter", minFilter);
+ ReadMember(obj, "wrapS", wrapS);
+ ReadMember(obj, "wrapT", wrapT);
+}
+
+inline void Sampler::SetDefaults()
+{
+ //only wrapping modes have defaults
+ wrapS = SamplerWrap::Repeat;
+ wrapT = SamplerWrap::Repeat;
+ magFilter = SamplerMagFilter::UNSET;
+ minFilter = SamplerMinFilter::UNSET;
+}
+
+inline void Texture::Read(Value& obj, Asset& r)
+{
+ if (Value* sourceVal = FindUInt(obj, "source")) {
+ source = r.images.Retrieve(sourceVal->GetUint());
+ }
+
+ if (Value* samplerVal = FindUInt(obj, "sampler")) {
+ sampler = r.samplers.Retrieve(samplerVal->GetUint());
+ }
+}
+
+namespace {
+ inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out)
+ {
+ if (Value* index = FindUInt(*prop, "index")) {
+ out.texture = r.textures.Retrieve(index->GetUint());
+ }
+
+ if (Value* texcoord = FindUInt(*prop, "texCoord")) {
+ out.texCoord = texcoord->GetUint();
+ }
+ }
+
+ inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, TextureInfo& out)
+ {
+ if (Value* prop = FindMember(vals, propName)) {
+ SetTextureProperties(r, prop, out);
+ }
+ }
+
+ inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, NormalTextureInfo& out)
+ {
+ if (Value* prop = FindMember(vals, propName)) {
+ SetTextureProperties(r, prop, out);
+
+ if (Value* scale = FindNumber(*prop, "scale")) {
+ out.scale = static_cast<float>(scale->GetDouble());
+ }
+ }
+ }
+
+ inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, OcclusionTextureInfo& out)
+ {
+ if (Value* prop = FindMember(vals, propName)) {
+ SetTextureProperties(r, prop, out);
+
+ if (Value* strength = FindNumber(*prop, "strength")) {
+ out.strength = static_cast<float>(strength->GetDouble());
+ }
+ }
+ }
+}
+
+inline void Material::Read(Value& material, Asset& r)
+{
+ SetDefaults();
+
+ if (Value* pbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) {
+ ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor);
+ ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture);
+ ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture);
+ ReadMember(*pbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor);
+ ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor);
+ }
+
+ ReadTextureProperty(r, material, "normalTexture", this->normalTexture);
+ ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture);
+ ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture);
+ ReadMember(material, "emissiveFactor", this->emissiveFactor);
+
+ ReadMember(material, "doubleSided", this->doubleSided);
+ ReadMember(material, "alphaMode", this->alphaMode);
+ ReadMember(material, "alphaCutoff", this->alphaCutoff);
+
+ if (Value* extensions = FindObject(material, "extensions")) {
+ if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
+ if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) {
+ PbrSpecularGlossiness pbrSG;
+
+ ReadMember(*pbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor);
+ ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture);
+ ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture);
+ ReadMember(*pbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor);
+ ReadMember(*pbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor);
+
+ this->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
+ }
+ }
+ }
+}
+
+namespace {
+ void SetVector(vec4& v, const float(&in)[4])
+ { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; v[3] = in[3]; }
+
+ void SetVector(vec3& v, const float(&in)[3])
+ { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; }
+}
+
+inline void Material::SetDefaults()
+{
+ //pbr materials
+ SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor);
+ pbrMetallicRoughness.metallicFactor = 1.0;
+ pbrMetallicRoughness.roughnessFactor = 1.0;
+
+ SetVector(emissiveFactor, defaultEmissiveFactor);
+ alphaMode = "OPAQUE";
+ alphaCutoff = 0.5;
+ doubleSided = false;
+}
+
+inline void PbrSpecularGlossiness::SetDefaults()
+{
+ //pbrSpecularGlossiness properties
+ SetVector(diffuseFactor, defaultDiffuseFactor);
+ SetVector(specularFactor, defaultSpecularFactor);
+ glossinessFactor = 1.0;
+}
+
+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, "TANGENT"))) {
+ v = &(p.attributes.tangent);
+ }
+ 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& pJSON_Object, Asset& pAsset_Root)
+{
+ if (Value* name = FindMember(pJSON_Object, "name")) {
+ this->name = name->GetString();
+ }
+
+ /****************** Mesh primitives ******************/
+ if (Value* primitives = FindArray(pJSON_Object, "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.IsUint()) continue;
+ const char* attr = it->name.GetString();
+ // Valid attribute semantics include POSITION, NORMAL, TANGENT, 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] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
+ }
+ }
+ }
+
+ if (Value* indices = FindUInt(primitive, "indices")) {
+ prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
+ }
+
+ if (Value* material = FindUInt(primitive, "material")) {
+ prim.material = pAsset_Root.materials.Retrieve(material->GetUint());
+ }
+ }
+ }
+}
+
+inline void Camera::Read(Value& obj, Asset& /*r*/)
+{
+ type = MemberOrDefault(obj, "type", Camera::Perspective);
+
+ const char* subobjId = (type == Camera::Orthographic) ? "orthographic" : "perspective";
+
+ Value* it = FindObject(obj, subobjId);
+ if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters");
+
+ if (type == Camera::Perspective) {
+ cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
+ cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f);
+ cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
+ cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
+ }
+ else {
+ cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
+ cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
+ cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
+ cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f);
+ }
+}
+
+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.IsUint()) {
+ // get/create the child node
+ Ref<Node> chn = r.nodes.Retrieve(child.GetUint());
+ 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* mesh = FindUInt(obj, "mesh")) {
+ unsigned numMeshes = 1;
+
+ this->meshes.reserve(numMeshes);
+
+ Ref<Mesh> meshRef = r.meshes.Retrieve((*mesh).GetUint());
+
+ if (meshRef) this->meshes.push_back(meshRef);
+ }
+
+ if (Value* camera = FindUInt(obj, "camera")) {
+ this->camera = r.cameras.Retrieve(camera->GetUint());
+ if (this->camera)
+ this->camera->id = this->id;
+ }
+}
+
+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].IsUint()) continue;
+ Ref<Node> node = r.nodes.Retrieve((*array)[i].GetUint());
+ if (node)
+ this->nodes.push_back(node);
+ }
+ }
+}
+
+inline void AssetMetadata::Read(Document& doc)
+{
+ if (Value* obj = FindObject(doc, "asset")) {
+ ReadMember(*obj, "copyright", copyright);
+ ReadMember(*obj, "generator", generator);
+
+ if (Value* versionString = FindString(*obj, "version")) {
+ version = versionString->GetString();
+ } else if (Value* versionNumber = FindNumber (*obj, "version")) {
+ char buf[4];
+
+ ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
+
+ version = buf;
+ }
+
+ if (Value* profile = FindObject(*obj, "profile")) {
+ ReadMember(*profile, "api", this->profile.api);
+ ReadMember(*profile, "version", this->profile.version);
+ }
+ }
+
+ if (version.empty() || version[0] != '2') {
+ throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
+ }
+}
+
+//
+// Asset methods implementation
+//
+
+inline void Asset::ReadBinaryHeader(IOStream& stream, std::vector<char>& sceneData)
+{
+ 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 = to_string(header.version);
+ if (header.version != 2) {
+ throw DeadlyImportError("GLTF: Unsupported binary glTF version");
+ }
+
+ GLB_Chunk chunk;
+ if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
+ throw DeadlyImportError("GLTF: Unable to read JSON chunk");
+ }
+
+ AI_SWAP4(chunk.chunkLength);
+ AI_SWAP4(chunk.chunkType);
+
+ if (chunk.chunkType != ChunkType_JSON) {
+ throw DeadlyImportError("GLTF: JSON chunk missing");
+ }
+
+ // read the scene data
+
+ mSceneLength = chunk.chunkLength;
+ sceneData.resize(mSceneLength + 1);
+ sceneData[mSceneLength] = '\0';
+
+ if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
+ throw DeadlyImportError("GLTF: Could not read the file contents");
+ }
+
+ uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength;
+ if (padding > 0) {
+ stream.Seek(padding, aiOrigin_CUR);
+ }
+
+ AI_SWAP4(header.length);
+ mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8;
+ if (header.length >= mBodyOffset) {
+ if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
+ throw DeadlyImportError("GLTF: Unable to read BIN chunk");
+ }
+
+ AI_SWAP4(chunk.chunkLength);
+ AI_SWAP4(chunk.chunkType);
+
+ if (chunk.chunkType != ChunkType_BIN) {
+ throw DeadlyImportError("GLTF: BIN chunk missing");
+ }
+
+ mBodyLength = chunk.chunkLength;
+ }
+ else {
+ mBodyOffset = mBodyLength = 0;
+ }
+}
+
+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
+ std::vector<char> sceneData;
+ if (isBinary) {
+ SetAsBinary(); // also creates the body buffer
+ ReadBinaryHeader(*stream, sceneData);
+ }
+ else {
+ mSceneLength = stream->FileSize();
+ mBodyLength = 0;
+
+
+ // read the scene data
+
+ sceneData.resize(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 = FindUInt(doc, "scene")) {
+ unsigned int sceneIndex = scene->GetUint();
+
+ Ref<Scene> s = scenes.Retrieve(sceneIndex);
+
+ this->scene = s;
+ }
+
+ // Clean up
+ for (size_t i = 0; i < mDicts.size(); ++i) {
+ mDicts[i]->DetachFromDocument();
+ }
+}
+
+inline void Asset::SetAsBinary()
+{
+ if (!mBodyBuffer) {
+ 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_materials_pbrSpecularGlossiness);
+
+ #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;
+
+ std::vector<char> buffer;
+ buffer.resize(id.size() + 16);
+ int offset = ai_snprintf(buffer.data(), buffer.size(), "%s_", id.c_str());
+ for (int i = 0; it != mUsedIds.end(); ++i) {
+ ai_snprintf(buffer.data() + offset, buffer.size() - offset, "%d", i);
+ id = buffer.data();
+ 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++] = '=';
+ }
+ }
+ }
+
+}
+
+} // ns glTF
diff --git a/src/3rdparty/assimp/code/glTF2AssetWriter.h b/src/3rdparty/assimp/code/glTF2AssetWriter.h
new file mode 100644
index 000000000..bce2b1bd1
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2AssetWriter.h
@@ -0,0 +1,93 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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_materials_pbrSpecularGlossiness: full
+ */
+#ifndef GLTF2ASSETWRITER_H_INC
+#define GLTF2ASSETWRITER_H_INC
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#include "glTF2Asset.h"
+
+namespace glTF2
+{
+
+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 "glTF2AssetWriter.inl"
+
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // GLTF2ASSETWRITER_H_INC
diff --git a/src/3rdparty/assimp/code/glTF2AssetWriter.inl b/src/3rdparty/assimp/code/glTF2AssetWriter.inl
new file mode 100644
index 000000000..8b2769a37
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2AssetWriter.inl
@@ -0,0 +1,638 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 glTF2 {
+
+ 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;
+ }
+
+ inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
+ val.SetArray();
+ val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
+ for (unsigned int i = 0; i < r.size(); ++i) {
+ val.PushBack(r[i], al);
+ }
+ return val;
+ }
+
+ inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& /*al*/) {
+ val.SetDouble(r);
+
+ 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(v[i]->index, al);
+ }
+ obj.AddMember(StringRef(fieldId), lst, al);
+ }
+
+
+ }
+
+ inline void Write(Value& obj, Accessor& a, AssetWriter& w)
+ {
+ obj.AddMember("bufferView", a.bufferView->index, w.mAl);
+ obj.AddMember("byteOffset", a.byteOffset, 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);
+
+ Value vTmpMax, vTmpMin;
+ obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
+ obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
+ }
+
+ inline void Write(Value& obj, Animation& a, AssetWriter& w)
+ {
+ /****************** Channels *******************/
+ Value channels;
+ channels.SetArray();
+ channels.Reserve(unsigned(a.Channels.size()), w.mAl);
+
+ for (size_t i = 0; i < unsigned(a.Channels.size()); ++i) {
+ Animation::AnimChannel& c = a.Channels[i];
+ Value valChannel;
+ valChannel.SetObject();
+ {
+ valChannel.AddMember("sampler", c.sampler, w.mAl);
+
+ Value valTarget;
+ valTarget.SetObject();
+ {
+ valTarget.AddMember("node", c.target.node->index, w.mAl);
+ valTarget.AddMember("path", c.target.path, w.mAl);
+ }
+ valChannel.AddMember("target", valTarget, w.mAl);
+ }
+ channels.PushBack(valChannel, w.mAl);
+ }
+ obj.AddMember("channels", channels, w.mAl);
+
+ /****************** Samplers *******************/
+ Value valSamplers;
+ valSamplers.SetArray();
+
+ for (size_t i = 0; i < unsigned(a.Samplers.size()); ++i) {
+ Animation::AnimSampler& s = a.Samplers[i];
+ Value valSampler;
+ valSampler.SetObject();
+ {
+ Ref<Accessor> inputAccessor = a.GetAccessor(s.input);
+ Ref<Accessor> outputAccessor = a.GetAccessor(s.output);
+ valSampler.AddMember("input", inputAccessor->index, w.mAl);
+ valSampler.AddMember("interpolation", s.interpolation, w.mAl);
+ valSampler.AddMember("output", outputAccessor->index, w.mAl);
+ }
+ valSamplers.PushBack(valSampler, w.mAl);
+ }
+ obj.AddMember("samplers", valSamplers, w.mAl);
+ }
+
+ inline void Write(Value& obj, Buffer& b, AssetWriter& w)
+ {
+ obj.AddMember("byteLength", static_cast<uint64_t>(b.byteLength), w.mAl);
+ obj.AddMember("uri", Value(b.GetURI(), w.mAl).Move(), w.mAl);
+ }
+
+ inline void Write(Value& obj, BufferView& bv, AssetWriter& w)
+ {
+ obj.AddMember("buffer", bv.buffer->index, w.mAl);
+ obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
+ obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
+ if (bv.byteStride != 0) {
+ obj.AddMember("byteStride", bv.byteStride, 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 (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 SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al)
+ {
+ tex.SetObject();
+ tex.AddMember("index", t.texture->index, al);
+
+ if (t.texCoord != 0) {
+ tex.AddMember("texCoord", t.texCoord, al);
+ }
+ }
+
+ inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
+ {
+
+ if (t.texture) {
+ Value tex;
+
+ SetTexBasic(t, tex, al);
+
+ obj.AddMember(StringRef(propName), tex, al);
+ }
+ }
+
+ inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
+ {
+
+ if (t.texture) {
+ Value tex;
+
+ SetTexBasic(t, tex, al);
+
+ if (t.scale != 1) {
+ tex.AddMember("scale", t.scale, al);
+ }
+
+ obj.AddMember(StringRef(propName), tex, al);
+ }
+ }
+
+ inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
+ {
+
+ if (t.texture) {
+ Value tex;
+
+ SetTexBasic(t, tex, al);
+
+ if (t.strength != 1) {
+ tex.AddMember("strength", t.strength, al);
+ }
+
+ obj.AddMember(StringRef(propName), tex, al);
+ }
+ }
+
+ template<size_t N>
+ inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al)
+ {
+ Value arr;
+ obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al);
+ }
+
+ template<size_t N>
+ inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al)
+ {
+ if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) {
+ WriteVec(obj, prop, propName, al);
+ }
+ }
+
+ inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al)
+ {
+ Value num;
+ obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al);
+ }
+ }
+
+ inline void Write(Value& obj, Material& m, AssetWriter& w)
+ {
+ Value pbrMetallicRoughness;
+ pbrMetallicRoughness.SetObject();
+ {
+ WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl);
+ WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
+ WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl);
+
+ if (m.pbrMetallicRoughness.metallicFactor != 1) {
+ WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl);
+ }
+
+ if (m.pbrMetallicRoughness.roughnessFactor != 1) {
+ WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl);
+ }
+ }
+
+ if (!pbrMetallicRoughness.ObjectEmpty()) {
+ obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl);
+ }
+
+ WriteTex(obj, m.normalTexture, "normalTexture", w.mAl);
+ WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl);
+ WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl);
+ WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl);
+
+ if (m.alphaCutoff != 0.5) {
+ WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl);
+ }
+
+ if (m.alphaMode != "OPAQUE") {
+ obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl);
+ }
+
+ if (m.doubleSided) {
+ obj.AddMember("doubleSided", m.doubleSided, w.mAl);
+ }
+
+ Value exts;
+ exts.SetObject();
+
+ if (m.pbrSpecularGlossiness.isPresent) {
+ Value pbrSpecularGlossiness;
+ pbrSpecularGlossiness.SetObject();
+
+ PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value;
+
+ //pbrSpecularGlossiness
+ WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl);
+ WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl);
+
+ if (pbrSG.glossinessFactor != 1) {
+ WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl);
+ }
+
+ WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl);
+ WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl);
+
+ if (!pbrSpecularGlossiness.ObjectEmpty()) {
+ exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl);
+ }
+ }
+
+ if (!exts.ObjectEmpty()) {
+ obj.AddMember("extensions", exts, 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), lst[0]->index, 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(), lst[i]->index, w.mAl);
+ }
+ }
+ }
+ }
+
+ inline void Write(Value& obj, Mesh& m, AssetWriter& w)
+ {
+ /****************** Primitives *******************/
+ 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->index, w.mAl);
+
+ if (p.indices)
+ prim.AddMember("indices", p.indices->index, 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", true);
+ WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true);
+ WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true);
+ }
+ 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);
+
+ if (!n.meshes.empty()) {
+ obj.AddMember("mesh", n.meshes[0]->index, w.mAl);
+ }
+
+ AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
+
+ if (n.skin) {
+ obj.AddMember("skin", n.skin->index, w.mAl);
+ }
+
+ if (!n.jointName.empty()) {
+ obj.AddMember("jointName", n.jointName, w.mAl);
+ }
+ }
+
+ inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
+ {
+
+ }
+
+ inline void Write(Value& obj, Sampler& b, AssetWriter& w)
+ {
+ if (!b.name.empty()) {
+ obj.AddMember("name", b.name, w.mAl);
+ }
+
+ if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) {
+ obj.AddMember("wrapS", static_cast<unsigned int>(b.wrapS), w.mAl);
+ }
+
+ if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) {
+ obj.AddMember("wrapT", static_cast<unsigned int>(b.wrapT), w.mAl);
+ }
+
+ if (b.magFilter != SamplerMagFilter::UNSET) {
+ obj.AddMember("magFilter", static_cast<unsigned int>(b.magFilter), w.mAl);
+ }
+
+ if (b.minFilter != SamplerMinFilter::UNSET) {
+ obj.AddMember("minFilter", static_cast<unsigned int>(b.minFilter), w.mAl);
+ }
+ }
+
+ 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)
+ {
+ /****************** jointNames *******************/
+ Value vJointNames;
+ vJointNames.SetArray();
+ vJointNames.Reserve(unsigned(b.jointNames.size()), w.mAl);
+
+ for (size_t i = 0; i < unsigned(b.jointNames.size()); ++i) {
+ vJointNames.PushBack(b.jointNames[i]->index, w.mAl);
+ }
+ obj.AddMember("joints", vJointNames, w.mAl);
+
+ if (b.bindShapeMatrix.isPresent) {
+ Value val;
+ obj.AddMember("bindShapeMatrix", MakeValue(val, b.bindShapeMatrix.value, w.mAl).Move(), w.mAl);
+ }
+
+ if (b.inverseBindMatrices) {
+ obj.AddMember("inverseBindMatrices", b.inverseBindMatrices->index, w.mAl);
+ }
+
+ }
+
+ inline void Write(Value& obj, Texture& tex, AssetWriter& w)
+ {
+ if (tex.source) {
+ obj.AddMember("source", tex.source->index, w.mAl);
+ }
+ if (tex.sampler) {
+ obj.AddMember("sampler", tex.sampler->index, w.mAl);
+ }
+ }
+
+
+ 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", mAsset.scene->index, mAl);
+ }
+ }
+
+ inline void AssetWriter::WriteFile(const char* path)
+ {
+ std::unique_ptr<IOStream> jsonOutFile(mAsset.OpenFile(path, "wt", true));
+
+ if (jsonOutFile == 0) {
+ throw DeadlyExportError("Could not open output file: " + std::string(path));
+ }
+
+ StringBuffer docBuffer;
+
+ PrettyWriter<StringBuffer> writer(docBuffer);
+ mDoc.Accept(writer);
+
+ if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
+ throw DeadlyExportError("Failed to write scene data!");
+ }
+
+ // Write buffer data to separate .bin files
+ for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) {
+ Ref<Buffer> b = mAsset.buffers.Get(i);
+
+ std::string binPath = b->GetURI();
+
+ std::unique_ptr<IOStream> binOutFile(mAsset.OpenFile(binPath, "wb", true));
+
+ if (binOutFile == 0) {
+ throw DeadlyExportError("Could not open output file: " + binPath);
+ }
+
+ if (b->byteLength > 0) {
+ if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
+ throw DeadlyExportError("Failed to write binary file: " + binPath);
+ }
+ }
+ }
+ }
+
+ inline void AssetWriter::WriteMetadata()
+ {
+ Value asset;
+ asset.SetObject();
+ asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
+ asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
+ mDoc.AddMember("asset", asset, mAl);
+ }
+
+ inline void AssetWriter::WriteExtensionsUsed()
+ {
+ Value exts;
+ exts.SetArray();
+ {
+ // This is used to export pbrSpecularGlossiness materials with GLTF 2.
+ if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
+ exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), 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 = FindArray(*container, d.mDictId))) {
+ container->AddMember(StringRef(d.mDictId), Value().SetArray().Move(), mDoc.GetAllocator());
+ dict = FindArray(*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->PushBack(obj, mAl);
+ }
+ }
+
+ template<class T>
+ void WriteLazyDict(LazyDict<T>& d, AssetWriter& w)
+ {
+ w.WriteObjects(d);
+ }
+
+}
+
+
diff --git a/src/3rdparty/assimp/code/glTF2Exporter.cpp b/src/3rdparty/assimp/code/glTF2Exporter.cpp
new file mode 100644
index 000000000..c1a803c1f
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2Exporter.cpp
@@ -0,0 +1,1080 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 "glTF2Exporter.h"
+
+#include "Exceptional.h"
+#include "StringComparison.h"
+#include "ByteSwapper.h"
+
+#include "SplitLargeMeshes.h"
+
+#include <assimp/SceneCombiner.h>
+#include <assimp/version.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+
+// Header files, standard library.
+#include <memory>
+#include <inttypes.h>
+
+#include "glTF2AssetWriter.h"
+
+using namespace rapidjson;
+
+using namespace Assimp;
+using namespace glTF2;
+
+namespace Assimp {
+
+ // ------------------------------------------------------------------------------------------------
+ // Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp
+ void ExportSceneGLTF2(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+ {
+ // invoke the exporter
+ glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, false);
+ }
+
+} // end of namespace Assimp
+
+glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
+ const ExportProperties* pProperties, bool /*isBinary*/)
+ : mFilename(filename)
+ , mIOSystem(pIOSystem)
+ , mProperties(pProperties)
+{
+ 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());
+
+ mScene = sceneCopy.get();
+
+ mAsset.reset( new Asset( pIOSystem ) );
+
+ ExportMetadata();
+
+ ExportMaterials();
+
+ if (mScene->mRootNode) {
+ ExportNodeHierarchy(mScene->mRootNode);
+ }
+
+ ExportMeshes();
+ MergeMeshes();
+
+ ExportScene();
+
+ ExportAnimations();
+
+ AssetWriter writer(*mAsset);
+
+ writer.WriteFile(filename);
+}
+
+/*
+ * Copy a 4x4 matrix from struct aiMatrix to typedef mat4.
+ * Also converts from row-major to column-major storage.
+ */
+static void CopyValue(const aiMatrix4x4& v, 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;
+}
+
+static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
+{
+ o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
+ o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
+ o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
+ o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
+}
+
+static void IdentityMatrix4(mat4& o)
+{
+ o[ 0] = 1; o[ 1] = 0; o[ 2] = 0; o[ 3] = 0;
+ o[ 4] = 0; o[ 5] = 1; o[ 6] = 0; o[ 7] = 0;
+ o[ 8] = 0; o[ 9] = 0; o[10] = 1; o[11] = 0;
+ o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1;
+}
+
+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;
+ // make sure offset is correctly byte-aligned, as required by spec
+ size_t padding = offset % bytesPerComp;
+ offset += padding;
+ size_t length = count * numCompsOut * bytesPerComp;
+ buffer->Grow(length + padding);
+
+ // 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->byteStride = 0;
+ 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->componentType = compType;
+ acc->count = count;
+ acc->type = typeOut;
+
+ // calculate min and max values
+ {
+ // Allocate and initialize with large values.
+ float float_MAX = 10000000000000.0f;
+ for (unsigned int i = 0 ; i < numCompsOut ; i++) {
+ acc->min.push_back( float_MAX);
+ acc->max.push_back(-float_MAX);
+ }
+
+ // Search and set extreme values.
+ float valueTmp;
+ for (unsigned int i = 0 ; i < count ; i++) {
+ for (unsigned int j = 0 ; j < numCompsOut ; j++) {
+ if (numCompsOut == 1) {
+ valueTmp = static_cast<unsigned short*>(data)[i];
+ } else {
+ valueTmp = static_cast<aiVector3D*>(data)[i][j];
+ }
+
+ if (valueTmp < acc->min[j]) {
+ acc->min[j] = valueTmp;
+ }
+ if (valueTmp > acc->max[j]) {
+ acc->max[j] = valueTmp;
+ }
+ }
+ }
+ }
+
+ // copy the data
+ acc->WriteData(count, data, numCompsIn*bytesPerComp);
+
+ return acc;
+}
+
+inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map)
+{
+ switch (map) {
+ case aiTextureMapMode_Clamp:
+ wrap = SamplerWrap::Clamp_To_Edge;
+ break;
+ case aiTextureMapMode_Mirror:
+ wrap = SamplerWrap::Mirrored_Repeat;
+ break;
+ case aiTextureMapMode_Wrap:
+ case aiTextureMapMode_Decal:
+ default:
+ wrap = SamplerWrap::Repeat;
+ break;
+ };
+}
+
+void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
+{
+ aiString aId;
+ std::string id;
+ if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
+ id = aId.C_Str();
+ }
+
+ if (Ref<Sampler> ref = mAsset->samplers.Get(id.c_str())) {
+ texture->sampler = ref;
+ } else {
+ id = mAsset->FindUniqueID(id, "sampler");
+
+ texture->sampler = mAsset->samplers.Create(id.c_str());
+
+ aiTextureMapMode mapU, mapV;
+ SamplerMagFilter filterMag;
+ SamplerMinFilter filterMin;
+
+ if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
+ SetSamplerWrap(texture->sampler->wrapS, mapU);
+ }
+
+ if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
+ SetSamplerWrap(texture->sampler->wrapT, mapV);
+ }
+
+ if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
+ texture->sampler->magFilter = filterMag;
+ }
+
+ if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
+ texture->sampler->minFilter = filterMin;
+ }
+
+ aiString name;
+ if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
+ texture->sampler->name = name.C_Str();
+ }
+ }
+}
+
+void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
+{
+ std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
+
+ mat->Get(textureKey.c_str(), tt, slot, prop);
+}
+
+void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
+{
+ std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
+
+ mat->Get(textureKey.c_str(), tt, slot, prop);
+}
+
+void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
+{
+
+ if (mat->GetTextureCount(tt) > 0) {
+ aiString tex;
+
+ if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), 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()) {
+ texture = mAsset->textures.Get(it->second);
+ }
+ }
+
+ if (!texture) {
+ std::string texId = mAsset->FindUniqueID("", "texture");
+ texture = mAsset->textures.Create(texId);
+ mTexturesByPath[path] = texture.GetIndex();
+
+ std::string imgId = mAsset->FindUniqueID("", "image");
+ 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);
+ 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;
+ texture->source->mimeType = mimeType;
+ }
+ }
+ else {
+ texture->source->uri = path;
+ }
+
+ GetTexSampler(mat, texture, tt, slot);
+ }
+ }
+ }
+ }
+}
+
+void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
+{
+ Ref<Texture>& texture = prop.texture;
+
+ GetMatTex(mat, texture, tt, slot);
+
+ if (texture) {
+ GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
+ }
+}
+
+void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
+{
+ Ref<Texture>& texture = prop.texture;
+
+ GetMatTex(mat, texture, tt, slot);
+
+ if (texture) {
+ GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
+ GetMatTexProp(mat, prop.scale, "scale", tt, slot);
+ }
+}
+
+void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
+{
+ Ref<Texture>& texture = prop.texture;
+
+ GetMatTex(mat, texture, tt, slot);
+
+ if (texture) {
+ GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
+ GetMatTexProp(mat, prop.strength, "strength", tt, slot);
+ }
+}
+
+aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx)
+{
+ aiColor4D col;
+ aiReturn result = mat->Get(propName, type, idx, col);
+
+ if (result == AI_SUCCESS) {
+ prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
+ }
+
+ return result;
+}
+
+aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx)
+{
+ aiColor3D col;
+ aiReturn result = mat->Get(propName, type, idx, col);
+
+ if (result == AI_SUCCESS) {
+ prop[0] = col.r; prop[1] = col.g; prop[2] = col.b;
+ }
+
+ return result;
+}
+
+void glTF2Exporter::ExportMaterials()
+{
+ aiString aiName;
+ for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
+ const aiMaterial* mat = mScene->mMaterials[i];
+
+ std::string id = "material_" + to_string(i);
+
+ Ref<Material> m = mAsset->materials.Create(id);
+
+ std::string name;
+ if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
+ name = aiName.C_Str();
+ }
+ name = mAsset->FindUniqueID(name, "material");
+
+ m->name = name;
+
+ GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE);
+
+ if (!m->pbrMetallicRoughness.baseColorTexture.texture) {
+ //if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture
+ GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE);
+ }
+
+ GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
+
+ if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR) != AI_SUCCESS) {
+ // if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material.
+ //a fallback to any diffuse color should be used instead
+ GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
+ }
+
+ if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
+ //if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
+ m->pbrMetallicRoughness.metallicFactor = 0;
+ }
+
+ // get roughness if source is gltf2 file
+ if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) {
+ // otherwise, try to derive and convert from specular + shininess values
+ aiColor4D specularColor;
+ ai_real shininess;
+
+ if (
+ mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
+ mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS
+ ) {
+ // convert specular color to luminance
+ float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
+ //normalize shininess (assuming max is 1000) with an inverse exponentional curve
+ float normalizedShininess = std::sqrt(shininess / 1000);
+
+ //clamp the shininess value between 0 and 1
+ normalizedShininess = std::min(std::max(normalizedShininess, 0.0f), 1.0f);
+ // low specular intensity values should produce a rough material even if shininess is high.
+ normalizedShininess = normalizedShininess * specularIntensity;
+
+ m->pbrMetallicRoughness.roughnessFactor = 1 - normalizedShininess;
+ }
+ }
+
+ GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS);
+ GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP);
+ GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE);
+ GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
+
+ mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided);
+ mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
+
+ aiString alphaMode;
+
+ if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
+ m->alphaMode = alphaMode.C_Str();
+ } else {
+ float opacity;
+
+ if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
+ if (opacity < 1) {
+ m->alphaMode = "BLEND";
+ m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
+ }
+ }
+ }
+
+ bool hasPbrSpecularGlossiness = false;
+ mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness);
+
+ if (hasPbrSpecularGlossiness) {
+
+ if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
+ mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
+ }
+
+ PbrSpecularGlossiness pbrSG;
+
+ GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE);
+ GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR);
+
+ if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) {
+ float shininess;
+
+ if (mat->Get(AI_MATKEY_SHININESS, shininess)) {
+ pbrSG.glossinessFactor = shininess / 1000;
+ }
+ }
+
+ GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
+ GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
+
+ m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
+ }
+ }
+}
+
+/*
+ * Search through node hierarchy and find the node containing the given meshID.
+ * Returns true on success, and false otherwise.
+ */
+bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID)
+{
+ for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
+ if (meshID.compare(nodeIn->meshes[i]->id) == 0) {
+ meshNode = nodeIn;
+ return true;
+ }
+ }
+
+ for (unsigned int i = 0; i < nodeIn->children.size(); ++i) {
+ if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Find the root joint of the skeleton.
+ * Starts will any joint node and traces up the tree,
+ * until a parent is found that does not have a jointName.
+ * Returns the first parent Ref<Node> found that does not have a jointName.
+ */
+Ref<Node> FindSkeletonRootJoint(Ref<Skin>& skinRef)
+{
+ Ref<Node> startNodeRef;
+ Ref<Node> parentNodeRef;
+
+ // Arbitrarily use the first joint to start the search.
+ startNodeRef = skinRef->jointNames[0];
+ parentNodeRef = skinRef->jointNames[0];
+
+ do {
+ startNodeRef = parentNodeRef;
+ parentNodeRef = startNodeRef->parent;
+ } while (!parentNodeRef->jointName.empty());
+
+ return parentNodeRef;
+}
+
+void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buffer>& bufferRef, Ref<Skin>& skinRef, std::vector<aiMatrix4x4>& inverseBindMatricesData)
+{
+ if (aimesh->mNumBones < 1) {
+ return;
+ }
+
+ // Store the vertex joint and weight data.
+ const size_t NumVerts( aimesh->mNumVertices );
+ vec4* vertexJointData = new vec4[ NumVerts ];
+ vec4* vertexWeightData = new vec4[ NumVerts ];
+ int* jointsPerVertex = new int[ NumVerts ];
+ for (size_t i = 0; i < NumVerts; ++i) {
+ jointsPerVertex[i] = 0;
+ for (size_t j = 0; j < 4; ++j) {
+ vertexJointData[i][j] = 0;
+ vertexWeightData[i][j] = 0;
+ }
+ }
+
+ for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) {
+ const aiBone* aib = aimesh->mBones[idx_bone];
+
+ // aib->mName =====> skinRef->jointNames
+ // Find the node with id = mName.
+ Ref<Node> nodeRef = mAsset.nodes.Get(aib->mName.C_Str());
+ nodeRef->jointName = nodeRef->name;
+
+ unsigned int jointNamesIndex = 0;
+ bool addJointToJointNames = true;
+ for ( unsigned int idx_joint = 0; idx_joint < skinRef->jointNames.size(); ++idx_joint) {
+ if (skinRef->jointNames[idx_joint]->jointName.compare(nodeRef->jointName) == 0) {
+ addJointToJointNames = false;
+ jointNamesIndex = idx_joint;
+ }
+ }
+
+ if (addJointToJointNames) {
+ skinRef->jointNames.push_back(nodeRef);
+
+ // aib->mOffsetMatrix =====> skinRef->inverseBindMatrices
+ aiMatrix4x4 tmpMatrix4;
+ CopyValue(aib->mOffsetMatrix, tmpMatrix4);
+ inverseBindMatricesData.push_back(tmpMatrix4);
+ jointNamesIndex = static_cast<unsigned int>(inverseBindMatricesData.size() - 1);
+ }
+
+ // aib->mWeights =====> vertexWeightData
+ for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) {
+ unsigned int vertexId = aib->mWeights[idx_weights].mVertexId;
+ float vertWeight = aib->mWeights[idx_weights].mWeight;
+
+ // A vertex can only have at most four joint weights. Ignore all others.
+ if (jointsPerVertex[vertexId] > 3) {
+ continue;
+ }
+
+ vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex);
+ vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
+
+ jointsPerVertex[vertexId] += 1;
+ }
+
+ } // End: for-loop mNumMeshes
+
+ Mesh::Primitive& p = meshRef->primitives.back();
+ Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+ if ( vertexJointAccessor ) {
+ p.attributes.joint.push_back( vertexJointAccessor );
+ }
+
+ Ref<Accessor> vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+ if ( vertexWeightAccessor ) {
+ p.attributes.weight.push_back( vertexWeightAccessor );
+ }
+ delete[] jointsPerVertex;
+ delete[] vertexWeightData;
+ delete[] vertexJointData;
+}
+
+void glTF2Exporter::ExportMeshes()
+{
+ // Not for
+ // using IndicesType = decltype(aiFace::mNumIndices);
+ // But yes for
+ // using IndicesType = unsigned short;
+ // because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification.
+ typedef unsigned short IndicesType;
+
+ std::string fname = std::string(mFilename);
+ std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf"));
+ std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str());
+
+ Ref<Buffer> b = mAsset->GetBodyBuffer();
+ if (!b) {
+ b = mAsset->buffers.Create(bufferId);
+ }
+
+ //----------------------------------------
+ // Initialize variables for the skin
+ bool createSkin = false;
+ for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) {
+ const aiMesh* aim = mScene->mMeshes[idx_mesh];
+ if(aim->HasBones()) {
+ createSkin = true;
+ break;
+ }
+ }
+
+ Ref<Skin> skinRef;
+ std::string skinName = mAsset->FindUniqueID("skin", "skin");
+ std::vector<aiMatrix4x4> inverseBindMatricesData;
+ if(createSkin) {
+ skinRef = mAsset->skins.Create(skinName);
+ skinRef->name = skinName;
+ }
+ //----------------------------------------
+
+ for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) {
+ const aiMesh* aim = mScene->mMeshes[idx_mesh];
+
+ std::string name = aim->mName.C_Str();
+
+ std::string meshId = mAsset->FindUniqueID(name, "mesh");
+ Ref<Mesh> m = mAsset->meshes.Create(meshId);
+ m->primitives.resize(1);
+ Mesh::Primitive& p = m->primitives.back();
+
+ m->name = name;
+
+ p.material = mAsset->materials.Get(aim->mMaterialIndex);
+
+ /******************* Vertices ********************/
+ 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);
+
+ /******************** Normals ********************/
+ 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);
+
+ /************** Texture coordinates **************/
+ for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ // Flip UV y coords
+ if (aim -> mNumUVComponents[i] > 1) {
+ for (unsigned int j = 0; j < aim->mNumVertices; ++j) {
+ aim->mTextureCoords[i][j].y = 1 - aim->mTextureCoords[i][j].y;
+ }
+ }
+
+ 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, false);
+ if (tc) p.attributes.texcoord.push_back(tc);
+ }
+ }
+
+ /*************** Vertices indices ****************/
+ if (aim->mNumFaces > 0) {
+ std::vector<IndicesType> indices;
+ unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices;
+ 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;
+ }
+
+ /*************** Skins ****************/
+ if(aim->HasBones()) {
+ ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData);
+ }
+ }
+
+ //----------------------------------------
+ // Finish the skin
+ // Create the Accessor for skinRef->inverseBindMatrices
+ if (createSkin) {
+ mat4* invBindMatrixData = new mat4[inverseBindMatricesData.size()];
+ for ( unsigned int idx_joint = 0; idx_joint < inverseBindMatricesData.size(); ++idx_joint) {
+ CopyValue(inverseBindMatricesData[idx_joint], invBindMatrixData[idx_joint]);
+ }
+
+ Ref<Accessor> invBindMatrixAccessor = ExportData(*mAsset, skinName, b, static_cast<unsigned int>(inverseBindMatricesData.size()), invBindMatrixData, AttribType::MAT4, AttribType::MAT4, ComponentType_FLOAT);
+ if (invBindMatrixAccessor) skinRef->inverseBindMatrices = invBindMatrixAccessor;
+
+ // Identity Matrix =====> skinRef->bindShapeMatrix
+ // Temporary. Hard-coded identity matrix here
+ skinRef->bindShapeMatrix.isPresent = true;
+ IdentityMatrix4(skinRef->bindShapeMatrix.value);
+
+ // Find nodes that contain a mesh with bones and add "skeletons" and "skin" attributes to those nodes.
+ Ref<Node> rootNode = mAsset->nodes.Get(unsigned(0));
+ Ref<Node> meshNode;
+ for (unsigned int meshIndex = 0; meshIndex < mAsset->meshes.Size(); ++meshIndex) {
+ Ref<Mesh> mesh = mAsset->meshes.Get(meshIndex);
+ bool hasBones = false;
+ for (unsigned int i = 0; i < mesh->primitives.size(); ++i) {
+ if (!mesh->primitives[i].attributes.weight.empty()) {
+ hasBones = true;
+ break;
+ }
+ }
+ if (!hasBones) {
+ continue;
+ }
+ std::string meshID = mesh->id;
+ FindMeshNode(rootNode, meshNode, meshID);
+ Ref<Node> rootJoint = FindSkeletonRootJoint(skinRef);
+ meshNode->skeletons.push_back(rootJoint);
+ meshNode->skin = skinRef;
+ }
+ }
+}
+
+//merges a node's multiple meshes (with one primitive each) into one mesh with multiple primitives
+void glTF2Exporter::MergeMeshes()
+{
+ for (unsigned int n = 0; n < mAsset->nodes.Size(); ++n) {
+ Ref<Node> node = mAsset->nodes.Get(n);
+
+ unsigned int nMeshes = static_cast<unsigned int>(node->meshes.size());
+
+ //skip if it's 1 or less meshes per node
+ if (nMeshes > 1) {
+ Ref<Mesh> firstMesh = node->meshes.at(0);
+
+ //loop backwards to allow easy removal of a mesh from a node once it's merged
+ for (unsigned int m = nMeshes - 1; m >= 1; --m) {
+ Ref<Mesh> mesh = node->meshes.at(m);
+
+ //append this mesh's primitives to the first mesh's primitives
+ firstMesh->primitives.insert(
+ firstMesh->primitives.end(),
+ mesh->primitives.begin(),
+ mesh->primitives.end()
+ );
+
+ //remove the mesh from the list of meshes
+ unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str());
+
+ //find the presence of the removed mesh in other nodes
+ for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) {
+ Ref<Node> node = mAsset->nodes.Get(nn);
+
+ for (unsigned int mm = 0; mm < node->meshes.size(); ++mm) {
+ Ref<Mesh>& meshRef = node->meshes.at(mm);
+ unsigned int meshIndex = meshRef.GetIndex();
+
+ if (meshIndex == removedIndex) {
+ node->meshes.erase(node->meshes.begin() + mm);
+ } else if (meshIndex > removedIndex) {
+ Ref<Mesh> newMeshRef = mAsset->meshes.Get(meshIndex - 1);
+
+ meshRef = newMeshRef;
+ }
+ }
+ }
+ }
+
+ //since we were looping backwards, reverse the order of merged primitives to their original order
+ std::reverse(firstMesh->primitives.begin() + 1, firstMesh->primitives.end());
+ }
+ }
+}
+
+/*
+ * Export the root node of the node hierarchy.
+ * Calls ExportNode for all children.
+ */
+unsigned int glTF2Exporter::ExportNodeHierarchy(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);
+ node->children.push_back(mAsset->nodes.Get(idx));
+ }
+
+ return node.GetIndex();
+}
+
+/*
+ * Export node and recursively calls ExportNode for all children.
+ * Since these nodes are not the root node, we also export the parent Ref<Node>
+ */
+unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref<Node>& parent)
+{
+ std::string name = mAsset->FindUniqueID(n->mName.C_Str(), "node");
+ Ref<Node> node = mAsset->nodes.Create(name);
+
+ node->parent = parent;
+ node->name = name;
+
+ 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);
+ node->children.push_back(mAsset->nodes.Get(idx));
+ }
+
+ return node.GetIndex();
+}
+
+
+void glTF2Exporter::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 glTF2Exporter::ExportMetadata()
+{
+ AssetMetadata& asset = mAsset->asset;
+ asset.version = "2.0";
+
+ char buffer[256];
+ ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)",
+ aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision());
+
+ asset.generator = buffer;
+}
+
+inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animation>& animRef, Ref<Buffer>& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond)
+{
+ // Loop over the data and check to see if it exactly matches an existing buffer.
+ // If yes, then reference the existing corresponding accessor.
+ // Otherwise, add to the buffer and create a new accessor.
+
+ size_t counts[3] = {
+ nodeChannel->mNumPositionKeys,
+ nodeChannel->mNumScalingKeys,
+ nodeChannel->mNumRotationKeys,
+ };
+ size_t numKeyframes = 1;
+ for (int i = 0; i < 3; ++i) {
+ if (counts[i] > numKeyframes) {
+ numKeyframes = counts[i];
+ }
+ }
+
+ //-------------------------------------------------------
+ // Extract TIME parameter data.
+ // Check if the timeStamps are the same for mPositionKeys, mRotationKeys, and mScalingKeys.
+ if(nodeChannel->mNumPositionKeys > 0) {
+ typedef float TimeType;
+ std::vector<TimeType> timeData;
+ timeData.resize(numKeyframes);
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes;
+ // mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
+ // Check if we have to cast type here. e.g. uint16_t()
+ timeData[i] = static_cast<float>(nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond);
+ }
+
+ Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT);
+ if (timeAccessor) animRef->Parameters.TIME = timeAccessor;
+ }
+
+ //-------------------------------------------------------
+ // Extract translation parameter data
+ if(nodeChannel->mNumPositionKeys > 0) {
+ C_STRUCT aiVector3D* translationData = new aiVector3D[numKeyframes];
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes;
+ translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue;
+ }
+
+ Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+ if ( tranAccessor ) {
+ animRef->Parameters.translation = tranAccessor;
+ }
+ delete[] translationData;
+ }
+
+ //-------------------------------------------------------
+ // Extract scale parameter data
+ if(nodeChannel->mNumScalingKeys > 0) {
+ C_STRUCT aiVector3D* scaleData = new aiVector3D[numKeyframes];
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumScalingKeys / numKeyframes;
+ scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue;
+ }
+
+ Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+ if ( scaleAccessor ) {
+ animRef->Parameters.scale = scaleAccessor;
+ }
+ delete[] scaleData;
+ }
+
+ //-------------------------------------------------------
+ // Extract rotation parameter data
+ if(nodeChannel->mNumRotationKeys > 0) {
+ vec4* rotationData = new vec4[numKeyframes];
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumRotationKeys / numKeyframes;
+ rotationData[i][0] = nodeChannel->mRotationKeys[frameIndex].mValue.x;
+ rotationData[i][1] = nodeChannel->mRotationKeys[frameIndex].mValue.y;
+ rotationData[i][2] = nodeChannel->mRotationKeys[frameIndex].mValue.z;
+ rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w;
+ }
+
+ Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+ if ( rotAccessor ) {
+ animRef->Parameters.rotation = rotAccessor;
+ }
+ delete[] rotationData;
+ }
+}
+
+void glTF2Exporter::ExportAnimations()
+{
+ Ref<Buffer> bufferRef = mAsset->buffers.Get(unsigned (0));
+
+ for (unsigned int i = 0; i < mScene->mNumAnimations; ++i) {
+ const aiAnimation* anim = mScene->mAnimations[i];
+
+ std::string nameAnim = "anim";
+ if (anim->mName.length > 0) {
+ nameAnim = anim->mName.C_Str();
+ }
+
+ for (unsigned int channelIndex = 0; channelIndex < anim->mNumChannels; ++channelIndex) {
+ const aiNodeAnim* nodeChannel = anim->mChannels[channelIndex];
+
+ // It appears that assimp stores this type of animation as multiple animations.
+ // where each aiNodeAnim in mChannels animates a specific node.
+ std::string name = nameAnim + "_" + to_string(channelIndex);
+ name = mAsset->FindUniqueID(name, "animation");
+ Ref<Animation> animRef = mAsset->animations.Create(name);
+
+ // Parameters
+ ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, static_cast<float>(anim->mTicksPerSecond));
+
+ for (unsigned int j = 0; j < 3; ++j) {
+ std::string channelType;
+ int channelSize;
+ switch (j) {
+ case 0:
+ channelType = "rotation";
+ channelSize = nodeChannel->mNumRotationKeys;
+ break;
+ case 1:
+ channelType = "scale";
+ channelSize = nodeChannel->mNumScalingKeys;
+ break;
+ case 2:
+ channelType = "translation";
+ channelSize = nodeChannel->mNumPositionKeys;
+ break;
+ }
+
+ if (channelSize < 1) { continue; }
+
+ Animation::AnimChannel tmpAnimChannel;
+ Animation::AnimSampler tmpAnimSampler;
+
+ tmpAnimChannel.sampler = static_cast<int>(animRef->Samplers.size());
+ tmpAnimChannel.target.path = channelType;
+ tmpAnimSampler.output = channelType;
+ tmpAnimSampler.id = name + "_" + channelType;
+
+ tmpAnimChannel.target.node = mAsset->nodes.Get(nodeChannel->mNodeName.C_Str());
+
+ tmpAnimSampler.input = "TIME";
+ tmpAnimSampler.interpolation = "LINEAR";
+
+ animRef->Channels.push_back(tmpAnimChannel);
+ animRef->Samplers.push_back(tmpAnimSampler);
+ }
+
+ }
+
+ // Assimp documentation staes this is not used (not implemented)
+ // for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) {
+ // const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex];
+ // }
+
+ } // End: for-loop mNumAnimations
+}
+
+
+#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/glTF2Exporter.h b/src/3rdparty/assimp/code/glTF2Exporter.h
new file mode 100644
index 000000000..e9f7c113a
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2Exporter.h
@@ -0,0 +1,134 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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_GLTF2EXPORTER_H_INC
+#define AI_GLTF2EXPORTER_H_INC
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#include <assimp/types.h>
+#include <assimp/material.h>
+
+#include <sstream>
+#include <vector>
+#include <map>
+#include <memory>
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+
+namespace glTF2
+{
+ template<class T>
+ class Ref;
+
+ class Asset;
+ struct TexProperty;
+ struct TextureInfo;
+ struct NormalTextureInfo;
+ struct OcclusionTextureInfo;
+ struct Node;
+ struct Texture;
+
+ // Vec/matrix types, as raw float arrays
+ typedef float (vec3)[3];
+ typedef float (vec4)[4];
+}
+
+namespace Assimp
+{
+ class IOSystem;
+ class IOStream;
+ class ExportProperties;
+
+ // ------------------------------------------------------------------------------------------------
+ /** Helper class to export a given scene to an glTF file. */
+ // ------------------------------------------------------------------------------------------------
+ class glTF2Exporter
+ {
+ public:
+ /// Constructor for a specific scene to export
+ glTF2Exporter(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;
+
+ std::shared_ptr<glTF2::Asset> mAsset;
+
+ std::vector<unsigned char> mBodyData;
+
+ void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
+
+ void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
+ void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
+ void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
+ void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
+ void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
+ void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
+ void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
+ aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
+ aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
+ void ExportMetadata();
+ void ExportMaterials();
+ void ExportMeshes();
+ void MergeMeshes();
+ unsigned int ExportNodeHierarchy(const aiNode* n);
+ unsigned int ExportNode(const aiNode* node, glTF2::Ref<glTF2::Node>& parent);
+ void ExportScene();
+ void ExportAnimations();
+ };
+
+}
+
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // AI_GLTF2EXPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/glTF2Importer.cpp b/src/3rdparty/assimp/code/glTF2Importer.cpp
new file mode 100644
index 000000000..94e5ca3f1
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2Importer.cpp
@@ -0,0 +1,694 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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 "glTF2Importer.h"
+#include "StringComparison.h"
+#include "StringUtils.h"
+
+#include <assimp/Importer.hpp>
+#include <assimp/scene.h>
+#include <assimp/ai_assert.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
+
+#include <memory>
+
+#include "MakeVerboseFormat.h"
+
+#include "glTF2Asset.h"
+// This is included here so WriteLazyDict<T>'s definition is found.
+#include "glTF2AssetWriter.h"
+#include <rapidjson/document.h>
+#include <rapidjson/rapidjson.h>
+
+using namespace Assimp;
+using namespace glTF2;
+
+
+//
+// glTF2Importer
+//
+
+static const aiImporterDesc desc = {
+ "glTF2 Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+ 0,
+ 0,
+ 0,
+ 0,
+ "gltf glb"
+};
+
+glTF2Importer::glTF2Importer()
+: BaseImporter()
+, meshOffsets()
+, embeddedTexIdxs()
+, mScene( NULL ) {
+ // empty
+}
+
+glTF2Importer::~glTF2Importer() {
+ // empty
+}
+
+const aiImporterDesc* glTF2Importer::GetInfo() const
+{
+ return &desc;
+}
+
+bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+{
+ const std::string &extension = GetExtension(pFile);
+
+ if (extension != "gltf" && extension != "glb")
+ return false;
+
+ if (checkSig && pIOHandler) {
+ glTF2::Asset asset(pIOHandler);
+ try {
+ asset.Load(pFile, extension == "glb");
+ std::string version = asset.asset.version;
+ return !version.empty() && version[0] == '2';
+ } catch (...) {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+
+//static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
+//{
+// out.r = v[0]; out.g = v[1]; out.b = v[2];
+//}
+
+static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
+{
+ out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
+}
+
+/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
+{
+ out.r = v[0]; out.g = v[1]; out.b = v[2];
+}*/
+
+static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
+{
+ out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
+}
+
+static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
+{
+ out.x = v[0]; out.y = v[1]; out.z = v[2];
+}
+
+static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
+{
+ out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
+}
+
+static void CopyValue(const glTF2::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(Asset& /*r*/, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
+{
+ aiColor4D col;
+ CopyValue(prop, col);
+ mat->AddProperty(&col, 1, pKey, type, idx);
+}
+
+inline void SetMaterialColorProperty(Asset& /*r*/, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
+{
+ aiColor4D col;
+ CopyValue(prop, col);
+ mat->AddProperty(&col, 1, pKey, type, idx);
+}
+
+inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0)
+{
+ if (prop.texture && 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(texType, texSlot));
+ mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot);
+
+ if (prop.texture->sampler) {
+ Ref<Sampler> sampler = prop.texture->sampler;
+
+ aiString name(sampler->name);
+ aiString id(sampler->id);
+
+ mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
+ mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
+
+ mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
+ mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
+
+ if (sampler->magFilter != SamplerMagFilter::UNSET) {
+ mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot));
+ }
+
+ if (sampler->minFilter != SamplerMinFilter::UNSET) {
+ mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot));
+ }
+ }
+ }
+}
+
+void glTF2Importer::ImportMaterials(glTF2::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.name);
+
+ aimat->AddProperty(&str, AI_MATKEY_NAME);
+ }
+
+ SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
+ SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR);
+
+ SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
+ SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE);
+
+ SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
+
+ aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR);
+ aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR);
+
+ float roughnessAsShininess = (1 - mat.pbrMetallicRoughness.roughnessFactor) * 1000;
+ aimat->AddProperty(&roughnessAsShininess, 1, AI_MATKEY_SHININESS);
+
+ SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS);
+ SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP);
+ SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE);
+ SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
+
+ aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
+
+ aiString alphaMode(mat.alphaMode);
+ aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE);
+ aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF);
+
+ //pbrSpecularGlossiness
+ if (mat.pbrSpecularGlossiness.isPresent) {
+ PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
+
+ aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS);
+ SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
+ SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR);
+
+ float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f;
+ aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS);
+ aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR);
+
+ SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE);
+
+ SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR);
+ }
+ }
+}
+
+
+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;
+}
+
+#ifdef ASSIMP_BUILD_DEBUG
+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;
+}
+#endif // ASSIMP_BUILD_DEBUG
+
+void glTF2Importer::ImportMeshes(glTF2::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.name.empty() ? mesh.id : mesh.name;
+
+ 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);
+
+ // only extract tangents if normals are present
+ if (attr.tangent.size() > 0 && attr.tangent[0]) {
+ // generate bitangents from normals and tangents according to spec
+ struct Tangent
+ {
+ aiVector3D xyz;
+ ai_real w;
+ } *tangents = nullptr;
+
+ attr.tangent[0]->ExtractData(tangents);
+
+ aim->mTangents = new aiVector3D[aim->mNumVertices];
+ aim->mBitangents = new aiVector3D[aim->mNumVertices];
+
+ for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
+ aim->mTangents[i] = tangents[i].xyz;
+ aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w;
+ }
+
+ delete tangents;
+ }
+ }
+
+ 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 glTF2Importer::ImportCameras(glTF2::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.cameraProperties.perspective.aspectRatio;
+ aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * aicam->mAspect;
+ aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar;
+ aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear;
+ }
+ else {
+ // assimp does not support orthographic cameras
+ }
+ }
+}
+
+aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr)
+{
+ Node& node = *ptr;
+
+ std::string nameOrId = node.name.empty() ? node.id : node.name;
+
+ aiNode* ainode = new aiNode(nameOrId);
+
+ 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 = matrix * t;
+ }
+
+ if (node.rotation.isPresent) {
+ aiQuaternion rot;
+ CopyValue(node.rotation.value, rot);
+ matrix = matrix * aiMatrix4x4(rot.GetMatrix());
+ }
+
+ if (node.scale.isPresent) {
+ aiVector3D scal(1.f);
+ CopyValue(node.scale.value, scal);
+ aiMatrix4x4 s;
+ aiMatrix4x4::Scaling(scal, s);
+ matrix = matrix * s;
+ }
+ }
+
+ 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;
+ }
+
+ return ainode;
+}
+
+void glTF2Importer::ImportNodes(glTF2::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 glTF2Importer::ImportEmbeddedTextures(glTF2::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 glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
+
+ this->mScene = pScene;
+
+ // read the asset file
+ glTF2::Asset asset(pIOHandler);
+ asset.Load(pFile, GetExtension(pFile) == "glb");
+
+ //
+ // Copy the data out
+ //
+
+ ImportEmbeddedTextures(asset);
+ ImportMaterials(asset);
+
+ ImportMeshes(asset);
+
+ ImportCameras(asset);
+
+ ImportNodes(asset);
+
+ // TODO: it does not split the loaded vertices, should it?
+ //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ 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/glTF2Importer.h b/src/3rdparty/assimp/code/glTF2Importer.h
new file mode 100644
index 000000000..6be7131d1
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTF2Importer.h
@@ -0,0 +1,91 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+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_GLTF2IMPORTER_H_INC
+#define AI_GLTF2IMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include <assimp/DefaultIOSystem.h>
+
+struct aiNode;
+
+
+namespace glTF2
+{
+ class Asset;
+}
+
+namespace Assimp {
+
+/**
+ * Load the glTF2 format.
+ * https://github.com/KhronosGroup/glTF/tree/master/specification
+ */
+class glTF2Importer : public BaseImporter{
+public:
+ glTF2Importer();
+ virtual ~glTF2Importer();
+ 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(glTF2::Asset& a);
+ void ImportMaterials(glTF2::Asset& a);
+ void ImportMeshes(glTF2::Asset& a);
+ void ImportCameras(glTF2::Asset& a);
+ void ImportLights(glTF2::Asset& a);
+ void ImportNodes(glTF2::Asset& a);
+
+};
+
+} // Namespace assimp
+
+#endif // AI_GLTF2IMPORTER_H_INC
+
diff --git a/src/3rdparty/assimp/code/glTFAsset.h b/src/3rdparty/assimp/code/glTFAsset.h
index f2d375c6b..0c3de16a5 100644
--- a/src/3rdparty/assimp/code/glTFAsset.h
+++ b/src/3rdparty/assimp/code/glTFAsset.h
@@ -1,8 +1,9 @@
-/*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,11 +46,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* KHR_binary_glTF: full
* KHR_materials_common: full
*/
-#ifndef glTFAsset_H_INC
-#define glTFAsset_H_INC
+#ifndef GLTFASSET_H_INC
+#define GLTFASSET_H_INC
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include <map>
#include <string>
+#include <list>
#include <vector>
#include <algorithm>
#include <stdexcept>
@@ -61,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_API
# include <memory>
-# include "DefaultIOSystem.h"
+# include <assimp/DefaultIOSystem.h>
# include "ByteSwapper.h"
#else
# include <memory>
@@ -127,6 +131,7 @@ namespace glTF
struct BufferView; // here due to cross-reference
struct Texture;
struct Light;
+ struct Skin;
// Vec/matrix types, as raw float arrays
@@ -208,6 +213,7 @@ namespace glTF
ComponentType_UNSIGNED_BYTE = 5121,
ComponentType_SHORT = 5122,
ComponentType_UNSIGNED_SHORT = 5123,
+ ComponentType_UNSIGNED_INT = 5125,
ComponentType_FLOAT = 5126
};
@@ -218,13 +224,17 @@ namespace glTF
case ComponentType_UNSIGNED_SHORT:
return 2;
+ case ComponentType_UNSIGNED_INT:
case ComponentType_FLOAT:
return 4;
- //case Accessor::ComponentType_BYTE:
- //case Accessor::ComponentType_UNSIGNED_BYTE:
- default:
+ case ComponentType_BYTE:
+ case ComponentType_UNSIGNED_BYTE:
return 1;
+ default:
+ std::string err = "GLTF: Unsupported Component Type ";
+ err += t;
+ throw DeadlyImportError(err);
}
}
@@ -235,6 +245,32 @@ namespace glTF
BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
};
+ //! Values for the Sampler::magFilter field
+ enum SamplerMagFilter
+ {
+ SamplerMagFilter_Nearest = 9728,
+ SamplerMagFilter_Linear = 9729
+ };
+
+ //! Values for the Sampler::minFilter field
+ enum SamplerMinFilter
+ {
+ SamplerMinFilter_Nearest = 9728,
+ SamplerMinFilter_Linear = 9729,
+ SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
+ SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
+ SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
+ SamplerMinFilter_Linear_Mipmap_Linear = 9987
+ };
+
+ //! Values for the Sampler::wrapS and Sampler::wrapT field
+ enum SamplerWrap
+ {
+ SamplerWrap_Clamp_To_Edge = 33071,
+ SamplerWrap_Mirrored_Repeat = 33648,
+ SamplerWrap_Repeat = 10497
+ };
+
//! Values for the Texture::format and Texture::internalFormat fields
enum TextureFormat
{
@@ -357,19 +393,17 @@ namespace glTF
virtual ~Object() {}
//! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
- static const char* TranslateId(Asset& r, const char* id)
+ 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.
+ //! 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)
@@ -378,8 +412,8 @@ namespace glTF
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.
+ 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();
@@ -430,53 +464,117 @@ namespace glTF
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);
+ {
+ /********************* Types *********************/
+ public:
+
+ enum Type
+ {
+ Type_arraybuffer,
+ Type_text
+ };
+
+ /// \struct SEncodedRegion
+ /// Descriptor of encoded region in "bufferView".
+ struct SEncodedRegion
+ {
+ const size_t Offset;///< Offset from begin of "bufferView" to encoded region, in bytes.
+ const size_t EncodedData_Length;///< Size of encoded region, in bytes.
+ uint8_t* const DecodedData;///< Cached encoded data.
+ const size_t DecodedData_Length;///< Size of decoded region, in bytes.
+ const std::string ID;///< ID of the region.
+
+ /// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
+ /// Constructor.
+ /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
+ /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pDecodedData - pointer to decoded data array.
+ /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pID - ID of the region.
+ SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
+ : Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID)
+ {}
+
+ /// \fn ~SEncodedRegion()
+ /// Destructor.
+ ~SEncodedRegion() { delete [] DecodedData; }
+ };
+
+ /******************* Variables *******************/
+
+ //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;
+
+ /// \var EncodedRegion_Current
+ /// Pointer to currently active encoded region.
+ /// Why not decoding all regions at once and not to set one buffer with decoded data?
+ /// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded
+ /// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But
+ /// offset is counted for another regions is encoded.
+ /// Example. You have two meshes. For every of it you have 4 bytes of data. That data compressed to 2 bytes. So, you have buffer with encoded data:
+ /// M1_E0, M1_E1, M2_E0, M2_E1.
+ /// After decoding you'll get:
+ /// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3.
+ /// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like
+ /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4}
+ /// but in real life you'll get:
+ /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
+ /// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
+ /// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished
+ /// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
+ ///
+ /// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
+ /// exporter and importer. And, thanks to such way, there is no need to load whole file into memory.
+ SEncodedRegion* EncodedRegion_Current;
+
+ private:
+
+ shared_ptr<uint8_t> mData; //!< Pointer to the data
+ bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
+
+ /// \var EncodedRegion_List
+ /// List of encoded regions.
+ std::list<SEncodedRegion*> EncodedRegion_List;
+
+ /******************* Functions *******************/
+
+ public:
+
+ Buffer();
+ ~Buffer();
+
+ void Read(Value& obj, Asset& r);
bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0);
+ /// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
+ /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
+ /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
+ /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pDecodedData - pointer to decoded data array.
+ /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
+ /// \param [in] pID - ID of the region.
+ void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID);
+
+ /// \fn void EncodedRegion_SetCurrent(const std::string& pID)
+ /// Select current encoded region by ID. \sa EncodedRegion_Current.
+ /// \param [in] pID - ID of the region.
+ void EncodedRegion_SetCurrent(const std::string& pID);
+
+ /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
+ /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
+ /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
+ /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
+ /// \param [in] pReplace_Data - pointer to array with new data for buffer.
+ /// \param [in] pReplace_Count - count of bytes in new data.
+ /// \return true - if successfully replaced, false if input arguments is out of range.
+ bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count);
+
size_t AppendData(uint8_t* data, size_t length);
void Grow(size_t amount);
@@ -489,10 +587,12 @@ namespace glTF
bool IsSpecial() const
{ return mIsSpecial; }
+ std::string GetURI()
+ { return std::string(this->id) + ".bin"; }
+
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
{
@@ -502,11 +602,9 @@ namespace glTF
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
@@ -631,10 +729,86 @@ namespace glTF
Ref<Material> material;
};
+ /// \struct SExtension
+ /// Extension used for mesh.
+ struct SExtension
+ {
+ /// \enum EType
+ /// Type of extension.
+ enum EType
+ {
+ #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ Compression_Open3DGC,///< Compression of mesh data using Open3DGC algorithm.
+ #endif
+
+ Unknown
+ };
+
+ EType Type;///< Type of extension.
+
+ /// \fn SExtension
+ /// Constructor.
+ /// \param [in] pType - type of extension.
+ SExtension(const EType pType)
+ : Type(pType)
+ {}
+
+ virtual ~SExtension() {
+ // empty
+ }
+ };
+
+ #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ /// \struct SCompression_Open3DGC
+ /// Compression of mesh data using Open3DGC algorithm.
+ struct SCompression_Open3DGC : public SExtension
+ {
+ using SExtension::Type;
+
+ std::string Buffer;///< ID of "buffer" used for storing compressed data.
+ size_t Offset;///< Offset in "bufferView" where compressed data are stored.
+ size_t Count;///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type".
+ bool Binary;///< If true then "binary" mode is used for coding, if false - "ascii" mode.
+ size_t IndicesCount;///< Count of indices in mesh.
+ size_t VerticesCount;///< Count of vertices in mesh.
+ // AttribType::Value Type;///< Is always "SCALAR".
+ // ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121).
+
+ /// \fn SCompression_Open3DGC
+ /// Constructor.
+ SCompression_Open3DGC()
+ : SExtension(Compression_Open3DGC) {
+ // empty
+ }
+
+ virtual ~SCompression_Open3DGC() {
+ // empty
+ }
+ };
+ #endif
+
std::vector<Primitive> primitives;
+ std::list<SExtension*> Extension;///< List of extensions used in mesh.
Mesh() {}
- void Read(Value& obj, Asset& r);
+
+ /// \fn ~Mesh()
+ /// Destructor.
+ ~Mesh() { for(std::list<SExtension*>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { delete *it; }; }
+
+ /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
+ /// Get mesh data from JSON-object and place them to root asset.
+ /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
+ /// \param [out] pAsset_Root - reference to root assed where data will be stored.
+ void Read(Value& pJSON_Object, Asset& pAsset_Root);
+
+ #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ /// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
+ /// Decode part of "buffer" which encoded with Open3DGC algorithm.
+ /// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
+ /// \param [out] pAsset_Root - reference to root assed where data will be stored.
+ void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root);
+ #endif
};
struct Node : public Object
@@ -650,6 +824,12 @@ namespace glTF
Ref<Camera> camera;
Ref<Light> light;
+ std::vector< Ref<Node> > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
+ Ref<Skin> skin; //!< The ID of the skin referenced by this node.
+ std::string jointName; //!< Name used when this node is a joint in a skin.
+
+ Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
+
Node() {}
void Read(Value& obj, Asset& r);
};
@@ -663,8 +843,14 @@ namespace glTF
struct Sampler : public Object
{
+ SamplerMagFilter magFilter; //!< The texture magnification filter. (required)
+ SamplerMinFilter minFilter; //!< The texture minification filter. (required)
+ SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
+ SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
+
Sampler() {}
void Read(Value& obj, Asset& r);
+ void SetDefaults();
};
struct Scene : public Object
@@ -683,6 +869,11 @@ namespace glTF
struct Skin : public Object
{
+ Nullable<mat4> bindShapeMatrix; //!< Floating-point 4x4 transformation matrix stored in column-major order.
+ Ref<Accessor> inverseBindMatrices; //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
+ std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
+ std::string name; //!< The user-defined name of this object.
+
Skin() {}
void Read(Value& obj, Asset& r);
};
@@ -711,8 +902,8 @@ namespace glTF
//! 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)
+ Ref<Sampler> sampler; //!< 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)
@@ -753,6 +944,44 @@ namespace glTF
void SetDefaults();
};
+ struct Animation : public Object
+ {
+ struct AnimSampler {
+ std::string id; //!< The ID of this sampler.
+ std::string input; //!< The ID of a parameter in this animation to use as key-frame input.
+ std::string interpolation; //!< Type of interpolation algorithm to use between key-frames.
+ std::string output; //!< The ID of a parameter in this animation to use as key-frame output.
+ };
+
+ struct AnimChannel {
+ std::string sampler; //!< The ID of one sampler present in the containing animation's samplers property.
+
+ struct AnimTarget {
+ Ref<Node> id; //!< The ID of the node to animate.
+ std::string path; //!< The name of property of the node to animate ("translation", "rotation", or "scale").
+ } target;
+ };
+
+ struct AnimParameters {
+ Ref<Accessor> TIME; //!< Accessor reference to a buffer storing a array of floating point scalar values.
+ Ref<Accessor> rotation; //!< Accessor reference to a buffer storing a array of four-component floating-point vectors.
+ Ref<Accessor> scale; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
+ Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
+ };
+
+ // AnimChannel Channels[3]; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
+ // AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
+ // AnimSampler Samplers[3]; //!< The parameterized inputs representing the key-frame data.
+
+ std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
+ AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
+ std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
+
+ Animation() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
//! Base class for LazyDict that acts as an interface
class LazyDictBase
{
@@ -772,7 +1001,7 @@ namespace glTF
//! (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
@@ -785,7 +1014,7 @@ namespace glTF
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
+ Dict mObjsById; //! The read objects accessible 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
@@ -805,6 +1034,7 @@ namespace glTF
Ref<T> Get(const char* id);
Ref<T> Get(unsigned int i);
+ Ref<T> Get(const std::string& pID) { return Get(pID.c_str()); }
Ref<T> Create(const char* id);
Ref<T> Create(const std::string& id)
@@ -830,13 +1060,13 @@ namespace glTF
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)
+ std::string version; //!< The glTF format version (should be 1.0)
void Read(Document& doc);
-
+
AssetMetadata()
: premultipliedAlpha(false)
- , version(0)
+ , version("")
{
}
};
@@ -899,10 +1129,10 @@ namespace glTF
LazyDict<Mesh> meshes;
LazyDict<Node> nodes;
//LazyDict<Program> programs;
- //LazyDict<Sampler> samplers;
+ LazyDict<Sampler> samplers;
LazyDict<Scene> scenes;
//LazyDict<Shader> shaders;
- //LazyDict<Skin> skins;
+ LazyDict<Skin> skins;
//LazyDict<Technique> techniques;
LazyDict<Texture> textures;
@@ -924,10 +1154,10 @@ namespace glTF
, meshes (*this, "meshes")
, nodes (*this, "nodes")
//, programs (*this, "programs")
- //, samplers (*this, "samplers")
+ , samplers (*this, "samplers")
, scenes (*this, "scenes")
//, shaders (*this, "shaders")
- //, skins (*this, "skins")
+ , skins (*this, "skins")
//, techniques (*this, "techniques")
, textures (*this, "textures")
, lights (*this, "lights", "KHR_materials_common")
@@ -961,4 +1191,6 @@ namespace glTF
// Include the implementation of the methods
#include "glTFAsset.inl"
-#endif
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // GLTFASSET_H_INC
diff --git a/src/3rdparty/assimp/code/glTFAsset.inl b/src/3rdparty/assimp/code/glTFAsset.inl
index d52c825c4..a5d74f5a0 100644
--- a/src/3rdparty/assimp/code/glTFAsset.inl
+++ b/src/3rdparty/assimp/code/glTFAsset.inl
@@ -1,8 +1,9 @@
-/*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -39,11 +40,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "StringUtils.h"
+#include <iomanip>
+
+// Header files, Assimp
+#include <assimp/DefaultLogger.hpp>
+
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ // Header files, Open3DGC.
+# include <Open3DGC/o3dgcSC3DMCDecoder.h>
+#endif
+
+using namespace Assimp;
namespace glTF {
namespace {
-
+
//
// JSON Value reading helpers
//
@@ -52,7 +64,7 @@ namespace {
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;
}};
@@ -60,7 +72,7 @@ namespace {
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) {
@@ -117,6 +129,12 @@ namespace {
return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
}
+ inline Value* FindNumber(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
+ }
+
inline Value* FindArray(Value& val, const char* id)
{
Value::MemberIterator it = val.FindMember(id);
@@ -241,9 +259,14 @@ Ref<T> LazyDict<T>::Create(const char* id)
inline Buffer::Buffer()
-: byteLength(0), type(Type_arraybuffer), mIsSpecial(false)
+ : byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false)
{ }
+inline Buffer::~Buffer()
+{
+ for(SEncodedRegion* reg : EncodedRegion_List) delete reg;
+}
+
inline const char* Buffer::TranslateId(Asset& r, const char* id)
{
// Compatibility with old spec
@@ -277,14 +300,14 @@ inline void Buffer::Read(Value& obj, Asset& r)
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));
+ throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) +
+ " bytes, but found " + 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));
+ throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) +
+ " bytes, but found " + to_string(dataURI.dataLength));
}
this->mData.reset(new uint8_t[dataURI.dataLength]);
@@ -293,11 +316,13 @@ inline void Buffer::Read(Value& obj, Asset& r)
}
else { // Local file
if (byteLength > 0) {
- IOStream* file = r.OpenFile(uri, "rb");
+ std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : "";
+
+ IOStream* file = r.OpenFile(dir + uri, "rb");
if (file) {
bool ok = LoadFromStream(*file, byteLength);
delete file;
-
+
if (!ok)
throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" );
}
@@ -316,7 +341,7 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO
stream.Seek(baseOffset, aiOrigin_SET);
}
- mData.reset(new uint8_t[byteLength]);
+ mData.reset(new uint8_t[byteLength], std::default_delete<uint8_t[]>());
if (stream.Read(mData.get(), byteLength, 1) != 1) {
return false;
@@ -324,6 +349,79 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO
return true;
}
+inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
+{
+ // Check pointer to data
+ if(pDecodedData == nullptr) throw DeadlyImportError("GLTF: for marking encoded region pointer to decoded data must be provided.");
+
+ // Check offset
+ if(pOffset > byteLength)
+ {
+ const uint8_t val_size = 32;
+
+ char val[val_size];
+
+ ai_snprintf(val, val_size, "%llu", (long long)pOffset);
+ throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region.");
+ }
+
+ // Check length
+ if((pOffset + pEncodedData_Length) > byteLength)
+ {
+ const uint8_t val_size = 64;
+
+ char val[val_size];
+
+ ai_snprintf(val, val_size, "%llu, %llu", (long long)pOffset, (long long)pEncodedData_Length);
+ throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range.");
+ }
+
+ // Add new region
+ EncodedRegion_List.push_back(new SEncodedRegion(pOffset, pEncodedData_Length, pDecodedData, pDecodedData_Length, pID));
+ // And set new value for "byteLength"
+ byteLength += (pDecodedData_Length - pEncodedData_Length);
+}
+
+inline void Buffer::EncodedRegion_SetCurrent(const std::string& pID)
+{
+ if((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return;
+
+ for(SEncodedRegion* reg : EncodedRegion_List)
+ {
+ if(reg->ID == pID)
+ {
+ EncodedRegion_Current = reg;
+
+ return;
+ }
+
+ }
+
+ throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found.");
+}
+
+inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
+{
+const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count;
+
+uint8_t* new_data;
+
+ if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false;
+
+ new_data = new uint8_t[new_data_size];
+ // Copy data which place before replacing part.
+ memcpy(new_data, mData.get(), pBufferData_Offset);
+ // Copy new data.
+ memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count);
+ // Copy data which place after replacing part.
+ memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset);
+ // Apply new data
+ mData.reset(new_data);
+ byteLength = new_data_size;
+
+ return true;
+}
+
inline size_t Buffer::AppendData(uint8_t* data, size_t length)
{
size_t offset = this->byteLength;
@@ -341,6 +439,9 @@ inline void Buffer::Grow(size_t amount)
byteLength += amount;
}
+//
+// struct BufferView
+//
inline void BufferView::Read(Value& obj, Asset& r)
{
@@ -348,12 +449,14 @@ inline void BufferView::Read(Value& obj, Asset& r)
if (bufferId) {
buffer = r.buffers.Get(bufferId);
}
-
+
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
byteLength = MemberOrDefault(obj, "byteLength", 0u);
}
-
+//
+// struct Accessor
+//
inline void Accessor::Read(Value& obj, Asset& r)
{
@@ -393,7 +496,18 @@ inline uint8_t* Accessor::GetPointer()
if (!basePtr) return 0;
size_t offset = byteOffset + bufferView->byteOffset;
- return basePtr + offset;
+
+ // Check if region is encoded.
+ if(bufferView->buffer->EncodedRegion_Current != nullptr)
+ {
+ const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset;
+ const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length;
+
+ if((offset >= begin) && (offset < end))
+ return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin];
+ }
+
+ return basePtr + offset;
}
namespace {
@@ -495,7 +609,7 @@ inline Image::Image()
inline void Image::Read(Value& obj, Asset& r)
{
- // Check for extensions first (to detect binary embedded data)
+ // 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")) {
@@ -561,12 +675,35 @@ inline void Image::SetData(uint8_t* data, size_t length, Asset& r)
}
}
+inline void Sampler::Read(Value& obj, Asset& /*r*/)
+{
+ SetDefaults();
+
+ ReadMember(obj, "magFilter", magFilter);
+ ReadMember(obj, "minFilter", minFilter);
+ ReadMember(obj, "wrapS", wrapS);
+ ReadMember(obj, "wrapT", wrapT);
+}
+
+inline void Sampler::SetDefaults()
+{
+ magFilter = SamplerMagFilter_Linear;
+ minFilter = SamplerMinFilter_Linear;
+ wrapS = SamplerWrap_Repeat;
+ wrapT = SamplerWrap_Repeat;
+}
+
inline void Texture::Read(Value& obj, Asset& r)
{
const char* sourcestr;
if (ReadMember(obj, "source", sourcestr)) {
source = r.images.Get(sourcestr);
}
+
+ const char* samplerstr;
+ if (ReadMember(obj, "sampler", samplerstr)) {
+ sampler = r.samplers.Get(samplerstr);
+ }
}
namespace {
@@ -592,6 +729,7 @@ inline void Material::Read(Value& material, Asset& r)
ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
ReadMaterialProperty(r, *values, "specular", this->specular);
+ ReadMember(*values, "transparency", transparency);
ReadMember(*values, "shininess", shininess);
}
@@ -676,9 +814,10 @@ namespace {
}
}
-inline void Mesh::Read(Value& obj, Asset& r)
-{
- if (Value* primitives = FindArray(obj, "primitives")) {
+inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
+{
+ /****************** Mesh primitives ******************/
+ if (Value* primitives = FindArray(pJSON_Object, "primitives")) {
this->primitives.resize(primitives->Size());
for (unsigned int i = 0; i < primitives->Size(); ++i) {
Value& primitive = (*primitives)[i];
@@ -698,24 +837,263 @@ inline void Mesh::Read(Value& obj, Asset& r)
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());
+ (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetString());
}
}
}
if (Value* indices = FindString(primitive, "indices")) {
- prim.indices = r.accessors.Get(indices->GetString());
+ prim.indices = pAsset_Root.accessors.Get(indices->GetString());
}
if (Value* material = FindString(primitive, "material")) {
- prim.material = r.materials.Get(material->GetString());
+ prim.material = pAsset_Root.materials.Get(material->GetString());
}
}
}
+
+ /****************** Mesh extensions ******************/
+ Value* json_extensions = FindObject(pJSON_Object, "extensions");
+
+ if(json_extensions == nullptr) goto mr_skip_extensions;
+
+ for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); it_memb++)
+ {
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ if(it_memb->name.GetString() == std::string("Open3DGC-compression"))
+ {
+ // Search for compressed data.
+ // Compressed data contain description of part of "buffer" which is encoded. This part must be decoded and
+ // new data will replace old encoded part by request. In fact \"compressedData\" is kind of "accessor" structure.
+ Value* comp_data = FindObject(it_memb->value, "compressedData");
+
+ if(comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\".");
+
+ DefaultLogger::get()->info("GLTF: Decompressing Open3DGC data.");
+
+ /************** Read data from JSON-document **************/
+ #define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \
+ if(!ReadMember(*comp_data, pFieldName, pOut)) \
+ { \
+ throw DeadlyImportError(std::string("GLTF: \"compressedData\" must has \"") + pFieldName + "\"."); \
+ }
+
+ const char* mode_str;
+ const char* type_str;
+ ComponentType component_type;
+ SCompression_Open3DGC* ext_o3dgc = new SCompression_Open3DGC;
+
+ MESH_READ_COMPRESSEDDATA_MEMBER("buffer", ext_o3dgc->Buffer);
+ MESH_READ_COMPRESSEDDATA_MEMBER("byteOffset", ext_o3dgc->Offset);
+ MESH_READ_COMPRESSEDDATA_MEMBER("componentType", component_type);
+ MESH_READ_COMPRESSEDDATA_MEMBER("type", type_str);
+ MESH_READ_COMPRESSEDDATA_MEMBER("count", ext_o3dgc->Count);
+ MESH_READ_COMPRESSEDDATA_MEMBER("mode", mode_str);
+ MESH_READ_COMPRESSEDDATA_MEMBER("indicesCount", ext_o3dgc->IndicesCount);
+ MESH_READ_COMPRESSEDDATA_MEMBER("verticesCount", ext_o3dgc->VerticesCount);
+
+ #undef MESH_READ_COMPRESSEDDATA_MEMBER
+
+ // Check some values
+ if(strcmp(type_str, "SCALAR")) throw DeadlyImportError("GLTF: only \"SCALAR\" type is supported for compressed data.");
+ if(component_type != ComponentType_UNSIGNED_BYTE) throw DeadlyImportError("GLTF: only \"UNSIGNED_BYTE\" component type is supported for compressed data.");
+
+ // Set read/write data mode.
+ if(strcmp(mode_str, "binary") == 0)
+ ext_o3dgc->Binary = true;
+ else if(strcmp(mode_str, "ascii") == 0)
+ ext_o3dgc->Binary = false;
+ else
+ throw DeadlyImportError(std::string("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"") + mode_str + "\".");
+
+ /************************ Decoding ************************/
+ Decode_O3DGC(*ext_o3dgc, pAsset_Root);
+ Extension.push_back(ext_o3dgc);// store info in mesh extensions list.
+ }// if(it_memb->name.GetString() == "Open3DGC-compression")
+ else
+#endif
+ {
+ throw DeadlyImportError(std::string("GLTF: Unknown mesh extension: \"") + it_memb->name.GetString() + "\".");
+ }
+ }// for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++)
+
+mr_skip_extensions:
+
+ return;// After label some operators must be present.
}
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
+{
+typedef unsigned short IndicesType;///< \sa glTFExporter::ExportMeshes.
+
+o3dgc::SC3DMCDecoder<IndicesType> decoder;
+o3dgc::IndexedFaceSet<IndicesType> ifs;
+o3dgc::BinaryStream bstream;
+uint8_t* decoded_data;
+size_t decoded_data_size = 0;
+Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
+
+ // Read data from buffer and place it in BinaryStream for decoder.
+ // Just "Count" because always is used type equivalent to uint8_t.
+ bstream.LoadFromBuffer(&buf->GetPointer()[pCompression_Open3DGC.Offset], static_cast<unsigned long>(pCompression_Open3DGC.Count));
+
+ // After decoding header we can get size of primitives.
+ if(decoder.DecodeHeader(ifs, bstream) != o3dgc::O3DGC_OK) throw DeadlyImportError("GLTF: can not decode Open3DGC header.");
+
+ /****************** Get sizes of arrays and check sizes ******************/
+ // Note. See "Limitations for meshes when using Open3DGC-compression".
+
+ // Indices
+ size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note.
+
+ if(primitives[0].indices->count != size_coordindex)
+ throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + std::to_string(size_coordindex) +
+ ") not equal to uncompressed (" + std::to_string(primitives[0].indices->count) + ").");
+
+ size_coordindex *= sizeof(IndicesType);
+ // Coordinates
+ size_t size_coord = ifs.GetNCoord();// See float attributes note.
+
+ if(primitives[0].attributes.position[0]->count != size_coord)
+ throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + std::to_string(size_coord) +
+ ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.position[0]->count) + ").");
+
+ size_coord *= 3 * sizeof(float);
+ // Normals
+ size_t size_normal = ifs.GetNNormal();// See float attributes note.
+
+ if(primitives[0].attributes.normal[0]->count != size_normal)
+ throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + std::to_string(size_normal) +
+ ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.normal[0]->count) + ").");
+
+ size_normal *= 3 * sizeof(float);
+ // Additional attributes.
+ std::vector<size_t> size_floatattr;
+ std::vector<size_t> size_intattr;
+
+ size_floatattr.resize(ifs.GetNumFloatAttributes());
+ size_intattr.resize(ifs.GetNumIntAttributes());
+
+ decoded_data_size = size_coordindex + size_coord + size_normal;
+ for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++)
+ {
+ // size = number_of_elements * components_per_element * size_of_component.
+ // Note. But as you can see above, at first we are use this variable in meaning "count". After checking count of objects...
+ size_t tval = ifs.GetNFloatAttribute(static_cast<unsigned long>(idx));
+
+ switch(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))
+ {
+ case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
+ // Check situation when encoded data contain texture coordinates but primitive not.
+ if(idx_texcoord < primitives[0].attributes.texcoord.size())
+ {
+ if(primitives[0].attributes.texcoord[idx]->count != tval)
+ throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + std::to_string(tval) +
+ ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.texcoord[idx]->count) + ").");
+
+ idx_texcoord++;
+ }
+ else
+ {
+ ifs.SetNFloatAttribute(static_cast<unsigned long>(idx), 0ul);// Disable decoding this attribute.
+ }
+
+ break;
+ default:
+ throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
+ }
+
+ tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real);// After checking count of objects we can get size of array.
+ size_floatattr[idx] = tval;
+ decoded_data_size += tval;
+ }
+
+ for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++)
+ {
+ // size = number_of_elements * components_per_element * size_of_component. See float attributes note.
+ size_t tval = ifs.GetNIntAttribute(static_cast<unsigned long>(idx));
+ switch( ifs.GetIntAttributeType(static_cast<unsigned long>(idx) ) )
+ {
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
+ break;
+
+ default:
+ throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
+ }
+
+ tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long);// See float attributes note.
+ size_intattr[idx] = tval;
+ decoded_data_size += tval;
+ }
+
+ // Create array for decoded data.
+ decoded_data = new uint8_t[decoded_data_size];
+
+ /****************** Set right array regions for decoder ******************/
+
+ auto get_buf_offset = [](Ref<Accessor>& pAccessor) -> size_t { return pAccessor->byteOffset + pAccessor->bufferView->byteOffset; };
+
+ // Indices
+ ifs.SetCoordIndex((IndicesType* const)(decoded_data + get_buf_offset(primitives[0].indices)));
+ // Coordinates
+ ifs.SetCoord((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.position[0])));
+ // Normals
+ if(size_normal)
+ {
+ ifs.SetNormal((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0])));
+ }
+
+ for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++)
+ {
+ switch(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))
+ {
+ case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
+ if(idx_texcoord < primitives[0].attributes.texcoord.size())
+ {
+ // See above about absent attributes.
+ ifs.SetFloatAttribute(static_cast<unsigned long>(idx), (o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx])));
+ idx_texcoord++;
+ }
+
+ break;
+ default:
+ throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
+ }
+ }
+
+ for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) {
+ switch(ifs.GetIntAttributeType(static_cast<unsigned int>(idx))) {
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
+ case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
+ break;
+
+ // ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
+ default:
+ throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
+ }
+ }
+
+ //
+ // Decode data
+ //
+ if ( decoder.DecodePayload( ifs, bstream ) != o3dgc::O3DGC_OK ) {
+ throw DeadlyImportError( "GLTF: can not decode Open3DGC data." );
+ }
+
+ // Set encoded region for "buffer".
+ buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id);
+ // No. Do not delete "output_data". After calling "EncodedRegion_Mark" bufferView is owner of "output_data".
+ // "delete [] output_data;"
+}
+#endif
-inline void Camera::Read(Value& obj, Asset& r)
+inline void Camera::Read(Value& obj, Asset& /*r*/)
{
type = MemberOrDefault(obj, "type", Camera::Perspective);
@@ -738,7 +1116,7 @@ inline void Camera::Read(Value& obj, Asset& r)
}
}
-inline void Light::Read(Value& obj, Asset& r)
+inline void Light::Read(Value& obj, Asset& /*r*/)
{
SetDefaults();
@@ -798,7 +1176,7 @@ inline void Node::Read(Value& obj, Asset& r)
}
}
-
+
if (Value* matrix = FindArray(obj, "matrix")) {
ReadValue(*matrix, this->matrix);
}
@@ -859,13 +1237,21 @@ inline void Scene::Read(Value& obj, Asset& r)
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* versionString = FindString(*obj, "version")) {
+ version = versionString->GetString();
+ } else if (Value* versionNumber = FindNumber (*obj, "version")) {
+ char buf[4];
+
+ ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
+
+ version = buf;
+ }
if (Value* profile = FindObject(*obj, "profile")) {
ReadMember(*profile, "api", this->profile.api);
@@ -873,16 +1259,8 @@ inline void AssetMetadata::Read(Document& doc)
}
}
- 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);
+ if (version.empty() || version[0] != '1') {
+ throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
}
}
@@ -904,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream)
}
AI_SWAP4(header.version);
- asset.version = header.version;
+ asset.version = to_string(header.version);
if (header.version != 1) {
throw DeadlyImportError("GLTF: Unsupported binary glTF version");
}
@@ -1036,7 +1414,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
#undef CHECK_EXT
}
-inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool absolute)
+inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool /*absolute*/)
{
#ifdef ASSIMP_API
return mIOSystem->Open(path, mode);
@@ -1074,13 +1452,13 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
id = buffer;
it = mUsedIds.find(id);
}
-
+
return id;
}
namespace Util {
- inline
+ inline
bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
if ( NULL == const_uri ) {
return false;
@@ -1264,6 +1642,4 @@ namespace Util {
}
-}
-
-
+} // ns glTF
diff --git a/src/3rdparty/assimp/code/glTFAssetWriter.h b/src/3rdparty/assimp/code/glTFAssetWriter.h
index 370d2c0ab..186d32a15 100644
--- a/src/3rdparty/assimp/code/glTFAssetWriter.h
+++ b/src/3rdparty/assimp/code/glTFAssetWriter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,8 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* KHR_binary_glTF: full
* KHR_materials_common: full
*/
-#ifndef glTFAssetWriter_H_INC
-#define glTFAssetWriter_H_INC
+#ifndef GLTFASSETWRITER_H_INC
+#define GLTFASSETWRITER_H_INC
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include "glTFAsset.h"
@@ -79,6 +82,7 @@ public:
AssetWriter(Asset& asset);
void WriteFile(const char* path);
+ void WriteGLBFile(const char* path);
};
}
@@ -86,4 +90,6 @@ public:
// Include the implementation of the methods
#include "glTFAssetWriter.inl"
-#endif
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // GLTFASSETWRITER_H_INC
diff --git a/src/3rdparty/assimp/code/glTFAssetWriter.inl b/src/3rdparty/assimp/code/glTFAssetWriter.inl
index 595cb8a81..485abc4f6 100644
--- a/src/3rdparty/assimp/code/glTFAssetWriter.inl
+++ b/src/3rdparty/assimp/code/glTFAssetWriter.inl
@@ -1,8 +1,9 @@
-/*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -60,7 +61,16 @@ namespace glTF {
val.PushBack(r[i], al);
}
return val;
- };
+ }
+
+ inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
+ val.SetArray();
+ val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
+ for (unsigned int i = 0; i < r.size(); ++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) {
@@ -72,7 +82,7 @@ namespace glTF {
lst.PushBack(StringRef(v[i]->id), al);
}
obj.AddMember(StringRef(fieldId), lst, al);
- };
+ }
}
@@ -85,18 +95,77 @@ namespace glTF {
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);
+
+ Value vTmpMax, vTmpMin;
+ obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
+ obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
}
inline void Write(Value& obj, Animation& a, AssetWriter& w)
{
+ /****************** Channels *******************/
+ Value channels;
+ channels.SetArray();
+ channels.Reserve(unsigned(a.Channels.size()), w.mAl);
+
+ for (size_t i = 0; i < unsigned(a.Channels.size()); ++i) {
+ Animation::AnimChannel& c = a.Channels[i];
+ Value valChannel;
+ valChannel.SetObject();
+ {
+ valChannel.AddMember("sampler", c.sampler, w.mAl);
+
+ Value valTarget;
+ valTarget.SetObject();
+ {
+ valTarget.AddMember("id", StringRef(c.target.id->id), w.mAl);
+ valTarget.AddMember("path", c.target.path, w.mAl);
+ }
+ valChannel.AddMember("target", valTarget, w.mAl);
+ }
+ channels.PushBack(valChannel, w.mAl);
+ }
+ obj.AddMember("channels", channels, w.mAl);
+ /****************** Parameters *******************/
+ Value valParameters;
+ valParameters.SetObject();
+ {
+ if (a.Parameters.TIME) {
+ valParameters.AddMember("TIME", StringRef(a.Parameters.TIME->id), w.mAl);
+ }
+ if (a.Parameters.rotation) {
+ valParameters.AddMember("rotation", StringRef(a.Parameters.rotation->id), w.mAl);
+ }
+ if (a.Parameters.scale) {
+ valParameters.AddMember("scale", StringRef(a.Parameters.scale->id), w.mAl);
+ }
+ if (a.Parameters.translation) {
+ valParameters.AddMember("translation", StringRef(a.Parameters.translation->id), w.mAl);
+ }
+ }
+ obj.AddMember("parameters", valParameters, w.mAl);
+
+ /****************** Samplers *******************/
+ Value valSamplers;
+ valSamplers.SetObject();
+
+ for (size_t i = 0; i < unsigned(a.Samplers.size()); ++i) {
+ Animation::AnimSampler& s = a.Samplers[i];
+ Value valSampler;
+ valSampler.SetObject();
+ {
+ valSampler.AddMember("input", s.input, w.mAl);
+ valSampler.AddMember("interpolation", s.interpolation, w.mAl);
+ valSampler.AddMember("output", s.output, w.mAl);
+ }
+ valSamplers.AddMember(StringRef(s.id), valSampler, w.mAl);
+ }
+ obj.AddMember("samplers", valSamplers, w.mAl);
}
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:
@@ -105,20 +174,20 @@ namespace glTF {
type = "arraybuffer";
}
- obj.AddMember("byteLength", b.byteLength, w.mAl);
+ obj.AddMember("byteLength", static_cast<uint64_t>(b.byteLength), w.mAl);
obj.AddMember("type", StringRef(type), w.mAl);
- obj.AddMember("uri", Value(dataURI, w.mAl).Move(), w.mAl);
+ obj.AddMember("uri", Value(b.GetURI(), 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("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
+ obj.AddMember("byteLength", static_cast<uint64_t>(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*/, Camera& /*c*/, AssetWriter& /*w*/)
{
}
@@ -174,6 +243,9 @@ namespace glTF {
WriteColorOrTex(v, m.specular, "specular", w.mAl);
WriteColorOrTex(v, m.emission, "emission", w.mAl);
+ if (m.transparent)
+ v.AddMember("transparency", m.transparency, w.mAl);
+
v.AddMember("shininess", m.shininess, w.mAl);
}
obj.AddMember("values", v, w.mAl);
@@ -199,6 +271,60 @@ namespace glTF {
inline void Write(Value& obj, Mesh& m, AssetWriter& w)
{
+ /********************* Name **********************/
+ obj.AddMember("name", m.name, w.mAl);
+
+ /**************** Mesh extensions ****************/
+ if(m.Extension.size() > 0)
+ {
+ Value json_extensions;
+
+ json_extensions.SetObject();
+ for(Mesh::SExtension* ptr_ext : m.Extension)
+ {
+ switch(ptr_ext->Type)
+ {
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ case Mesh::SExtension::EType::Compression_Open3DGC:
+ {
+ Value json_comp_data;
+ Mesh::SCompression_Open3DGC* ptr_ext_comp = (Mesh::SCompression_Open3DGC*)ptr_ext;
+
+ // filling object "compressedData"
+ json_comp_data.SetObject();
+ json_comp_data.AddMember("buffer", ptr_ext_comp->Buffer, w.mAl);
+ json_comp_data.AddMember("byteOffset", ptr_ext_comp->Offset, w.mAl);
+ json_comp_data.AddMember("componentType", 5121, w.mAl);
+ json_comp_data.AddMember("type", "SCALAR", w.mAl);
+ json_comp_data.AddMember("count", ptr_ext_comp->Count, w.mAl);
+ if(ptr_ext_comp->Binary)
+ json_comp_data.AddMember("mode", "binary", w.mAl);
+ else
+ json_comp_data.AddMember("mode", "ascii", w.mAl);
+
+ json_comp_data.AddMember("indicesCount", ptr_ext_comp->IndicesCount, w.mAl);
+ json_comp_data.AddMember("verticesCount", ptr_ext_comp->VerticesCount, w.mAl);
+ // filling object "Open3DGC-compression"
+ Value json_o3dgc;
+
+ json_o3dgc.SetObject();
+ json_o3dgc.AddMember("compressedData", json_comp_data, w.mAl);
+ // add member to object "extensions"
+ json_extensions.AddMember("Open3DGC-compression", json_o3dgc, w.mAl);
+ }
+
+ break;
+#endif
+ default:
+ throw DeadlyImportError("GLTF: Can not write mesh: unknown mesh extension, only Open3DGC is supported.");
+ }// switch(ptr_ext->Type)
+ }// for(Mesh::SExtension* ptr_ext : m.Extension)
+
+ // Add extensions to mesh
+ obj.AddMember("extensions", json_extensions, w.mAl);
+ }// if(m.Extension.size() > 0)
+
+ /****************** Primitives *******************/
Value primitives;
primitives.SetArray();
primitives.Reserve(unsigned(m.primitives.size()), w.mAl);
@@ -231,7 +357,7 @@ namespace glTF {
}
primitives.PushBack(prim, w.mAl);
}
-
+
obj.AddMember("primitives", primitives, w.mAl);
}
@@ -260,16 +386,37 @@ namespace glTF {
AddRefsVector(obj, "children", n.children, w.mAl);
AddRefsVector(obj, "meshes", n.meshes, w.mAl);
+
+ AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
+
+ if (n.skin) {
+ obj.AddMember("skin", Value(n.skin->id, w.mAl).Move(), w.mAl);
+ }
+
+ if (!n.jointName.empty()) {
+ obj.AddMember("jointName", n.jointName, w.mAl);
+ }
}
- inline void Write(Value& obj, Program& b, AssetWriter& w)
+ inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
{
}
inline void Write(Value& obj, Sampler& b, AssetWriter& w)
{
-
+ if (b.wrapS) {
+ obj.AddMember("wrapS", b.wrapS, w.mAl);
+ }
+ if (b.wrapT) {
+ obj.AddMember("wrapT", b.wrapT, w.mAl);
+ }
+ if (b.magFilter) {
+ obj.AddMember("magFilter", b.magFilter, w.mAl);
+ }
+ if (b.minFilter) {
+ obj.AddMember("minFilter", b.minFilter, w.mAl);
+ }
}
inline void Write(Value& scene, Scene& s, AssetWriter& w)
@@ -277,17 +424,35 @@ namespace glTF {
AddRefsVector(scene, "nodes", s.nodes, w.mAl);
}
- inline void Write(Value& obj, Shader& b, AssetWriter& w)
+ inline void Write(Value& /*obj*/, Shader& /*b*/, AssetWriter& /*w*/)
{
}
inline void Write(Value& obj, Skin& b, AssetWriter& w)
{
+ /****************** jointNames *******************/
+ Value vJointNames;
+ vJointNames.SetArray();
+ vJointNames.Reserve(unsigned(b.jointNames.size()), w.mAl);
+
+ for (size_t i = 0; i < unsigned(b.jointNames.size()); ++i) {
+ vJointNames.PushBack(StringRef(b.jointNames[i]->jointName), w.mAl);
+ }
+ obj.AddMember("jointNames", vJointNames, w.mAl);
+
+ if (b.bindShapeMatrix.isPresent) {
+ Value val;
+ obj.AddMember("bindShapeMatrix", MakeValue(val, b.bindShapeMatrix.value, w.mAl).Move(), w.mAl);
+ }
+
+ if (b.inverseBindMatrices) {
+ obj.AddMember("inverseBindMatrices", Value(b.inverseBindMatrices->id, w.mAl).Move(), w.mAl);
+ }
}
- inline void Write(Value& obj, Technique& b, AssetWriter& w)
+ inline void Write(Value& /*obj*/, Technique& /*b*/, AssetWriter& /*w*/)
{
}
@@ -297,9 +462,12 @@ namespace glTF {
if (tex.source) {
obj.AddMember("source", Value(tex.source->id, w.mAl).Move(), w.mAl);
}
+ if (tex.sampler) {
+ obj.AddMember("sampler", Value(tex.sampler->id, w.mAl).Move(), w.mAl);
+ }
}
- inline void Write(Value& obj, Light& b, AssetWriter& w)
+ inline void Write(Value& /*obj*/, Light& /*b*/, AssetWriter& /*w*/)
{
}
@@ -328,39 +496,61 @@ namespace glTF {
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));
+ std::unique_ptr<IOStream> jsonOutFile(mAsset.OpenFile(path, "wt", true));
- if (outfile == 0) {
+ if (jsonOutFile == 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;
+
+ PrettyWriter<StringBuffer> writer(docBuffer);
+ mDoc.Accept(writer);
+
+ if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
+ throw DeadlyExportError("Failed to write scene data!");
}
- StringBuffer docBuffer;
+ // Write buffer data to separate .bin files
+ for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) {
+ Ref<Buffer> b = mAsset.buffers.Get(i);
- bool pretty = true;
- if (!isBinary && pretty) {
- PrettyWriter<StringBuffer> writer(docBuffer);
- mDoc.Accept(writer);
+ std::string binPath = b->GetURI();
+
+ std::unique_ptr<IOStream> binOutFile(mAsset.OpenFile(binPath, "wb", true));
+
+ if (binOutFile == 0) {
+ throw DeadlyExportError("Could not open output file: " + binPath);
+ }
+
+ if (b->byteLength > 0) {
+ if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
+ throw DeadlyExportError("Failed to write binary file: " + binPath);
+ }
+ }
}
- else {
- Writer<StringBuffer> writer(docBuffer);
- mDoc.Accept(writer);
+ }
+
+ inline void AssetWriter::WriteGLBFile(const char* path)
+ {
+ std::unique_ptr<IOStream> outfile(mAsset.OpenFile(path, "wb", true));
+
+ if (outfile == 0) {
+ throw DeadlyExportError("Could not open output file: " + std::string(path));
}
+ // we will write the header later, skip its size
+ outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
+
+ StringBuffer docBuffer;
+ Writer<StringBuffer> writer(docBuffer);
+ mDoc.Accept(writer);
+
if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
- throw DeadlyExportError("Failed to write scene data!");
+ throw DeadlyExportError("Failed to write scene data!");
}
- if (isBinary) {
- WriteBinaryData(outfile.get(), docBuffer.GetSize());
- }
+ WriteBinaryData(outfile.get(), docBuffer.GetSize());
}
inline void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength)
@@ -385,7 +575,6 @@ namespace glTF {
}
}
-
//
// write the header
//
@@ -412,16 +601,13 @@ namespace glTF {
}
}
-
+
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);
- }
+ asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
+ asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
mDoc.AddMember("asset", asset, mAl);
}
@@ -490,3 +676,5 @@ namespace glTF {
}
}
+
+
diff --git a/src/3rdparty/assimp/code/glTFExporter.cpp b/src/3rdparty/assimp/code/glTFExporter.cpp
index 7f0c086cf..d88081884 100644
--- a/src/3rdparty/assimp/code/glTFExporter.cpp
+++ b/src/3rdparty/assimp/code/glTFExporter.cpp
@@ -1,8 +1,9 @@
-/*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -37,9 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-
-
-
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
@@ -49,16 +47,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h"
#include "ByteSwapper.h"
+#include "SplitLargeMeshes.h"
+
+#include <assimp/SceneCombiner.h>
#include <assimp/version.h>
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/material.h>
#include <assimp/scene.h>
+// Header files, standard library.
#include <memory>
+#include <inttypes.h>
#include "glTFAssetWriter.h"
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ // Header files, Open3DGC.
+# include <Open3DGC/o3dgcSC3DMCEncoder.h>
+#endif
+
using namespace rapidjson;
using namespace Assimp;
@@ -84,50 +92,65 @@ namespace Assimp {
} // 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();
+ 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());
+
+ mScene = sceneCopy.get();
+
+ mAsset.reset( new glTF::Asset( pIOSystem ) );
if (isBinary) {
- asset->SetAsBinary();
+ mAsset->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();
+ if (mScene->mRootNode) {
+ ExportNodeHierarchy(mScene->mRootNode);
+ }
+
ExportMeshes();
//for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {}
-
- if (mScene->mRootNode) {
- ExportNode(mScene->mRootNode);
- }
-
ExportScene();
+ ExportAnimations();
glTF::AssetWriter writer(*mAsset);
- writer.WriteFile(filename);
-}
+ if (isBinary) {
+ writer.WriteGLBFile(filename);
+ } else {
+ writer.WriteFile(filename);
+ }
+}
+/*
+ * Copy a 4x4 matrix from struct aiMatrix to typedef mat4.
+ * Also converts from row-major to column-major storage.
+ */
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;
@@ -136,6 +159,22 @@ static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o)
o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4;
}
+static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
+{
+ o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
+ o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
+ o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
+ o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
+}
+
+static void IdentityMatrix4(glTF::mat4& o)
+{
+ o[ 0] = 1; o[ 1] = 0; o[ 2] = 0; o[ 3] = 0;
+ o[ 4] = 0; o[ 5] = 1; o[ 6] = 0; o[ 7] = 0;
+ o[ 8] = 0; o[ 9] = 0; o[10] = 1; o[11] = 0;
+ o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1;
+}
+
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)
{
@@ -146,8 +185,11 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
unsigned int bytesPerComp = ComponentTypeSize(compType);
size_t offset = buffer->byteLength;
+ // make sure offset is correctly byte-aligned, as required by spec
+ size_t padding = offset % bytesPerComp;
+ offset += padding;
size_t length = count * numCompsOut * bytesPerComp;
- buffer->Grow(length);
+ buffer->Grow(length + padding);
// bufferView
Ref<BufferView> bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view"));
@@ -165,6 +207,35 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
acc->count = count;
acc->type = typeOut;
+ // calculate min and max values
+ {
+ // Allocate and initialize with large values.
+ float float_MAX = 10000000000000.0f;
+ for (unsigned int i = 0 ; i < numCompsOut ; i++) {
+ acc->min.push_back( float_MAX);
+ acc->max.push_back(-float_MAX);
+ }
+
+ // Search and set extreme values.
+ float valueTmp;
+ for (unsigned int i = 0 ; i < count ; i++) {
+ for (unsigned int j = 0 ; j < numCompsOut ; j++) {
+ if (numCompsOut == 1) {
+ valueTmp = static_cast<unsigned short*>(data)[i];
+ } else {
+ valueTmp = static_cast<aiVector3D*>(data)[i][j];
+ }
+
+ if (valueTmp < acc->min[j]) {
+ acc->min[j] = valueTmp;
+ }
+ if (valueTmp > acc->max[j]) {
+ acc->max[j] = valueTmp;
+ }
+ }
+ }
+ }
+
// copy the data
acc->WriteData(count, data, numCompsIn*bytesPerComp);
@@ -177,6 +248,52 @@ namespace {
}
}
+void glTFExporter::GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop)
+{
+ std::string samplerId = mAsset->FindUniqueID("", "sampler");
+ prop.texture->sampler = mAsset->samplers.Create(samplerId);
+
+ aiTextureMapMode mapU, mapV;
+ aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
+ aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
+
+ switch (mapU) {
+ case aiTextureMapMode_Wrap:
+ prop.texture->sampler->wrapS = SamplerWrap_Repeat;
+ break;
+ case aiTextureMapMode_Clamp:
+ prop.texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge;
+ break;
+ case aiTextureMapMode_Mirror:
+ prop.texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat;
+ break;
+ case aiTextureMapMode_Decal:
+ default:
+ prop.texture->sampler->wrapS = SamplerWrap_Repeat;
+ break;
+ };
+
+ switch (mapV) {
+ case aiTextureMapMode_Wrap:
+ prop.texture->sampler->wrapT = SamplerWrap_Repeat;
+ break;
+ case aiTextureMapMode_Clamp:
+ prop.texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge;
+ break;
+ case aiTextureMapMode_Mirror:
+ prop.texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat;
+ break;
+ case aiTextureMapMode_Decal:
+ default:
+ prop.texture->sampler->wrapT = SamplerWrap_Repeat;
+ break;
+ };
+
+ // Hard coded Texture filtering options because I do not know where to find them in the aiMaterial.
+ prop.texture->sampler->magFilter = SamplerMagFilter_Linear;
+ prop.texture->sampler->minFilter = SamplerMinFilter_Linear;
+}
+
void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
{
aiString tex;
@@ -216,6 +333,8 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
else {
prop.texture->source->uri = path;
}
+
+ GetTexSampler(mat, prop);
}
}
}
@@ -226,6 +345,7 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
}
}
+
void glTFExporter::ExportMaterials()
{
aiString aiName;
@@ -246,14 +366,210 @@ void glTFExporter::ExportMaterials()
GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR);
GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE);
+ m->transparent = mat->Get(AI_MATKEY_OPACITY, m->transparency) == aiReturn_SUCCESS && m->transparency != 1.0;
+
GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS);
}
}
+/*
+ * Search through node hierarchy and find the node containing the given meshID.
+ * Returns true on success, and false otherwise.
+ */
+bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID)
+{
+ for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
+ if (meshID.compare(nodeIn->meshes[i]->id) == 0) {
+ meshNode = nodeIn;
+ return true;
+ }
+ }
+
+ for (unsigned int i = 0; i < nodeIn->children.size(); ++i) {
+ if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Find the root joint of the skeleton.
+ * Starts will any joint node and traces up the tree,
+ * until a parent is found that does not have a jointName.
+ * Returns the first parent Ref<Node> found that does not have a jointName.
+ */
+Ref<Node> FindSkeletonRootJoint(Ref<Skin>& skinRef)
+{
+ Ref<Node> startNodeRef;
+ Ref<Node> parentNodeRef;
+
+ // Arbitrarily use the first joint to start the search.
+ startNodeRef = skinRef->jointNames[0];
+ parentNodeRef = skinRef->jointNames[0];
+
+ do {
+ startNodeRef = parentNodeRef;
+ parentNodeRef = startNodeRef->parent;
+ } while (!parentNodeRef->jointName.empty());
+
+ return parentNodeRef;
+}
+
+void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buffer>& bufferRef, Ref<Skin>& skinRef, std::vector<aiMatrix4x4>& inverseBindMatricesData)
+{
+ if (aimesh->mNumBones < 1) {
+ return;
+ }
+
+ // Store the vertex joint and weight data.
+ const size_t NumVerts( aimesh->mNumVertices );
+ vec4* vertexJointData = new vec4[ NumVerts ];
+ vec4* vertexWeightData = new vec4[ NumVerts ];
+ int* jointsPerVertex = new int[ NumVerts ];
+ for (size_t i = 0; i < NumVerts; ++i) {
+ jointsPerVertex[i] = 0;
+ for (size_t j = 0; j < 4; ++j) {
+ vertexJointData[i][j] = 0;
+ vertexWeightData[i][j] = 0;
+ }
+ }
+
+ for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) {
+ const aiBone* aib = aimesh->mBones[idx_bone];
+
+ // aib->mName =====> skinRef->jointNames
+ // Find the node with id = mName.
+ Ref<Node> nodeRef = mAsset.nodes.Get(aib->mName.C_Str());
+ nodeRef->jointName = nodeRef->id;
+
+ unsigned int jointNamesIndex = 0;
+ bool addJointToJointNames = true;
+ for ( unsigned int idx_joint = 0; idx_joint < skinRef->jointNames.size(); ++idx_joint) {
+ if (skinRef->jointNames[idx_joint]->jointName.compare(nodeRef->jointName) == 0) {
+ addJointToJointNames = false;
+ jointNamesIndex = idx_joint;
+ }
+ }
+
+ if (addJointToJointNames) {
+ skinRef->jointNames.push_back(nodeRef);
+
+ // aib->mOffsetMatrix =====> skinRef->inverseBindMatrices
+ aiMatrix4x4 tmpMatrix4;
+ CopyValue(aib->mOffsetMatrix, tmpMatrix4);
+ inverseBindMatricesData.push_back(tmpMatrix4);
+ jointNamesIndex = static_cast<unsigned int>(inverseBindMatricesData.size() - 1);
+ }
+
+ // aib->mWeights =====> vertexWeightData
+ for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) {
+ unsigned int vertexId = aib->mWeights[idx_weights].mVertexId;
+ float vertWeight = aib->mWeights[idx_weights].mWeight;
+
+ // A vertex can only have at most four joint weights. Ignore all others.
+ if (jointsPerVertex[vertexId] > 3) {
+ continue;
+ }
+
+ vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex);
+ vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
+
+ jointsPerVertex[vertexId] += 1;
+ }
+
+ } // End: for-loop mNumMeshes
+
+ Mesh::Primitive& p = meshRef->primitives.back();
+ Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+ if ( vertexJointAccessor ) {
+ p.attributes.joint.push_back( vertexJointAccessor );
+ }
+
+ Ref<Accessor> vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+ if ( vertexWeightAccessor ) {
+ p.attributes.weight.push_back( vertexWeightAccessor );
+ }
+ delete[] jointsPerVertex;
+ delete[] vertexWeightData;
+ delete[] vertexJointData;
+}
+
void glTFExporter::ExportMeshes()
{
- for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) {
- const aiMesh* aim = mScene->mMeshes[i];
+ // Not for
+ // using IndicesType = decltype(aiFace::mNumIndices);
+ // But yes for
+ // using IndicesType = unsigned short;
+ // because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification.
+ typedef unsigned short IndicesType;
+
+ // Variables needed for compression. BEGIN.
+ // Indices, not pointers - because pointer to buffer is changing while writing to it.
+ size_t idx_srcdata_begin = 0; // Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer.
+ size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals.
+ std::vector<size_t> idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer.
+ size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer.
+ bool comp_allow;// Point that data of current mesh can be compressed.
+ // Variables needed for compression. END.
+
+ std::string fname = std::string(mFilename);
+ std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf"));
+ std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str());
+
+ Ref<Buffer> b = mAsset->GetBodyBuffer();
+ if (!b) {
+ b = mAsset->buffers.Create(bufferId);
+ }
+
+ //----------------------------------------
+ // Initialize variables for the skin
+ bool createSkin = false;
+ for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) {
+ const aiMesh* aim = mScene->mMeshes[idx_mesh];
+ if(aim->HasBones()) {
+ createSkin = true;
+ break;
+ }
+ }
+
+ Ref<Skin> skinRef;
+ std::string skinName = mAsset->FindUniqueID("skin", "skin");
+ std::vector<aiMatrix4x4> inverseBindMatricesData;
+ if(createSkin) {
+ skinRef = mAsset->skins.Create(skinName);
+ skinRef->name = skinName;
+ }
+ //----------------------------------------
+
+ for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) {
+ const aiMesh* aim = mScene->mMeshes[idx_mesh];
+
+ // Check if compressing requested and mesh can be encoded.
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ comp_allow = mProperties->GetPropertyBool("extensions.Open3DGC.use", false);
+#else
+ comp_allow = false;
+#endif
+
+ if(comp_allow && (aim->mPrimitiveTypes == aiPrimitiveType_TRIANGLE) && (aim->mNumVertices > 0) && (aim->mNumFaces > 0))
+ {
+ idx_srcdata_tc.clear();
+ idx_srcdata_tc.reserve(AI_MAX_NUMBER_OF_TEXTURECOORDS);
+ }
+ else
+ {
+ std::string msg;
+
+ if(aim->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
+ msg = "all primitives of the mesh must be a triangles.";
+ else
+ msg = "mesh must has vertices and faces.";
+
+ DefaultLogger::get()->warn("GLTF: can not use Open3DGC-compression: " + msg);
+ comp_allow = false;
+ }
std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh");
Ref<Mesh> m = mAsset->meshes.Create(meshId);
@@ -262,38 +578,53 @@ void glTFExporter::ExportMeshes()
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);
- }
+ /******************* Vertices ********************/
+ // If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored.
+ if(comp_allow) idx_srcdata_begin = b->byteLength;
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);
+ if (v) p.attributes.position.push_back(v);
+
+ /******************** Normals ********************/
+ if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array.
- 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);
+ 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);
+ /************** Texture coordinates **************/
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ // Flip UV y coords
+ if (aim -> mNumUVComponents[i] > 1) {
+ for (unsigned int j = 0; j < aim->mNumVertices; ++j) {
+ aim->mTextureCoords[i][j].y = 1 - aim->mTextureCoords[i][j].y;
+ }
+ }
+
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;
+ if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
+
+ Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false);
+ if (tc) p.attributes.texcoord.push_back(tc);
+ }
+ }
+
+ /*************** Vertices indices ****************/
+ idx_srcdata_ind = b->byteLength;// Store index of indices array.
+
+ if (aim->mNumFaces > 0) {
+ std::vector<IndicesType> indices;
+ unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices;
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);
- }
+
+ 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:
@@ -305,13 +636,169 @@ void glTFExporter::ExportMeshes()
default: // aiPrimitiveType_TRIANGLE
p.mode = PrimitiveMode_TRIANGLES;
}
+
+ /*************** Skins ****************/
+ if(aim->HasBones()) {
+ ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData);
+ }
+
+ /****************** Compression ******************/
+ ///TODO: animation: weights, joints.
+ if(comp_allow)
+ {
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ // Only one type of compression supported at now - Open3DGC.
+ //
+ o3dgc::BinaryStream bs;
+ o3dgc::SC3DMCEncoder<IndicesType> encoder;
+ o3dgc::IndexedFaceSet<IndicesType> comp_o3dgc_ifs;
+ o3dgc::SC3DMCEncodeParams comp_o3dgc_params;
+
+ //
+ // Fill data for encoder.
+ //
+ // Quantization
+ unsigned quant_coord = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.POSITION", 12);
+ unsigned quant_normal = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.NORMAL", 10);
+ unsigned quant_texcoord = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.TEXCOORD", 10);
+
+ // Prediction
+ o3dgc::O3DGCSC3DMCPredictionMode prediction_position = o3dgc::O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION;
+ o3dgc::O3DGCSC3DMCPredictionMode prediction_normal = o3dgc::O3DGC_SC3DMC_SURF_NORMALS_PREDICTION;
+ o3dgc::O3DGCSC3DMCPredictionMode prediction_texcoord = o3dgc::O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION;
+
+ // IndexedFacesSet: "Crease angle", "solid", "convex" are set to default.
+ comp_o3dgc_ifs.SetCCW(true);
+ comp_o3dgc_ifs.SetIsTriangularMesh(true);
+ comp_o3dgc_ifs.SetNumFloatAttributes(0);
+ // Coordinates
+ comp_o3dgc_params.SetCoordQuantBits(quant_coord);
+ comp_o3dgc_params.SetCoordPredMode(prediction_position);
+ comp_o3dgc_ifs.SetNCoord(aim->mNumVertices);
+ comp_o3dgc_ifs.SetCoord((o3dgc::Real* const)&b->GetPointer()[idx_srcdata_begin]);
+ // Normals
+ if(idx_srcdata_normal != SIZE_MAX)
+ {
+ comp_o3dgc_params.SetNormalQuantBits(quant_normal);
+ comp_o3dgc_params.SetNormalPredMode(prediction_normal);
+ comp_o3dgc_ifs.SetNNormal(aim->mNumVertices);
+ comp_o3dgc_ifs.SetNormal((o3dgc::Real* const)&b->GetPointer()[idx_srcdata_normal]);
+ }
+
+ // Texture coordinates
+ for(size_t num_tc = 0; num_tc < idx_srcdata_tc.size(); num_tc++)
+ {
+ size_t num = comp_o3dgc_ifs.GetNumFloatAttributes();
+
+ comp_o3dgc_params.SetFloatAttributeQuantBits(static_cast<unsigned long>(num), quant_texcoord);
+ comp_o3dgc_params.SetFloatAttributePredMode(static_cast<unsigned long>(num), prediction_texcoord);
+ comp_o3dgc_ifs.SetNFloatAttribute(static_cast<unsigned long>(num), aim->mNumVertices);// number of elements.
+ comp_o3dgc_ifs.SetFloatAttributeDim(static_cast<unsigned long>(num), aim->mNumUVComponents[num_tc]);// components per element: aiVector3D => x * float
+ comp_o3dgc_ifs.SetFloatAttributeType(static_cast<unsigned long>(num), o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD);
+ comp_o3dgc_ifs.SetFloatAttribute(static_cast<unsigned long>(num), (o3dgc::Real* const)&b->GetPointer()[idx_srcdata_tc[num_tc]]);
+ comp_o3dgc_ifs.SetNumFloatAttributes(static_cast<unsigned long>(num + 1));
+ }
+
+ // Coordinates indices
+ comp_o3dgc_ifs.SetNCoordIndex(aim->mNumFaces);
+ comp_o3dgc_ifs.SetCoordIndex((IndicesType* const)&b->GetPointer()[idx_srcdata_ind]);
+ // Prepare to enconding
+ comp_o3dgc_params.SetNumFloatAttributes(comp_o3dgc_ifs.GetNumFloatAttributes());
+ if(mProperties->GetPropertyBool("extensions.Open3DGC.binary", true))
+ comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_BINARY);
+ else
+ comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_ASCII);
+
+ comp_o3dgc_ifs.ComputeMinMax(o3dgc::O3DGC_SC3DMC_MAX_ALL_DIMS);
+ //
+ // Encoding
+ //
+ encoder.Encode(comp_o3dgc_params, comp_o3dgc_ifs, bs);
+ // Replace data in buffer.
+ b->ReplaceData(idx_srcdata_begin, b->byteLength - idx_srcdata_begin, bs.GetBuffer(), bs.GetSize());
+ //
+ // Add information about extension to mesh.
+ //
+ // Create extension structure.
+ Mesh::SCompression_Open3DGC* ext = new Mesh::SCompression_Open3DGC;
+
+ // Fill it.
+ ext->Buffer = b->id;
+ ext->Offset = idx_srcdata_begin;
+ ext->Count = b->byteLength - idx_srcdata_begin;
+ ext->Binary = mProperties->GetPropertyBool("extensions.Open3DGC.binary");
+ ext->IndicesCount = comp_o3dgc_ifs.GetNCoordIndex() * 3;
+ ext->VerticesCount = comp_o3dgc_ifs.GetNCoord();
+ // And assign to mesh.
+ m->Extension.push_back(ext);
+#endif
+ }// if(comp_allow)
+ }// for (unsigned int i = 0; i < mScene->mNumMeshes; ++i)
+
+ //----------------------------------------
+ // Finish the skin
+ // Create the Accessor for skinRef->inverseBindMatrices
+ if (createSkin) {
+ mat4* invBindMatrixData = new mat4[inverseBindMatricesData.size()];
+ for ( unsigned int idx_joint = 0; idx_joint < inverseBindMatricesData.size(); ++idx_joint) {
+ CopyValue(inverseBindMatricesData[idx_joint], invBindMatrixData[idx_joint]);
+ }
+
+ Ref<Accessor> invBindMatrixAccessor = ExportData(*mAsset, skinName, b, static_cast<unsigned int>(inverseBindMatricesData.size()), invBindMatrixData, AttribType::MAT4, AttribType::MAT4, ComponentType_FLOAT);
+ if (invBindMatrixAccessor) skinRef->inverseBindMatrices = invBindMatrixAccessor;
+
+ // Identity Matrix =====> skinRef->bindShapeMatrix
+ // Temporary. Hard-coded identity matrix here
+ skinRef->bindShapeMatrix.isPresent = true;
+ IdentityMatrix4(skinRef->bindShapeMatrix.value);
+
+ // Find node that contains this mesh and add "skeletons" and "skin" attributes to that node.
+ Ref<Node> rootNode = mAsset->nodes.Get(unsigned(0));
+ Ref<Node> meshNode;
+ std::string meshID = mAsset->meshes.Get(unsigned(0))->id;
+ FindMeshNode(rootNode, meshNode, meshID);
+
+ Ref<Node> rootJoint = FindSkeletonRootJoint(skinRef);
+ meshNode->skeletons.push_back(rootJoint);
+ meshNode->skin = skinRef;
+ }
+}
+
+/*
+ * Export the root node of the node hierarchy.
+ * Calls ExportNode for all children.
+ */
+unsigned int glTFExporter::ExportNodeHierarchy(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);
+ node->children.push_back(mAsset->nodes.Get(idx));
}
+
+ return node.GetIndex();
}
-unsigned int glTFExporter::ExportNode(const aiNode* n)
+/*
+ * Export node and recursively calls ExportNode for all children.
+ * Since these nodes are not the root node, we also export the parent Ref<Node>
+ */
+unsigned int glTFExporter::ExportNode(const aiNode* n, Ref<Node>& parent)
{
Ref<Node> node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node"));
+ node->parent = parent;
+
if (!n->mTransformation.IsIdentity()) {
node->matrix.isPresent = true;
CopyValue(n->mTransformation, node->matrix.value);
@@ -322,7 +809,7 @@ unsigned int glTFExporter::ExportNode(const aiNode* n)
}
for (unsigned int i = 0; i < n->mNumChildren; ++i) {
- unsigned int idx = ExportNode(n->mChildren[i]);
+ unsigned int idx = ExportNode(n->mChildren[i], node);
node->children.push_back(mAsset->nodes.Get(idx));
}
@@ -347,7 +834,7 @@ void glTFExporter::ExportScene()
void glTFExporter::ExportMetadata()
{
glTF::AssetMetadata& asset = mAsset->asset;
- asset.version = 1;
+ asset.version = "1.0";
char buffer[256];
ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)",
@@ -356,10 +843,164 @@ void glTFExporter::ExportMetadata()
asset.generator = buffer;
}
+inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animation>& animRef, Ref<Buffer>& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond)
+{
+ // Loop over the data and check to see if it exactly matches an existing buffer.
+ // If yes, then reference the existing corresponding accessor.
+ // Otherwise, add to the buffer and create a new accessor.
+
+ size_t counts[3] = {
+ nodeChannel->mNumPositionKeys,
+ nodeChannel->mNumScalingKeys,
+ nodeChannel->mNumRotationKeys,
+ };
+ size_t numKeyframes = 1;
+ for (int i = 0; i < 3; ++i) {
+ if (counts[i] > numKeyframes) {
+ numKeyframes = counts[i];
+ }
+ }
+ //-------------------------------------------------------
+ // Extract TIME parameter data.
+ // Check if the timeStamps are the same for mPositionKeys, mRotationKeys, and mScalingKeys.
+ if(nodeChannel->mNumPositionKeys > 0) {
+ typedef float TimeType;
+ std::vector<TimeType> timeData;
+ timeData.resize(numKeyframes);
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes;
+ // mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
+ // Check if we have to cast type here. e.g. uint16_t()
+ timeData[i] = static_cast<float>(nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond);
+ }
+ Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT);
+ if (timeAccessor) animRef->Parameters.TIME = timeAccessor;
+ }
+ //-------------------------------------------------------
+ // Extract translation parameter data
+ if(nodeChannel->mNumPositionKeys > 0) {
+ C_STRUCT aiVector3D* translationData = new aiVector3D[numKeyframes];
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes;
+ translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue;
+ }
+
+ Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+ if ( tranAccessor ) {
+ animRef->Parameters.translation = tranAccessor;
+ }
+ delete[] translationData;
+ }
+
+ //-------------------------------------------------------
+ // Extract scale parameter data
+ if(nodeChannel->mNumScalingKeys > 0) {
+ C_STRUCT aiVector3D* scaleData = new aiVector3D[numKeyframes];
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumScalingKeys / numKeyframes;
+ scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue;
+ }
+
+ Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+ if ( scaleAccessor ) {
+ animRef->Parameters.scale = scaleAccessor;
+ }
+ delete[] scaleData;
+ }
+
+ //-------------------------------------------------------
+ // Extract rotation parameter data
+ if(nodeChannel->mNumRotationKeys > 0) {
+ vec4* rotationData = new vec4[numKeyframes];
+ for (size_t i = 0; i < numKeyframes; ++i) {
+ size_t frameIndex = i * nodeChannel->mNumRotationKeys / numKeyframes;
+ rotationData[i][0] = nodeChannel->mRotationKeys[frameIndex].mValue.x;
+ rotationData[i][1] = nodeChannel->mRotationKeys[frameIndex].mValue.y;
+ rotationData[i][2] = nodeChannel->mRotationKeys[frameIndex].mValue.z;
+ rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w;
+ }
+ Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+ if ( rotAccessor ) {
+ animRef->Parameters.rotation = rotAccessor;
+ }
+ delete[] rotationData;
+ }
+}
+
+void glTFExporter::ExportAnimations()
+{
+ Ref<Buffer> bufferRef = mAsset->buffers.Get(unsigned (0));
+
+ for (unsigned int i = 0; i < mScene->mNumAnimations; ++i) {
+ const aiAnimation* anim = mScene->mAnimations[i];
+
+ std::string nameAnim = "anim";
+ if (anim->mName.length > 0) {
+ nameAnim = anim->mName.C_Str();
+ }
+
+ for (unsigned int channelIndex = 0; channelIndex < anim->mNumChannels; ++channelIndex) {
+ const aiNodeAnim* nodeChannel = anim->mChannels[channelIndex];
+
+ // It appears that assimp stores this type of animation as multiple animations.
+ // where each aiNodeAnim in mChannels animates a specific node.
+ std::string name = nameAnim + "_" + to_string(channelIndex);
+ name = mAsset->FindUniqueID(name, "animation");
+ Ref<Animation> animRef = mAsset->animations.Create(name);
+
+ /******************* Parameters ********************/
+ ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, static_cast<float>(anim->mTicksPerSecond));
+
+ for (unsigned int j = 0; j < 3; ++j) {
+ std::string channelType;
+ int channelSize;
+ switch (j) {
+ case 0:
+ channelType = "rotation";
+ channelSize = nodeChannel->mNumRotationKeys;
+ break;
+ case 1:
+ channelType = "scale";
+ channelSize = nodeChannel->mNumScalingKeys;
+ break;
+ case 2:
+ channelType = "translation";
+ channelSize = nodeChannel->mNumPositionKeys;
+ break;
+ }
+
+ if (channelSize < 1) { continue; }
+
+ Animation::AnimChannel tmpAnimChannel;
+ Animation::AnimSampler tmpAnimSampler;
+
+ tmpAnimChannel.sampler = name + "_" + channelType;
+ tmpAnimChannel.target.path = channelType;
+ tmpAnimSampler.output = channelType;
+ tmpAnimSampler.id = name + "_" + channelType;
+
+ tmpAnimChannel.target.id = mAsset->nodes.Get(nodeChannel->mNodeName.C_Str());
+
+ tmpAnimSampler.input = "TIME";
+ tmpAnimSampler.interpolation = "LINEAR";
+
+ animRef->Channels.push_back(tmpAnimChannel);
+ animRef->Samplers.push_back(tmpAnimSampler);
+ }
+
+ }
+
+ // Assimp documentation staes this is not used (not implemented)
+ // for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) {
+ // const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex];
+ // }
+
+ } // End: for-loop mNumAnimations
+}
#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
diff --git a/src/3rdparty/assimp/code/glTFExporter.h b/src/3rdparty/assimp/code/glTFExporter.h
index 884d1fe38..c813fff44 100644
--- a/src/3rdparty/assimp/code/glTFExporter.h
+++ b/src/3rdparty/assimp/code/glTFExporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -44,24 +45,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_GLTFEXPORTER_H_INC
#define AI_GLTFEXPORTER_H_INC
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+
#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;
+ template<class T>
+ class Ref;
+ class Asset;
struct TexProperty;
+ struct Node;
}
namespace Assimp
@@ -89,20 +94,25 @@ namespace Assimp
std::map<std::string, unsigned int> mTexturesByPath;
- glTF::Asset* mAsset;
+ std::shared_ptr<glTF::Asset> mAsset;
std::vector<unsigned char> mBodyData;
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
+ void GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop);
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);
+ unsigned int ExportNodeHierarchy(const aiNode* n);
+ unsigned int ExportNode(const aiNode* node, glTF::Ref<glTF::Node>& parent);
void ExportScene();
+ void ExportAnimations();
};
}
-#endif
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // AI_GLTFEXPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/glTFImporter.cpp b/src/3rdparty/assimp/code/glTFImporter.cpp
index 6a6619b81..5d1b5afab 100644
--- a/src/3rdparty/assimp/code/glTFImporter.cpp
+++ b/src/3rdparty/assimp/code/glTFImporter.cpp
@@ -1,8 +1,9 @@
-/*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,13 +42,15 @@ 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 "StringUtils.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
+
#include <memory>
#include "MakeVerboseFormat.h"
@@ -97,24 +100,19 @@ const aiImporterDesc* glTFImporter::GetInfo() const
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;
- }
+ const std::string &extension = GetExtension(pFile);
+
+ if (extension != "gltf" && extension != "glb")
+ return false;
+
+ if (checkSig && pIOHandler) {
+ glTF::Asset asset(pIOHandler);
+ try {
+ asset.Load(pFile, extension == "glb");
+ std::string version = asset.asset.version;
+ return !version.empty() && version[0] == '1';
+ } catch (...) {
+ return false;
}
}
@@ -156,7 +154,7 @@ static void CopyValue(const glTF::mat4& v, aiMatrix4x4& o)
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,
+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) {
@@ -176,9 +174,7 @@ inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& r
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);
- }
+ mat->AddProperty(&col, 1, pKey, type, idx);
}
}
@@ -238,6 +234,7 @@ static inline void SetFace(aiFace& face, int a, int b, int c)
face.mIndices[2] = c;
}
+#ifdef ASSIMP_BUILD_DEBUG
static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts)
{
for (unsigned i = 0; i < nFaces; ++i) {
@@ -249,6 +246,7 @@ static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsign
}
return true;
}
+#endif // ASSIMP_BUILD_DEBUG
void glTFImporter::ImportMeshes(glTF::Asset& r)
{
@@ -259,7 +257,39 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
Mesh& mesh = r.meshes[m];
- meshOffsets.push_back(k);
+ // Check if mesh extensions is used
+ if(mesh.Extension.size() > 0)
+ {
+ for(Mesh::SExtension* cur_ext : mesh.Extension)
+ {
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+ if(cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC)
+ {
+ // Limitations for meshes when using Open3DGC-compression.
+ // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive?
+ // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can
+ // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression"
+ // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives.
+ // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem.
+ // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor
+ // of primitive must point to one continuous region of the buffer.
+ if(mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed.");
+
+ Mesh::SCompression_Open3DGC* o3dgc_ext = (Mesh::SCompression_Open3DGC*)cur_ext;
+ Ref<Buffer> buf = r.buffers.Get(o3dgc_ext->Buffer);
+
+ buf->EncodedRegion_SetCurrent(mesh.id);
+ }
+ else
+#endif
+ {
+ throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) +
+ "\"), only Open3DGC is supported.");
+ }
+ }
+ }// if(mesh.Extension.size() > 0)
+
+ meshOffsets.push_back(k);
k += unsigned(mesh.primitives.size());
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
@@ -294,16 +324,15 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
}
Mesh::Primitive::Attributes& attr = prim.attributes;
- if (attr.position.size() > 0 && attr.position[0]) {
+
+ 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);
- }
+ 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) {
+ 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();
@@ -315,7 +344,7 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
if (prim.indices) {
- aiFace* faces = 0;
+ aiFace* faces = 0;
unsigned int nFaces = 0;
unsigned int count = prim.indices->count;
@@ -641,9 +670,9 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS
// TODO: it does not split the loaded vertices, should it?
//pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
- Assimp::MakeVerboseFormatProcess process;
+ MakeVerboseFormatProcess process;
process.Execute(pScene);
-
+
if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
diff --git a/src/3rdparty/assimp/code/glTFImporter.h b/src/3rdparty/assimp/code/glTFImporter.h
index 5d06730a5..46f450f86 100644
--- a/src/3rdparty/assimp/code/glTFImporter.h
+++ b/src/3rdparty/assimp/code/glTFImporter.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_GLTFIMPORTER_H_INC
#include "BaseImporter.h"
-#include "DefaultIOSystem.h"
+#include <assimp/DefaultIOSystem.h>
struct aiNode;
diff --git a/src/3rdparty/assimp/code/irrXMLWrapper.h b/src/3rdparty/assimp/code/irrXMLWrapper.h
index 41e418811..bbda7c0f0 100644
--- a/src/3rdparty/assimp/code/irrXMLWrapper.h
+++ b/src/3rdparty/assimp/code/irrXMLWrapper.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -42,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_IRRXML_WRAPPER
// some long includes ....
-#include "./../contrib/irrXML/irrXML.h"
+#include <irrXML.h>
#include "./../include/assimp/IOStream.hpp"
#include "BaseImporter.h"
#include <vector>
@@ -69,9 +70,7 @@ namespace Assimp {
* }
* @endcode
**/
-class CIrrXML_IOStreamReader
- : public irr::io::IFileReadCallBack
-{
+class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack {
public:
// ----------------------------------------------------------------------------------
@@ -92,7 +91,7 @@ public:
// Remove null characters from the input sequence otherwise the parsing will utterly fail
unsigned int size = 0;
- unsigned int size_max = data.size();
+ unsigned int size_max = static_cast<unsigned int>(data.size());
for(unsigned int i = 0; i < size_max; i++) {
if(data[i] != '\0') {
data[size++] = data[i];
@@ -117,7 +116,7 @@ public:
return 0;
}
if(t+sizeToRead>data.size()) {
- sizeToRead = data.size()-t;
+ sizeToRead = static_cast<int>(data.size()-t);
}
memcpy(buffer,&data.front()+t,sizeToRead);
diff --git a/src/3rdparty/assimp/code/makefile.mingw b/src/3rdparty/assimp/code/makefile.mingw
deleted file mode 100644
index 711d57f57..000000000
--- a/src/3rdparty/assimp/code/makefile.mingw
+++ /dev/null
@@ -1,105 +0,0 @@
-### USE OF THIS MAKEFILE IS NOT RECOMMENDED.
-### It is no longer maintained. Use CMAKE instead.
-
-# ---------------------------------------------------------------------------
-# Makefile for Open Asset Import Library (MinGW32-make)
-# aramis_acg@users.sourceforge.net
-# - just a quick'n'dirty one, could be buggy ...
-#
-# Usage: mingw32-make -f makefile.mingw <target> <macros>
-
-# TARGETS:
-# all Build a shared so from the whole library
-# clean Cleanup object files, prepare for rebuild
-# static Build a static library (*.a)
-
-# MACROS: (make clean before you change one)
-# NOBOOST=1 Build against boost workaround
-# SINGLETHREADED=1 Build single-threaded library
-# DEBUG=1 Build debug build of library
-#
-# ---------------------------------------------------------------------------
-
-# C++ object files
-OBJECTS := $(patsubst %.cpp,%.o, $(wildcard *.cpp))
-OBJECTS += $(patsubst %.cpp,%.o, $(wildcard extra/*.cpp))
-OBJECTS += $(patsubst %.cpp,%.o, $(wildcard ./../contrib/irrXML/*.cpp))
-
-# C object files
-OBJECTSC := $(patsubst %.c,%.oc, $(wildcard ./../contrib/zlib/*.c))
-OBJECTSC += $(patsubst %.c,%.oc, $(wildcard ./../contrib/ConvertUTF/*.c))
-OBJECTSC += $(patsubst %.c,%.oc, $(wildcard ./../contrib/unzip/*.c))
-
-# Include flags for gcc
-INCLUDEFLAGS =
-
-# Preprocessor defines for gcc
-DEFINEFLAGS =
-
-# Suffix for the output binary, represents build type
-NAMESUFFIX =
-
-# Output path for binaries
-BINPATH = ../bin/mingw/
-
-# GCC compiler flags
-CPPFLAGS=-Wall
-
-# Setup environment for noboost build
-ifeq ($(NOBOOST),1)
- SINGLETHREADED = 1
- INCLUDEFLAGS += -I./BoostWorkaround/
- DEFINEFLAGS += -DASSIMP_BUILD_BOOST_WORKAROUND
-# NAMESUFFIX += -noboost
-else
- # adjust this manually if your boost is stored elsewhere
- INCLUDEFLAGS += -I"C:/Program Files/boost/boost_1_38"
- #INCLUDEFLAGS += -I"$(BOOST_DIR)"
-
-endif
-
-# Setup environment for st build
-ifeq ($(SINGLETHREADED),1)
- DEFINEFLAGS += -DASSIMP_BUILD_SINGLETHREADED
-# NAMESUFFIX += -st
-endif
-
-# Setup environment for debug build
-ifeq ($(DEBUG),1)
- DEFINEFLAGS += -D_DEBUG -DDEBUG
- CPPFLAGS += -g
-# NAMESUFFIX += -debug
-else
- CPPFLAGS += -O2 -s
- DEFINEFLAGS += -DNDEBUG -D_NDEBUG
-endif
-
-# Output name of shared library
-SHARED_TARGET = $(BINPATH)/libassimp$(NAMESUFFIX).so
-
-# Output name of static library
-STATIC = $(BINPATH)/libassimp$(NAMESUFFIX).a
-
-# target: all
-# usage : build a shared library (*.so)
-all: $(SHARED_TARGET)
-
-$(SHARED_TARGET): $(OBJECTS) $(OBJECTSC)
- gcc -o $@ $(OBJECTS) $(OBJECTSC) -shared -lstdc++
-%.o:%.cpp
- $(CXX) -c $(CPPFLAGS) $? -o $@ $(INCLUDEFLAGS) $(DEFINEFLAGS)
-%.oc:%.c
- $(CXX) -x c -c -ansi $(CPPFLAGS) $? -o $@
-
-# target: clean
-# usage : cleanup all object files, prepare for a rebuild
-.PHONY: clean
-clean:
- -del *.o .\..\contrib\irrXML\*.o .\..\contrib\zlib\*.oc .\..\contrib\unzip\*.oc .\..\contrib\ConvertUTF\*.oc
-
-# target: static
-# usage : build a static library (*.a)
-static: $(STATIC)
-$(STATIC): $(OBJECTS) $(OBJECTSC)
- ar rcs $@ $(OBJECTS) $(OBJECTSC)
-
diff --git a/src/3rdparty/assimp/code/qnan.h b/src/3rdparty/assimp/code/qnan.h
index 02412bf21..fcff16b74 100644
--- a/src/3rdparty/assimp/code/qnan.h
+++ b/src/3rdparty/assimp/code/qnan.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -68,7 +69,21 @@ union _IEEESingle
uint32_t Exp : 8;
uint32_t Sign : 1;
} IEEE;
-} ;
+};
+
+// ---------------------------------------------------------------------------
+/** Data structure to represent the bit pattern of a 64 Bit
+ * IEEE 754 floating-point number. */
+union _IEEEDouble
+{
+ double Double;
+ struct
+ {
+ uint64_t Frac : 52;
+ uint64_t Exp : 11;
+ uint64_t Sign : 1;
+ } IEEE;
+};
// ---------------------------------------------------------------------------
/** Check whether a given float is qNaN.
@@ -87,11 +102,19 @@ AI_FORCE_INLINE bool is_qnan(float in)
}
// ---------------------------------------------------------------------------
-/** Check whether a float is NOT qNaN.
+/** Check whether a given double is qNaN.
* @param in Input value */
-AI_FORCE_INLINE bool is_not_qnan(float in)
+AI_FORCE_INLINE bool is_qnan(double in)
{
- return !is_qnan(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<_IEEEDouble*>(&in)->IEEE.Exp == (1u << 11)-1 &&
+ reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Frac);
}
// ---------------------------------------------------------------------------
@@ -105,10 +128,29 @@ AI_FORCE_INLINE bool is_special_float(float in)
}
// ---------------------------------------------------------------------------
+/** @brief check whether a double 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(double in)
+{
+ return (reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Exp == (1u << 11)-1);
+}
+
+// ---------------------------------------------------------------------------
+/** Check whether a float is NOT qNaN.
+ * @param in Input value */
+template<class TReal>
+AI_FORCE_INLINE bool is_not_qnan(TReal in)
+{
+ return !is_qnan(in);
+}
+
+// ---------------------------------------------------------------------------
/** @brief Get a fresh qnan. */
-AI_FORCE_INLINE float get_qnan()
+AI_FORCE_INLINE ai_real get_qnan()
{
- return std::numeric_limits<float>::quiet_NaN();
+ return std::numeric_limits<ai_real>::quiet_NaN();
}
#endif // !! AI_QNAN_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/scene.cpp b/src/3rdparty/assimp/code/scene.cpp
new file mode 100644
index 000000000..467a2895d
--- /dev/null
+++ b/src/3rdparty/assimp/code/scene.cpp
@@ -0,0 +1,139 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+#include <assimp/scene.h>
+
+aiNode::aiNode()
+: mName("")
+, mParent(NULL)
+, mNumChildren(0)
+, mChildren(NULL)
+, mNumMeshes(0)
+, mMeshes(NULL)
+, mMetaData(NULL) {
+ // empty
+}
+
+aiNode::aiNode(const std::string& name)
+: mName(name)
+, mParent(NULL)
+, mNumChildren(0)
+, mChildren(NULL)
+, mNumMeshes(0)
+, mMeshes(NULL)
+, mMetaData(NULL) {
+ // empty
+}
+
+/** Destructor */
+aiNode::~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;
+}
+
+const aiNode *aiNode::FindNode(const char* name) const {
+ if (nullptr == name) {
+ return nullptr;
+ }
+ if (!::strcmp(mName.data, name)) {
+ return this;
+ }
+ for (unsigned int i = 0; i < mNumChildren; ++i) {
+ const aiNode* const p = mChildren[i]->FindNode(name);
+ if (p) {
+ return p;
+ }
+ }
+ // there is definitely no sub-node with this name
+ return nullptr;
+}
+
+aiNode *aiNode::FindNode(const char* name) {
+ if (!::strcmp(mName.data, name))return this;
+ for (unsigned int i = 0; i < mNumChildren; ++i)
+ {
+ aiNode* const p = mChildren[i]->FindNode(name);
+ if (p) {
+ return p;
+ }
+ }
+ // there is definitely no sub-node with this name
+ return nullptr;
+}
+
+void aiNode::addChildren(unsigned int numChildren, aiNode **children) {
+ if (nullptr == children || 0 == numChildren) {
+ return;
+ }
+
+ for (unsigned int i = 0; i < numChildren; i++) {
+ aiNode *child = children[i];
+ if (nullptr != child) {
+ child->mParent = this;
+ }
+ }
+
+ if (mNumChildren > 0) {
+ aiNode **tmp = new aiNode*[mNumChildren];
+ ::memcpy(tmp, mChildren, sizeof(aiNode*) * mNumChildren);
+ delete[] mChildren;
+ mChildren = new aiNode*[mNumChildren + numChildren];
+ ::memcpy(mChildren, tmp, sizeof(aiNode*) * mNumChildren);
+ ::memcpy(&mChildren[mNumChildren], children, sizeof(aiNode*)* numChildren);
+ mNumChildren += numChildren;
+ delete[] tmp;
+ }
+ else {
+ mChildren = new aiNode*[numChildren];
+ for (unsigned int i = 0; i < numChildren; i++) {
+ mChildren[i] = children[i];
+ }
+ mNumChildren = numChildren;
+ }
+}
diff --git a/src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.c b/src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.c
deleted file mode 100644
index 9b3deebd6..000000000
--- a/src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Copyright 2001-2004 Unicode, Inc.
- *
- * Disclaimer
- *
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- *
- * Limitations on Rights to Redistribute This Code
- *
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
-
-/* ---------------------------------------------------------------------
-
- Conversions between UTF32, UTF-16, and UTF-8. Source code file.
- Author: Mark E. Davis, 1994.
- Rev History: Rick McGowan, fixes & updates May 2001.
- Sept 2001: fixed const & error conditions per
- mods suggested by S. Parent & A. Lillich.
- June 2002: Tim Dodd added detection and handling of incomplete
- source sequences, enhanced error detection, added casts
- to eliminate compiler warnings.
- July 2003: slight mods to back out aggressive FFFE detection.
- Jan 2004: updated switches in from-UTF8 conversions.
- Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
-
- See the header file "ConvertUTF.h" for complete documentation.
-
------------------------------------------------------------------------- */
-
-
-#include "ConvertUTF.h"
-#ifdef CVTUTF_DEBUG
-#include <stdio.h>
-#endif
-
-static const int halfShift = 10; /* used for shifting by 10 bits */
-
-static const UTF32 halfBase = 0x0010000UL;
-static const UTF32 halfMask = 0x3FFUL;
-
-#define UNI_SUR_HIGH_START (UTF32)0xD800
-#define UNI_SUR_HIGH_END (UTF32)0xDBFF
-#define UNI_SUR_LOW_START (UTF32)0xDC00
-#define UNI_SUR_LOW_END (UTF32)0xDFFF
-#define false 0
-#define true 1
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF16 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF32* source = *sourceStart;
- UTF16* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- if (target >= targetEnd) {
- result = targetExhausted; break;
- }
- ch = *source++;
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_LEGAL_UTF32) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- --source; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF32 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF16* source = *sourceStart;
- UTF32* target = *targetStart;
- UTF32 ch, ch2;
- while (source < sourceEnd) {
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- if (target >= targetEnd) {
- source = oldSource; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- *target++ = ch;
- }
- *sourceStart = source;
- *targetStart = target;
-#ifdef CVTUTF_DEBUG
-if (result == sourceIllegal) {
- fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
- fflush(stderr);
-}
-#endif
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Index into the table below with the first byte of a UTF-8 sequence to
- * get the number of trailing bytes that are supposed to follow it.
- * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
- * left as-is for anyone who may want to do such conversion, which was
- * allowed in earlier algorithms.
- */
-static const char trailingBytesForUTF8[256] = {
- 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,
- 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,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-
-/*
- * Magic values subtracted from a buffer value during UTF8 conversion.
- * This table contains as many values as there might be trailing bytes
- * in a UTF-8 sequence.
- */
-static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
-
-/*
- * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
- * into the first byte, depending on how many bytes follow. There are
- * as many entries in this table as there are UTF-8 sequence types.
- * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
- * for *legal* UTF-8 will be 4 or fewer bytes total.
- */
-static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-/* --------------------------------------------------------------------- */
-
-/* The interface converts a whole buffer to avoid function-call overhead.
- * Constants have been gathered. Loops & conditionals have been removed as
- * much as possible for efficiency, in favor of drop-through switches.
- * (See "Note A" at the bottom of the file for equivalent code.)
- * If your compiler supports it, the "isLegalUTF8" call can be turned
- * into an inline function.
- */
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF8 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF16* source = *sourceStart;
- UTF8* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- UTF32 ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /* Figure out how many bytes the result will require */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- source = oldSource; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Utility routine to tell whether a sequence of bytes is legal UTF-8.
- * This must be called with the length pre-determined by the first byte.
- * If not calling this from ConvertUTF8to*, then the length can be set by:
- * length = trailingBytesForUTF8[*source]+1;
- * and the sequence is illegal right away if there aren't that many bytes
- * available.
- * If presented with a length > 4, this returns false. The Unicode
- * definition of UTF-8 goes up to 4-byte sequences.
- */
-
-static Boolean isLegalUTF8(const UTF8 *source, int length) {
- UTF8 a;
- const UTF8 *srcptr = source+length;
- switch (length) {
- default: return false;
- /* Everything else falls through when "true"... */
- case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
- case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
- case 2: if ((a = (*--srcptr)) > 0xBF) return false;
-
- switch (*source) {
- /* no fall-through in this inner switch */
- case 0xE0: if (a < 0xA0) return false; break;
- case 0xED: if (a > 0x9F) return false; break;
- case 0xF0: if (a < 0x90) return false; break;
- case 0xF4: if (a > 0x8F) return false; break;
- default: if (a < 0x80) return false;
- }
-
- case 1: if (*source >= 0x80 && *source < 0xC2) return false;
- }
- if (*source > 0xF4) return false;
- return true;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return whether a UTF-8 sequence is legal or not.
- * This is not used here; it's just exported.
- */
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
- int length = trailingBytesForUTF8[*source]+1;
- if (source+length > sourceEnd) {
- return false;
- }
- return isLegalUTF8(source, length);
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF16 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF8* source = *sourceStart;
- UTF16* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (! isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_UTF16) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- source -= (extraBytesToRead+1); /* return to the start */
- break; /* Bail out; shouldn't continue */
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF8 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF32* source = *sourceStart;
- UTF8* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- ch = *source++;
- if (flags == strictConversion ) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /*
- * Figure out how many bytes the result will require. Turn any
- * illegally large UTF32 things (> Plane 17) into replacement chars.
- */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- result = sourceIllegal;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- --source; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF32 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF8* source = *sourceStart;
- UTF32* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (! isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6;
- case 4: ch += *source++; ch <<= 6;
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up the source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_LEGAL_UTF32) {
- /*
- * UTF-16 surrogate values are illegal in UTF-32, and anything
- * over Plane 17 (> 0x10FFFF) is illegal.
- */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = ch;
- }
- } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
- result = sourceIllegal;
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* ---------------------------------------------------------------------
-
- Note A.
- The fall-through switches in UTF-8 reading code save a
- temp variable, some decrements & conditionals. The switches
- are equivalent to the following loop:
- {
- int tmpBytesToRead = extraBytesToRead+1;
- do {
- ch += *source++;
- --tmpBytesToRead;
- if (tmpBytesToRead) ch <<= 6;
- } while (tmpBytesToRead > 0);
- }
- In UTF-8 writing code, the switches on "bytesToWrite" are
- similarly unrolled loops.
-
- --------------------------------------------------------------------- */
diff --git a/src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.h b/src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.h
deleted file mode 100644
index 05e800ad8..000000000
--- a/src/3rdparty/assimp/contrib/ConvertUTF/ConvertUTF.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2001-2004 Unicode, Inc.
- *
- * Disclaimer
- *
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- *
- * Limitations on Rights to Redistribute This Code
- *
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
-#ifndef CONVERTUTF_H
-#define CONVERTUTF_H
-/* ---------------------------------------------------------------------
-
- Conversions between UTF32, UTF-16, and UTF-8. Header file.
-
- Several funtions are included here, forming a complete set of
- conversions between the three formats. UTF-7 is not included
- here, but is handled in a separate source file.
-
- Each of these routines takes pointers to input buffers and output
- buffers. The input buffers are const.
-
- Each routine converts the text between *sourceStart and sourceEnd,
- putting the result into the buffer between *targetStart and
- targetEnd. Note: the end pointers are *after* the last item: e.g.
- *(sourceEnd - 1) is the last item.
-
- The return result indicates whether the conversion was successful,
- and if not, whether the problem was in the source or target buffers.
- (Only the first encountered problem is indicated.)
-
- After the conversion, *sourceStart and *targetStart are both
- updated to point to the end of last text successfully converted in
- the respective buffers.
-
- Input parameters:
- sourceStart - pointer to a pointer to the source buffer.
- The contents of this are modified on return so that
- it points at the next thing to be converted.
- targetStart - similarly, pointer to pointer to the target buffer.
- sourceEnd, targetEnd - respectively pointers to the ends of the
- two buffers, for overflow checking only.
-
- These conversion functions take a ConversionFlags argument. When this
- flag is set to strict, both irregular sequences and isolated surrogates
- will cause an error. When the flag is set to lenient, both irregular
- sequences and isolated surrogates are converted.
-
- Whether the flag is strict or lenient, all illegal sequences will cause
- an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
- or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
- must check for illegal sequences.
-
- When the flag is set to lenient, characters over 0x10FFFF are converted
- to the replacement character; otherwise (when the flag is set to strict)
- they constitute an error.
-
- Output parameters:
- The value "sourceIllegal" is returned from some routines if the input
- sequence is malformed. When "sourceIllegal" is returned, the source
- value will point to the illegal value that caused the problem. E.g.,
- in UTF-8 when a sequence is malformed, it points to the start of the
- malformed sequence.
-
- Author: Mark E. Davis, 1994.
- Rev History: Rick McGowan, fixes & updates May 2001.
- Fixes & updates, Sept 2001.
-
------------------------------------------------------------------------- */
-
-/* ---------------------------------------------------------------------
- The following 4 definitions are compiler-specific.
- The C standard does not guarantee that wchar_t has at least
- 16 bits, so wchar_t is no less portable than unsigned short!
- All should be unsigned values to avoid sign extension during
- bit mask & shift operations.
------------------------------------------------------------------------- */
-
-typedef unsigned long UTF32; /* at least 32 bits */
-typedef unsigned short UTF16; /* at least 16 bits */
-typedef unsigned char UTF8; /* typically 8 bits */
-typedef unsigned char Boolean; /* 0 or 1 */
-
-/* Some fundamental constants */
-#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
-#define UNI_MAX_BMP (UTF32)0x0000FFFF
-#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
-#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
-#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
-
-typedef enum {
- conversionOK, /* conversion successful */
- sourceExhausted, /* partial character in source, but hit end */
- targetExhausted, /* insuff. room in target for conversion */
- sourceIllegal /* source sequence is illegal/malformed */
-} ConversionResult;
-
-typedef enum {
- strictConversion = 0,
- lenientConversion
-} ConversionFlags;
-
-/* This is for C++ and does no harm in C */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-ConversionResult ConvertUTF8toUTF16 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF16toUTF8 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF8toUTF32 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF32toUTF8 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF16toUTF32 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF32toUTF16 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
-
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-#endif // CONVERTUTF_H
diff --git a/src/3rdparty/assimp/contrib/ConvertUTF/readme.txt b/src/3rdparty/assimp/contrib/ConvertUTF/readme.txt
deleted file mode 100644
index b9f17fb81..000000000
--- a/src/3rdparty/assimp/contrib/ConvertUTF/readme.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-
-The accompanying C source code file "ConvertUTF.c" and the associated header
-file "ConvertUTF.h" provide for conversion between various transformation
-formats of Unicode characters. The following conversions are supported:
-
- UTF-32 to UTF-16
- UTF-32 to UTF-8
- UTF-16 to UTF-32
- UTF-16 to UTF-8
- UTF-8 to UTF-16
- UTF-8 to UTF-32
-
-In addition, there is a test harness which runs various tests.
-
-The files "CVTUTF7.C" and "CVTUTF7.H" are for archival and historical purposes
-only. They have not been updated to Unicode 3.0 or later and should be
-considered obsolescent. "CVTUTF7.C" contains two functions that can convert
-between UCS2 (i.e., the BMP characters only) and UTF-7. Surrogates are
-not supported, the code has not been tested, and should be considered
-unsuitable for general purpose use.
-
-Please submit any bug reports about these programs here:
-
- http://www.unicode.org/unicode/reporting.html
-
-Version 1.0: initial version.
-
-Version 1.1: corrected some minor problems; added stricter checks.
-
-Version 1.2: corrected switch statements associated with "extraBytesToRead"
- in 4 & 5 byte cases, in functions for conversion from UTF8.
- Note: formally, the 4 & 5 byte cases are illegal in the latest
- UTF8, but the table and this code has always catered for those,
- cases since at one time they were legal.
-
-Version 1.3: Updated UTF-8 legality check;
- updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions
- Updated UTF-8 legality tests in harness.c
-
-
-Last update: October 19, 2004
-
-
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcAdjacencyInfo.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcAdjacencyInfo.h
new file mode 100644
index 000000000..72fe3d4c6
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcAdjacencyInfo.h
@@ -0,0 +1,155 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_ADJACENCY_INFO_H
+#define O3DGC_ADJACENCY_INFO_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ const long O3DGC_MIN_NEIGHBORS_SIZE = 128;
+ const long O3DGC_MIN_NUM_NEIGHBORS_SIZE = 16;
+ //!
+ class AdjacencyInfo
+ {
+ public:
+ //! Constructor.
+ AdjacencyInfo(long numNeighborsSize = O3DGC_MIN_NUM_NEIGHBORS_SIZE,
+ long neighborsSize = O3DGC_MIN_NUM_NEIGHBORS_SIZE)
+ {
+ m_numElements = 0;
+ m_neighborsSize = neighborsSize;
+ m_numNeighborsSize = numNeighborsSize;
+ m_numNeighbors = new long [m_numNeighborsSize];
+ m_neighbors = new long [m_neighborsSize ];
+ };
+ //! Destructor.
+ ~AdjacencyInfo(void)
+ {
+ delete [] m_neighbors;
+ delete [] m_numNeighbors;
+ };
+ O3DGCErrorCode Allocate(long numNeighborsSize, long neighborsSize)
+ {
+ m_numElements = numNeighborsSize;
+ if (neighborsSize > m_neighborsSize)
+ {
+ delete [] m_numNeighbors;
+ m_neighborsSize = neighborsSize;
+ m_numNeighbors = new long [m_numNeighborsSize];
+ }
+ if (numNeighborsSize > m_numNeighborsSize)
+ {
+ delete [] m_neighbors;
+ m_numNeighborsSize = numNeighborsSize;
+ m_neighbors = new long [m_neighborsSize];
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode AllocateNumNeighborsArray(long numElements)
+ {
+ if (numElements > m_numNeighborsSize)
+ {
+ delete [] m_numNeighbors;
+ m_numNeighborsSize = numElements;
+ m_numNeighbors = new long [m_numNeighborsSize];
+ }
+ m_numElements = numElements;
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode AllocateNeighborsArray()
+ {
+ for(long i = 1; i < m_numElements; ++i)
+ {
+ m_numNeighbors[i] += m_numNeighbors[i-1];
+ }
+ if (m_numNeighbors[m_numElements-1] > m_neighborsSize)
+ {
+ delete [] m_neighbors;
+ m_neighborsSize = m_numNeighbors[m_numElements-1];
+ m_neighbors = new long [m_neighborsSize];
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode ClearNumNeighborsArray()
+ {
+ memset(m_numNeighbors, 0x00, sizeof(long) * m_numElements);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode ClearNeighborsArray()
+ {
+ memset(m_neighbors, 0xFF, sizeof(long) * m_neighborsSize);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode AddNeighbor(long element, long neighbor)
+ {
+ assert(m_numNeighbors[element] <= m_numNeighbors[m_numElements-1]);
+ long p0 = Begin(element);
+ long p1 = End(element);
+ for(long p = p0; p < p1; p++)
+ {
+ if (m_neighbors[p] == -1)
+ {
+ m_neighbors[p] = neighbor;
+ return O3DGC_OK;
+ }
+ }
+ return O3DGC_ERROR_BUFFER_FULL;
+ }
+ long Begin(long element) const
+ {
+ assert(element < m_numElements);
+ assert(element >= 0);
+ return (element>0)?m_numNeighbors[element-1]:0;
+ }
+ long End(long element) const
+ {
+ assert(element < m_numElements);
+ assert(element >= 0);
+ return m_numNeighbors[element];
+ }
+ long GetNeighbor(long element) const
+ {
+ assert(element < m_neighborsSize);
+ assert(element >= 0);
+ return m_neighbors[element];
+ }
+ long GetNumNeighbors(long element) const
+ {
+ return End(element) - Begin(element);
+ }
+ long * GetNumNeighborsBuffer() { return m_numNeighbors;}
+ long * GetNeighborsBuffer() { return m_neighbors;}
+
+ private:
+ long m_neighborsSize; // actual allocated size for m_neighbors
+ long m_numNeighborsSize; // actual allocated size for m_numNeighbors
+ long m_numElements; // number of elements
+ long * m_neighbors; //
+ long * m_numNeighbors; //
+ };
+}
+#endif // O3DGC_ADJACENCY_INFO_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.cpp b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.cpp
new file mode 100644
index 000000000..3597ec39a
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.cpp
@@ -0,0 +1,865 @@
+/*
+Copyright (c) 2004 Amir Said (said@ieee.org) & William A. Pearlman (pearlw@ecse.rpi.edu)
+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.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER 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.
+
+*/
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// **************************** -
+// ARITHMETIC CODING EXAMPLES -
+// **************************** -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// Fast arithmetic coding implementation -
+// -> 32-bit variables, 32-bit product, periodic updates, table decoding -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// Version 1.00 - April 25, 2004 -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// WARNING -
+// ========= -
+// -
+// The only purpose of this program is to demonstrate the basic principles -
+// of arithmetic coding. It is provided as is, without any express or -
+// implied warranty, without even the warranty of fitness for any particular -
+// purpose, or that the implementations are correct. -
+// -
+// Permission to copy and redistribute this code is hereby granted, provided -
+// that this warning and copyright notices are not removed or altered. -
+// -
+// Copyright (c) 2004 by Amir Said (said@ieee.org) & -
+// William A. Pearlman (pearlw@ecse.rpi.edu) -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// A description of the arithmetic coding method used here is available in -
+// -
+// Lossless Compression Handbook, ed. K. Sayood -
+// Chapter 5: Arithmetic Coding (A. Said), pp. 101-152, Academic Press, 2003 -
+// -
+// A. Said, Introduction to Arithetic Coding Theory and Practice -
+// HP Labs report HPL-2004-76 - http://www.hpl.hp.com/techreports/ -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#include <stdlib.h>
+#include "o3dgcArithmeticCodec.h"
+
+namespace o3dgc
+{
+ // - - Constants - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ const unsigned AC__MinLength = 0x01000000U; // threshold for renormalization
+ const unsigned AC__MaxLength = 0xFFFFFFFFU; // maximum AC interval length
+
+ // Maximum values for binary models
+ const unsigned BM__LengthShift = 13; // length bits discarded before mult.
+ const unsigned BM__MaxCount = 1 << BM__LengthShift; // for adaptive models
+
+ // Maximum values for general models
+ const unsigned DM__LengthShift = 15; // length bits discarded before mult.
+ const unsigned DM__MaxCount = 1 << DM__LengthShift; // for adaptive models
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Static functions - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ static void AC_Error(const char * msg)
+ {
+ fprintf(stderr, "\n\n -> Arithmetic coding error: ");
+ fputs(msg, stderr);
+ fputs("\n Execution terminated!\n", stderr);
+ getchar();
+ exit(1);
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Coding implementations - - - - - - - - - - - - - - - - - - - - - - - -
+
+ inline void Arithmetic_Codec::propagate_carry(void)
+ {
+ unsigned char * p; // carry propagation on compressed data buffer
+ for (p = ac_pointer - 1; *p == 0xFFU; p--) *p = 0;
+ ++*p;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ inline void Arithmetic_Codec::renorm_enc_interval(void)
+ {
+ do { // output and discard top byte
+ *ac_pointer++ = (unsigned char)(base >> 24);
+ base <<= 8;
+ } while ((length <<= 8) < AC__MinLength); // length multiplied by 256
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ inline void Arithmetic_Codec::renorm_dec_interval(void)
+ {
+ do { // read least-significant byte
+ value = (value << 8) | unsigned(*++ac_pointer);
+ } while ((length <<= 8) < AC__MinLength); // length multiplied by 256
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::put_bit(unsigned bit)
+ {
+ #ifdef _DEBUG
+ if (mode != 1) AC_Error("encoder not initialized");
+ #endif
+
+ length >>= 1; // halve interval
+ if (bit) {
+ unsigned init_base = base;
+ base += length; // move base
+ if (init_base > base) propagate_carry(); // overflow = carry
+ }
+
+ if (length < AC__MinLength) renorm_enc_interval(); // renormalization
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::get_bit(void)
+ {
+ #ifdef _DEBUG
+ if (mode != 2) AC_Error("decoder not initialized");
+ #endif
+
+ length >>= 1; // halve interval
+ unsigned bit = (value >= length); // decode bit
+ if (bit) value -= length; // move base
+
+ if (length < AC__MinLength) renorm_dec_interval(); // renormalization
+
+ return bit; // return data bit value
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::put_bits(unsigned data, unsigned bits)
+ {
+ #ifdef _DEBUG
+ if (mode != 1) AC_Error("encoder not initialized");
+ if ((bits < 1) || (bits > 20)) AC_Error("invalid number of bits");
+ if (data >= (1U << bits)) AC_Error("invalid data");
+ #endif
+
+ unsigned init_base = base;
+ base += data * (length >>= bits); // new interval base and length
+
+ if (init_base > base) propagate_carry(); // overflow = carry
+ if (length < AC__MinLength) renorm_enc_interval(); // renormalization
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::get_bits(unsigned bits)
+ {
+ #ifdef _DEBUG
+ if (mode != 2) AC_Error("decoder not initialized");
+ if ((bits < 1) || (bits > 20)) AC_Error("invalid number of bits");
+ #endif
+
+ unsigned s = value / (length >>= bits); // decode symbol, change length
+
+ value -= length * s; // update interval
+ if (length < AC__MinLength) renorm_dec_interval(); // renormalization
+
+ return s;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::encode(unsigned bit,
+ Static_Bit_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 1) AC_Error("encoder not initialized");
+ #endif
+
+ unsigned x = M.bit_0_prob * (length >> BM__LengthShift); // product l x p0
+ // update interval
+ if (bit == 0)
+ length = x;
+ else {
+ unsigned init_base = base;
+ base += x;
+ length -= x;
+ if (init_base > base) propagate_carry(); // overflow = carry
+ }
+
+ if (length < AC__MinLength) renorm_enc_interval(); // renormalization
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::decode(Static_Bit_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 2) AC_Error("decoder not initialized");
+ #endif
+
+ unsigned x = M.bit_0_prob * (length >> BM__LengthShift); // product l x p0
+ unsigned bit = (value >= x); // decision
+ // update & shift interval
+ if (bit == 0)
+ length = x;
+ else {
+ value -= x; // shifted interval base = 0
+ length -= x;
+ }
+
+ if (length < AC__MinLength) renorm_dec_interval(); // renormalization
+
+ return bit; // return data bit value
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::encode(unsigned bit,
+ Adaptive_Bit_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 1) AC_Error("encoder not initialized");
+ #endif
+
+ unsigned x = M.bit_0_prob * (length >> BM__LengthShift); // product l x p0
+ // update interval
+ if (bit == 0) {
+ length = x;
+ ++M.bit_0_count;
+ }
+ else {
+ unsigned init_base = base;
+ base += x;
+ length -= x;
+ if (init_base > base) propagate_carry(); // overflow = carry
+ }
+
+ if (length < AC__MinLength) renorm_enc_interval(); // renormalization
+
+ if (--M.bits_until_update == 0) M.update(); // periodic model update
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::decode(Adaptive_Bit_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 2) AC_Error("decoder not initialized");
+ #endif
+
+ unsigned x = M.bit_0_prob * (length >> BM__LengthShift); // product l x p0
+ unsigned bit = (value >= x); // decision
+ // update interval
+ if (bit == 0) {
+ length = x;
+ ++M.bit_0_count;
+ }
+ else {
+ value -= x;
+ length -= x;
+ }
+
+ if (length < AC__MinLength) renorm_dec_interval(); // renormalization
+
+ if (--M.bits_until_update == 0) M.update(); // periodic model update
+
+ return bit; // return data bit value
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::encode(unsigned data,
+ Static_Data_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 1) AC_Error("encoder not initialized");
+ if (data >= M.data_symbols) AC_Error("invalid data symbol");
+ #endif
+
+ unsigned x, init_base = base;
+ // compute products
+ if (data == M.last_symbol) {
+ x = M.distribution[data] * (length >> DM__LengthShift);
+ base += x; // update interval
+ length -= x; // no product needed
+ }
+ else {
+ x = M.distribution[data] * (length >>= DM__LengthShift);
+ base += x; // update interval
+ length = M.distribution[data+1] * length - x;
+ }
+
+ if (init_base > base) propagate_carry(); // overflow = carry
+
+ if (length < AC__MinLength) renorm_enc_interval(); // renormalization
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::decode(Static_Data_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 2) AC_Error("decoder not initialized");
+ #endif
+
+ unsigned n, s, x, y = length;
+
+ if (M.decoder_table) { // use table look-up for faster decoding
+
+ unsigned dv = value / (length >>= DM__LengthShift);
+ unsigned t = dv >> M.table_shift;
+
+ s = M.decoder_table[t]; // initial decision based on table look-up
+ n = M.decoder_table[t+1] + 1;
+
+ while (n > s + 1) { // finish with bisection search
+ unsigned m = (s + n) >> 1;
+ if (M.distribution[m] > dv) n = m; else s = m;
+ }
+ // compute products
+ x = M.distribution[s] * length;
+ if (s != M.last_symbol) y = M.distribution[s+1] * length;
+ }
+
+ else { // decode using only multiplications
+
+ x = s = 0;
+ length >>= DM__LengthShift;
+ unsigned m = (n = M.data_symbols) >> 1;
+ // decode via bisection search
+ do {
+ unsigned z = length * M.distribution[m];
+ if (z > value) {
+ n = m;
+ y = z; // value is smaller
+ }
+ else {
+ s = m;
+ x = z; // value is larger or equal
+ }
+ } while ((m = (s + n) >> 1) != s);
+ }
+
+ value -= x; // update interval
+ length = y - x;
+
+ if (length < AC__MinLength) renorm_dec_interval(); // renormalization
+
+ return s;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::encode(unsigned data,
+ Adaptive_Data_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 1) AC_Error("encoder not initialized");
+ if (data >= M.data_symbols)
+ {
+ AC_Error("invalid data symbol");
+ }
+ #endif
+
+ unsigned x, init_base = base;
+ // compute products
+ if (data == M.last_symbol) {
+ x = M.distribution[data] * (length >> DM__LengthShift);
+ base += x; // update interval
+ length -= x; // no product needed
+ }
+ else {
+ x = M.distribution[data] * (length >>= DM__LengthShift);
+ base += x; // update interval
+ length = M.distribution[data+1] * length - x;
+ }
+
+ if (init_base > base) propagate_carry(); // overflow = carry
+
+ if (length < AC__MinLength) renorm_enc_interval(); // renormalization
+
+ ++M.symbol_count[data];
+ if (--M.symbols_until_update == 0) M.update(true); // periodic model update
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::decode(Adaptive_Data_Model & M)
+ {
+ #ifdef _DEBUG
+ if (mode != 2) AC_Error("decoder not initialized");
+ #endif
+
+ unsigned n, s, x, y = length;
+
+ if (M.decoder_table) { // use table look-up for faster decoding
+
+ unsigned dv = value / (length >>= DM__LengthShift);
+ unsigned t = dv >> M.table_shift;
+
+ s = M.decoder_table[t]; // initial decision based on table look-up
+ n = M.decoder_table[t+1] + 1;
+
+ while (n > s + 1) { // finish with bisection search
+ unsigned m = (s + n) >> 1;
+ if (M.distribution[m] > dv) n = m; else s = m;
+ }
+ // compute products
+ x = M.distribution[s] * length;
+ if (s != M.last_symbol) {
+ y = M.distribution[s+1] * length;
+ }
+ }
+
+ else { // decode using only multiplications
+
+ x = s = 0;
+ length >>= DM__LengthShift;
+ unsigned m = (n = M.data_symbols) >> 1;
+ // decode via bisection search
+ do {
+ unsigned z = length * M.distribution[m];
+ if (z > value) {
+ n = m;
+ y = z; // value is smaller
+ }
+ else {
+ s = m;
+ x = z; // value is larger or equal
+ }
+ } while ((m = (s + n) >> 1) != s);
+ }
+
+ value -= x; // update interval
+ length = y - x;
+
+ if (length < AC__MinLength) renorm_dec_interval(); // renormalization
+
+ ++M.symbol_count[s];
+ if (--M.symbols_until_update == 0) M.update(false); // periodic model update
+
+ return s;
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Other Arithmetic_Codec implementations - - - - - - - - - - - - - - - -
+
+ Arithmetic_Codec::Arithmetic_Codec(void)
+ {
+ mode = buffer_size = 0;
+ new_buffer = code_buffer = 0;
+ }
+
+ Arithmetic_Codec::Arithmetic_Codec(unsigned max_code_bytes,
+ unsigned char * user_buffer)
+ {
+ mode = buffer_size = 0;
+ new_buffer = code_buffer = 0;
+ set_buffer(max_code_bytes, user_buffer);
+ }
+
+ Arithmetic_Codec::~Arithmetic_Codec(void)
+ {
+ delete [] new_buffer;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::set_buffer(unsigned max_code_bytes,
+ unsigned char * user_buffer)
+ {
+ // test for reasonable sizes
+ if (!max_code_bytes)// || (max_code_bytes > 0x10000000U)) // updated by K. Mammou
+ {
+ AC_Error("invalid codec buffer size");
+ }
+ if (mode != 0) AC_Error("cannot set buffer while encoding or decoding");
+
+ if (user_buffer != 0) { // user provides memory buffer
+ buffer_size = max_code_bytes;
+ code_buffer = user_buffer; // set buffer for compressed data
+ delete [] new_buffer; // free anything previously assigned
+ new_buffer = 0;
+ return;
+ }
+
+ if (max_code_bytes <= buffer_size) return; // enough available
+
+ buffer_size = max_code_bytes; // assign new memory
+ delete [] new_buffer; // free anything previously assigned
+ if ((new_buffer = new unsigned char[buffer_size+16]) == 0) // 16 extra bytes
+ AC_Error("cannot assign memory for compressed data buffer");
+ code_buffer = new_buffer; // set buffer for compressed data
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::start_encoder(void)
+ {
+ if (mode != 0) AC_Error("cannot start encoder");
+ if (buffer_size == 0) AC_Error("no code buffer set");
+
+ mode = 1;
+ base = 0; // initialize encoder variables: interval and pointer
+ length = AC__MaxLength;
+ ac_pointer = code_buffer; // pointer to next data byte
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::start_decoder(void)
+ {
+ if (mode != 0) AC_Error("cannot start decoder");
+ if (buffer_size == 0) AC_Error("no code buffer set");
+
+ // initialize decoder: interval, pointer, initial code value
+ mode = 2;
+ length = AC__MaxLength;
+ ac_pointer = code_buffer + 3;
+ value = (unsigned(code_buffer[0]) << 24)|(unsigned(code_buffer[1]) << 16) |
+ (unsigned(code_buffer[2]) << 8)| unsigned(code_buffer[3]);
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::read_from_file(FILE * code_file)
+ {
+ unsigned shift = 0, code_bytes = 0;
+ int file_byte;
+ // read variable-length header with number of code bytes
+ do {
+ if ((file_byte = getc(code_file)) == EOF)
+ AC_Error("cannot read code from file");
+ code_bytes |= unsigned(file_byte & 0x7F) << shift;
+ shift += 7;
+ } while (file_byte & 0x80);
+ // read compressed data
+ if (code_bytes > buffer_size) AC_Error("code buffer overflow");
+ if (fread(code_buffer, 1, code_bytes, code_file) != code_bytes)
+ AC_Error("cannot read code from file");
+
+ start_decoder(); // initialize decoder
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::stop_encoder(void)
+ {
+ if (mode != 1) AC_Error("invalid to stop encoder");
+ mode = 0;
+
+ unsigned init_base = base; // done encoding: set final data bytes
+
+ if (length > 2 * AC__MinLength) {
+ base += AC__MinLength; // base offset
+ length = AC__MinLength >> 1; // set new length for 1 more byte
+ }
+ else {
+ base += AC__MinLength >> 1; // base offset
+ length = AC__MinLength >> 9; // set new length for 2 more bytes
+ }
+
+ if (init_base > base) propagate_carry(); // overflow = carry
+
+ renorm_enc_interval(); // renormalization = output last bytes
+
+ unsigned code_bytes = unsigned(ac_pointer - code_buffer);
+ if (code_bytes > buffer_size) AC_Error("code buffer overflow");
+
+ return code_bytes; // number of bytes used
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ unsigned Arithmetic_Codec::write_to_file(FILE * code_file)
+ {
+ unsigned header_bytes = 0, code_bytes = stop_encoder(), nb = code_bytes;
+
+ // write variable-length header with number of code bytes
+ do {
+ int file_byte = int(nb & 0x7FU);
+ if ((nb >>= 7) > 0) file_byte |= 0x80;
+ if (putc(file_byte, code_file) == EOF)
+ AC_Error("cannot write compressed data to file");
+ header_bytes++;
+ } while (nb);
+ // write compressed data
+ if (fwrite(code_buffer, 1, code_bytes, code_file) != code_bytes)
+ AC_Error("cannot write compressed data to file");
+
+ return code_bytes + header_bytes; // bytes used
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Arithmetic_Codec::stop_decoder(void)
+ {
+ if (mode != 2) AC_Error("invalid to stop decoder");
+ mode = 0;
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - Static bit model implementation - - - - - - - - - - - - - - - - - - - - -
+
+ Static_Bit_Model::Static_Bit_Model(void)
+ {
+ bit_0_prob = 1U << (BM__LengthShift - 1); // p0 = 0.5
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Static_Bit_Model::set_probability_0(double p0)
+ {
+ if ((p0 < 0.0001)||(p0 > 0.9999)) AC_Error("invalid bit probability");
+ bit_0_prob = unsigned(p0 * (1 << BM__LengthShift));
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - Adaptive bit model implementation - - - - - - - - - - - - - - - - - - - -
+
+ Adaptive_Bit_Model::Adaptive_Bit_Model(void)
+ {
+ reset();
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Adaptive_Bit_Model::reset(void)
+ {
+ // initialization to equiprobable model
+ bit_0_count = 1;
+ bit_count = 2;
+ bit_0_prob = 1U << (BM__LengthShift - 1);
+ update_cycle = bits_until_update = 4; // start with frequent updates
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Adaptive_Bit_Model::update(void)
+ {
+ // halve counts when a threshold is reached
+
+ if ((bit_count += update_cycle) > BM__MaxCount) {
+ bit_count = (bit_count + 1) >> 1;
+ bit_0_count = (bit_0_count + 1) >> 1;
+ if (bit_0_count == bit_count) ++bit_count;
+ }
+ // compute scaled bit 0 probability
+ unsigned scale = 0x80000000U / bit_count;
+ bit_0_prob = (bit_0_count * scale) >> (31 - BM__LengthShift);
+
+ // set frequency of model updates
+ update_cycle = (5 * update_cycle) >> 2;
+ if (update_cycle > 64) update_cycle = 64;
+ bits_until_update = update_cycle;
+ }
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Static data model implementation - - - - - - - - - - - - - - - - - - -
+
+ Static_Data_Model::Static_Data_Model(void)
+ {
+ data_symbols = 0;
+ distribution = 0;
+ }
+
+ Static_Data_Model::~Static_Data_Model(void)
+ {
+ delete [] distribution;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Static_Data_Model::set_distribution(unsigned number_of_symbols,
+ const double probability[])
+ {
+ if ((number_of_symbols < 2) || (number_of_symbols > (1 << 11)))
+ AC_Error("invalid number of data symbols");
+
+ if (data_symbols != number_of_symbols) { // assign memory for data model
+ data_symbols = number_of_symbols;
+ last_symbol = data_symbols - 1;
+ delete [] distribution;
+ // define size of table for fast decoding
+ if (data_symbols > 16) {
+ unsigned table_bits = 3;
+ while (data_symbols > (1U << (table_bits + 2))) ++table_bits;
+ table_size = 1 << table_bits;
+ table_shift = DM__LengthShift - table_bits;
+ distribution = new unsigned[data_symbols+table_size+2];
+ decoder_table = distribution + data_symbols;
+ }
+ else { // small alphabet: no table needed
+ decoder_table = 0;
+ table_size = table_shift = 0;
+ distribution = new unsigned[data_symbols];
+ }
+ if (distribution == 0) AC_Error("cannot assign model memory");
+ }
+ // compute cumulative distribution, decoder table
+ unsigned s = 0;
+ double sum = 0.0, p = 1.0 / double(data_symbols);
+
+ for (unsigned k = 0; k < data_symbols; k++) {
+ if (probability) p = probability[k];
+ if ((p < 0.0001) || (p > 0.9999)) AC_Error("invalid symbol probability");
+ distribution[k] = unsigned(sum * (1 << DM__LengthShift));
+ sum += p;
+ if (table_size == 0) continue;
+ unsigned w = distribution[k] >> table_shift;
+ while (s < w) decoder_table[++s] = k - 1;
+ }
+
+ if (table_size != 0) {
+ decoder_table[0] = 0;
+ while (s <= table_size) decoder_table[++s] = data_symbols - 1;
+ }
+
+ if ((sum < 0.9999) || (sum > 1.0001)) AC_Error("invalid probabilities");
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Adaptive data model implementation - - - - - - - - - - - - - - - - - -
+
+ Adaptive_Data_Model::Adaptive_Data_Model(void)
+ {
+ data_symbols = 0;
+ distribution = 0;
+ }
+
+ Adaptive_Data_Model::Adaptive_Data_Model(unsigned number_of_symbols)
+ {
+ data_symbols = 0;
+ distribution = 0;
+ set_alphabet(number_of_symbols);
+ }
+
+ Adaptive_Data_Model::~Adaptive_Data_Model(void)
+ {
+ delete [] distribution;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Adaptive_Data_Model::set_alphabet(unsigned number_of_symbols)
+ {
+ if ((number_of_symbols < 2) || (number_of_symbols > (1 << 11)))
+ AC_Error("invalid number of data symbols");
+
+ if (data_symbols != number_of_symbols) { // assign memory for data model
+ data_symbols = number_of_symbols;
+ last_symbol = data_symbols - 1;
+ delete [] distribution;
+ // define size of table for fast decoding
+ if (data_symbols > 16) {
+ unsigned table_bits = 3;
+ while (data_symbols > (1U << (table_bits + 2))) ++table_bits;
+ table_size = 1 << table_bits;
+ table_shift = DM__LengthShift - table_bits;
+ distribution = new unsigned[2*data_symbols+table_size+2];
+ decoder_table = distribution + 2 * data_symbols;
+ }
+ else { // small alphabet: no table needed
+ decoder_table = 0;
+ table_size = table_shift = 0;
+ distribution = new unsigned[2*data_symbols];
+ }
+ symbol_count = distribution + data_symbols;
+ if (distribution == 0) AC_Error("cannot assign model memory");
+ }
+
+ reset(); // initialize model
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Adaptive_Data_Model::update(bool from_encoder)
+ {
+ // halve counts when a threshold is reached
+
+ if ((total_count += update_cycle) > DM__MaxCount) {
+ total_count = 0;
+ for (unsigned n = 0; n < data_symbols; n++)
+ total_count += (symbol_count[n] = (symbol_count[n] + 1) >> 1);
+ }
+ assert(total_count > 0);
+ // compute cumulative distribution, decoder table
+ unsigned k, sum = 0, s = 0;
+ unsigned scale = 0x80000000U / total_count;
+
+ if (from_encoder || (table_size == 0))
+ for (k = 0; k < data_symbols; k++) {
+ distribution[k] = (scale * sum) >> (31 - DM__LengthShift);
+ sum += symbol_count[k];
+ }
+ else {
+ assert(decoder_table);
+ for (k = 0; k < data_symbols; k++) {
+ distribution[k] = (scale * sum) >> (31 - DM__LengthShift);
+ sum += symbol_count[k];
+ unsigned w = distribution[k] >> table_shift;
+ while (s < w) decoder_table[++s] = k - 1;
+ }
+ decoder_table[0] = 0;
+ while (s <= table_size) decoder_table[++s] = data_symbols - 1;
+ }
+ // set frequency of model updates
+ update_cycle = (5 * update_cycle) >> 2;
+ unsigned max_cycle = (data_symbols + 6) << 3;
+ if (update_cycle > max_cycle) update_cycle = max_cycle;
+ symbols_until_update = update_cycle;
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ void Adaptive_Data_Model::reset(void)
+ {
+ if (data_symbols == 0) return;
+
+ // restore probability estimates to uniform distribution
+ total_count = 0;
+ update_cycle = data_symbols;
+ for (unsigned k = 0; k < data_symbols; k++) symbol_count[k] = 1;
+ update(false);
+ symbols_until_update = update_cycle = (data_symbols + 6) >> 1;
+ }
+}
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.h
new file mode 100644
index 000000000..d3cf6d14a
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.h
@@ -0,0 +1,339 @@
+/*
+Copyright (c) 2004 Amir Said (said@ieee.org) & William A. Pearlman (pearlw@ecse.rpi.edu)
+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.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER 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.
+*/
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// **************************** -
+// ARITHMETIC CODING EXAMPLES -
+// **************************** -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// Fast arithmetic coding implementation -
+// -> 32-bit variables, 32-bit product, periodic updates, table decoding -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// Version 1.00 - April 25, 2004 -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// WARNING -
+// ========= -
+// -
+// The only purpose of this program is to demonstrate the basic principles -
+// of arithmetic coding. It is provided as is, without any express or -
+// implied warranty, without even the warranty of fitness for any particular -
+// purpose, or that the implementations are correct. -
+// -
+// Permission to copy and redistribute this code is hereby granted, provided -
+// that this warning and copyright notices are not removed or altered. -
+// -
+// Copyright (c) 2004 by Amir Said (said@ieee.org) & -
+// William A. Pearlman (pearlw@ecse.rpi.edu) -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// -
+// A description of the arithmetic coding method used here is available in -
+// -
+// Lossless Compression Handbook, ed. K. Sayood -
+// Chapter 5: Arithmetic Coding (A. Said), pp. 101-152, Academic Press, 2003 -
+// -
+// A. Said, Introduction to Arithetic Coding Theory and Practice -
+// HP Labs report HPL-2004-76 - http://www.hpl.hp.com/techreports/ -
+// -
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+// - - Definitions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#ifndef O3DGC_ARITHMETIC_CODEC
+#define O3DGC_ARITHMETIC_CODEC
+
+#include <stdio.h>
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Class definitions - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ class Static_Bit_Model // static model for binary data
+ {
+ public:
+
+ Static_Bit_Model(void);
+
+ void set_probability_0(double); // set probability of symbol '0'
+
+ private: // . . . . . . . . . . . . . . . . . . . . . .
+ unsigned bit_0_prob;
+ friend class Arithmetic_Codec;
+ };
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ class Static_Data_Model // static model for general data
+ {
+ public:
+
+ Static_Data_Model(void);
+ ~Static_Data_Model(void);
+
+ unsigned model_symbols(void) { return data_symbols; }
+
+ void set_distribution(unsigned number_of_symbols,
+ const double probability[] = 0); // 0 means uniform
+
+ private: // . . . . . . . . . . . . . . . . . . . . . .
+ unsigned * distribution, * decoder_table;
+ unsigned data_symbols, last_symbol, table_size, table_shift;
+ friend class Arithmetic_Codec;
+ };
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ class Adaptive_Bit_Model // adaptive model for binary data
+ {
+ public:
+
+ Adaptive_Bit_Model(void);
+
+ void reset(void); // reset to equiprobable model
+
+ private: // . . . . . . . . . . . . . . . . . . . . . .
+ void update(void);
+ unsigned update_cycle, bits_until_update;
+ unsigned bit_0_prob, bit_0_count, bit_count;
+ friend class Arithmetic_Codec;
+ };
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ class Adaptive_Data_Model // adaptive model for binary data
+ {
+ public:
+
+ Adaptive_Data_Model(void);
+ Adaptive_Data_Model(unsigned number_of_symbols);
+ ~Adaptive_Data_Model(void);
+
+ unsigned model_symbols(void) { return data_symbols; }
+
+ void reset(void); // reset to equiprobable model
+ void set_alphabet(unsigned number_of_symbols);
+
+ private: // . . . . . . . . . . . . . . . . . . . . . .
+ void update(bool);
+ unsigned * distribution, * symbol_count, * decoder_table;
+ unsigned total_count, update_cycle, symbols_until_update;
+ unsigned data_symbols, last_symbol, table_size, table_shift;
+ friend class Arithmetic_Codec;
+ };
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // - - Encoder and decoder class - - - - - - - - - - - - - - - - - - - - - - -
+
+ // Class with both the arithmetic encoder and decoder. All compressed data is
+ // saved to a memory buffer
+
+ class Arithmetic_Codec
+ {
+ public:
+
+ Arithmetic_Codec(void);
+ ~Arithmetic_Codec(void);
+ Arithmetic_Codec(unsigned max_code_bytes,
+ unsigned char * user_buffer = 0); // 0 = assign new
+
+ unsigned char * buffer(void) { return code_buffer; }
+
+ void set_buffer(unsigned max_code_bytes,
+ unsigned char * user_buffer = 0); // 0 = assign new
+
+ void start_encoder(void);
+ void start_decoder(void);
+ void read_from_file(FILE * code_file); // read code data, start decoder
+
+ unsigned stop_encoder(void); // returns number of bytes used
+ unsigned write_to_file(FILE * code_file); // stop encoder, write code data
+ void stop_decoder(void);
+
+ void put_bit(unsigned bit);
+ unsigned get_bit(void);
+
+ void put_bits(unsigned data, unsigned number_of_bits);
+ unsigned get_bits(unsigned number_of_bits);
+
+ void encode(unsigned bit,
+ Static_Bit_Model &);
+ unsigned decode(Static_Bit_Model &);
+
+ void encode(unsigned data,
+ Static_Data_Model &);
+ unsigned decode(Static_Data_Model &);
+
+ void encode(unsigned bit,
+ Adaptive_Bit_Model &);
+ unsigned decode(Adaptive_Bit_Model &);
+
+ void encode(unsigned data,
+ Adaptive_Data_Model &);
+ unsigned decode(Adaptive_Data_Model &);
+
+// This section was added by K. Mammou
+ void ExpGolombEncode(unsigned int symbol,
+ int k,
+ Static_Bit_Model & bModel0,
+ Adaptive_Bit_Model & bModel1)
+ {
+ while(1)
+ {
+ if (symbol >= (unsigned int)(1<<k))
+ {
+ encode(1, bModel1);
+ symbol = symbol - (1<<k);
+ k++;
+ }
+ else
+ {
+ encode(0, bModel1); // now terminated zero of unary part
+ while (k--) // next binary part
+ {
+ encode((signed short)((symbol>>k)&1), bModel0);
+ }
+ break;
+ }
+ }
+ }
+
+
+ unsigned ExpGolombDecode(int k,
+ Static_Bit_Model & bModel0,
+ Adaptive_Bit_Model & bModel1)
+ {
+ unsigned int l;
+ int symbol = 0;
+ int binary_symbol = 0;
+ do
+ {
+ l=decode(bModel1);
+ if (l==1)
+ {
+ symbol += (1<<k);
+ k++;
+ }
+ }
+ while (l!=0);
+ while (k--) //next binary part
+ if (decode(bModel0)==1)
+ {
+ binary_symbol |= (1<<k);
+ }
+ return (unsigned int) (symbol+binary_symbol);
+ }
+//----------------------------------------------------------
+
+ private: // . . . . . . . . . . . . . . . . . . . . . .
+ void propagate_carry(void);
+ void renorm_enc_interval(void);
+ void renorm_dec_interval(void);
+ unsigned char * code_buffer, * new_buffer, * ac_pointer;
+ unsigned base, value, length; // arithmetic coding state
+ unsigned buffer_size, mode; // mode: 0 = undef, 1 = encoder, 2 = decoder
+ };
+ inline long DecodeIntACEGC(Arithmetic_Codec & acd,
+ Adaptive_Data_Model & mModelValues,
+ Static_Bit_Model & bModel0,
+ Adaptive_Bit_Model & bModel1,
+ const unsigned long exp_k,
+ const unsigned long M)
+ {
+ unsigned long uiValue = acd.decode(mModelValues);
+ if (uiValue == M)
+ {
+ uiValue += acd.ExpGolombDecode(exp_k, bModel0, bModel1);
+ }
+ return UIntToInt(uiValue);
+ }
+ inline unsigned long DecodeUIntACEGC(Arithmetic_Codec & acd,
+ Adaptive_Data_Model & mModelValues,
+ Static_Bit_Model & bModel0,
+ Adaptive_Bit_Model & bModel1,
+ const unsigned long exp_k,
+ const unsigned long M)
+ {
+ unsigned long uiValue = acd.decode(mModelValues);
+ if (uiValue == M)
+ {
+ uiValue += acd.ExpGolombDecode(exp_k, bModel0, bModel1);
+ }
+ return uiValue;
+ }
+
+ inline void EncodeIntACEGC(long predResidual,
+ Arithmetic_Codec & ace,
+ Adaptive_Data_Model & mModelValues,
+ Static_Bit_Model & bModel0,
+ Adaptive_Bit_Model & bModel1,
+ const unsigned long M)
+ {
+ unsigned long uiValue = IntToUInt(predResidual);
+ if (uiValue < M)
+ {
+ ace.encode(uiValue, mModelValues);
+ }
+ else
+ {
+ ace.encode(M, mModelValues);
+ ace.ExpGolombEncode(uiValue-M, 0, bModel0, bModel1);
+ }
+ }
+ inline void EncodeUIntACEGC(long predResidual,
+ Arithmetic_Codec & ace,
+ Adaptive_Data_Model & mModelValues,
+ Static_Bit_Model & bModel0,
+ Adaptive_Bit_Model & bModel1,
+ const unsigned long M)
+ {
+ unsigned long uiValue = (unsigned long) predResidual;
+ if (uiValue < M)
+ {
+ ace.encode(uiValue, mModelValues);
+ }
+ else
+ {
+ ace.encode(M, mModelValues);
+ ace.ExpGolombEncode(uiValue-M, 0, bModel0, bModel1);
+ }
+ }
+
+}
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#endif
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcBinaryStream.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcBinaryStream.h
new file mode 100644
index 000000000..b7b7678b7
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcBinaryStream.h
@@ -0,0 +1,433 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_BINARY_STREAM_H
+#define O3DGC_BINARY_STREAM_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcVector.h"
+
+namespace o3dgc
+{
+ const unsigned long O3DGC_BINARY_STREAM_DEFAULT_SIZE = 4096;
+ const unsigned long O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0 = 7;
+ const unsigned long O3DGC_BINARY_STREAM_MAX_SYMBOL0 = (1 << O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0) - 1;
+ const unsigned long O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1 = 6;
+ const unsigned long O3DGC_BINARY_STREAM_MAX_SYMBOL1 = (1 << O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1) - 1;
+ const unsigned long O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32 = (32+O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0-1) /
+ O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0;
+
+ //!
+ class BinaryStream
+ {
+ public:
+ //! Constructor.
+ BinaryStream(unsigned long size = O3DGC_BINARY_STREAM_DEFAULT_SIZE)
+ {
+ m_endianness = SystemEndianness();
+ m_stream.Allocate(size);
+ };
+ //! Destructor.
+ ~BinaryStream(void){};
+
+ void WriteFloat32(float value, O3DGCStreamType streamType)
+ {
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ WriteFloat32ASCII(value);
+ }
+ else
+ {
+ WriteFloat32Bin(value);
+ }
+ }
+ void WriteUInt32(unsigned long position, unsigned long value, O3DGCStreamType streamType)
+ {
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ WriteUInt32ASCII(position, value);
+ }
+ else
+ {
+ WriteUInt32Bin(position, value);
+ }
+ }
+ void WriteUInt32(unsigned long value, O3DGCStreamType streamType)
+ {
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ WriteUInt32ASCII(value);
+ }
+ else
+ {
+ WriteUInt32Bin(value);
+ }
+ }
+ void WriteUChar(unsigned int position, unsigned char value, O3DGCStreamType streamType)
+ {
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ WriteUInt32ASCII(position, value);
+ }
+ else
+ {
+ WriteUInt32Bin(position, value);
+ }
+ }
+ void WriteUChar(unsigned char value, O3DGCStreamType streamType)
+ {
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ WriteUCharASCII(value);
+ }
+ else
+ {
+ WriteUChar8Bin(value);
+ }
+ }
+ float ReadFloat32(unsigned long & position, O3DGCStreamType streamType) const
+ {
+ float value;
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ value = ReadFloat32ASCII(position);
+ }
+ else
+ {
+ value = ReadFloat32Bin(position);
+ }
+ return value;
+ }
+ unsigned long ReadUInt32(unsigned long & position, O3DGCStreamType streamType) const
+ {
+ unsigned long value;
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ value = ReadUInt32ASCII(position);
+ }
+ else
+ {
+ value = ReadUInt32Bin(position);
+ }
+ return value;
+ }
+ unsigned char ReadUChar(unsigned long & position, O3DGCStreamType streamType) const
+ {
+ unsigned char value;
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ value = ReadUCharASCII(position);
+ }
+ else
+ {
+ value = ReadUChar8Bin(position);
+ }
+ return value;
+ }
+
+ void WriteFloat32Bin(unsigned long position, float value)
+ {
+ assert(position < m_stream.GetSize() - 4);
+ unsigned char * ptr = (unsigned char *) (&value);
+ if (m_endianness == O3DGC_BIG_ENDIAN)
+ {
+ m_stream[position++] = ptr[3];
+ m_stream[position++] = ptr[2];
+ m_stream[position++] = ptr[1];
+ m_stream[position ] = ptr[0];
+ }
+ else
+ {
+ m_stream[position++] = ptr[0];
+ m_stream[position++] = ptr[1];
+ m_stream[position++] = ptr[2];
+ m_stream[position ] = ptr[3];
+ }
+ }
+ void WriteFloat32Bin(float value)
+ {
+ unsigned char * ptr = (unsigned char *) (&value);
+ if (m_endianness == O3DGC_BIG_ENDIAN)
+ {
+ m_stream.PushBack(ptr[3]);
+ m_stream.PushBack(ptr[2]);
+ m_stream.PushBack(ptr[1]);
+ m_stream.PushBack(ptr[0]);
+ }
+ else
+ {
+ m_stream.PushBack(ptr[0]);
+ m_stream.PushBack(ptr[1]);
+ m_stream.PushBack(ptr[2]);
+ m_stream.PushBack(ptr[3]);
+ }
+ }
+ void WriteUInt32Bin(unsigned long position, unsigned long value)
+ {
+ assert(position < m_stream.GetSize() - 4);
+ unsigned char * ptr = (unsigned char *) (&value);
+ if (m_endianness == O3DGC_BIG_ENDIAN)
+ {
+ m_stream[position++] = ptr[3];
+ m_stream[position++] = ptr[2];
+ m_stream[position++] = ptr[1];
+ m_stream[position ] = ptr[0];
+ }
+ else
+ {
+ m_stream[position++] = ptr[0];
+ m_stream[position++] = ptr[1];
+ m_stream[position++] = ptr[2];
+ m_stream[position ] = ptr[3];
+ }
+ }
+ void WriteUInt32Bin(unsigned long value)
+ {
+ unsigned char * ptr = (unsigned char *) (&value);
+ if (m_endianness == O3DGC_BIG_ENDIAN)
+ {
+ m_stream.PushBack(ptr[3]);
+ m_stream.PushBack(ptr[2]);
+ m_stream.PushBack(ptr[1]);
+ m_stream.PushBack(ptr[0]);
+ }
+ else
+ {
+ m_stream.PushBack(ptr[0]);
+ m_stream.PushBack(ptr[1]);
+ m_stream.PushBack(ptr[2]);
+ m_stream.PushBack(ptr[3]);
+ }
+ }
+ void WriteUChar8Bin(unsigned int position, unsigned char value)
+ {
+ m_stream[position] = value;
+ }
+ void WriteUChar8Bin(unsigned char value)
+ {
+ m_stream.PushBack(value);
+ }
+ float ReadFloat32Bin(unsigned long & position) const
+ {
+ unsigned long value = ReadUInt32Bin(position);
+ float fvalue;
+ memcpy(&fvalue, &value, 4);
+ return fvalue;
+ }
+ unsigned long ReadUInt32Bin(unsigned long & position) const
+ {
+ assert(position < m_stream.GetSize() - 4);
+ unsigned long value = 0;
+ if (m_endianness == O3DGC_BIG_ENDIAN)
+ {
+ value += (m_stream[position++]<<24);
+ value += (m_stream[position++]<<16);
+ value += (m_stream[position++]<<8);
+ value += (m_stream[position++]);
+ }
+ else
+ {
+ value += (m_stream[position++]);
+ value += (m_stream[position++]<<8);
+ value += (m_stream[position++]<<16);
+ value += (m_stream[position++]<<24);
+ }
+ return value;
+ }
+ unsigned char ReadUChar8Bin(unsigned long & position) const
+ {
+ return m_stream[position++];
+ }
+
+ void WriteFloat32ASCII(float value)
+ {
+ unsigned long uiValue;
+ memcpy(&uiValue, &value, 4);
+ WriteUInt32ASCII(uiValue);
+ }
+ void WriteUInt32ASCII(unsigned long position, unsigned long value)
+ {
+ assert(position < m_stream.GetSize() - O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32);
+ unsigned long value0 = value;
+ for(unsigned long i = 0; i < O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32; ++i)
+ {
+ m_stream[position++] = (value0 & O3DGC_BINARY_STREAM_MAX_SYMBOL0);
+ value0 >>= O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0;
+ }
+ }
+ void WriteUInt32ASCII(unsigned long value)
+ {
+ for(unsigned long i = 0; i < O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32; ++i)
+ {
+ m_stream.PushBack(value & O3DGC_BINARY_STREAM_MAX_SYMBOL0);
+ value >>= O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0;
+ }
+ }
+ void WriteIntASCII(long value)
+ {
+ WriteUIntASCII(IntToUInt(value));
+ }
+ void WriteUIntASCII(unsigned long value)
+ {
+ if (value >= O3DGC_BINARY_STREAM_MAX_SYMBOL0)
+ {
+ m_stream.PushBack(O3DGC_BINARY_STREAM_MAX_SYMBOL0);
+ value -= O3DGC_BINARY_STREAM_MAX_SYMBOL0;
+ unsigned char a, b;
+ do
+ {
+ a = ((value & O3DGC_BINARY_STREAM_MAX_SYMBOL1) << 1);
+ b = ( (value >>= O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1) > 0);
+ a += b;
+ m_stream.PushBack(a);
+ } while (b);
+ }
+ else
+ {
+ m_stream.PushBack((unsigned char) value);
+ }
+ }
+ void WriteUCharASCII(unsigned char value)
+ {
+ assert(value <= O3DGC_BINARY_STREAM_MAX_SYMBOL0);
+ m_stream.PushBack(value);
+ }
+ float ReadFloat32ASCII(unsigned long & position) const
+ {
+ unsigned long value = ReadUInt32ASCII(position);
+ float fvalue;
+ memcpy(&fvalue, &value, 4);
+ return fvalue;
+ }
+ unsigned long ReadUInt32ASCII(unsigned long & position) const
+ {
+ assert(position < m_stream.GetSize() - O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32);
+ unsigned long value = 0;
+ unsigned long shift = 0;
+ for(unsigned long i = 0; i < O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32; ++i)
+ {
+ value += (m_stream[position++] << shift);
+ shift += O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0;
+ }
+ return value;
+ }
+ long ReadIntASCII(unsigned long & position) const
+ {
+ return UIntToInt(ReadUIntASCII(position));
+ }
+ unsigned long ReadUIntASCII(unsigned long & position) const
+ {
+ unsigned long value = m_stream[position++];
+ if (value == O3DGC_BINARY_STREAM_MAX_SYMBOL0)
+ {
+ long x;
+ unsigned long i = 0;
+ do
+ {
+ x = m_stream[position++];
+ value += ( (x>>1) << i);
+ i += O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1;
+ } while (x & 1);
+ }
+ return value;
+ }
+ unsigned char ReadUCharASCII(unsigned long & position) const
+ {
+ return m_stream[position++];
+ }
+ O3DGCErrorCode Save(const char * const fileName)
+ {
+ FILE * fout = fopen(fileName, "wb");
+ if (!fout)
+ {
+ return O3DGC_ERROR_CREATE_FILE;
+ }
+ fwrite(m_stream.GetBuffer(), 1, m_stream.GetSize(), fout);
+ fclose(fout);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode Load(const char * const fileName)
+ {
+ FILE * fin = fopen(fileName, "rb");
+ if (!fin)
+ {
+ return O3DGC_ERROR_OPEN_FILE;
+ }
+ fseek(fin, 0, SEEK_END);
+ unsigned long size = ftell(fin);
+ m_stream.Allocate(size);
+ rewind(fin);
+ unsigned int nread = (unsigned int) fread((void *) m_stream.GetBuffer(), 1, size, fin);
+ m_stream.SetSize(size);
+ if (nread != size)
+ {
+ return O3DGC_ERROR_READ_FILE;
+ }
+ fclose(fin);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadFromBuffer(unsigned char * buffer, unsigned long bufferSize)
+ {
+ m_stream.Allocate(bufferSize);
+ memcpy(m_stream.GetBuffer(), buffer, bufferSize);
+ m_stream.SetSize(bufferSize);
+ return O3DGC_OK;
+ }
+ unsigned long GetSize() const
+ {
+ return m_stream.GetSize();
+ }
+ const unsigned char * GetBuffer(unsigned long position) const
+ {
+ return m_stream.GetBuffer() + position;
+ }
+ unsigned char * GetBuffer(unsigned long position)
+ {
+ return (m_stream.GetBuffer() + position);
+ }
+ unsigned char * GetBuffer()
+ {
+ return m_stream.GetBuffer();
+ }
+ void GetBuffer(unsigned long position, unsigned char * & buffer) const
+ {
+ buffer = (unsigned char *) (m_stream.GetBuffer() + position); // fix me: ugly!
+ }
+ void SetSize(unsigned long size)
+ {
+ m_stream.SetSize(size);
+ };
+ void Allocate(unsigned long size)
+ {
+ m_stream.Allocate(size);
+ }
+
+ private:
+ Vector<unsigned char> m_stream;
+ O3DGCEndianness m_endianness;
+ };
+
+}
+#endif // O3DGC_BINARY_STREAM_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcCommon.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcCommon.h
new file mode 100644
index 000000000..ff6bf7558
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcCommon.h
@@ -0,0 +1,412 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_COMMON_H
+#define O3DGC_COMMON_H
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+namespace o3dgc
+{
+ typedef float Real;
+ const double O3DGC_MAX_DOUBLE = 1.79769e+308;
+ const long O3DGC_MIN_LONG = -2147483647;
+ const long O3DGC_MAX_LONG = 2147483647;
+ const long O3DGC_MAX_UCHAR8 = 255;
+ const long O3DGC_MAX_TFAN_SIZE = 256;
+ const unsigned long O3DGC_MAX_ULONG = 4294967295;
+
+ const unsigned long O3DGC_SC3DMC_START_CODE = 0x00001F1;
+ const unsigned long O3DGC_DV_START_CODE = 0x00001F2;
+ const unsigned long O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES = 256;
+ const unsigned long O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES = 256;
+ const unsigned long O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES = 32;
+
+ const unsigned long O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS = 2;
+ const unsigned long O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS = 257;
+
+ enum O3DGCEndianness
+ {
+ O3DGC_BIG_ENDIAN = 0,
+ O3DGC_LITTLE_ENDIAN = 1
+ };
+ enum O3DGCErrorCode
+ {
+ O3DGC_OK,
+ O3DGC_ERROR_BUFFER_FULL,
+ O3DGC_ERROR_CREATE_FILE,
+ O3DGC_ERROR_OPEN_FILE,
+ O3DGC_ERROR_READ_FILE,
+ O3DGC_ERROR_CORRUPTED_STREAM,
+ O3DGC_ERROR_NON_SUPPORTED_FEATURE
+ };
+ enum O3DGCSC3DMCBinarization
+ {
+ O3DGC_SC3DMC_BINARIZATION_FL = 0, // Fixed Length (not supported)
+ O3DGC_SC3DMC_BINARIZATION_BP = 1, // BPC (not supported)
+ O3DGC_SC3DMC_BINARIZATION_FC = 2, // 4 bits Coding (not supported)
+ O3DGC_SC3DMC_BINARIZATION_AC = 3, // Arithmetic Coding (not supported)
+ O3DGC_SC3DMC_BINARIZATION_AC_EGC = 4, // Arithmetic Coding & EGCk
+ O3DGC_SC3DMC_BINARIZATION_ASCII = 5 // Arithmetic Coding & EGCk
+ };
+ enum O3DGCStreamType
+ {
+ O3DGC_STREAM_TYPE_UNKOWN = 0,
+ O3DGC_STREAM_TYPE_ASCII = 1,
+ O3DGC_STREAM_TYPE_BINARY = 2
+ };
+ enum O3DGCSC3DMCQuantizationMode
+ {
+ O3DGC_SC3DMC_DIAG_BB = 0, // supported
+ O3DGC_SC3DMC_MAX_ALL_DIMS = 1, // supported
+ O3DGC_SC3DMC_MAX_SEP_DIM = 2 // supported
+ };
+ enum O3DGCSC3DMCPredictionMode
+ {
+ O3DGC_SC3DMC_NO_PREDICTION = 0, // supported
+ O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION = 1, // supported
+ O3DGC_SC3DMC_XOR_PREDICTION = 2, // not supported
+ O3DGC_SC3DMC_ADAPTIVE_DIFFERENTIAL_PREDICTION = 3, // not supported
+ O3DGC_SC3DMC_CIRCULAR_DIFFERENTIAL_PREDICTION = 4, // not supported
+ O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION = 5, // supported
+ O3DGC_SC3DMC_SURF_NORMALS_PREDICTION = 6 // supported
+ };
+ enum O3DGCSC3DMCEncodingMode
+ {
+ O3DGC_SC3DMC_ENCODE_MODE_QBCR = 0, // not supported
+ O3DGC_SC3DMC_ENCODE_MODE_SVA = 1, // not supported
+ O3DGC_SC3DMC_ENCODE_MODE_TFAN = 2, // supported
+ };
+ enum O3DGCDVEncodingMode
+ {
+ O3DGC_DYNAMIC_VECTOR_ENCODE_MODE_LIFT = 0
+ };
+ enum O3DGCIFSFloatAttributeType
+ {
+ O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_UNKOWN = 0,
+ O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_POSITION = 1,
+ O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_NORMAL = 2,
+ O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_COLOR = 3,
+ O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD = 4,
+ O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_WEIGHT = 5
+
+ };
+ enum O3DGCIFSIntAttributeType
+ {
+ O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN = 0,
+ O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX = 1,
+ O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID = 2,
+ O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID = 3
+ };
+
+ template<class T>
+ inline const T absolute(const T& a)
+ {
+ return (a < (T)(0)) ? -a : a;
+ }
+ template<class T>
+ inline const T min(const T& a, const T& b)
+ {
+ return (b < a) ? b : a;
+ }
+ template<class T>
+ inline const T max(const T& a, const T& b)
+ {
+ return (b > a) ? b : a;
+ }
+ template<class T>
+ inline void swap(T& a, T& b)
+ {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+ inline double log2( double n )
+ {
+ return log(n) / log(2.0);
+ }
+
+ inline O3DGCEndianness SystemEndianness()
+ {
+ unsigned long num = 1;
+ return ( *((char *)(&num)) == 1 )? O3DGC_LITTLE_ENDIAN : O3DGC_BIG_ENDIAN ;
+ }
+ class SC3DMCStats
+ {
+ public:
+ SC3DMCStats(void)
+ {
+ memset(this, 0, sizeof(SC3DMCStats));
+ };
+ ~SC3DMCStats(void){};
+
+ double m_timeCoord;
+ double m_timeNormal;
+ double m_timeCoordIndex;
+ double m_timeFloatAttribute[O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ double m_timeIntAttribute [O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES ];
+ double m_timeReorder;
+
+ unsigned long m_streamSizeCoord;
+ unsigned long m_streamSizeNormal;
+ unsigned long m_streamSizeCoordIndex;
+ unsigned long m_streamSizeFloatAttribute[O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ unsigned long m_streamSizeIntAttribute [O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES ];
+
+ };
+ typedef struct
+ {
+ long m_a;
+ long m_b;
+ long m_c;
+ } SC3DMCTriplet;
+
+ typedef struct
+ {
+ SC3DMCTriplet m_id;
+ long m_pred[O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES];
+ } SC3DMCPredictor;
+
+ inline bool operator< (const SC3DMCTriplet& lhs, const SC3DMCTriplet& rhs)
+ {
+ if (lhs.m_c != rhs.m_c)
+ {
+ return (lhs.m_c < rhs.m_c);
+ }
+ else if (lhs.m_b != rhs.m_b)
+ {
+ return (lhs.m_b < rhs.m_b);
+ }
+ return (lhs.m_a < rhs.m_a);
+ }
+ inline bool operator== (const SC3DMCTriplet& lhs, const SC3DMCTriplet& rhs)
+ {
+ return (lhs.m_c == rhs.m_c && lhs.m_b == rhs.m_b && lhs.m_a == rhs.m_a);
+ }
+
+
+ // fix me: optimize this function (e.g., binary search)
+ inline unsigned long Insert(SC3DMCTriplet e, unsigned long & nPred, SC3DMCPredictor * const list)
+ {
+ unsigned long pos = 0xFFFFFFFF;
+ bool foundOrInserted = false;
+ for (unsigned long j = 0; j < nPred; ++j)
+ {
+ if (e == list[j].m_id)
+ {
+ foundOrInserted = true;
+ break;
+ }
+ else if (e < list[j].m_id)
+ {
+ if (nPred < O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS)
+ {
+ ++nPred;
+ }
+ for (unsigned long h = nPred-1; h > j; --h)
+ {
+ list[h] = list[h-1];
+ }
+ list[j].m_id = e;
+ pos = j;
+ foundOrInserted = true;
+ break;
+ }
+ }
+ if (!foundOrInserted && nPred < O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS)
+ {
+ pos = nPred;
+ list[nPred++].m_id = e;
+ }
+ return pos;
+ }
+ template <class T>
+ inline void SphereToCube(const T x, const T y, const T z,
+ T & a, T & b, char & index)
+ {
+ T ax = absolute(x);
+ T ay = absolute(y);
+ T az = absolute(z);
+ if (az >= ax && az >= ay)
+ {
+ if (z >= (T)(0))
+ {
+ index = 0;
+ a = x;
+ b = y;
+ }
+ else
+ {
+ index = 1;
+ a = -x;
+ b = -y;
+ }
+ }
+ else if (ay >= ax && ay >= az)
+ {
+ if (y >= (T)(0))
+ {
+ index = 2;
+ a = z;
+ b = x;
+ }
+ else
+ {
+ index = 3;
+ a = -z;
+ b = -x;
+ }
+ }
+ else if (ax >= ay && ax >= az)
+ {
+ if (x >= (T)(0))
+ {
+ index = 4;
+ a = y;
+ b = z;
+ }
+ else
+ {
+ index = 5;
+ a = -y;
+ b = -z;
+ }
+ }
+ }
+ inline void CubeToSphere(const Real a, const Real b, const char index,
+ Real & x, Real & y, Real & z)
+ {
+ switch( index )
+ {
+ case 0:
+ x = a;
+ y = b;
+ z = (Real) sqrt(max(0.0, 1.0 - x*x-y*y));
+ break;
+ case 1:
+ x = -a;
+ y = -b;
+ z = -(Real) sqrt(max(0.0, 1.0 - x*x-y*y));
+ break;
+ case 2:
+ z = a;
+ x = b;
+ y = (Real) sqrt(max(0.0, 1.0 - x*x-z*z));
+ break;
+ case 3:
+ z = -a;
+ x = -b;
+ y = -(Real) sqrt(max(0.0, 1.0 - x*x-z*z));
+ break;
+ case 4:
+ y = a;
+ z = b;
+ x = (Real) sqrt(max(0.0, 1.0 - y*y-z*z));
+ break;
+ case 5:
+ y = -a;
+ z = -b;
+ x = -(Real) sqrt(max(0.0, 1.0 - y*y-z*z));
+ break;
+ }
+ }
+ inline unsigned long IntToUInt(long value)
+ {
+ return (value < 0)?(unsigned long) (-1 - (2 * value)):(unsigned long) (2 * value);
+ }
+ inline long UIntToInt(unsigned long uiValue)
+ {
+ return (uiValue & 1)?-((long) ((uiValue+1) >> 1)):((long) (uiValue >> 1));
+ }
+ inline void ComputeVectorMinMax(const Real * const tab,
+ unsigned long size,
+ unsigned long dim,
+ unsigned long stride,
+ Real * minTab,
+ Real * maxTab,
+ O3DGCSC3DMCQuantizationMode quantMode)
+ {
+ if (size == 0 || dim == 0)
+ {
+ return;
+ }
+ unsigned long p = 0;
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ maxTab[d] = minTab[d] = tab[p++];
+ }
+ p = stride;
+ for(unsigned long i = 1; i < size; ++i)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ if (maxTab[d] < tab[p+d]) maxTab[d] = tab[p+d];
+ if (minTab[d] > tab[p+d]) minTab[d] = tab[p+d];
+ }
+ p += stride;
+ }
+
+ if (quantMode == O3DGC_SC3DMC_DIAG_BB)
+ {
+ Real diag = Real( 0.0 );
+ Real r;
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ r = (maxTab[d] - minTab[d]);
+ diag += r*r;
+ }
+ diag = static_cast<Real>(sqrt(diag));
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ maxTab[d] = minTab[d] + diag;
+ }
+ }
+ else if (quantMode == O3DGC_SC3DMC_MAX_ALL_DIMS)
+ {
+ Real maxr = (maxTab[0] - minTab[0]);
+ Real r;
+ for(unsigned long d = 1; d < dim; ++d)
+ {
+ r = (maxTab[d] - minTab[d]);
+ if ( r > maxr)
+ {
+ maxr = r;
+ }
+ }
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ maxTab[d] = minTab[d] + maxr;
+ }
+ }
+ }
+}
+#endif // O3DGC_COMMON_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDVEncodeParams.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDVEncodeParams.h
new file mode 100644
index 000000000..6f639f678
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDVEncodeParams.h
@@ -0,0 +1,62 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_DV_ENCODE_PARAMS_H
+#define O3DGC_DV_ENCODE_PARAMS_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ class DVEncodeParams
+ {
+ public:
+ //! Constructor.
+ DVEncodeParams(void)
+ {
+ m_quantBits = 10;
+ m_streamTypeMode = O3DGC_STREAM_TYPE_ASCII;
+ m_encodeMode = O3DGC_DYNAMIC_VECTOR_ENCODE_MODE_LIFT;
+ };
+ //! Destructor.
+ ~DVEncodeParams(void) {};
+
+ unsigned long GetQuantBits() const { return m_quantBits;}
+ O3DGCStreamType GetStreamType() const { return m_streamTypeMode;}
+ O3DGCDVEncodingMode GetEncodeMode() const { return m_encodeMode;}
+
+ void SetQuantBits (unsigned long quantBits ) { m_quantBits = quantBits;}
+
+ void SetStreamType(O3DGCStreamType streamTypeMode) { m_streamTypeMode = streamTypeMode;}
+ void SetEncodeMode(O3DGCDVEncodingMode encodeMode ) { m_encodeMode = encodeMode ;}
+
+
+ private:
+ unsigned long m_quantBits;
+ O3DGCStreamType m_streamTypeMode;
+ O3DGCDVEncodingMode m_encodeMode;
+ };
+}
+#endif // O3DGC_DV_ENCODE_PARAMS_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVector.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVector.h
new file mode 100644
index 000000000..aa7fb3142
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVector.h
@@ -0,0 +1,84 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_DYNAMIC_VECTOR_SET_H
+#define O3DGC_DYNAMIC_VECTOR_SET_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ class DynamicVector
+ {
+ public:
+ //! Constructor.
+ DynamicVector(void)
+ {
+ m_num = 0;
+ m_dim = 0;
+ m_stride = 0;
+ m_max = 0;
+ m_min = 0;
+ m_vectors = 0;
+ };
+ //! Destructor.
+ ~DynamicVector(void) {};
+
+ unsigned long GetNVector() const { return m_num;}
+ unsigned long GetDimVector() const { return m_dim;}
+ unsigned long GetStride() const { return m_stride;}
+ const Real * GetMin() const { return m_min;}
+ const Real * GetMax() const { return m_max;}
+ const Real * GetVectors() const { return m_vectors;}
+ Real * GetVectors() { return m_vectors;}
+ Real GetMin(unsigned long j) const { return m_min[j];}
+ Real GetMax(unsigned long j) const { return m_max[j];}
+
+ void SetNVector (unsigned long num ) { m_num = num ;}
+ void SetDimVector (unsigned long dim ) { m_dim = dim ;}
+ void SetStride (unsigned long stride ) { m_stride = stride ;}
+ void SetMin (Real * const min ) { m_min = min ;}
+ void SetMax (Real * const max ) { m_max = max ;}
+ void SetMin (unsigned long j, Real min) { m_min[j] = min ;}
+ void SetMax (unsigned long j, Real max) { m_max[j] = max ;}
+ void SetVectors (Real * const vectors) { m_vectors = vectors ;}
+
+ void ComputeMinMax(O3DGCSC3DMCQuantizationMode quantMode)
+ {
+ assert( m_max && m_min && m_vectors && m_stride && m_dim && m_num);
+ ComputeVectorMinMax(m_vectors, m_num , m_dim, m_stride, m_min , m_max , quantMode);
+ }
+
+ private:
+ unsigned long m_num;
+ unsigned long m_dim;
+ unsigned long m_stride;
+ Real * m_max;
+ Real * m_min;
+ Real * m_vectors;
+ };
+
+}
+#endif // O3DGC_DYNAMIC_VECTOR_SET_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.cpp b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.cpp
new file mode 100644
index 000000000..b92452eb6
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.cpp
@@ -0,0 +1,278 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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 "o3dgcDynamicVectorDecoder.h"
+#include "o3dgcArithmeticCodec.h"
+
+
+//#define DEBUG_VERBOSE
+
+namespace o3dgc
+{
+#ifdef DEBUG_VERBOSE
+ FILE * g_fileDebugDVCDec = NULL;
+#endif //DEBUG_VERBOSE
+
+ O3DGCErrorCode IUpdate(long * const data, const long size)
+ {
+ assert(size > 1);
+ const long size1 = size - 1;
+ long p = 2;
+ data[0] -= data[1] >> 1;
+ while(p < size1)
+ {
+ data[p] -= (data[p-1] + data[p+1] + 2) >> 2;
+ p += 2;
+ }
+ if ( p == size1)
+ {
+ data[p] -= data[p-1]>>1;
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode IPredict(long * const data, const long size)
+ {
+ assert(size > 1);
+ const long size1 = size - 1;
+ long p = 1;
+ while(p < size1)
+ {
+ data[p] += (data[p-1] + data[p+1] + 1) >> 1;
+ p += 2;
+ }
+ if ( p == size1)
+ {
+ data[p] += data[p-1];
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode Merge(long * const data, const long size)
+ {
+ assert(size > 1);
+ const long h = (size >> 1) + (size & 1);
+ long a = h-1;
+ long b = h;
+ while (a > 0)
+ {
+ for (long i = a; i < b; i += 2)
+ {
+ swap(data[i], data[i+1]);
+ }
+ --a;
+ ++b;
+ }
+ return O3DGC_OK;
+ }
+ inline O3DGCErrorCode ITransform(long * const data, const unsigned long size)
+ {
+ unsigned long n = size;
+ unsigned long even = 0;
+ unsigned long k = 0;
+ even += ((n&1) << k++);
+ while(n > 1)
+ {
+ n = (n >> 1) + (n & 1);
+ even += ((n&1) << k++);
+ }
+ for(long i = k-2; i >= 0; --i)
+ {
+ n = (n << 1) - ((even>>i) & 1);
+ Merge (data, n);
+ IUpdate (data, n);
+ IPredict(data, n);
+ }
+ return O3DGC_OK;
+ }
+ DynamicVectorDecoder::DynamicVectorDecoder(void)
+ {
+ m_streamSize = 0;
+ m_maxNumVectors = 0;
+ m_numVectors = 0;
+ m_dimVectors = 0;
+ m_quantVectors = 0;
+ m_iterator = 0;
+ m_streamType = O3DGC_STREAM_TYPE_UNKOWN;
+ }
+ DynamicVectorDecoder::~DynamicVectorDecoder()
+ {
+ delete [] m_quantVectors;
+ }
+ O3DGCErrorCode DynamicVectorDecoder::DecodeHeader(DynamicVector & dynamicVector,
+ const BinaryStream & bstream)
+ {
+ unsigned long iterator0 = m_iterator;
+ unsigned long start_code = bstream.ReadUInt32(m_iterator, O3DGC_STREAM_TYPE_BINARY);
+ if (start_code != O3DGC_DV_START_CODE)
+ {
+ m_iterator = iterator0;
+ start_code = bstream.ReadUInt32(m_iterator, O3DGC_STREAM_TYPE_ASCII);
+ if (start_code != O3DGC_DV_START_CODE)
+ {
+ return O3DGC_ERROR_CORRUPTED_STREAM;
+ }
+ else
+ {
+ m_streamType = O3DGC_STREAM_TYPE_ASCII;
+ }
+ }
+ else
+ {
+ m_streamType = O3DGC_STREAM_TYPE_BINARY;
+ }
+ m_streamSize = bstream.ReadUInt32(m_iterator, m_streamType);
+ m_params.SetEncodeMode( (O3DGCDVEncodingMode) bstream.ReadUChar(m_iterator, m_streamType));
+ dynamicVector.SetNVector ( bstream.ReadUInt32(m_iterator, m_streamType) );
+
+ if (dynamicVector.GetNVector() > 0)
+ {
+ dynamicVector.SetDimVector( bstream.ReadUInt32(m_iterator, m_streamType) );
+ m_params.SetQuantBits(bstream.ReadUChar(m_iterator, m_streamType));
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode DynamicVectorDecoder::DecodePlayload(DynamicVector & dynamicVector,
+ const BinaryStream & bstream)
+ {
+ O3DGCErrorCode ret = O3DGC_OK;
+#ifdef DEBUG_VERBOSE
+ g_fileDebugDVCDec = fopen("dv_dec.txt", "w");
+#endif //DEBUG_VERBOSE
+ unsigned long start = m_iterator;
+ unsigned long streamSize = bstream.ReadUInt32(m_iterator, m_streamType); // bitsream size
+
+ const unsigned long dim = dynamicVector.GetDimVector();
+ const unsigned long num = dynamicVector.GetNVector();
+ const unsigned long size = dim * num;
+ for(unsigned long j=0 ; j < dynamicVector.GetDimVector() ; ++j)
+ {
+ dynamicVector.SetMin(j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ dynamicVector.SetMax(j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ }
+ Arithmetic_Codec acd;
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+ unsigned char * buffer = 0;
+ streamSize -= (m_iterator - start);
+ unsigned int exp_k = 0;
+ unsigned int M = 0;
+ if (m_streamType == O3DGC_STREAM_TYPE_BINARY)
+ {
+ bstream.GetBuffer(m_iterator, buffer);
+ m_iterator += streamSize;
+ acd.set_buffer(streamSize, buffer);
+ acd.start_decoder();
+ exp_k = acd.ExpGolombDecode(0, bModel0, bModel1);
+ M = acd.ExpGolombDecode(0, bModel0, bModel1);
+ }
+ Adaptive_Data_Model mModelValues(M+2);
+
+ if (m_maxNumVectors < size)
+ {
+ delete [] m_quantVectors;
+ m_maxNumVectors = size;
+ m_quantVectors = new long [size];
+ }
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ for(unsigned long v = 0; v < num; ++v)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ m_quantVectors[d * num + v] = bstream.ReadIntASCII(m_iterator);
+ }
+ }
+ }
+ else
+ {
+ for(unsigned long v = 0; v < num; ++v)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ m_quantVectors[d * num + v] = DecodeIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ }
+ }
+ #ifdef DEBUG_VERBOSE
+ printf("IntArray (%i, %i)\n", num, dim);
+ fprintf(g_fileDebugDVCDec, "IntArray (%i, %i)\n", num, dim);
+ for(unsigned long v = 0; v < num; ++v)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ printf("%i\t %i \t %i\n", d * num + v, m_quantVectors[d * num + v], IntToUInt(m_quantVectors[d * num + v]));
+ fprintf(g_fileDebugDVCDec, "%i\t %i \t %i\n", d * num + v, m_quantVectors[d * num + v], IntToUInt(m_quantVectors[d * num + v]));
+ }
+ }
+ fflush(g_fileDebugDVCDec);
+ #endif //DEBUG_VERBOSE
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ ITransform(m_quantVectors + d * num, num);
+ }
+ IQuantize(dynamicVector.GetVectors(),
+ num,
+ dim,
+ dynamicVector.GetStride(),
+ dynamicVector.GetMin(),
+ dynamicVector.GetMax(),
+ m_params.GetQuantBits());
+
+#ifdef DEBUG_VERBOSE
+ fclose(g_fileDebugDVCDec);
+#endif //DEBUG_VERBOSE
+ return ret;
+ }
+ O3DGCErrorCode DynamicVectorDecoder::IQuantize(Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits)
+ {
+ const unsigned long size = numFloatArray * dimFloatArray;
+ Real r;
+ if (m_maxNumVectors < size)
+ {
+ delete [] m_quantVectors;
+ m_maxNumVectors = size;
+ m_quantVectors = new long [m_maxNumVectors];
+ }
+ Real idelta;
+ for(unsigned long d = 0; d < dimFloatArray; ++d)
+ {
+ r = maxFloatArray[d] - minFloatArray[d];
+ if (r > 0.0f)
+ {
+ idelta = (float)(r) / ((1 << nQBits) - 1);
+ }
+ else
+ {
+ idelta = 1.0f;
+ }
+ for(unsigned long v = 0; v < numFloatArray; ++v)
+ {
+ floatArray[v * stride + d] = m_quantVectors[v + d * numFloatArray] * idelta + minFloatArray[d];
+ }
+ }
+ return O3DGC_OK;
+ }
+}
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.h
new file mode 100644
index 000000000..6e21b4fa3
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorDecoder.h
@@ -0,0 +1,76 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_DYNAMIC_VECTOR_DECODER_H
+#define O3DGC_DYNAMIC_VECTOR_DECODER_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcDVEncodeParams.h"
+#include "o3dgcDynamicVector.h"
+
+namespace o3dgc
+{
+ //!
+ class DynamicVectorDecoder
+ {
+ public:
+ //! Constructor.
+ DynamicVectorDecoder(void);
+ //! Destructor.
+ ~DynamicVectorDecoder(void);
+ //!
+ //!
+ O3DGCErrorCode DecodeHeader(DynamicVector & dynamicVector,
+ const BinaryStream & bstream);
+ //!
+ O3DGCErrorCode DecodePlayload(DynamicVector & dynamicVector,
+ const BinaryStream & bstream);
+
+ O3DGCStreamType GetStreamType() const { return m_streamType; }
+ void SetStreamType(O3DGCStreamType streamType) { m_streamType = streamType; }
+ unsigned long GetIterator() const { return m_iterator;}
+ O3DGCErrorCode SetIterator(unsigned long iterator) { m_iterator = iterator; return O3DGC_OK; }
+
+ private:
+ O3DGCErrorCode IQuantize(Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits);
+
+ unsigned long m_streamSize;
+ unsigned long m_maxNumVectors;
+ unsigned long m_numVectors;
+ unsigned long m_dimVectors;
+ unsigned long m_iterator;
+ long * m_quantVectors;
+ DVEncodeParams m_params;
+ O3DGCStreamType m_streamType;
+ };
+}
+#endif // O3DGC_DYNAMIC_VECTOR_DECODER_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.cpp b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.cpp
new file mode 100644
index 000000000..00ae75e35
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.cpp
@@ -0,0 +1,295 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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 "o3dgcDVEncodeParams.h"
+#include "o3dgcDynamicVectorEncoder.h"
+#include "o3dgcArithmeticCodec.h"
+#include "o3dgcBinaryStream.h"
+
+//#define DEBUG_VERBOSE
+
+namespace o3dgc
+{
+#ifdef DEBUG_VERBOSE
+ FILE * g_fileDebugDVEnc = NULL;
+#endif //DEBUG_VERBOSE
+
+ inline O3DGCErrorCode Update(long * const data, const long size)
+ {
+ assert(size > 1);
+ const long size1 = size - 1;
+ long p = 2;
+ data[0] += data[1] >> 1;
+ while(p < size1)
+ {
+ data[p] += (data[p-1] + data[p+1] + 2) >> 2;
+ p += 2;
+ }
+ if ( p == size1)
+ {
+ data[p] += data[p-1]>>1;
+ }
+ return O3DGC_OK;
+ }
+ inline O3DGCErrorCode Predict(long * const data, const long size)
+ {
+ assert(size > 1);
+ const long size1 = size - 1;
+ long p = 1;
+ while(p < size1)
+ {
+ data[p] -= (data[p-1] + data[p+1] + 1) >> 1;
+ p += 2;
+ }
+ if ( p == size1)
+ {
+ data[p] -= data[p-1];
+ }
+ return O3DGC_OK;
+ }
+ inline O3DGCErrorCode Split(long * const data, const long size)
+ {
+ assert(size > 1);
+ long a = 1;
+ long b = size-1;
+ while (a < b)
+ {
+ for (long i = a; i < b; i += 2)
+ {
+ swap(data[i], data[i+1]);
+ }
+ ++a;
+ --b;
+ }
+ return O3DGC_OK;
+ }
+ inline O3DGCErrorCode Transform(long * const data, const unsigned long size)
+ {
+ unsigned long n = size;
+ while(n > 1)
+ {
+ Predict(data, n);
+ Update (data, n);
+ Split(data, n);
+ n = (n >> 1) + (n & 1);
+ }
+ return O3DGC_OK;
+ }
+ DynamicVectorEncoder::DynamicVectorEncoder(void)
+ {
+ m_maxNumVectors = 0;
+ m_numVectors = 0;
+ m_dimVectors = 0;
+ m_quantVectors = 0;
+ m_sizeBufferAC = 0;
+ m_bufferAC = 0;
+ m_posSize = 0;
+ m_streamType = O3DGC_STREAM_TYPE_UNKOWN;
+ }
+ DynamicVectorEncoder::~DynamicVectorEncoder()
+ {
+ delete [] m_quantVectors;
+ delete [] m_bufferAC;
+ }
+ O3DGCErrorCode DynamicVectorEncoder::Encode(const DVEncodeParams & params,
+ const DynamicVector & dynamicVector,
+ BinaryStream & bstream)
+ {
+ assert(params.GetQuantBits() > 0);
+ assert(dynamicVector.GetNVector() > 0);
+ assert(dynamicVector.GetDimVector() > 0);
+ assert(dynamicVector.GetStride() >= dynamicVector.GetDimVector());
+ assert(dynamicVector.GetVectors() && dynamicVector.GetMin() && dynamicVector.GetMax());
+ assert(m_streamType != O3DGC_STREAM_TYPE_UNKOWN);
+ // Encode header
+ unsigned long start = bstream.GetSize();
+ EncodeHeader(params, dynamicVector, bstream);
+ // Encode payload
+ EncodePayload(params, dynamicVector, bstream);
+ bstream.WriteUInt32(m_posSize, bstream.GetSize() - start, m_streamType);
+ return O3DGC_OK;
+
+ }
+ O3DGCErrorCode DynamicVectorEncoder::EncodeHeader(const DVEncodeParams & params,
+ const DynamicVector & dynamicVector,
+ BinaryStream & bstream)
+ {
+ m_streamType = params.GetStreamType();
+ bstream.WriteUInt32(O3DGC_DV_START_CODE, m_streamType);
+ m_posSize = bstream.GetSize();
+ bstream.WriteUInt32(0, m_streamType); // to be filled later
+ bstream.WriteUChar((unsigned char) params.GetEncodeMode(), m_streamType);
+ bstream.WriteUInt32(dynamicVector.GetNVector() , m_streamType);
+ if (dynamicVector.GetNVector() > 0)
+ {
+ bstream.WriteUInt32(dynamicVector.GetDimVector(), m_streamType);
+ bstream.WriteUChar ((unsigned char) params.GetQuantBits(), m_streamType);
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode DynamicVectorEncoder::EncodeAC(unsigned long num,
+ unsigned long dim,
+ unsigned long M,
+ unsigned long & encodedBytes)
+ {
+ Arithmetic_Codec ace;
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+ Adaptive_Data_Model mModelValues(M+2);
+ const unsigned int NMAX = num * dim * 8 + 100;
+ if ( m_sizeBufferAC < NMAX )
+ {
+ delete [] m_bufferAC;
+ m_sizeBufferAC = NMAX;
+ m_bufferAC = new unsigned char [m_sizeBufferAC];
+ }
+ ace.set_buffer(NMAX, m_bufferAC);
+ ace.start_encoder();
+ ace.ExpGolombEncode(0, 0, bModel0, bModel1);
+ ace.ExpGolombEncode(M, 0, bModel0, bModel1);
+ for(unsigned long v = 0; v < num; ++v)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ EncodeIntACEGC(m_quantVectors[d * num + v], ace, mModelValues, bModel0, bModel1, M);
+ }
+ }
+ encodedBytes = ace.stop_encoder();
+ return O3DGC_OK;
+ }
+
+ O3DGCErrorCode DynamicVectorEncoder::EncodePayload(const DVEncodeParams & params,
+ const DynamicVector & dynamicVector,
+ BinaryStream & bstream)
+ {
+#ifdef DEBUG_VERBOSE
+ g_fileDebugDVEnc = fopen("dv_enc.txt", "w");
+#endif //DEBUG_VERBOSE
+ unsigned long start = bstream.GetSize();
+ const unsigned long dim = dynamicVector.GetDimVector();
+ const unsigned long num = dynamicVector.GetNVector();
+
+ bstream.WriteUInt32(0, m_streamType);
+
+ for(unsigned long j=0 ; j<dynamicVector.GetDimVector() ; ++j)
+ {
+ bstream.WriteFloat32((float) dynamicVector.GetMin(j), m_streamType);
+ bstream.WriteFloat32((float) dynamicVector.GetMax(j), m_streamType);
+ }
+ Quantize(dynamicVector.GetVectors(),
+ num,
+ dim,
+ dynamicVector.GetStride(),
+ dynamicVector.GetMin(),
+ dynamicVector.GetMax(),
+ params.GetQuantBits());
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ Transform(m_quantVectors + d * num, num);
+ }
+ #ifdef DEBUG_VERBOSE
+ printf("IntArray (%i, %i)\n", num, dim);
+ fprintf(g_fileDebugDVEnc, "IntArray (%i, %i)\n", num, dim);
+ for(unsigned long v = 0; v < num; ++v)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ printf("%i\t %i \t %i\n", d * num + v, m_quantVectors[d * num + v], IntToUInt(m_quantVectors[d * num + v]));
+ fprintf(g_fileDebugDVEnc, "%i\t %i \t %i\n", d * num + v, m_quantVectors[d * num + v], IntToUInt(m_quantVectors[d * num + v]));
+ }
+ }
+ #endif //DEBUG_VERBOSE
+
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ for(unsigned long v = 0; v < num; ++v)
+ {
+ for(unsigned long d = 0; d < dim; ++d)
+ {
+ bstream.WriteIntASCII(m_quantVectors[d * num + v]);
+ }
+ }
+ }
+ else
+ {
+ unsigned long encodedBytes = 0;
+ unsigned long bestEncodedBytes = O3DGC_MAX_ULONG;
+ unsigned long M = 1;
+ unsigned long bestM = 1;
+ while (M < 1024)
+ {
+ EncodeAC(num, dim, M, encodedBytes);
+ if (encodedBytes > bestEncodedBytes)
+ {
+ break;
+ }
+ bestM = M;
+ bestEncodedBytes = encodedBytes;
+ M *= 2;
+ }
+ EncodeAC(num, dim, bestM, encodedBytes);
+ for(unsigned long i = 0; i < encodedBytes; ++i)
+ {
+ bstream.WriteUChar8Bin(m_bufferAC[i]);
+ }
+ }
+ bstream.WriteUInt32(start, bstream.GetSize() - start, m_streamType);
+#ifdef DEBUG_VERBOSE
+ fclose(g_fileDebugDVEnc);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode DynamicVectorEncoder::Quantize(const Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits)
+ {
+ const unsigned long size = numFloatArray * dimFloatArray;
+ Real r;
+ if (m_maxNumVectors < size)
+ {
+ delete [] m_quantVectors;
+ m_maxNumVectors = size;
+ m_quantVectors = new long [m_maxNumVectors];
+ }
+ Real delta;
+ for(unsigned long d = 0; d < dimFloatArray; ++d)
+ {
+ r = maxFloatArray[d] - minFloatArray[d];
+ if (r > 0.0f)
+ {
+ delta = (float)((1 << nQBits) - 1) / r;
+ }
+ else
+ {
+ delta = 1.0f;
+ }
+ for(unsigned long v = 0; v < numFloatArray; ++v)
+ {
+ m_quantVectors[v + d * numFloatArray] = (long)((floatArray[v * stride + d]-minFloatArray[d]) * delta + 0.5f);
+ }
+ }
+ return O3DGC_OK;
+ }
+}
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.h
new file mode 100644
index 000000000..de42a020f
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcDynamicVectorEncoder.h
@@ -0,0 +1,79 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_DYNAMIC_VECTOR_ENCODER_H
+#define O3DGC_DYNAMIC_VECTOR_ENCODER_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcDynamicVector.h"
+
+namespace o3dgc
+{
+ //!
+ class DynamicVectorEncoder
+ {
+ public:
+ //! Constructor.
+ DynamicVectorEncoder(void);
+ //! Destructor.
+ ~DynamicVectorEncoder(void);
+ //!
+ O3DGCErrorCode Encode(const DVEncodeParams & params,
+ const DynamicVector & dynamicVector,
+ BinaryStream & bstream);
+ O3DGCStreamType GetStreamType() const { return m_streamType; }
+ void SetStreamType(O3DGCStreamType streamType) { m_streamType = streamType; }
+
+ private:
+ O3DGCErrorCode EncodeHeader(const DVEncodeParams & params,
+ const DynamicVector & dynamicVector,
+ BinaryStream & bstream);
+ O3DGCErrorCode EncodePayload(const DVEncodeParams & params,
+ const DynamicVector & dynamicVector,
+ BinaryStream & bstream);
+ O3DGCErrorCode Quantize(const Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits);
+ O3DGCErrorCode EncodeAC(unsigned long num,
+ unsigned long dim,
+ unsigned long M,
+ unsigned long & encodedBytes);
+
+ unsigned long m_posSize;
+ unsigned long m_sizeBufferAC;
+ unsigned long m_maxNumVectors;
+ unsigned long m_numVectors;
+ unsigned long m_dimVectors;
+ unsigned char * m_bufferAC;
+ long * m_quantVectors;
+ O3DGCStreamType m_streamType;
+ };
+}
+#endif // O3DGC_DYNAMIC_VECTOR_ENCODER_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcFIFO.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcFIFO.h
new file mode 100644
index 000000000..4a5555f2a
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcFIFO.h
@@ -0,0 +1,97 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_FIFO_H
+#define O3DGC_FIFO_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ //!
+ template < typename T > class FIFO
+ {
+ public:
+ //! Constructor.
+ FIFO()
+ {
+ m_buffer = 0;
+ m_allocated = 0;
+ m_size = 0;
+ m_start = 0;
+ m_end = 0;
+ };
+ //! Destructor.
+ ~FIFO(void)
+ {
+ delete [] m_buffer;
+ };
+ O3DGCErrorCode Allocate(unsigned long size)
+ {
+ assert(size > 0);
+ if (size > m_allocated)
+ {
+ delete [] m_buffer;
+ m_allocated = size;
+ m_buffer = new T [m_allocated];
+ }
+ Clear();
+ return O3DGC_OK;
+ }
+ const T & PopFirst()
+ {
+ assert(m_size > 0);
+ --m_size;
+ unsigned long current = m_start++;
+ if (m_start == m_allocated)
+ {
+ m_end = 0;
+ }
+ return m_buffer[current];
+ };
+ void PushBack(const T & value)
+ {
+ assert( m_size < m_allocated);
+ m_buffer[m_end] = value;
+ ++m_size;
+ ++m_end;
+ if (m_end == m_allocated)
+ {
+ m_end = 0;
+ }
+ }
+ unsigned long GetSize() const { return m_size;};
+ unsigned long GetAllocatedSize() const { return m_allocated;};
+ void Clear() { m_start = m_end = m_size = 0;};
+
+ private:
+ T * m_buffer;
+ unsigned long m_allocated;
+ unsigned long m_size;
+ unsigned long m_start;
+ unsigned long m_end;
+ };
+}
+#endif // O3DGC_FIFO_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.h
new file mode 100644
index 000000000..adb8cb001
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.h
@@ -0,0 +1,263 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_INDEXED_FACE_SET_H
+#define O3DGC_INDEXED_FACE_SET_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ template<class T>
+ class IndexedFaceSet
+ {
+ public:
+ //! Constructor.
+ IndexedFaceSet(void)
+ {
+ memset(this, 0, sizeof(IndexedFaceSet));
+ m_ccw = true;
+ m_solid = true;
+ m_convex = true;
+ m_isTriangularMesh = true;
+ m_creaseAngle = 30;
+ };
+ //! Destructor.
+ ~IndexedFaceSet(void) {};
+
+ unsigned long GetNCoordIndex() const { return m_nCoordIndex ;}
+ // only coordIndex is supported
+ unsigned long GetNCoord() const { return m_nCoord ;}
+ unsigned long GetNNormal() const { return m_nNormal ;}
+ unsigned long GetNFloatAttribute(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_nFloatAttribute[a];
+ }
+ unsigned long GetNIntAttribute(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ return m_nIntAttribute[a];
+ }
+ unsigned long GetNumFloatAttributes() const { return m_numFloatAttributes;}
+ unsigned long GetNumIntAttributes() const { return m_numIntAttributes ;}
+ const Real * GetCoordMin () const { return m_coordMin;}
+ const Real * GetCoordMax () const { return m_coordMax;}
+ const Real * GetNormalMin () const { return m_normalMin;}
+ const Real * GetNormalMax () const { return m_normalMax;}
+ Real GetCoordMin (int j) const { return m_coordMin[j] ;}
+ Real GetCoordMax (int j) const { return m_coordMax[j] ;}
+ Real GetNormalMin (int j) const { return m_normalMin[j] ;}
+ Real GetNormalMax (int j) const { return m_normalMax[j] ;}
+
+ O3DGCIFSFloatAttributeType GetFloatAttributeType(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_typeFloatAttribute[a];
+ }
+ O3DGCIFSIntAttributeType GetIntAttributeType(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ return m_typeIntAttribute[a];
+ }
+ unsigned long GetFloatAttributeDim(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_dimFloatAttribute[a];
+ }
+ unsigned long GetIntAttributeDim(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ return m_dimIntAttribute[a];
+ }
+ const Real * GetFloatAttributeMin(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return &(m_minFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES]);
+ }
+ const Real * GetFloatAttributeMax(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return &(m_maxFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES]);
+ }
+ Real GetFloatAttributeMin(unsigned long a, unsigned long dim) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ assert(dim < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ return m_minFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim];
+ }
+ Real GetFloatAttributeMax(unsigned long a, unsigned long dim) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ assert(dim < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ return m_maxFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim];
+ }
+ Real GetCreaseAngle() const { return m_creaseAngle ;}
+ bool GetCCW() const { return m_ccw ;}
+ bool GetSolid() const { return m_solid ;}
+ bool GetConvex() const { return m_convex ;}
+ bool GetIsTriangularMesh() const { return m_isTriangularMesh;}
+ const unsigned long * GetIndexBufferID() const { return m_indexBufferID ;}
+ const T * GetCoordIndex() const { return m_coordIndex;}
+ T * GetCoordIndex() { return m_coordIndex;}
+ Real * GetCoord() const { return m_coord ;}
+ Real * GetNormal() const { return m_normal ;}
+ Real * GetFloatAttribute(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_floatAttribute[a];
+ }
+ long * GetIntAttribute(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ return m_intAttribute[a] ;
+ }
+ // only coordIndex is supported
+ void SetNNormalIndex(unsigned long) {}
+ void SetNTexCoordIndex(unsigned long) {}
+ void SetNFloatAttributeIndex(int, unsigned long) {}
+ void SetNIntAttributeIndex (int, unsigned long) {}
+ // per triangle attributes not supported
+ void SetNormalPerVertex(bool) {}
+ void SetColorPerVertex(bool) {}
+ void SetFloatAttributePerVertex(int, bool){}
+ void SetIntAttributePerVertex (int, bool){}
+ void SetNCoordIndex (unsigned long nCoordIndex) { m_nCoordIndex = nCoordIndex;}
+ void SetNCoord (unsigned long nCoord) { m_nCoord = nCoord ;}
+ void SetNNormal (unsigned long nNormal) { m_nNormal = nNormal ;}
+ void SetNumFloatAttributes(unsigned long numFloatAttributes)
+ {
+ assert(numFloatAttributes < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_numFloatAttributes = numFloatAttributes;
+ }
+ void SetNumIntAttributes (unsigned long numIntAttributes)
+ {
+ assert(numIntAttributes < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_numIntAttributes = numIntAttributes;
+ }
+ void SetCreaseAngle (Real creaseAngle) { m_creaseAngle = creaseAngle ;}
+ void SetCCW (bool ccw) { m_ccw = ccw ;}
+ void SetSolid (bool solid) { m_solid = solid ;}
+ void SetConvex (bool convex) { m_convex = convex ;}
+ void SetIsTriangularMesh (bool isTriangularMesh) { m_isTriangularMesh = isTriangularMesh;}
+ void SetCoordMin (int j, Real min) { m_coordMin[j] = min;}
+ void SetCoordMax (int j, Real max) { m_coordMax[j] = max;}
+ void SetNormalMin (int j, Real min) { m_normalMin[j] = min;}
+ void SetNormalMax (int j, Real max) { m_normalMax[j] = max;}
+ void SetNFloatAttribute(unsigned long a, unsigned long nFloatAttribute)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_nFloatAttribute[a] = nFloatAttribute;
+ }
+ void SetNIntAttribute(unsigned long a, unsigned long nIntAttribute)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_nIntAttribute[a] = nIntAttribute;
+ }
+ void SetFloatAttributeDim(unsigned long a, unsigned long d)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_dimFloatAttribute[a] = d;
+ }
+ void SetIntAttributeDim(unsigned long a, unsigned long d)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_dimIntAttribute[a] = d;
+ }
+ void SetFloatAttributeType(unsigned long a, O3DGCIFSFloatAttributeType t)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_typeFloatAttribute[a] = t;
+ }
+ void SetIntAttributeType(unsigned long a, O3DGCIFSIntAttributeType t)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_typeIntAttribute[a] = t;
+ }
+ void SetFloatAttributeMin(unsigned long a, unsigned long dim, Real min)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ assert(dim < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ m_minFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim] = min;
+ }
+ void SetFloatAttributeMax(unsigned long a, unsigned long dim, Real max)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ assert(dim < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ m_maxFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim] = max;
+ }
+ void SetIndexBufferID (unsigned long * const indexBufferID) { m_indexBufferID = indexBufferID;}
+ void SetCoordIndex (T * const coordIndex) { m_coordIndex = coordIndex;}
+ void SetCoord (Real * const coord ) { m_coord = coord ;}
+ void SetNormal (Real * const normal ) { m_normal = normal ;}
+ void SetFloatAttribute (unsigned long a, Real * const floatAttribute)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_floatAttribute[a] = floatAttribute;
+ }
+ void SetIntAttribute (unsigned long a, long * const intAttribute)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_intAttribute[a] = intAttribute ;
+ }
+ void ComputeMinMax(O3DGCSC3DMCQuantizationMode quantMode);
+
+ private:
+ // triangles list
+ unsigned long m_nCoordIndex;
+ T * m_coordIndex;
+ unsigned long * m_indexBufferID;
+ // coord, normals, texcoord and color
+ unsigned long m_nCoord;
+ unsigned long m_nNormal;
+ Real m_coordMin [3];
+ Real m_coordMax [3];
+ Real m_normalMin [3];
+ Real m_normalMax [3];
+ Real * m_coord;
+ Real * m_normal;
+ // other attributes
+ unsigned long m_numFloatAttributes;
+ unsigned long m_numIntAttributes;
+ O3DGCIFSFloatAttributeType m_typeFloatAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ O3DGCIFSIntAttributeType m_typeIntAttribute [O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES ];
+ unsigned long m_nFloatAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ unsigned long m_nIntAttribute [O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES ];
+ unsigned long m_dimFloatAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ unsigned long m_dimIntAttribute [O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES ];
+ Real m_minFloatAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES];
+ Real m_maxFloatAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES];
+ Real * m_floatAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ long * m_intAttribute [O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ // mesh info
+ Real m_creaseAngle;
+ bool m_ccw;
+ bool m_solid;
+ bool m_convex;
+ bool m_isTriangularMesh;
+ };
+}
+#include "o3dgcIndexedFaceSet.inl" // template implementation
+#endif // O3DGC_INDEXED_FACE_SET_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.inl b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.inl
new file mode 100644
index 000000000..ddac26d76
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcIndexedFaceSet.inl
@@ -0,0 +1,47 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_INDEXED_FACE_SET_INL
+#define O3DGC_INDEXED_FACE_SET_INL
+
+#include <math.h>
+namespace o3dgc
+{
+ template <class T>
+ void IndexedFaceSet<T>::ComputeMinMax(O3DGCSC3DMCQuantizationMode quantMode)
+ {
+ ComputeVectorMinMax(m_coord , m_nCoord , 3, 3, m_coordMin , m_coordMax , quantMode);
+ ComputeVectorMinMax(m_normal , m_nNormal , 3, 3, m_normalMin , m_normalMax , quantMode);
+ unsigned long numFloatAttributes = GetNumFloatAttributes();
+ for(unsigned long a = 0; a < numFloatAttributes; ++a)
+ {
+ ComputeVectorMinMax(m_floatAttribute[a],
+ m_nFloatAttribute[a],
+ m_dimFloatAttribute[a],
+ m_dimFloatAttribute[a], // stride
+ m_minFloatAttribute + (a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES),
+ m_maxFloatAttribute + (a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES), quantMode);
+ }
+ }
+}
+#endif // O3DGC_INDEXED_FACE_SET_INL
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.h
new file mode 100644
index 000000000..f3f1617c4
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.h
@@ -0,0 +1,111 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_SC3DMC_DECODER_H
+#define O3DGC_SC3DMC_DECODER_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcIndexedFaceSet.h"
+#include "o3dgcSC3DMCEncodeParams.h"
+#include "o3dgcTriangleListDecoder.h"
+
+namespace o3dgc
+{
+ //!
+ template <class T>
+ class SC3DMCDecoder
+ {
+ public:
+ //! Constructor.
+ SC3DMCDecoder(void)
+ {
+ m_iterator = 0;
+ m_streamSize = 0;
+ m_quantFloatArray = 0;
+ m_quantFloatArraySize = 0;
+ m_normals = 0;
+ m_normalsSize = 0;
+ m_streamType = O3DGC_STREAM_TYPE_UNKOWN;
+ };
+ //! Destructor.
+ ~SC3DMCDecoder(void)
+ {
+ delete [] m_normals;
+ delete [] m_quantFloatArray;
+ }
+ //!
+ O3DGCErrorCode DecodeHeader(IndexedFaceSet<T> & ifs,
+ const BinaryStream & bstream);
+ //!
+ O3DGCErrorCode DecodePayload(IndexedFaceSet<T> & ifs,
+ const BinaryStream & bstream);
+ const SC3DMCStats & GetStats() const { return m_stats;}
+ unsigned long GetIterator() const { return m_iterator;}
+ O3DGCErrorCode SetIterator(unsigned long iterator) { m_iterator = iterator; return O3DGC_OK; }
+
+
+ private:
+ O3DGCErrorCode DecodeFloatArray(Real * const floatArray,
+ unsigned long numfloatArraySize,
+ unsigned long dimfloatArraySize,
+ unsigned long stride,
+ const Real * const minfloatArray,
+ const Real * const maxfloatArray,
+ unsigned long nQBits,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode & predMode,
+ const BinaryStream & bstream);
+ O3DGCErrorCode IQuantizeFloatArray(Real * const floatArray,
+ unsigned long numfloatArraySize,
+ unsigned long dimfloatArraySize,
+ unsigned long stride,
+ const Real * const minfloatArray,
+ const Real * const maxfloatArray,
+ unsigned long nQBits);
+ O3DGCErrorCode DecodeIntArray(long * const intArray,
+ unsigned long numIntArraySize,
+ unsigned long dimIntArraySize,
+ unsigned long stride,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode & predMode,
+ const BinaryStream & bstream);
+ O3DGCErrorCode ProcessNormals(const IndexedFaceSet<T> & ifs);
+
+ unsigned long m_iterator;
+ unsigned long m_streamSize;
+ SC3DMCEncodeParams m_params;
+ TriangleListDecoder<T> m_triangleListDecoder;
+ long * m_quantFloatArray;
+ unsigned long m_quantFloatArraySize;
+ Vector<char> m_orientation;
+ Real * m_normals;
+ unsigned long m_normalsSize;
+ SC3DMCStats m_stats;
+ O3DGCStreamType m_streamType;
+ };
+}
+#include "o3dgcSC3DMCDecoder.inl" // template implementation
+#endif // O3DGC_SC3DMC_DECODER_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl
new file mode 100644
index 000000000..aa6f24b73
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl
@@ -0,0 +1,850 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_SC3DMC_DECODER_INL
+#define O3DGC_SC3DMC_DECODER_INL
+
+#include "o3dgcArithmeticCodec.h"
+#include "o3dgcTimer.h"
+
+//#define DEBUG_VERBOSE
+
+namespace o3dgc
+{
+#ifdef DEBUG_VERBOSE
+ FILE * g_fileDebugSC3DMCDec = NULL;
+#endif //DEBUG_VERBOSE
+
+ template<class T>
+ O3DGCErrorCode SC3DMCDecoder<T>::DecodeHeader(IndexedFaceSet<T> & ifs,
+ const BinaryStream & bstream)
+ {
+ unsigned long iterator0 = m_iterator;
+ unsigned long start_code = bstream.ReadUInt32(m_iterator, O3DGC_STREAM_TYPE_BINARY);
+ if (start_code != O3DGC_SC3DMC_START_CODE)
+ {
+ m_iterator = iterator0;
+ start_code = bstream.ReadUInt32(m_iterator, O3DGC_STREAM_TYPE_ASCII);
+ if (start_code != O3DGC_SC3DMC_START_CODE)
+ {
+ return O3DGC_ERROR_CORRUPTED_STREAM;
+ }
+ else
+ {
+ m_streamType = O3DGC_STREAM_TYPE_ASCII;
+ }
+ }
+ else
+ {
+ m_streamType = O3DGC_STREAM_TYPE_BINARY;
+ }
+
+ m_streamSize = bstream.ReadUInt32(m_iterator, m_streamType);
+ m_params.SetEncodeMode( (O3DGCSC3DMCEncodingMode) bstream.ReadUChar(m_iterator, m_streamType));
+
+ ifs.SetCreaseAngle((Real) bstream.ReadFloat32(m_iterator, m_streamType));
+
+ unsigned char mask = bstream.ReadUChar(m_iterator, m_streamType);
+
+ ifs.SetCCW ((mask & 1) == 1);
+ ifs.SetSolid ((mask & 2) == 1);
+ ifs.SetConvex ((mask & 4) == 1);
+ ifs.SetIsTriangularMesh((mask & 8) == 1);
+ //bool markerBit0 = (mask & 16 ) == 1;
+ //bool markerBit1 = (mask & 32 ) == 1;
+ //bool markerBit2 = (mask & 64 ) == 1;
+ //bool markerBit3 = (mask & 128) == 1;
+
+ ifs.SetNCoord (bstream.ReadUInt32(m_iterator, m_streamType));
+ ifs.SetNNormal (bstream.ReadUInt32(m_iterator, m_streamType));
+
+
+ ifs.SetNumFloatAttributes(bstream.ReadUInt32(m_iterator, m_streamType));
+ ifs.SetNumIntAttributes (bstream.ReadUInt32(m_iterator, m_streamType));
+
+ if (ifs.GetNCoord() > 0)
+ {
+ ifs.SetNCoordIndex(bstream.ReadUInt32(m_iterator, m_streamType));
+ for(int j=0 ; j<3 ; ++j)
+ {
+ ifs.SetCoordMin(j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ ifs.SetCoordMax(j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ }
+ m_params.SetCoordQuantBits( bstream.ReadUChar(m_iterator, m_streamType) );
+ }
+ if (ifs.GetNNormal() > 0)
+ {
+ ifs.SetNNormalIndex(bstream.ReadUInt32(m_iterator, m_streamType));
+ for(int j=0 ; j<3 ; ++j)
+ {
+ ifs.SetNormalMin(j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ ifs.SetNormalMax(j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ }
+ ifs.SetNormalPerVertex(bstream.ReadUChar(m_iterator, m_streamType) == 1);
+ m_params.SetNormalQuantBits(bstream.ReadUChar(m_iterator, m_streamType));
+ }
+
+ for(unsigned long a = 0; a < ifs.GetNumFloatAttributes(); ++a)
+ {
+ ifs.SetNFloatAttribute(a, bstream.ReadUInt32(m_iterator, m_streamType));
+ if (ifs.GetNFloatAttribute(a) > 0)
+ {
+ ifs.SetNFloatAttributeIndex(a, bstream.ReadUInt32(m_iterator, m_streamType));
+ unsigned char d = bstream.ReadUChar(m_iterator, m_streamType);
+ ifs.SetFloatAttributeDim(a, d);
+ for(unsigned char j = 0 ; j < d ; ++j)
+ {
+ ifs.SetFloatAttributeMin(a, j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ ifs.SetFloatAttributeMax(a, j, (Real) bstream.ReadFloat32(m_iterator, m_streamType));
+ }
+ ifs.SetFloatAttributePerVertex(a, bstream.ReadUChar(m_iterator, m_streamType) == 1);
+ ifs.SetFloatAttributeType(a, (O3DGCIFSFloatAttributeType) bstream.ReadUChar(m_iterator, m_streamType));
+ m_params.SetFloatAttributeQuantBits(a, bstream.ReadUChar(m_iterator, m_streamType));
+ }
+ }
+ for(unsigned long a = 0; a < ifs.GetNumIntAttributes(); ++a)
+ {
+ ifs.SetNIntAttribute(a, bstream.ReadUInt32(m_iterator, m_streamType));
+ if (ifs.GetNIntAttribute(a) > 0)
+ {
+ ifs.SetNIntAttributeIndex(a, bstream.ReadUInt32(m_iterator, m_streamType));
+ ifs.SetIntAttributeDim(a, bstream.ReadUChar(m_iterator, m_streamType));
+ ifs.SetIntAttributePerVertex(a, bstream.ReadUChar(m_iterator, m_streamType) == 1);
+ ifs.SetIntAttributeType(a, (O3DGCIFSIntAttributeType) bstream.ReadUChar(m_iterator, m_streamType));
+ }
+ }
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode SC3DMCDecoder<T>::DecodePayload(IndexedFaceSet<T> & ifs,
+ const BinaryStream & bstream)
+ {
+ O3DGCErrorCode ret = O3DGC_OK;
+#ifdef DEBUG_VERBOSE
+ g_fileDebugSC3DMCDec = fopen("tfans_dec_main.txt", "w");
+#endif //DEBUG_VERBOSE
+
+ m_triangleListDecoder.SetStreamType(m_streamType);
+ m_stats.m_streamSizeCoordIndex = m_iterator;
+ Timer timer;
+ timer.Tic();
+ m_triangleListDecoder.Decode(ifs.GetCoordIndex(), ifs.GetNCoordIndex(), ifs.GetNCoord(), bstream, m_iterator);
+ timer.Toc();
+ m_stats.m_timeCoordIndex = timer.GetElapsedTime();
+ m_stats.m_streamSizeCoordIndex = m_iterator - m_stats.m_streamSizeCoordIndex;
+
+ // decode coord
+ m_stats.m_streamSizeCoord = m_iterator;
+ timer.Tic();
+ if (ifs.GetNCoord() > 0)
+ {
+ ret = DecodeFloatArray(ifs.GetCoord(), ifs.GetNCoord(), 3, 3, ifs.GetCoordMin(), ifs.GetCoordMax(),
+ m_params.GetCoordQuantBits(), ifs, m_params.GetCoordPredMode(), bstream);
+ }
+ if (ret != O3DGC_OK)
+ {
+ return ret;
+ }
+ timer.Toc();
+ m_stats.m_timeCoord = timer.GetElapsedTime();
+ m_stats.m_streamSizeCoord = m_iterator - m_stats.m_streamSizeCoord;
+
+ // decode Normal
+ m_stats.m_streamSizeNormal = m_iterator;
+ timer.Tic();
+ if (ifs.GetNNormal() > 0)
+ {
+ DecodeFloatArray(ifs.GetNormal(), ifs.GetNNormal(), 3, 3, ifs.GetNormalMin(), ifs.GetNormalMax(),
+ m_params.GetNormalQuantBits(), ifs, m_params.GetNormalPredMode(), bstream);
+ }
+ if (ret != O3DGC_OK)
+ {
+ return ret;
+ }
+ timer.Toc();
+ m_stats.m_timeNormal = timer.GetElapsedTime();
+ m_stats.m_streamSizeNormal = m_iterator - m_stats.m_streamSizeNormal;
+
+ // decode FloatAttributes
+ for(unsigned long a = 0; a < ifs.GetNumFloatAttributes(); ++a)
+ {
+ m_stats.m_streamSizeFloatAttribute[a] = m_iterator;
+ timer.Tic();
+ DecodeFloatArray(ifs.GetFloatAttribute(a), ifs.GetNFloatAttribute(a), ifs.GetFloatAttributeDim(a), ifs.GetFloatAttributeDim(a),
+ ifs.GetFloatAttributeMin(a), ifs.GetFloatAttributeMax(a),
+ m_params.GetFloatAttributeQuantBits(a), ifs, m_params.GetFloatAttributePredMode(a), bstream);
+ timer.Toc();
+ m_stats.m_timeFloatAttribute[a] = timer.GetElapsedTime();
+ m_stats.m_streamSizeFloatAttribute[a] = m_iterator - m_stats.m_streamSizeFloatAttribute[a];
+ }
+ if (ret != O3DGC_OK)
+ {
+ return ret;
+ }
+
+ // decode IntAttributes
+ for(unsigned long a = 0; a < ifs.GetNumIntAttributes(); ++a)
+ {
+ m_stats.m_streamSizeIntAttribute[a] = m_iterator;
+ timer.Tic();
+ DecodeIntArray(ifs.GetIntAttribute(a), ifs.GetNIntAttribute(a), ifs.GetIntAttributeDim(a), ifs.GetIntAttributeDim(a),
+ ifs, m_params.GetIntAttributePredMode(a), bstream);
+ timer.Toc();
+ m_stats.m_timeIntAttribute[a] = timer.GetElapsedTime();
+ m_stats.m_streamSizeIntAttribute[a] = m_iterator - m_stats.m_streamSizeIntAttribute[a];
+ }
+ if (ret != O3DGC_OK)
+ {
+ return ret;
+ }
+
+ timer.Tic();
+ m_triangleListDecoder.Reorder();
+ timer.Toc();
+ m_stats.m_timeReorder = timer.GetElapsedTime();
+
+#ifdef DEBUG_VERBOSE
+ fclose(g_fileDebugSC3DMCDec);
+#endif //DEBUG_VERBOSE
+ return ret;
+ }
+ template<class T>
+ O3DGCErrorCode SC3DMCDecoder<T>::DecodeIntArray(long * const intArray,
+ unsigned long numIntArray,
+ unsigned long dimIntArray,
+ unsigned long stride,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode & predMode,
+ const BinaryStream & bstream)
+ {
+ assert(dimIntArray < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ long predResidual;
+ SC3DMCPredictor m_neighbors [O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS];
+ Arithmetic_Codec acd;
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+ Adaptive_Data_Model mModelPreds(O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS+1);
+ unsigned long nPred;
+
+ const AdjacencyInfo & v2T = m_triangleListDecoder.GetVertexToTriangle();
+ const T * const triangles = ifs.GetCoordIndex();
+ const long nvert = (long) numIntArray;
+ unsigned char * buffer = 0;
+ unsigned long start = m_iterator;
+ unsigned long streamSize = bstream.ReadUInt32(m_iterator, m_streamType); // bitsream size
+ unsigned char mask = bstream.ReadUChar(m_iterator, m_streamType);
+ O3DGCSC3DMCBinarization binarization = (O3DGCSC3DMCBinarization)((mask >> 4) & 7);
+ predMode = (O3DGCSC3DMCPredictionMode)(mask & 7);
+ streamSize -= (m_iterator - start);
+ unsigned long iteratorPred = m_iterator + streamSize;
+ unsigned int exp_k = 0;
+ unsigned int M = 0;
+ if (m_streamType != O3DGC_STREAM_TYPE_ASCII)
+ {
+ if (binarization != O3DGC_SC3DMC_BINARIZATION_AC_EGC)
+ {
+ return O3DGC_ERROR_CORRUPTED_STREAM;
+ }
+ bstream.GetBuffer(m_iterator, buffer);
+ m_iterator += streamSize;
+ acd.set_buffer(streamSize, buffer);
+ acd.start_decoder();
+ exp_k = acd.ExpGolombDecode(0, bModel0, bModel1);
+ M = acd.ExpGolombDecode(0, bModel0, bModel1);
+ }
+ else
+ {
+ if (binarization != O3DGC_SC3DMC_BINARIZATION_ASCII)
+ {
+ return O3DGC_ERROR_CORRUPTED_STREAM;
+ }
+ bstream.ReadUInt32(iteratorPred, m_streamType); // predictors bitsream size
+ }
+ Adaptive_Data_Model mModelValues(M+2);
+
+#ifdef DEBUG_VERBOSE
+ printf("IntArray (%i, %i)\n", numIntArray, dimIntArray);
+ fprintf(g_fileDebugSC3DMCDec, "IntArray (%i, %i)\n", numIntArray, dimIntArray);
+#endif //DEBUG_VERBOSE
+
+ for (long v=0; v < nvert; ++v)
+ {
+ nPred = 0;
+ if ( v2T.GetNumNeighbors(v) > 0 &&
+ predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ int u0 = v2T.Begin(v);
+ int u1 = v2T.End(v);
+ for (long u = u0; u < u1; u++)
+ {
+ long ta = v2T.GetNeighbor(u);
+ if (ta < 0)
+ {
+ break;
+ }
+ for(long k = 0; k < 3; ++k)
+ {
+ long w = triangles[ta*3 + k];
+ if ( w < v )
+ {
+ SC3DMCTriplet id = {-1, -1, w};
+ unsigned long p = Insert(id, nPred, m_neighbors);
+ if (p != 0xFFFFFFFF)
+ {
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ m_neighbors[p].m_pred[i] = intArray[w*stride+i];
+ }
+ }
+ }
+ }
+ }
+ }
+ if (nPred > 1)
+ {
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t vm %i\n", v);
+ fprintf(g_fileDebugSC3DMCDec, "\t\t vm %i\n", v);
+ for (unsigned long p = 0; p < nPred; ++p)
+ {
+ printf("\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+ fprintf(g_fileDebugSC3DMCDec, "\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+ for (unsigned long i = 0; i < dimIntArray; ++i)
+ {
+ printf("\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCDec, "\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+ }
+ }
+#endif //DEBUG_VERBOSE
+ unsigned long bestPred;
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bestPred = bstream.ReadUCharASCII(iteratorPred);
+ }
+ else
+ {
+ bestPred = acd.decode(mModelPreds);
+ }
+#ifdef DEBUG_VERBOSE1
+ printf("best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+ fprintf(g_fileDebugSC3DMCDec, "best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+#endif //DEBUG_VERBOSE
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ predResidual = bstream.ReadIntASCII(m_iterator);
+ }
+ else
+ {
+ predResidual = DecodeIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ intArray[v*stride+i] = predResidual + m_neighbors[bestPred].m_pred[i];
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i \t [%i]\n", v*dimIntArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCDec, "%i \t %i \t [%i]\n", v*dimIntArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else if (v > 0 && predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ predResidual = bstream.ReadIntASCII(m_iterator);
+ }
+ else
+ {
+ predResidual = DecodeIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ intArray[v*stride+i] = predResidual + intArray[(v-1)*stride+i];
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", v*dimIntArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCDec, "%i \t %i\n", v*dimIntArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else
+ {
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ predResidual = bstream.ReadUIntASCII(m_iterator);
+ }
+ else
+ {
+ predResidual = DecodeUIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ intArray[v*stride+i] = predResidual;
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", v*dimIntArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCDec, "%i \t %i\n", v*dimIntArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ }
+ m_iterator = iteratorPred;
+#ifdef DEBUG_VERBOSE
+ fflush(g_fileDebugSC3DMCDec);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode SC3DMCDecoder<T>::ProcessNormals(const IndexedFaceSet<T> & ifs)
+ {
+ const long nvert = (long) ifs.GetNNormal();
+ const unsigned long normalSize = ifs.GetNNormal() * 2;
+ if (m_normalsSize < normalSize)
+ {
+ delete [] m_normals;
+ m_normalsSize = normalSize;
+ m_normals = new Real [normalSize];
+ }
+ const AdjacencyInfo & v2T = m_triangleListDecoder.GetVertexToTriangle();
+ const T * const triangles = ifs.GetCoordIndex();
+ Vec3<long> p1, p2, p3, n0, nt;
+ long na0 = 0, nb0 = 0;
+ Real rna0, rnb0, norm0;
+ char ni0 = 0, ni1 = 0;
+ long a, b, c;
+ for (long v=0; v < nvert; ++v)
+ {
+ n0.X() = 0;
+ n0.Y() = 0;
+ n0.Z() = 0;
+ int u0 = v2T.Begin(v);
+ int u1 = v2T.End(v);
+ for (long u = u0; u < u1; u++)
+ {
+ long ta = v2T.GetNeighbor(u);
+ if (ta == -1)
+ {
+ break;
+ }
+ a = triangles[ta*3 + 0];
+ b = triangles[ta*3 + 1];
+ c = triangles[ta*3 + 2];
+ p1.X() = m_quantFloatArray[3*a];
+ p1.Y() = m_quantFloatArray[3*a+1];
+ p1.Z() = m_quantFloatArray[3*a+2];
+ p2.X() = m_quantFloatArray[3*b];
+ p2.Y() = m_quantFloatArray[3*b+1];
+ p2.Z() = m_quantFloatArray[3*b+2];
+ p3.X() = m_quantFloatArray[3*c];
+ p3.Y() = m_quantFloatArray[3*c+1];
+ p3.Z() = m_quantFloatArray[3*c+2];
+ nt = (p2-p1)^(p3-p1);
+ n0 += nt;
+ }
+ norm0 = (Real) n0.GetNorm();
+ if (norm0 == 0.0)
+ {
+ norm0 = 1.0;
+ }
+ SphereToCube(n0.X(), n0.Y(), n0.Z(), na0, nb0, ni0);
+
+
+ rna0 = na0 / norm0;
+ rnb0 = nb0 / norm0;
+ ni1 = ni0 + m_orientation[v];
+ m_orientation[v] = ni1;
+ if ( (ni1 >> 1) != (ni0 >> 1) )
+ {
+ rna0 = Real(0.0);
+ rnb0 = Real(0.0);
+ }
+ m_normals[2*v] = rna0;
+ m_normals[2*v+1] = rnb0;
+
+#ifdef DEBUG_VERBOSE1
+ printf("n0 \t %i \t %i \t %i \t %i (%f, %f)\n", v, n0.X(), n0.Y(), n0.Z(), rna0, rnb0);
+ fprintf(g_fileDebugSC3DMCDec, "n0 \t %i \t %i \t %i \t %i (%f, %f)\n", v, n0.X(), n0.Y(), n0.Z(), rna0, rnb0);
+#endif //DEBUG_VERBOSE
+
+ }
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode SC3DMCDecoder<T>::DecodeFloatArray(Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode & predMode,
+ const BinaryStream & bstream)
+ {
+ assert(dimFloatArray < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ long predResidual;
+ SC3DMCPredictor m_neighbors [O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS];
+ Arithmetic_Codec acd;
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+ Adaptive_Data_Model mModelPreds(O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS+1);
+ unsigned long nPred;
+
+ const AdjacencyInfo & v2T = m_triangleListDecoder.GetVertexToTriangle();
+ const T * const triangles = ifs.GetCoordIndex();
+ const long nvert = (long) numFloatArray;
+ const unsigned long size = numFloatArray * dimFloatArray;
+ unsigned char * buffer = 0;
+ unsigned long start = m_iterator;
+ unsigned long streamSize = bstream.ReadUInt32(m_iterator, m_streamType); // bitsream size
+ unsigned char mask = bstream.ReadUChar(m_iterator, m_streamType);
+ O3DGCSC3DMCBinarization binarization = (O3DGCSC3DMCBinarization)((mask >> 4) & 7);
+ predMode = (O3DGCSC3DMCPredictionMode)(mask & 7);
+ streamSize -= (m_iterator - start);
+ unsigned long iteratorPred = m_iterator + streamSize;
+ unsigned int exp_k = 0;
+ unsigned int M = 0;
+ if (m_streamType != O3DGC_STREAM_TYPE_ASCII)
+ {
+ if (binarization != O3DGC_SC3DMC_BINARIZATION_AC_EGC)
+ {
+ return O3DGC_ERROR_CORRUPTED_STREAM;
+ }
+ bstream.GetBuffer(m_iterator, buffer);
+ m_iterator += streamSize;
+ acd.set_buffer(streamSize, buffer);
+ acd.start_decoder();
+ exp_k = acd.ExpGolombDecode(0, bModel0, bModel1);
+ M = acd.ExpGolombDecode(0, bModel0, bModel1);
+ }
+ else
+ {
+ if (binarization != O3DGC_SC3DMC_BINARIZATION_ASCII)
+ {
+ return O3DGC_ERROR_CORRUPTED_STREAM;
+ }
+ bstream.ReadUInt32(iteratorPred, m_streamType); // predictors bitsream size
+ }
+ Adaptive_Data_Model mModelValues(M+2);
+
+
+ if (predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION)
+ {
+ m_orientation.Allocate(size);
+ m_orientation.Clear();
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ for(unsigned long i = 0; i < numFloatArray; ++i)
+ {
+ m_orientation.PushBack((unsigned char) bstream.ReadIntASCII(m_iterator));
+ }
+ }
+ else
+ {
+ Adaptive_Data_Model dModel(12);
+ for(unsigned long i = 0; i < numFloatArray; ++i)
+ {
+ m_orientation.PushBack((unsigned char) UIntToInt(acd.decode(dModel)));
+ }
+ }
+ ProcessNormals(ifs);
+ dimFloatArray = 2;
+ }
+#ifdef DEBUG_VERBOSE
+ printf("FloatArray (%i, %i)\n", numFloatArray, dimFloatArray);
+ fprintf(g_fileDebugSC3DMCDec, "FloatArray (%i, %i)\n", numFloatArray, dimFloatArray);
+#endif //DEBUG_VERBOSE
+
+ if (m_quantFloatArraySize < size)
+ {
+ delete [] m_quantFloatArray;
+ m_quantFloatArraySize = size;
+ m_quantFloatArray = new long [size];
+ }
+ for (long v=0; v < nvert; ++v)
+ {
+ nPred = 0;
+ if ( v2T.GetNumNeighbors(v) > 0 &&
+ predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ int u0 = v2T.Begin(v);
+ int u1 = v2T.End(v);
+ for (long u = u0; u < u1; u++)
+ {
+ long ta = v2T.GetNeighbor(u);
+ if (ta < 0)
+ {
+ break;
+ }
+ if (predMode == O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION)
+ {
+ long a,b;
+ if ((long) triangles[ta*3] == v)
+ {
+ a = triangles[ta*3 + 1];
+ b = triangles[ta*3 + 2];
+ }
+ else if ((long)triangles[ta*3 + 1] == v)
+ {
+ a = triangles[ta*3 + 0];
+ b = triangles[ta*3 + 2];
+ }
+ else
+ {
+ a = triangles[ta*3 + 0];
+ b = triangles[ta*3 + 1];
+ }
+ if ( a < v && b < v)
+ {
+ int u0 = v2T.Begin(a);
+ int u1 = v2T.End(a);
+ for (long u = u0; u < u1; u++)
+ {
+ long tb = v2T.GetNeighbor(u);
+ if (tb < 0)
+ {
+ break;
+ }
+ long c = -1;
+ bool foundB = false;
+ for(long k = 0; k < 3; ++k)
+ {
+ long x = triangles[tb*3 + k];
+ if (x == b)
+ {
+ foundB = true;
+ }
+ if (x < v && x != a && x != b)
+ {
+ c = x;
+ }
+ }
+ if (c != -1 && foundB)
+ {
+ SC3DMCTriplet id = {min(a, b), max(a, b), -c-1};
+ unsigned long p = Insert(id, nPred, m_neighbors);
+ if (p != 0xFFFFFFFF)
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ m_neighbors[p].m_pred[i] = m_quantFloatArray[a*stride+i] +
+ m_quantFloatArray[b*stride+i] -
+ m_quantFloatArray[c*stride+i];
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION ||
+ predMode == O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION ||
+ predMode == O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION )
+ {
+ for(long k = 0; k < 3; ++k)
+ {
+ long w = triangles[ta*3 + k];
+ if ( w < v )
+ {
+ SC3DMCTriplet id = {-1, -1, w};
+ unsigned long p = Insert(id, nPred, m_neighbors);
+ if (p != 0xFFFFFFFF)
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ m_neighbors[p].m_pred[i] = m_quantFloatArray[w*stride+i];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (nPred > 1)
+ {
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t vm %i\n", v);
+ fprintf(g_fileDebugSC3DMCDec, "\t\t vm %i\n", v);
+ for (unsigned long p = 0; p < nPred; ++p)
+ {
+ printf("\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+ fprintf(g_fileDebugSC3DMCDec, "\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+ for (unsigned long i = 0; i < dimFloatArray; ++i)
+ {
+ printf("\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCDec, "\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+ }
+ }
+#endif //DEBUG_VERBOSE
+ unsigned long bestPred;
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bestPred = bstream.ReadUCharASCII(iteratorPred);
+ }
+ else
+ {
+ bestPred = acd.decode(mModelPreds);
+ }
+#ifdef DEBUG_VERBOSE1
+ printf("best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+ fprintf(g_fileDebugSC3DMCDec, "best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+#endif //DEBUG_VERBOSE
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ predResidual = bstream.ReadIntASCII(m_iterator);
+ }
+ else
+ {
+ predResidual = DecodeIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ m_quantFloatArray[v*stride+i] = predResidual + m_neighbors[bestPred].m_pred[i];
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i \t [%i]\n", v*dimFloatArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCDec, "%i \t %i \t [%i]\n", v*dimFloatArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else if (v > 0 && predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ predResidual = bstream.ReadIntASCII(m_iterator);
+ }
+ else
+ {
+ predResidual = DecodeIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ m_quantFloatArray[v*stride+i] = predResidual + m_quantFloatArray[(v-1)*stride+i];
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", v*dimFloatArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCDec, "%i \t %i\n", v*dimFloatArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ predResidual = bstream.ReadUIntASCII(m_iterator);
+ }
+ else
+ {
+ predResidual = DecodeUIntACEGC(acd, mModelValues, bModel0, bModel1, exp_k, M);
+ }
+ m_quantFloatArray[v*stride+i] = predResidual;
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", v*dimFloatArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCDec, "%i \t %i\n", v*dimFloatArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ }
+ m_iterator = iteratorPred;
+ if (predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION)
+ {
+ const Real minNormal[2] = {(Real)(-2),(Real)(-2)};
+ const Real maxNormal[2] = {(Real)(2),(Real)(2)};
+ Real na1, nb1;
+ Real na0, nb0;
+ char ni1;
+ IQuantizeFloatArray(floatArray, numFloatArray, dimFloatArray, stride, minNormal, maxNormal, nQBits+1);
+ for (long v=0; v < nvert; ++v)
+ {
+ na0 = m_normals[2*v];
+ nb0 = m_normals[2*v+1];
+ na1 = floatArray[stride*v] + na0;
+ nb1 = floatArray[stride*v+1] + nb0;
+ ni1 = m_orientation[v];
+
+ CubeToSphere(na1, nb1, ni1,
+ floatArray[stride*v],
+ floatArray[stride*v+1],
+ floatArray[stride*v+2]);
+
+#ifdef DEBUG_VERBOSE1
+ printf("normal \t %i \t %f \t %f \t %f \t (%i, %f, %f) \t (%f, %f)\n",
+ v,
+ floatArray[stride*v],
+ floatArray[stride*v+1],
+ floatArray[stride*v+2],
+ ni1, na1, nb1,
+ na0, nb0);
+ fprintf(g_fileDebugSC3DMCDec, "normal \t %i \t %f \t %f \t %f \t (%i, %f, %f) \t (%f, %f)\n",
+ v,
+ floatArray[stride*v],
+ floatArray[stride*v+1],
+ floatArray[stride*v+2],
+ ni1, na1, nb1,
+ na0, nb0);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else
+ {
+ IQuantizeFloatArray(floatArray, numFloatArray, dimFloatArray, stride, minFloatArray, maxFloatArray, nQBits);
+ }
+#ifdef DEBUG_VERBOSE
+ fflush(g_fileDebugSC3DMCDec);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode SC3DMCDecoder<T>::IQuantizeFloatArray(Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits)
+ {
+
+ Real idelta[O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES];
+ Real r;
+ for(unsigned long d = 0; d < dimFloatArray; d++)
+ {
+ r = maxFloatArray[d] - minFloatArray[d];
+ if (r > 0.0f)
+ {
+ idelta[d] = r/(float)((1 << nQBits) - 1);
+ }
+ else
+ {
+ idelta[d] = 1.0f;
+ }
+ }
+ for(unsigned long v = 0; v < numFloatArray; ++v)
+ {
+ for(unsigned long d = 0; d < dimFloatArray; ++d)
+ {
+// floatArray[v * stride + d] = m_quantFloatArray[v * stride + d];
+ floatArray[v * stride + d] = m_quantFloatArray[v * stride + d] * idelta[d] + minFloatArray[d];
+ }
+ }
+ return O3DGC_OK;
+ }
+}
+#endif // O3DGC_SC3DMC_DECODER_INL
+
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncodeParams.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncodeParams.h
new file mode 100644
index 000000000..5f3db969c
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncodeParams.h
@@ -0,0 +1,140 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_SC3DMC_ENCODE_PARAMS_H
+#define O3DGC_SC3DMC_ENCODE_PARAMS_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ class SC3DMCEncodeParams
+ {
+ public:
+ //! Constructor.
+ SC3DMCEncodeParams(void)
+ {
+ memset(this, 0, sizeof(SC3DMCEncodeParams));
+ m_encodeMode = O3DGC_SC3DMC_ENCODE_MODE_TFAN;
+ m_streamTypeMode = O3DGC_STREAM_TYPE_ASCII;
+ m_coordQuantBits = 14;
+ m_normalQuantBits = 8;
+ m_coordPredMode = O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION;
+ m_normalPredMode = O3DGC_SC3DMC_SURF_NORMALS_PREDICTION;
+ for(unsigned long a = 0; a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES; ++a)
+ {
+ m_floatAttributePredMode[a] = O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION;
+ }
+ for(unsigned long a = 0; a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES; ++a)
+ {
+ m_intAttributePredMode[a] = O3DGC_SC3DMC_NO_PREDICTION;
+ }
+ };
+ //! Destructor.
+ ~SC3DMCEncodeParams(void) {};
+
+ O3DGCStreamType GetStreamType() const { return m_streamTypeMode;}
+ O3DGCSC3DMCEncodingMode GetEncodeMode() const { return m_encodeMode;}
+
+ unsigned long GetNumFloatAttributes() const { return m_numFloatAttributes;}
+ unsigned long GetNumIntAttributes() const { return m_numIntAttributes;}
+ unsigned long GetCoordQuantBits() const { return m_coordQuantBits;}
+ unsigned long GetNormalQuantBits() const { return m_normalQuantBits;}
+ unsigned long GetFloatAttributeQuantBits(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_floatAttributeQuantBits[a];
+ }
+ O3DGCSC3DMCPredictionMode GetCoordPredMode() const { return m_coordPredMode; }
+ O3DGCSC3DMCPredictionMode GetNormalPredMode() const { return m_normalPredMode; }
+ O3DGCSC3DMCPredictionMode GetFloatAttributePredMode(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_floatAttributePredMode[a];
+ }
+ O3DGCSC3DMCPredictionMode GetIntAttributePredMode(unsigned long a) const
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ return m_intAttributePredMode[a];
+ }
+ O3DGCSC3DMCPredictionMode & GetCoordPredMode() { return m_coordPredMode; }
+ O3DGCSC3DMCPredictionMode & GetNormalPredMode() { return m_normalPredMode; }
+ O3DGCSC3DMCPredictionMode & GetFloatAttributePredMode(unsigned long a)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ return m_floatAttributePredMode[a];
+ }
+ O3DGCSC3DMCPredictionMode & GetIntAttributePredMode(unsigned long a)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ return m_intAttributePredMode[a];
+ }
+ void SetStreamType(O3DGCStreamType streamTypeMode) { m_streamTypeMode = streamTypeMode;}
+ void SetEncodeMode(O3DGCSC3DMCEncodingMode encodeMode) { m_encodeMode = encodeMode;}
+ void SetNumFloatAttributes(unsigned long numFloatAttributes)
+ {
+ assert(numFloatAttributes < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_numFloatAttributes = numFloatAttributes;
+ }
+ void SetNumIntAttributes (unsigned long numIntAttributes)
+ {
+ assert(numIntAttributes < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_numIntAttributes = numIntAttributes;
+ }
+ void SetCoordQuantBits (unsigned int coordQuantBits ) { m_coordQuantBits = coordQuantBits ; }
+ void SetNormalQuantBits (unsigned int normalQuantBits ) { m_normalQuantBits = normalQuantBits ; }
+ void SetFloatAttributeQuantBits(unsigned long a, unsigned long q)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_floatAttributeQuantBits[a] = q;
+ }
+ void SetCoordPredMode (O3DGCSC3DMCPredictionMode coordPredMode ) { m_coordPredMode = coordPredMode ; }
+ void SetNormalPredMode (O3DGCSC3DMCPredictionMode normalPredMode ) { m_normalPredMode = normalPredMode ; }
+ void SetFloatAttributePredMode(unsigned long a, O3DGCSC3DMCPredictionMode p)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES);
+ m_floatAttributePredMode[a] = p;
+ }
+ void SetIntAttributePredMode(unsigned long a, O3DGCSC3DMCPredictionMode p)
+ {
+ assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES);
+ m_intAttributePredMode[a] = p;
+ }
+ private:
+ unsigned long m_numFloatAttributes;
+ unsigned long m_numIntAttributes;
+ unsigned long m_coordQuantBits;
+ unsigned long m_normalQuantBits;
+ unsigned long m_floatAttributeQuantBits[O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+
+ O3DGCSC3DMCPredictionMode m_coordPredMode;
+ O3DGCSC3DMCPredictionMode m_normalPredMode;
+ O3DGCSC3DMCPredictionMode m_floatAttributePredMode[O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES];
+ O3DGCSC3DMCPredictionMode m_intAttributePredMode [O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES];
+ O3DGCStreamType m_streamTypeMode;
+ O3DGCSC3DMCEncodingMode m_encodeMode;
+ };
+}
+#endif // O3DGC_SC3DMC_ENCODE_PARAMS_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.h
new file mode 100644
index 000000000..9c4e95026
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.h
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_SC3DMC_ENCODER_H
+#define O3DGC_SC3DMC_ENCODER_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcIndexedFaceSet.h"
+#include "o3dgcSC3DMCEncodeParams.h"
+#include "o3dgcTriangleListEncoder.h"
+
+namespace o3dgc
+{
+ //!
+ template<class T>
+ class SC3DMCEncoder
+ {
+ public:
+ //! Constructor.
+ SC3DMCEncoder(void)
+ {
+ m_posSize = 0;
+ m_quantFloatArray = 0;
+ m_quantFloatArraySize = 0;
+ m_sizeBufferAC = 0;
+ m_bufferAC = 0;
+ m_normals = 0;
+ m_normalsSize = 0;
+ m_streamType = O3DGC_STREAM_TYPE_UNKOWN;
+ };
+ //! Destructor.
+ ~SC3DMCEncoder(void)
+ {
+ delete [] m_normals;
+ delete [] m_quantFloatArray;
+ delete [] m_bufferAC;
+ }
+ //!
+ O3DGCErrorCode Encode(const SC3DMCEncodeParams & params,
+ const IndexedFaceSet<T> & ifs,
+ BinaryStream & bstream);
+ const SC3DMCStats & GetStats() const { return m_stats;}
+
+ private:
+ O3DGCErrorCode EncodeHeader(const SC3DMCEncodeParams & params,
+ const IndexedFaceSet<T> & ifs,
+ BinaryStream & bstream);
+ O3DGCErrorCode EncodePayload(const SC3DMCEncodeParams & params,
+ const IndexedFaceSet<T> & ifs,
+ BinaryStream & bstream);
+ O3DGCErrorCode EncodeFloatArray(const Real * const floatArray,
+ unsigned long numfloatArray,
+ unsigned long dimfloatArray,
+ unsigned long stride,
+ const Real * const minfloatArray,
+ const Real * const maxfloatArray,
+ unsigned long nQBits,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode predMode,
+ BinaryStream & bstream);
+ O3DGCErrorCode QuantizeFloatArray(const Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minfloatArray,
+ const Real * const maxfloatArray,
+ unsigned long nQBits);
+ O3DGCErrorCode EncodeIntArray(const long * const intArray,
+ unsigned long numIntArray,
+ unsigned long dimIntArray,
+ unsigned long stride,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode predMode,
+ BinaryStream & bstream);
+ O3DGCErrorCode ProcessNormals(const IndexedFaceSet<T> & ifs);
+ TriangleListEncoder<T> m_triangleListEncoder;
+ long * m_quantFloatArray;
+ unsigned long m_posSize;
+ unsigned long m_quantFloatArraySize;
+ unsigned char * m_bufferAC;
+ unsigned long m_sizeBufferAC;
+ SC3DMCPredictor m_neighbors [O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS];
+ unsigned long m_freqSymbols[O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS];
+ unsigned long m_freqPreds [O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS];
+ Vector<long> m_predictors;
+ Real * m_normals;
+ unsigned long m_normalsSize;
+ SC3DMCStats m_stats;
+ O3DGCStreamType m_streamType;
+ };
+}
+#include "o3dgcSC3DMCEncoder.inl" // template implementation
+#endif // O3DGC_SC3DMC_ENCODER_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl
new file mode 100644
index 000000000..2d30b05a2
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl
@@ -0,0 +1,927 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_SC3DMC_ENCODER_INL
+#define O3DGC_SC3DMC_ENCODER_INL
+
+
+#include "o3dgcArithmeticCodec.h"
+#include "o3dgcTimer.h"
+#include "o3dgcVector.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcCommon.h"
+
+//#define DEBUG_VERBOSE
+
+namespace o3dgc
+{
+#ifdef DEBUG_VERBOSE
+ FILE * g_fileDebugSC3DMCEnc = NULL;
+#endif //DEBUG_VERBOSE
+
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::Encode(const SC3DMCEncodeParams & params,
+ const IndexedFaceSet<T> & ifs,
+ BinaryStream & bstream)
+ {
+ // Encode header
+ unsigned long start = bstream.GetSize();
+ EncodeHeader(params, ifs, bstream);
+ // Encode payload
+ EncodePayload(params, ifs, bstream);
+ bstream.WriteUInt32(m_posSize, bstream.GetSize() - start, m_streamType);
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::EncodeHeader(const SC3DMCEncodeParams & params,
+ const IndexedFaceSet<T> & ifs,
+ BinaryStream & bstream)
+ {
+ m_streamType = params.GetStreamType();
+ bstream.WriteUInt32(O3DGC_SC3DMC_START_CODE, m_streamType);
+ m_posSize = bstream.GetSize();
+ bstream.WriteUInt32(0, m_streamType); // to be filled later
+
+ bstream.WriteUChar(O3DGC_SC3DMC_ENCODE_MODE_TFAN, m_streamType);
+ bstream.WriteFloat32((float)ifs.GetCreaseAngle(), m_streamType);
+
+ unsigned char mask = 0;
+ bool markerBit0 = false;
+ bool markerBit1 = false;
+ bool markerBit2 = false;
+ bool markerBit3 = false;
+
+ mask += (ifs.GetCCW() );
+ mask += (ifs.GetSolid() << 1);
+ mask += (ifs.GetConvex() << 2);
+ mask += (ifs.GetIsTriangularMesh() << 3);
+ mask += (markerBit0 << 4);
+ mask += (markerBit1 << 5);
+ mask += (markerBit2 << 6);
+ mask += (markerBit3 << 7);
+
+ bstream.WriteUChar(mask, m_streamType);
+
+ bstream.WriteUInt32(ifs.GetNCoord(), m_streamType);
+ bstream.WriteUInt32(ifs.GetNNormal(), m_streamType);
+ bstream.WriteUInt32(ifs.GetNumFloatAttributes(), m_streamType);
+ bstream.WriteUInt32(ifs.GetNumIntAttributes(), m_streamType);
+
+ if (ifs.GetNCoord() > 0)
+ {
+ bstream.WriteUInt32(ifs.GetNCoordIndex(), m_streamType);
+ for(int j=0 ; j<3 ; ++j)
+ {
+ bstream.WriteFloat32((float) ifs.GetCoordMin(j), m_streamType);
+ bstream.WriteFloat32((float) ifs.GetCoordMax(j), m_streamType);
+ }
+ bstream.WriteUChar((unsigned char) params.GetCoordQuantBits(), m_streamType);
+ }
+ if (ifs.GetNNormal() > 0)
+ {
+ bstream.WriteUInt32(0, m_streamType);
+ for(int j=0 ; j<3 ; ++j)
+ {
+ bstream.WriteFloat32((float) ifs.GetNormalMin(j), m_streamType);
+ bstream.WriteFloat32((float) ifs.GetNormalMax(j), m_streamType);
+ }
+ bstream.WriteUChar(true, m_streamType); //(unsigned char) ifs.GetNormalPerVertex()
+ bstream.WriteUChar((unsigned char) params.GetNormalQuantBits(), m_streamType);
+ }
+ for(unsigned long a = 0; a < ifs.GetNumFloatAttributes(); ++a)
+ {
+ bstream.WriteUInt32(ifs.GetNFloatAttribute(a), m_streamType);
+ if (ifs.GetNFloatAttribute(a) > 0)
+ {
+ assert(ifs.GetFloatAttributeDim(a) < (unsigned long) O3DGC_MAX_UCHAR8);
+ bstream.WriteUInt32(0, m_streamType);
+ unsigned char d = (unsigned char) ifs.GetFloatAttributeDim(a);
+ bstream.WriteUChar(d, m_streamType);
+ for(unsigned char j = 0 ; j < d ; ++j)
+ {
+ bstream.WriteFloat32((float) ifs.GetFloatAttributeMin(a, j), m_streamType);
+ bstream.WriteFloat32((float) ifs.GetFloatAttributeMax(a, j), m_streamType);
+ }
+ bstream.WriteUChar(true, m_streamType); //(unsigned char) ifs.GetFloatAttributePerVertex(a)
+ bstream.WriteUChar((unsigned char) ifs.GetFloatAttributeType(a), m_streamType);
+ bstream.WriteUChar((unsigned char) params.GetFloatAttributeQuantBits(a), m_streamType);
+ }
+ }
+ for(unsigned long a = 0; a < ifs.GetNumIntAttributes(); ++a)
+ {
+ bstream.WriteUInt32(ifs.GetNIntAttribute(a), m_streamType);
+ if (ifs.GetNIntAttribute(a) > 0)
+ {
+ assert(ifs.GetFloatAttributeDim(a) < (unsigned long) O3DGC_MAX_UCHAR8);
+ bstream.WriteUInt32(0, m_streamType);
+ bstream.WriteUChar((unsigned char) ifs.GetIntAttributeDim(a), m_streamType);
+ bstream.WriteUChar(true, m_streamType); // (unsigned char) ifs.GetIntAttributePerVertex(a)
+ bstream.WriteUChar((unsigned char) ifs.GetIntAttributeType(a), m_streamType);
+ }
+ }
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::QuantizeFloatArray(const Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits)
+ {
+ const unsigned long size = numFloatArray * dimFloatArray;
+ Real delta[O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES];
+ Real r;
+ for(unsigned long d = 0; d < dimFloatArray; d++)
+ {
+ r = maxFloatArray[d] - minFloatArray[d];
+ if (r > 0.0f)
+ {
+ delta[d] = (float)((1 << nQBits) - 1) / r;
+ }
+ else
+ {
+ delta[d] = 1.0f;
+ }
+ }
+ if (m_quantFloatArraySize < size)
+ {
+ delete [] m_quantFloatArray;
+ m_quantFloatArraySize = size;
+ m_quantFloatArray = new long [size];
+ }
+ for(unsigned long v = 0; v < numFloatArray; ++v)
+ {
+ for(unsigned long d = 0; d < dimFloatArray; ++d)
+ {
+ m_quantFloatArray[v * stride + d] = (long)((floatArray[v * stride + d]-minFloatArray[d]) * delta[d] + 0.5f);
+ }
+ }
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::EncodeFloatArray(const Real * const floatArray,
+ unsigned long numFloatArray,
+ unsigned long dimFloatArray,
+ unsigned long stride,
+ const Real * const minFloatArray,
+ const Real * const maxFloatArray,
+ unsigned long nQBits,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode predMode,
+ BinaryStream & bstream)
+ {
+ assert(dimFloatArray < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ long predResidual, v, uPredResidual;
+ unsigned long nPred;
+ Arithmetic_Codec ace;
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+
+ const AdjacencyInfo & v2T = m_triangleListEncoder.GetVertexToTriangle();
+ const long * const vmap = m_triangleListEncoder.GetVMap();
+ const long * const invVMap = m_triangleListEncoder.GetInvVMap();
+ const T * const triangles = ifs.GetCoordIndex();
+ const long nvert = (long) numFloatArray;
+ unsigned long start = bstream.GetSize();
+ unsigned char mask = predMode & 7;
+ const unsigned long M = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS - 1;
+ unsigned long nSymbols = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS;
+ unsigned long nPredictors = O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS;
+
+
+ Adaptive_Data_Model mModelValues(M+2);
+ Adaptive_Data_Model mModelPreds(O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS+1);
+
+ memset(m_freqSymbols, 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS);
+ memset(m_freqPreds , 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS);
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ mask += (O3DGC_SC3DMC_BINARIZATION_ASCII & 7)<<4;
+ m_predictors.Allocate(nvert);
+ m_predictors.Clear();
+ }
+ else
+ {
+ mask += (O3DGC_SC3DMC_BINARIZATION_AC_EGC & 7)<<4;
+ const unsigned int NMAX = numFloatArray * dimFloatArray * 8 + 100;
+ if ( m_sizeBufferAC < NMAX )
+ {
+ delete [] m_bufferAC;
+ m_sizeBufferAC = NMAX;
+ m_bufferAC = new unsigned char [m_sizeBufferAC];
+ }
+ ace.set_buffer(NMAX, m_bufferAC);
+ ace.start_encoder();
+ ace.ExpGolombEncode(0, 0, bModel0, bModel1);
+ ace.ExpGolombEncode(M, 0, bModel0, bModel1);
+ }
+ bstream.WriteUInt32(0, m_streamType);
+ bstream.WriteUChar(mask, m_streamType);
+
+#ifdef DEBUG_VERBOSE
+ printf("FloatArray (%i, %i)\n", numFloatArray, dimFloatArray);
+ fprintf(g_fileDebugSC3DMCEnc, "FloatArray (%i, %i)\n", numFloatArray, dimFloatArray);
+#endif //DEBUG_VERBOSE
+
+ if (predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION)
+ {
+ const Real minFloatArray[2] = {(Real)(-2.0),(Real)(-2.0)};
+ const Real maxFloatArray[2] = {(Real)(2.0),(Real)(2.0)};
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ for(unsigned long i = 0; i < numFloatArray; ++i)
+ {
+ bstream.WriteIntASCII(m_predictors[i]);
+ }
+ }
+ else
+ {
+ Adaptive_Data_Model dModel(12);
+ for(unsigned long i = 0; i < numFloatArray; ++i)
+ {
+ ace.encode(IntToUInt(m_predictors[i]), dModel);
+ }
+ }
+ QuantizeFloatArray(floatArray, numFloatArray, dimFloatArray, stride, minFloatArray, maxFloatArray, nQBits+1);
+ }
+ else
+ {
+ QuantizeFloatArray(floatArray, numFloatArray, dimFloatArray, stride, minFloatArray, maxFloatArray, nQBits);
+ }
+
+ for (long vm=0; vm < nvert; ++vm)
+ {
+ nPred = 0;
+ v = invVMap[vm];
+ assert( v >= 0 && v < nvert);
+ if ( v2T.GetNumNeighbors(v) > 0 &&
+ predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ int u0 = v2T.Begin(v);
+ int u1 = v2T.End(v);
+ for (long u = u0; u < u1; u++)
+ {
+ long ta = v2T.GetNeighbor(u);
+ if ( predMode == O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION )
+ {
+ long a,b;
+ if ((long) triangles[ta*3] == v)
+ {
+ a = triangles[ta*3 + 1];
+ b = triangles[ta*3 + 2];
+ }
+ else if ((long) triangles[ta*3 + 1] == v)
+ {
+ a = triangles[ta*3 + 0];
+ b = triangles[ta*3 + 2];
+ }
+ else
+ {
+ a = triangles[ta*3 + 0];
+ b = triangles[ta*3 + 1];
+ }
+ if ( vmap[a] < vm && vmap[b] < vm)
+ {
+ int u0 = v2T.Begin(a);
+ int u1 = v2T.End(a);
+ for (long u = u0; u < u1; u++)
+ {
+ long tb = v2T.GetNeighbor(u);
+ long c = -1;
+ bool foundB = false;
+ for(long k = 0; k < 3; ++k)
+ {
+ long x = triangles[tb*3 + k];
+ if (x == b)
+ {
+ foundB = true;
+ }
+ if (vmap[x] < vm && x != a && x != b)
+ {
+ c = x;
+ }
+ }
+ if (c != -1 && foundB)
+ {
+ SC3DMCTriplet id = {min(vmap[a], vmap[b]), max(vmap[a], vmap[b]), -vmap[c]-1};
+ unsigned long p = Insert(id, nPred, m_neighbors);
+ if (p != 0xFFFFFFFF)
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ m_neighbors[p].m_pred[i] = m_quantFloatArray[a*stride+i] +
+ m_quantFloatArray[b*stride+i] -
+ m_quantFloatArray[c*stride+i];
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( predMode == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION ||
+ predMode == O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION ||
+ predMode == O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION )
+ {
+ for(long k = 0; k < 3; ++k)
+ {
+ long w = triangles[ta*3 + k];
+ if ( vmap[w] < vm )
+ {
+ SC3DMCTriplet id = {-1, -1, vmap[w]};
+ unsigned long p = Insert(id, nPred, m_neighbors);
+ if (p != 0xFFFFFFFF)
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ m_neighbors[p].m_pred[i] = m_quantFloatArray[w*stride+i];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (nPred > 1)
+ {
+ // find best predictor
+ unsigned long bestPred = 0xFFFFFFFF;
+ double bestCost = O3DGC_MAX_DOUBLE;
+ double cost;
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t vm %i\n", vm);
+ fprintf(g_fileDebugSC3DMCEnc, "\t\t vm %i\n", vm);
+#endif //DEBUG_VERBOSE
+
+ for (unsigned long p = 0; p < nPred; ++p)
+ {
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+ fprintf(g_fileDebugSC3DMCEnc, "\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+#endif //DEBUG_VERBOSE
+ cost = -log2((m_freqPreds[p]+1.0) / nPredictors );
+ for (unsigned long i = 0; i < dimFloatArray; ++i)
+ {
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCEnc, "\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+#endif //DEBUG_VERBOSE
+
+ predResidual = (long) IntToUInt(m_quantFloatArray[v*stride+i] - m_neighbors[p].m_pred[i]);
+ if (predResidual < (long) M)
+ {
+ cost += -log2((m_freqSymbols[predResidual]+1.0) / nSymbols );
+ }
+ else
+ {
+ cost += -log2((m_freqSymbols[M] + 1.0) / nSymbols ) + log2((double) (predResidual-M));
+ }
+ }
+ if (cost < bestCost)
+ {
+ bestCost = cost;
+ bestPred = p;
+ }
+ }
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ m_predictors.PushBack((unsigned char) bestPred);
+ }
+ else
+ {
+ ace.encode(bestPred, mModelPreds);
+ }
+#ifdef DEBUG_VERBOSE1
+ printf("best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+ fprintf(g_fileDebugSC3DMCEnc, "best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+#endif //DEBUG_VERBOSE
+ // use best predictor
+ for (unsigned long i = 0; i < dimFloatArray; ++i)
+ {
+ predResidual = m_quantFloatArray[v*stride+i] - m_neighbors[bestPred].m_pred[i];
+ uPredResidual = IntToUInt(predResidual);
+ ++m_freqSymbols[(uPredResidual < (long) M)? uPredResidual : M];
+
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i \t [%i]\n", vm*dimFloatArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCEnc, "%i \t %i \t [%i]\n", vm*dimFloatArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+#endif //DEBUG_VERBOSE
+
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bstream.WriteIntASCII(predResidual);
+ }
+ else
+ {
+ EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
+ }
+ }
+ ++m_freqPreds[bestPred];
+ nSymbols += dimFloatArray;
+ ++nPredictors;
+ }
+ else if ( vm > 0 && predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ long prev = invVMap[vm-1];
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ predResidual = m_quantFloatArray[v*stride+i] - m_quantFloatArray[prev*stride+i];
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bstream.WriteIntASCII(predResidual);
+ }
+ else
+ {
+ EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
+ }
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", vm*dimFloatArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimFloatArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else
+ {
+ for (unsigned long i = 0; i < dimFloatArray; i++)
+ {
+ predResidual = m_quantFloatArray[v*stride+i];
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bstream.WriteUIntASCII(predResidual);
+ }
+ else
+ {
+ EncodeUIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
+ }
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", vm*dimFloatArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimFloatArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ }
+ if (m_streamType != O3DGC_STREAM_TYPE_ASCII)
+ {
+ unsigned long encodedBytes = ace.stop_encoder();
+ for(unsigned long i = 0; i < encodedBytes; ++i)
+ {
+ bstream.WriteUChar8Bin(m_bufferAC[i]);
+ }
+ }
+ bstream.WriteUInt32(start, bstream.GetSize() - start, m_streamType);
+
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ unsigned long start = bstream.GetSize();
+ bstream.WriteUInt32ASCII(0);
+ const unsigned long size = m_predictors.GetSize();
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ bstream.WriteUCharASCII((unsigned char) m_predictors[i]);
+ }
+ bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
+ }
+#ifdef DEBUG_VERBOSE
+ fflush(g_fileDebugSC3DMCEnc);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::EncodeIntArray(const long * const intArray,
+ unsigned long numIntArray,
+ unsigned long dimIntArray,
+ unsigned long stride,
+ const IndexedFaceSet<T> & ifs,
+ O3DGCSC3DMCPredictionMode predMode,
+ BinaryStream & bstream)
+ {
+ assert(dimIntArray < O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES);
+ long predResidual, v, uPredResidual;
+ unsigned long nPred;
+ Arithmetic_Codec ace;
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+
+ const AdjacencyInfo & v2T = m_triangleListEncoder.GetVertexToTriangle();
+ const long * const vmap = m_triangleListEncoder.GetVMap();
+ const long * const invVMap = m_triangleListEncoder.GetInvVMap();
+ const T * const triangles = ifs.GetCoordIndex();
+ const long nvert = (long) numIntArray;
+ unsigned long start = bstream.GetSize();
+ unsigned char mask = predMode & 7;
+ const unsigned long M = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS - 1;
+ unsigned long nSymbols = O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS;
+ unsigned long nPredictors = O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS;
+
+
+ Adaptive_Data_Model mModelValues(M+2);
+ Adaptive_Data_Model mModelPreds(O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS+1);
+
+ memset(m_freqSymbols, 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_SYMBOLS);
+ memset(m_freqPreds , 0, sizeof(unsigned long) * O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS);
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ mask += (O3DGC_SC3DMC_BINARIZATION_ASCII & 7)<<4;
+ m_predictors.Allocate(nvert);
+ m_predictors.Clear();
+ }
+ else
+ {
+ mask += (O3DGC_SC3DMC_BINARIZATION_AC_EGC & 7)<<4;
+ const unsigned int NMAX = numIntArray * dimIntArray * 8 + 100;
+ if ( m_sizeBufferAC < NMAX )
+ {
+ delete [] m_bufferAC;
+ m_sizeBufferAC = NMAX;
+ m_bufferAC = new unsigned char [m_sizeBufferAC];
+ }
+ ace.set_buffer(NMAX, m_bufferAC);
+ ace.start_encoder();
+ ace.ExpGolombEncode(0, 0, bModel0, bModel1);
+ ace.ExpGolombEncode(M, 0, bModel0, bModel1);
+ }
+ bstream.WriteUInt32(0, m_streamType);
+ bstream.WriteUChar(mask, m_streamType);
+
+#ifdef DEBUG_VERBOSE
+ printf("IntArray (%i, %i)\n", numIntArray, dimIntArray);
+ fprintf(g_fileDebugSC3DMCEnc, "IntArray (%i, %i)\n", numIntArray, dimIntArray);
+#endif //DEBUG_VERBOSE
+
+ for (long vm=0; vm < nvert; ++vm)
+ {
+ nPred = 0;
+ v = invVMap[vm];
+ assert( v >= 0 && v < nvert);
+ if ( v2T.GetNumNeighbors(v) > 0 &&
+ predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ int u0 = v2T.Begin(v);
+ int u1 = v2T.End(v);
+ for (long u = u0; u < u1; u++)
+ {
+ long ta = v2T.GetNeighbor(u);
+ for(long k = 0; k < 3; ++k)
+ {
+ long w = triangles[ta*3 + k];
+ if ( vmap[w] < vm )
+ {
+ SC3DMCTriplet id = {-1, -1, vmap[w]};
+ unsigned long p = Insert(id, nPred, m_neighbors);
+ if (p != 0xFFFFFFFF)
+ {
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ m_neighbors[p].m_pred[i] = intArray[w*stride+i];
+ }
+ }
+ }
+ }
+ }
+ }
+ if (nPred > 1)
+ {
+ // find best predictor
+ unsigned long bestPred = 0xFFFFFFFF;
+ double bestCost = O3DGC_MAX_DOUBLE;
+ double cost;
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t vm %i\n", vm);
+ fprintf(g_fileDebugSC3DMCEnc, "\t\t vm %i\n", vm);
+#endif //DEBUG_VERBOSE
+
+ for (unsigned long p = 0; p < nPred; ++p)
+ {
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+ fprintf(g_fileDebugSC3DMCEnc, "\t\t pred a = %i b = %i c = %i \n", m_neighbors[p].m_id.m_a, m_neighbors[p].m_id.m_b, m_neighbors[p].m_id.m_c);
+#endif //DEBUG_VERBOSE
+ cost = -log2((m_freqPreds[p]+1.0) / nPredictors );
+ for (unsigned long i = 0; i < dimIntArray; ++i)
+ {
+#ifdef DEBUG_VERBOSE1
+ printf("\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCEnc, "\t\t\t %i\n", m_neighbors[p].m_pred[i]);
+#endif //DEBUG_VERBOSE
+
+ predResidual = (long) IntToUInt(intArray[v*stride+i] - m_neighbors[p].m_pred[i]);
+ if (predResidual < (long) M)
+ {
+ cost += -log2((m_freqSymbols[predResidual]+1.0) / nSymbols );
+ }
+ else
+ {
+ cost += -log2((m_freqSymbols[M] + 1.0) / nSymbols ) + log2((double) (predResidual-M));
+ }
+ }
+ if (cost < bestCost)
+ {
+ bestCost = cost;
+ bestPred = p;
+ }
+ }
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ m_predictors.PushBack((unsigned char) bestPred);
+ }
+ else
+ {
+ ace.encode(bestPred, mModelPreds);
+ }
+#ifdef DEBUG_VERBOSE1
+ printf("best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+ fprintf(g_fileDebugSC3DMCEnc, "best (%i, %i, %i) \t pos %i\n", m_neighbors[bestPred].m_id.m_a, m_neighbors[bestPred].m_id.m_b, m_neighbors[bestPred].m_id.m_c, bestPred);
+#endif //DEBUG_VERBOSE
+ // use best predictor
+ for (unsigned long i = 0; i < dimIntArray; ++i)
+ {
+ predResidual = intArray[v*stride+i] - m_neighbors[bestPred].m_pred[i];
+ uPredResidual = IntToUInt(predResidual);
+ ++m_freqSymbols[(uPredResidual < (long) M)? uPredResidual : M];
+
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i \t [%i]\n", vm*dimIntArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+ fprintf(g_fileDebugSC3DMCEnc, "%i \t %i \t [%i]\n", vm*dimIntArray+i, predResidual, m_neighbors[bestPred].m_pred[i]);
+#endif //DEBUG_VERBOSE
+
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bstream.WriteIntASCII(predResidual);
+ }
+ else
+ {
+ EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
+ }
+ }
+ ++m_freqPreds[bestPred];
+ nSymbols += dimIntArray;
+ ++nPredictors;
+ }
+ else if ( vm > 0 && predMode != O3DGC_SC3DMC_NO_PREDICTION)
+ {
+ long prev = invVMap[vm-1];
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ predResidual = intArray[v*stride+i] - intArray[prev*stride+i];
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bstream.WriteIntASCII(predResidual);
+ }
+ else
+ {
+ EncodeIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
+ }
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", vm*dimIntArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimIntArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ else
+ {
+ for (unsigned long i = 0; i < dimIntArray; i++)
+ {
+ predResidual = intArray[v*stride+i];
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ bstream.WriteUIntASCII(predResidual);
+ }
+ else
+ {
+ EncodeUIntACEGC(predResidual, ace, mModelValues, bModel0, bModel1, M);
+ }
+#ifdef DEBUG_VERBOSE
+ printf("%i \t %i\n", vm*dimIntArray+i, predResidual);
+ fprintf(g_fileDebugSC3DMCEnc, "%i \t %i\n", vm*dimIntArray+i, predResidual);
+#endif //DEBUG_VERBOSE
+ }
+ }
+ }
+ if (m_streamType != O3DGC_STREAM_TYPE_ASCII)
+ {
+ unsigned long encodedBytes = ace.stop_encoder();
+ for(unsigned long i = 0; i < encodedBytes; ++i)
+ {
+ bstream.WriteUChar8Bin(m_bufferAC[i]);
+ }
+ }
+ bstream.WriteUInt32(start, bstream.GetSize() - start, m_streamType);
+
+ if (m_streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ unsigned long start = bstream.GetSize();
+ bstream.WriteUInt32ASCII(0);
+ const unsigned long size = m_predictors.GetSize();
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ bstream.WriteUCharASCII((unsigned char) m_predictors[i]);
+ }
+ bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
+ }
+#ifdef DEBUG_VERBOSE
+ fflush(g_fileDebugSC3DMCEnc);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::ProcessNormals(const IndexedFaceSet<T> & ifs)
+ {
+ const long nvert = (long) ifs.GetNNormal();
+ const unsigned long normalSize = ifs.GetNNormal() * 2;
+ if (m_normalsSize < normalSize)
+ {
+ delete [] m_normals;
+ m_normalsSize = normalSize;
+ m_normals = new Real [normalSize];
+ }
+ const AdjacencyInfo & v2T = m_triangleListEncoder.GetVertexToTriangle();
+ const long * const invVMap = m_triangleListEncoder.GetInvVMap();
+ const T * const triangles = ifs.GetCoordIndex();
+ const Real * const originalNormals = ifs.GetNormal();
+ Vec3<long> p1, p2, p3, n0, nt;
+ Vec3<Real> n1;
+ long na0 = 0, nb0 = 0;
+ Real rna0, rnb0, na1 = 0, nb1 = 0, norm0, norm1;
+ char ni0 = 0, ni1 = 0;
+ long a, b, c, v;
+ m_predictors.Clear();
+ for (long i=0; i < nvert; ++i)
+ {
+ v = invVMap[i];
+ n0.X() = 0;
+ n0.Y() = 0;
+ n0.Z() = 0;
+ int u0 = v2T.Begin(v);
+ int u1 = v2T.End(v);
+ for (long u = u0; u < u1; u++)
+ {
+ long ta = v2T.GetNeighbor(u);
+ a = triangles[ta*3 + 0];
+ b = triangles[ta*3 + 1];
+ c = triangles[ta*3 + 2];
+ p1.X() = m_quantFloatArray[3*a];
+ p1.Y() = m_quantFloatArray[3*a+1];
+ p1.Z() = m_quantFloatArray[3*a+2];
+ p2.X() = m_quantFloatArray[3*b];
+ p2.Y() = m_quantFloatArray[3*b+1];
+ p2.Z() = m_quantFloatArray[3*b+2];
+ p3.X() = m_quantFloatArray[3*c];
+ p3.Y() = m_quantFloatArray[3*c+1];
+ p3.Z() = m_quantFloatArray[3*c+2];
+ nt = (p2-p1)^(p3-p1);
+ n0 += nt;
+ }
+ norm0 = (Real) n0.GetNorm();
+ if (norm0 == 0.0)
+ {
+ norm0 = 1.0;
+ }
+ SphereToCube(n0.X(), n0.Y(), n0.Z(), na0, nb0, ni0);
+ rna0 = na0 / norm0;
+ rnb0 = nb0 / norm0;
+
+ n1.X() = originalNormals[3*v];
+ n1.Y() = originalNormals[3*v+1];
+ n1.Z() = originalNormals[3*v+2];
+ norm1 = (Real) n1.GetNorm();
+ if (norm1 != 0.0)
+ {
+ n1.X() /= norm1;
+ n1.Y() /= norm1;
+ n1.Z() /= norm1;
+ }
+ SphereToCube(n1.X(), n1.Y(), n1.Z(), na1, nb1, ni1);
+ m_predictors.PushBack(ni1 - ni0);
+ if ( (ni1 >> 1) != (ni0 >> 1) )
+ {
+ rna0 = (Real)0.0;
+ rnb0 = (Real)0.0;
+ }
+ m_normals[2*v] = na1 - rna0;
+ m_normals[2*v+1] = nb1 - rnb0;
+
+#ifdef DEBUG_VERBOSE1
+ printf("n0 \t %i \t %i \t %i \t %i (%f, %f)\n", i, n0.X(), n0.Y(), n0.Z(), rna0, rnb0);
+ fprintf(g_fileDebugSC3DMCEnc,"n0 \t %i \t %i \t %i \t %i (%f, %f)\n", i, n0.X(), n0.Y(), n0.Z(), rna0, rnb0);
+#endif //DEBUG_VERBOSE
+
+#ifdef DEBUG_VERBOSE1
+ printf("normal \t %i \t %f \t %f \t %f \t (%i, %f, %f) \t (%f, %f)\n", i, n1.X(), n1.Y(), n1.Z(), ni1, na1, nb1, rna0, rnb0);
+ fprintf(g_fileDebugSC3DMCEnc, "normal \t %i \t %f \t %f \t %f \t (%i, %f, %f) \t (%f, %f)\n", i, n1.X(), n1.Y(), n1.Z(), ni1, na1, nb1, rna0, rnb0);
+#endif //DEBUG_VERBOSE
+
+ }
+ return O3DGC_OK;
+ }
+
+ template <class T>
+ O3DGCErrorCode SC3DMCEncoder<T>::EncodePayload(const SC3DMCEncodeParams & params,
+ const IndexedFaceSet<T> & ifs,
+ BinaryStream & bstream)
+ {
+#ifdef DEBUG_VERBOSE
+ g_fileDebugSC3DMCEnc = fopen("tfans_enc_main.txt", "w");
+#endif //DEBUG_VERBOSE
+
+ // encode triangle list
+ m_triangleListEncoder.SetStreamType(params.GetStreamType());
+ m_stats.m_streamSizeCoordIndex = bstream.GetSize();
+ Timer timer;
+ timer.Tic();
+ m_triangleListEncoder.Encode(ifs.GetCoordIndex(), ifs.GetIndexBufferID(), ifs.GetNCoordIndex(), ifs.GetNCoord(), bstream);
+ timer.Toc();
+ m_stats.m_timeCoordIndex = timer.GetElapsedTime();
+ m_stats.m_streamSizeCoordIndex = bstream.GetSize() - m_stats.m_streamSizeCoordIndex;
+
+ // encode coord
+ m_stats.m_streamSizeCoord = bstream.GetSize();
+ timer.Tic();
+ if (ifs.GetNCoord() > 0)
+ {
+ EncodeFloatArray(ifs.GetCoord(), ifs.GetNCoord(), 3, 3, ifs.GetCoordMin(), ifs.GetCoordMax(),
+ params.GetCoordQuantBits(), ifs, params.GetCoordPredMode(), bstream);
+ }
+ timer.Toc();
+ m_stats.m_timeCoord = timer.GetElapsedTime();
+ m_stats.m_streamSizeCoord = bstream.GetSize() - m_stats.m_streamSizeCoord;
+
+
+ // encode Normal
+ m_stats.m_streamSizeNormal = bstream.GetSize();
+ timer.Tic();
+ if (ifs.GetNNormal() > 0)
+ {
+ if (params.GetNormalPredMode() == O3DGC_SC3DMC_SURF_NORMALS_PREDICTION)
+ {
+ ProcessNormals(ifs);
+ EncodeFloatArray(m_normals, ifs.GetNNormal(), 2, 2, ifs.GetNormalMin(), ifs.GetNormalMax(),
+ params.GetNormalQuantBits(), ifs, params.GetNormalPredMode(), bstream);
+ }
+ else
+ {
+ EncodeFloatArray(ifs.GetNormal(), ifs.GetNNormal(), 3, 3, ifs.GetNormalMin(), ifs.GetNormalMax(),
+ params.GetNormalQuantBits(), ifs, params.GetNormalPredMode(), bstream);
+ }
+ }
+ timer.Toc();
+ m_stats.m_timeNormal = timer.GetElapsedTime();
+ m_stats.m_streamSizeNormal = bstream.GetSize() - m_stats.m_streamSizeNormal;
+
+
+ // encode FloatAttribute
+ for(unsigned long a = 0; a < ifs.GetNumFloatAttributes(); ++a)
+ {
+ m_stats.m_streamSizeFloatAttribute[a] = bstream.GetSize();
+ timer.Tic();
+ EncodeFloatArray(ifs.GetFloatAttribute(a), ifs.GetNFloatAttribute(a),
+ ifs.GetFloatAttributeDim(a), ifs.GetFloatAttributeDim(a),
+ ifs.GetFloatAttributeMin(a), ifs.GetFloatAttributeMax(a),
+ params.GetFloatAttributeQuantBits(a), ifs,
+ params.GetFloatAttributePredMode(a), bstream);
+ timer.Toc();
+ m_stats.m_timeFloatAttribute[a] = timer.GetElapsedTime();
+ m_stats.m_streamSizeFloatAttribute[a] = bstream.GetSize() - m_stats.m_streamSizeFloatAttribute[a];
+ }
+
+ // encode IntAttribute
+ for(unsigned long a = 0; a < ifs.GetNumIntAttributes(); ++a)
+ {
+ m_stats.m_streamSizeIntAttribute[a] = bstream.GetSize();
+ timer.Tic();
+ EncodeIntArray(ifs.GetIntAttribute(a), ifs.GetNIntAttribute(a), ifs.GetIntAttributeDim(a),
+ ifs.GetIntAttributeDim(a), ifs, params.GetIntAttributePredMode(a), bstream);
+ timer.Toc();
+ m_stats.m_timeIntAttribute[a] = timer.GetElapsedTime();
+ m_stats.m_streamSizeIntAttribute[a] = bstream.GetSize() - m_stats.m_streamSizeIntAttribute[a];
+ }
+#ifdef DEBUG_VERBOSE
+ fclose(g_fileDebugSC3DMCEnc);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+}
+#endif // O3DGC_SC3DMC_ENCODER_INL
+
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTimer.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTimer.h
new file mode 100644
index 000000000..00fe5b653
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTimer.h
@@ -0,0 +1,134 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_TIMER_H
+#define O3DGC_TIMER_H
+
+#include "o3dgcCommon.h"
+
+#ifdef _WIN32
+/* Thank you, Microsoft, for file WinDef.h with min/max redefinition. */
+#define NOMINMAX
+#include <windows.h>
+#elif __MACH__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#else
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+
+
+namespace o3dgc
+{
+#ifdef _WIN32
+ class Timer
+ {
+ public:
+ Timer(void)
+ {
+ m_start.QuadPart = 0;
+ m_stop.QuadPart = 0;
+ QueryPerformanceFrequency( &m_freq ) ;
+ };
+ ~Timer(void){};
+ void Tic()
+ {
+ QueryPerformanceCounter(&m_start) ;
+ }
+ void Toc()
+ {
+ QueryPerformanceCounter(&m_stop);
+ }
+ double GetElapsedTime() // in ms
+ {
+ LARGE_INTEGER delta;
+ delta.QuadPart = m_stop.QuadPart - m_start.QuadPart;
+ return (1000.0 * delta.QuadPart) / (double)m_freq.QuadPart;
+ }
+ private:
+ LARGE_INTEGER m_start;
+ LARGE_INTEGER m_stop;
+ LARGE_INTEGER m_freq;
+
+ };
+#elif __MACH__
+ class Timer
+ {
+ public:
+ Timer(void)
+ {
+ memset(this, 0, sizeof(Timer));
+ host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, & m_cclock);
+ };
+ ~Timer(void)
+ {
+ mach_port_deallocate(mach_task_self(), m_cclock);
+ };
+ void Tic()
+ {
+ clock_get_time( m_cclock, &m_start);
+ }
+ void Toc()
+ {
+ clock_get_time( m_cclock, &m_stop);
+ }
+ double GetElapsedTime() // in ms
+ {
+ return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
+ }
+ private:
+ clock_serv_t m_cclock;
+ mach_timespec_t m_start;
+ mach_timespec_t m_stop;
+ };
+#else
+ class Timer
+ {
+ public:
+ Timer(void)
+ {
+ memset(this, 0, sizeof(Timer));
+ };
+ ~Timer(void){};
+ void Tic()
+ {
+ clock_gettime(CLOCK_REALTIME, &m_start);
+ }
+ void Toc()
+ {
+ clock_gettime(CLOCK_REALTIME, &m_stop);
+ }
+ double GetElapsedTime() // in ms
+ {
+ return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
+ }
+ private:
+ struct timespec m_start;
+ struct timespec m_stop;
+ };
+#endif
+
+}
+#endif // O3DGC_TIMER_H
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTools.cpp b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTools.cpp
new file mode 100644
index 000000000..52b552304
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTools.cpp
@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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/Open3DGC/o3dgcTriangleFans.cpp b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.cpp
new file mode 100644
index 000000000..078ed16e6
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.cpp
@@ -0,0 +1,475 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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 "o3dgcTriangleFans.h"
+#include "o3dgcArithmeticCodec.h"
+
+//#define DEBUG_VERBOSE
+
+namespace o3dgc
+{
+#ifdef DEBUG_VERBOSE
+ FILE* g_fileDebugTF = NULL;
+#endif //DEBUG_VERBOSE
+
+ O3DGCErrorCode SaveUIntData(const Vector<long> & data,
+ BinaryStream & bstream)
+ {
+ unsigned long start = bstream.GetSize();
+ bstream.WriteUInt32ASCII(0);
+ const unsigned long size = data.GetSize();
+ bstream.WriteUInt32ASCII(size);
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ bstream.WriteUIntASCII(data[i]);
+ }
+ bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode SaveIntData(const Vector<long> & data,
+ BinaryStream & bstream)
+ {
+ unsigned long start = bstream.GetSize();
+ bstream.WriteUInt32ASCII(0);
+ const unsigned long size = data.GetSize();
+ bstream.WriteUInt32ASCII(size);
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ bstream.WriteIntASCII(data[i]);
+ }
+ bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode SaveBinData(const Vector<long> & data,
+ BinaryStream & bstream)
+ {
+ unsigned long start = bstream.GetSize();
+ bstream.WriteUInt32ASCII(0);
+ const unsigned long size = data.GetSize();
+ long symbol;
+ bstream.WriteUInt32ASCII(size);
+ for(unsigned long i = 0; i < size; )
+ {
+ symbol = 0;
+ for(unsigned long h = 0; h < O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0 && i < size; ++h)
+ {
+ symbol += (data[i] << h);
+ ++i;
+ }
+ bstream.WriteUCharASCII((unsigned char) symbol);
+ }
+ bstream.WriteUInt32ASCII(start, bstream.GetSize() - start);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode CompressedTriangleFans::SaveUIntAC(const Vector<long> & data,
+ const unsigned long M,
+ BinaryStream & bstream)
+ {
+ unsigned long start = bstream.GetSize();
+ const unsigned int NMAX = data.GetSize() * 8 + 100;
+ const unsigned long size = data.GetSize();
+ long minValue = O3DGC_MAX_LONG;
+ bstream.WriteUInt32Bin(0);
+ bstream.WriteUInt32Bin(size);
+ if (size > 0)
+ {
+ #ifdef DEBUG_VERBOSE
+ printf("-----------\nsize %i, start %i\n", size, start);
+ fprintf(g_fileDebugTF, "-----------\nsize %i, start %i\n", size, start);
+ #endif //DEBUG_VERBOSE
+
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ if (minValue > data[i])
+ {
+ minValue = data[i];
+ }
+ #ifdef DEBUG_VERBOSE
+ printf("%i\t%i\n", i, data[i]);
+ fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
+ #endif //DEBUG_VERBOSE
+ }
+ bstream.WriteUInt32Bin(minValue);
+ if ( m_sizeBufferAC < NMAX )
+ {
+ delete [] m_bufferAC;
+ m_sizeBufferAC = NMAX;
+ m_bufferAC = new unsigned char [m_sizeBufferAC];
+ }
+ Arithmetic_Codec ace;
+ ace.set_buffer(NMAX, m_bufferAC);
+ ace.start_encoder();
+ Adaptive_Data_Model mModelValues(M+1);
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ ace.encode(data[i]-minValue, mModelValues);
+ }
+ unsigned long encodedBytes = ace.stop_encoder();
+ for(unsigned long i = 0; i < encodedBytes; ++i)
+ {
+ bstream.WriteUChar8Bin(m_bufferAC[i]);
+ }
+ }
+ bstream.WriteUInt32Bin(start, bstream.GetSize() - start);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode CompressedTriangleFans::SaveBinAC(const Vector<long> & data,
+ BinaryStream & bstream)
+ {
+ unsigned long start = bstream.GetSize();
+ const unsigned int NMAX = data.GetSize() * 8 + 100;
+ const unsigned long size = data.GetSize();
+ bstream.WriteUInt32Bin(0);
+ bstream.WriteUInt32Bin(size);
+ if (size > 0)
+ {
+ if ( m_sizeBufferAC < NMAX )
+ {
+ delete [] m_bufferAC;
+ m_sizeBufferAC = NMAX;
+ m_bufferAC = new unsigned char [m_sizeBufferAC];
+ }
+ Arithmetic_Codec ace;
+ ace.set_buffer(NMAX, m_bufferAC);
+ ace.start_encoder();
+ Adaptive_Bit_Model bModel;
+ #ifdef DEBUG_VERBOSE
+ printf("-----------\nsize %i, start %i\n", size, start);
+ fprintf(g_fileDebugTF, "-----------\nsize %i, start %i\n", size, start);
+ #endif //DEBUG_VERBOSE
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ ace.encode(data[i], bModel);
+ #ifdef DEBUG_VERBOSE
+ printf("%i\t%i\n", i, data[i]);
+ fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
+ #endif //DEBUG_VERBOSE
+ }
+ unsigned long encodedBytes = ace.stop_encoder();
+ for(unsigned long i = 0; i < encodedBytes; ++i)
+ {
+ bstream.WriteUChar8Bin(m_bufferAC[i]);
+ }
+ }
+ bstream.WriteUInt32Bin(start, bstream.GetSize() - start);
+ return O3DGC_OK;
+ }
+
+ O3DGCErrorCode CompressedTriangleFans::SaveIntACEGC(const Vector<long> & data,
+ const unsigned long M,
+ BinaryStream & bstream)
+ {
+ unsigned long start = bstream.GetSize();
+ const unsigned int NMAX = data.GetSize() * 8 + 100;
+ const unsigned long size = data.GetSize();
+ long minValue = 0;
+ bstream.WriteUInt32Bin(0);
+ bstream.WriteUInt32Bin(size);
+ if (size > 0)
+ {
+#ifdef DEBUG_VERBOSE
+ printf("-----------\nsize %i, start %i\n", size, start);
+ fprintf(g_fileDebugTF, "-----------\nsize %i, start %i\n", size, start);
+#endif //DEBUG_VERBOSE
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ if (minValue > data[i])
+ {
+ minValue = data[i];
+ }
+#ifdef DEBUG_VERBOSE
+ printf("%i\t%i\n", i, data[i]);
+ fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
+#endif //DEBUG_VERBOSE
+ }
+ bstream.WriteUInt32Bin(minValue + O3DGC_MAX_LONG);
+ if ( m_sizeBufferAC < NMAX )
+ {
+ delete [] m_bufferAC;
+ m_sizeBufferAC = NMAX;
+ m_bufferAC = new unsigned char [m_sizeBufferAC];
+ }
+ Arithmetic_Codec ace;
+ ace.set_buffer(NMAX, m_bufferAC);
+ ace.start_encoder();
+ Adaptive_Data_Model mModelValues(M+2);
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+ unsigned long value;
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ value = data[i]-minValue;
+ if (value < M)
+ {
+ ace.encode(value, mModelValues);
+ }
+ else
+ {
+ ace.encode(M, mModelValues);
+ ace.ExpGolombEncode(value-M, 0, bModel0, bModel1);
+ }
+ }
+ unsigned long encodedBytes = ace.stop_encoder();
+ for(unsigned long i = 0; i < encodedBytes; ++i)
+ {
+ bstream.WriteUChar8Bin(m_bufferAC[i]);
+ }
+ }
+ bstream.WriteUInt32Bin(start, bstream.GetSize() - start);
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode CompressedTriangleFans::Save(BinaryStream & bstream, bool encodeTrianglesOrder, O3DGCStreamType streamType)
+ {
+#ifdef DEBUG_VERBOSE
+ g_fileDebugTF = fopen("SaveIntACEGC_new.txt", "w");
+#endif //DEBUG_VERBOSE
+
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ SaveUIntData(m_numTFANs , bstream);
+ SaveUIntData(m_degrees , bstream);
+ SaveUIntData(m_configs , bstream);
+ SaveBinData (m_operations, bstream);
+ SaveIntData (m_indices , bstream);
+ if (encodeTrianglesOrder)
+ {
+ SaveUIntData(m_trianglesOrder, bstream);
+ }
+ }
+ else
+ {
+ SaveIntACEGC(m_numTFANs , 4 , bstream);
+ SaveIntACEGC(m_degrees , 16, bstream);
+ SaveUIntAC (m_configs , 10, bstream);
+ SaveBinAC (m_operations, bstream);
+ SaveIntACEGC(m_indices , 8 , bstream);
+ if (encodeTrianglesOrder)
+ {
+ SaveIntACEGC(m_trianglesOrder , 16, bstream);
+ }
+ }
+#ifdef DEBUG_VERBOSE
+ fclose(g_fileDebugTF);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadUIntData(Vector<long> & data,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ bstream.ReadUInt32ASCII(iterator);
+ const unsigned long size = bstream.ReadUInt32ASCII(iterator);
+ data.Allocate(size);
+ data.Clear();
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ data.PushBack(bstream.ReadUIntASCII(iterator));
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadIntData(Vector<long> & data,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ bstream.ReadUInt32ASCII(iterator);
+ const unsigned long size = bstream.ReadUInt32ASCII(iterator);
+ data.Allocate(size);
+ data.Clear();
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ data.PushBack(bstream.ReadIntASCII(iterator));
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadBinData(Vector<long> & data,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ bstream.ReadUInt32ASCII(iterator);
+ const unsigned long size = bstream.ReadUInt32ASCII(iterator);
+ long symbol;
+ data.Allocate(size * O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0);
+ data.Clear();
+ for(unsigned long i = 0; i < size;)
+ {
+ symbol = bstream.ReadUCharASCII(iterator);
+ for(unsigned long h = 0; h < O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0; ++h)
+ {
+ data.PushBack(symbol & 1);
+ symbol >>= 1;
+ ++i;
+ }
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadUIntAC(Vector<long> & data,
+ const unsigned long M,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ unsigned long sizeSize = bstream.ReadUInt32Bin(iterator) - 12;
+ unsigned long size = bstream.ReadUInt32Bin(iterator);
+ if (size == 0)
+ {
+ return O3DGC_OK;
+ }
+ long minValue = bstream.ReadUInt32Bin(iterator);
+ unsigned char * buffer = 0;
+ bstream.GetBuffer(iterator, buffer);
+ iterator += sizeSize;
+ data.Allocate(size);
+ Arithmetic_Codec acd;
+ acd.set_buffer(sizeSize, buffer);
+ acd.start_decoder();
+ Adaptive_Data_Model mModelValues(M+1);
+#ifdef DEBUG_VERBOSE
+ printf("-----------\nsize %i\n", size);
+ fprintf(g_fileDebugTF, "size %i\n", size);
+#endif //DEBUG_VERBOSE
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ data.PushBack(acd.decode(mModelValues)+minValue);
+#ifdef DEBUG_VERBOSE
+ printf("%i\t%i\n", i, data[i]);
+ fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
+#endif //DEBUG_VERBOSE
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadIntACEGC(Vector<long> & data,
+ const unsigned long M,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ unsigned long sizeSize = bstream.ReadUInt32Bin(iterator) - 12;
+ unsigned long size = bstream.ReadUInt32Bin(iterator);
+ if (size == 0)
+ {
+ return O3DGC_OK;
+ }
+ long minValue = bstream.ReadUInt32Bin(iterator) - O3DGC_MAX_LONG;
+ unsigned char * buffer = 0;
+ bstream.GetBuffer(iterator, buffer);
+ iterator += sizeSize;
+ data.Allocate(size);
+ Arithmetic_Codec acd;
+ acd.set_buffer(sizeSize, buffer);
+ acd.start_decoder();
+ Adaptive_Data_Model mModelValues(M+2);
+ Static_Bit_Model bModel0;
+ Adaptive_Bit_Model bModel1;
+ unsigned long value;
+
+#ifdef DEBUG_VERBOSE
+ printf("-----------\nsize %i\n", size);
+ fprintf(g_fileDebugTF, "size %i\n", size);
+#endif //DEBUG_VERBOSE
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ value = acd.decode(mModelValues);
+ if ( value == M)
+ {
+ value += acd.ExpGolombDecode(0, bModel0, bModel1);
+ }
+ data.PushBack(value + minValue);
+#ifdef DEBUG_VERBOSE
+ printf("%i\t%i\n", i, data[i]);
+ fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
+#endif //DEBUG_VERBOSE
+ }
+#ifdef DEBUG_VERBOSE
+ fflush(g_fileDebugTF);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode LoadBinAC(Vector<long> & data,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ unsigned long sizeSize = bstream.ReadUInt32Bin(iterator) - 8;
+ unsigned long size = bstream.ReadUInt32Bin(iterator);
+ if (size == 0)
+ {
+ return O3DGC_OK;
+ }
+ unsigned char * buffer = 0;
+ bstream.GetBuffer(iterator, buffer);
+ iterator += sizeSize;
+ data.Allocate(size);
+ Arithmetic_Codec acd;
+ acd.set_buffer(sizeSize, buffer);
+ acd.start_decoder();
+ Adaptive_Bit_Model bModel;
+#ifdef DEBUG_VERBOSE
+ printf("-----------\nsize %i\n", size);
+ fprintf(g_fileDebugTF, "size %i\n", size);
+#endif //DEBUG_VERBOSE
+ for(unsigned long i = 0; i < size; ++i)
+ {
+ data.PushBack(acd.decode(bModel));
+#ifdef DEBUG_VERBOSE
+ printf("%i\t%i\n", i, data[i]);
+ fprintf(g_fileDebugTF, "%i\t%i\n", i, data[i]);
+#endif //DEBUG_VERBOSE
+ }
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode CompressedTriangleFans::Load(const BinaryStream & bstream,
+ unsigned long & iterator,
+ bool decodeTrianglesOrder,
+ O3DGCStreamType streamType)
+ {
+#ifdef DEBUG_VERBOSE
+ g_fileDebugTF = fopen("Load_new.txt", "w");
+#endif //DEBUG_VERBOSE
+ if (streamType == O3DGC_STREAM_TYPE_ASCII)
+ {
+ LoadUIntData(m_numTFANs , bstream, iterator);
+ LoadUIntData(m_degrees , bstream, iterator);
+ LoadUIntData(m_configs , bstream, iterator);
+ LoadBinData (m_operations, bstream, iterator);
+ LoadIntData (m_indices , bstream, iterator);
+ if (decodeTrianglesOrder)
+ {
+ LoadUIntData(m_trianglesOrder , bstream, iterator);
+ }
+ }
+ else
+ {
+ LoadIntACEGC(m_numTFANs , 4 , bstream, iterator);
+ LoadIntACEGC(m_degrees , 16, bstream, iterator);
+ LoadUIntAC (m_configs , 10, bstream, iterator);
+ LoadBinAC (m_operations, bstream, iterator);
+ LoadIntACEGC(m_indices , 8 , bstream, iterator);
+ if (decodeTrianglesOrder)
+ {
+ LoadIntACEGC(m_trianglesOrder , 16, bstream, iterator);
+ }
+ }
+
+#ifdef DEBUG_VERBOSE
+ fclose(g_fileDebugTF);
+#endif //DEBUG_VERBOSE
+ return O3DGC_OK;
+ }
+}
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.h
new file mode 100644
index 000000000..861836428
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleFans.h
@@ -0,0 +1,291 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_TRIANGLE_FANS_H
+#define O3DGC_TRIANGLE_FANS_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcVector.h"
+#include "o3dgcBinaryStream.h"
+
+
+namespace o3dgc
+{
+ const long O3DGC_TFANS_MIN_SIZE_ALLOCATED_VERTICES_BUFFER = 128;
+ const long O3DGC_TFANS_MIN_SIZE_TFAN_SIZE_BUFFER = 8;
+
+ class CompressedTriangleFans
+ {
+ public:
+ //! Constructor.
+ CompressedTriangleFans(void)
+ {
+ m_streamType = O3DGC_STREAM_TYPE_UNKOWN;
+ m_bufferAC = 0;
+ m_sizeBufferAC = 0;
+ };
+ //! Destructor.
+ ~CompressedTriangleFans(void)
+ {
+ delete [] m_bufferAC;
+ };
+ O3DGCStreamType GetStreamType() const { return m_streamType; }
+ void SetStreamType(O3DGCStreamType streamType) { m_streamType = streamType; }
+
+ O3DGCErrorCode Allocate(long numVertices, long numTriangles)
+ {
+ assert(numVertices > 0);
+ m_numTFANs.Allocate(numVertices);
+ m_degrees.Allocate(2*numVertices);
+ m_configs.Allocate(2*numVertices);
+ m_operations.Allocate(2*numVertices);
+ m_indices.Allocate(2*numVertices);
+ m_trianglesOrder.Allocate(numTriangles);
+ Clear();
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode PushNumTFans(long numTFans)
+ {
+ m_numTFANs.PushBack(numTFans);
+ return O3DGC_OK;
+ }
+ long ReadNumTFans(unsigned long & iterator) const
+ {
+ assert(iterator < m_numTFANs.GetSize());
+ return m_numTFANs[iterator++];
+ }
+ O3DGCErrorCode PushDegree(long degree)
+ {
+ m_degrees.PushBack(degree);
+ return O3DGC_OK;
+ }
+ long ReadDegree(unsigned long & iterator) const
+ {
+ assert(iterator < m_degrees.GetSize());
+ return m_degrees[iterator++];
+ }
+ O3DGCErrorCode PushConfig(long config)
+ {
+ m_configs.PushBack(config);
+ return O3DGC_OK;
+ }
+ long ReadConfig(unsigned long & iterator) const
+ {
+ assert(iterator < m_configs.GetSize());
+ return m_configs[iterator++];
+ }
+ O3DGCErrorCode PushOperation(long op)
+ {
+ m_operations.PushBack(op);
+ return O3DGC_OK;
+ }
+ long ReadOperation(unsigned long & iterator) const
+ {
+ assert(iterator < m_operations.GetSize());
+ return m_operations[iterator++];
+ }
+ O3DGCErrorCode PushIndex(long index)
+ {
+ m_indices.PushBack(index);
+ return O3DGC_OK;
+ }
+ long ReadIndex(unsigned long & iterator) const
+ {
+ assert(iterator < m_indices.GetSize());
+ return m_indices[iterator++];
+ }
+ O3DGCErrorCode PushTriangleIndex(long index)
+ {
+ m_trianglesOrder.PushBack(IntToUInt(index));
+ return O3DGC_OK;
+ }
+ long ReadTriangleIndex(unsigned long & iterator) const
+ {
+ assert(iterator < m_trianglesOrder.GetSize());
+ return UIntToInt(m_trianglesOrder[iterator++]);
+ }
+ O3DGCErrorCode Clear()
+ {
+ m_numTFANs.Clear();
+ m_degrees.Clear();
+ m_configs.Clear();
+ m_operations.Clear();
+ m_indices.Clear();
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode Save(BinaryStream & bstream,
+ bool encodeTrianglesOrder,
+ O3DGCStreamType streamType);
+ O3DGCErrorCode Load(const BinaryStream & bstream,
+ unsigned long & iterator,
+ bool decodeTrianglesOrder,
+ O3DGCStreamType streamType);
+
+ private:
+ O3DGCErrorCode SaveBinAC(const Vector<long> & data,
+ BinaryStream & bstream);
+ O3DGCErrorCode SaveUIntAC(const Vector<long> & data,
+ const unsigned long M,
+ BinaryStream & bstream);
+ O3DGCErrorCode SaveIntACEGC(const Vector<long> & data,
+ const unsigned long M,
+ BinaryStream & bstream);
+
+ Vector<long> m_numTFANs;
+ Vector<long> m_degrees;
+ Vector<long> m_configs;
+ Vector<long> m_operations;
+ Vector<long> m_indices;
+ Vector<long> m_trianglesOrder;
+ unsigned char * m_bufferAC;
+ unsigned long m_sizeBufferAC;
+ O3DGCStreamType m_streamType;
+ };
+
+ //!
+ class TriangleFans
+ {
+ public:
+ //! Constructor.
+ TriangleFans(long sizeTFAN = O3DGC_TFANS_MIN_SIZE_TFAN_SIZE_BUFFER,
+ long verticesSize = O3DGC_TFANS_MIN_SIZE_ALLOCATED_VERTICES_BUFFER)
+ {
+ assert(sizeTFAN > 0);
+ assert(verticesSize > 0);
+ m_numTFANs = 0;
+ m_numVertices = 0;
+ m_verticesAllocatedSize = verticesSize;
+ m_sizeTFANAllocatedSize = sizeTFAN;
+ m_sizeTFAN = new long [m_sizeTFANAllocatedSize];
+ m_vertices = new long [m_verticesAllocatedSize];
+ };
+ //! Destructor.
+ ~TriangleFans(void)
+ {
+ delete [] m_vertices;
+ delete [] m_sizeTFAN;
+ };
+
+ O3DGCErrorCode Allocate(long sizeTFAN, long verticesSize)
+ {
+ assert(sizeTFAN > 0);
+ assert(verticesSize > 0);
+ m_numTFANs = 0;
+ m_numVertices = 0;
+ if (m_verticesAllocatedSize < verticesSize)
+ {
+ delete [] m_vertices;
+ m_verticesAllocatedSize = verticesSize;
+ m_vertices = new long [m_verticesAllocatedSize];
+ }
+ if (m_sizeTFANAllocatedSize < sizeTFAN)
+ {
+ delete [] m_sizeTFAN;
+ m_sizeTFANAllocatedSize = sizeTFAN;
+ m_sizeTFAN = new long [m_sizeTFANAllocatedSize];
+ }
+ return O3DGC_OK;
+ };
+ O3DGCErrorCode Clear()
+ {
+ m_numTFANs = 0;
+ m_numVertices = 0;
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode AddVertex(long vertex)
+ {
+ assert(m_numTFANs >= 0);
+ assert(m_numTFANs < m_sizeTFANAllocatedSize);
+ assert(m_numVertices >= 0);
+ ++m_numVertices;
+ if (m_numVertices == m_verticesAllocatedSize)
+ {
+ m_verticesAllocatedSize *= 2;
+ long * tmp = m_vertices;
+ m_vertices = new long [m_verticesAllocatedSize];
+ memcpy(m_vertices, tmp, sizeof(long) * m_numVertices);
+ delete [] tmp;
+ }
+ m_vertices[m_numVertices-1] = vertex;
+ ++m_sizeTFAN[m_numTFANs-1];
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode AddTFAN()
+ {
+ assert(m_numTFANs >= 0);
+ ++m_numTFANs;
+ if (m_numTFANs == m_sizeTFANAllocatedSize)
+ {
+ m_sizeTFANAllocatedSize *= 2;
+ long * tmp = m_sizeTFAN;
+ m_sizeTFAN = new long [m_sizeTFANAllocatedSize];
+ memcpy(m_sizeTFAN, tmp, sizeof(long) * m_numTFANs);
+ delete [] tmp;
+ }
+ m_sizeTFAN[m_numTFANs-1] = (m_numTFANs > 1) ? m_sizeTFAN[m_numTFANs-2] : 0;
+ return O3DGC_OK;
+ }
+ long Begin(long tfan) const
+ {
+ assert(tfan < m_numTFANs);
+ assert(tfan >= 0);
+ return (tfan>0)?m_sizeTFAN[tfan-1]:0;
+ }
+ long End(long tfan) const
+ {
+ assert(tfan < m_numTFANs);
+ assert(tfan >= 0);
+ return m_sizeTFAN[tfan];
+ }
+ long GetVertex(long vertex) const
+ {
+ assert(vertex < m_numVertices);
+ assert(vertex >= 0);
+ return m_vertices[vertex];
+ }
+ long GetTFANSize(long tfan) const
+ {
+ return End(tfan) - Begin(tfan);
+ }
+ long GetNumTFANs() const
+ {
+ return m_numTFANs;
+ }
+ long GetNumVertices() const
+ {
+ return m_numVertices;
+ }
+
+ private:
+ long m_verticesAllocatedSize;
+ long m_sizeTFANAllocatedSize;
+ long m_numTFANs;
+ long m_numVertices;
+ long * m_vertices;
+ long * m_sizeTFAN;
+
+ };
+}
+#endif // O3DGC_TRIANGLE_FANS_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.h
new file mode 100644
index 000000000..65df526d1
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.h
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_TRIANGLE_LIST_DECODER_H
+#define O3DGC_TRIANGLE_LIST_DECODER_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcTriangleFans.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcAdjacencyInfo.h"
+
+namespace o3dgc
+{
+
+ //!
+ template <class T>
+ class TriangleListDecoder
+ {
+ public:
+ //! Constructor.
+ TriangleListDecoder(void)
+ {
+ m_vertexCount = 0;
+ m_triangleCount = 0;
+ m_numTriangles = 0;
+ m_numVertices = 0;
+ m_triangles = 0;
+ m_numConqueredTriangles = 0;
+ m_numVisitedVertices = 0;
+ m_visitedVertices = 0;
+ m_visitedVerticesValence = 0;
+ m_maxNumVertices = 0;
+ m_maxNumTriangles = 0;
+ m_itNumTFans = 0;
+ m_itDegree = 0;
+ m_itConfig = 0;
+ m_itOperation = 0;
+ m_itIndex = 0;
+ m_tempTriangles = 0;
+ m_tempTrianglesSize = 0;
+ m_decodeTrianglesOrder = false;
+ m_decodeVerticesOrder = false;
+ };
+ //! Destructor.
+ ~TriangleListDecoder(void)
+ {
+ delete [] m_tempTriangles;
+ };
+
+ O3DGCStreamType GetStreamType() const { return m_streamType; }
+ bool GetReorderTriangles() const { return m_decodeTrianglesOrder; }
+ bool GetReorderVertices() const { return m_decodeVerticesOrder; }
+ void SetStreamType(O3DGCStreamType streamType) { m_streamType = streamType; }
+ const AdjacencyInfo & GetVertexToTriangle() const { return m_vertexToTriangle;}
+ O3DGCErrorCode Decode(T * const triangles,
+ const long numTriangles,
+ const long numVertices,
+ const BinaryStream & bstream,
+ unsigned long & iterator)
+ {
+ unsigned char compressionMask = bstream.ReadUChar(iterator, m_streamType);
+ m_decodeTrianglesOrder = ( (compressionMask&2) != 0);
+ m_decodeVerticesOrder = ( (compressionMask&1) != 0);
+ if (m_decodeVerticesOrder) // vertices reordering not supported
+ {
+ return O3DGC_ERROR_NON_SUPPORTED_FEATURE;
+ }
+ unsigned long maxSizeV2T = bstream.ReadUInt32(iterator, m_streamType);
+ Init(triangles, numTriangles, numVertices, maxSizeV2T);
+ m_ctfans.Load(bstream, iterator, m_decodeTrianglesOrder, m_streamType);
+ Decompress();
+ return O3DGC_OK;
+ }
+ O3DGCErrorCode Reorder();
+
+ private:
+ O3DGCErrorCode Init(T * const triangles,
+ const long numTriangles,
+ const long numVertices,
+ const long maxSizeV2T);
+ O3DGCErrorCode Decompress();
+ O3DGCErrorCode CompueLocalConnectivityInfo(const long focusVertex);
+ O3DGCErrorCode DecompressTFAN(const long focusVertex);
+
+ unsigned long m_itNumTFans;
+ unsigned long m_itDegree;
+ unsigned long m_itConfig;
+ unsigned long m_itOperation;
+ unsigned long m_itIndex;
+ long m_maxNumVertices;
+ long m_maxNumTriangles;
+ long m_numTriangles;
+ long m_numVertices;
+ long m_tempTrianglesSize;
+ T * m_triangles;
+ T * m_tempTriangles;
+ long m_vertexCount;
+ long m_triangleCount;
+ long m_numConqueredTriangles;
+ long m_numVisitedVertices;
+ long * m_visitedVertices;
+ long * m_visitedVerticesValence;
+ AdjacencyInfo m_vertexToTriangle;
+ CompressedTriangleFans m_ctfans;
+ TriangleFans m_tfans;
+ O3DGCStreamType m_streamType;
+ bool m_decodeTrianglesOrder;
+ bool m_decodeVerticesOrder;
+ };
+}
+#include "o3dgcTriangleListDecoder.inl" // template implementation
+#endif // O3DGC_TRIANGLE_LIST_DECODER_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.inl b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.inl
new file mode 100644
index 000000000..dd3af4aa7
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListDecoder.inl
@@ -0,0 +1,364 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_TRIANGLE_LIST_DECODER_INL
+#define O3DGC_TRIANGLE_LIST_DECODER_INL
+
+namespace o3dgc
+{
+ template<class T>
+ O3DGCErrorCode TriangleListDecoder<T>::Init(T * const triangles,
+ const long numTriangles,
+ const long numVertices,
+ const long maxSizeV2T)
+ {
+ assert(numVertices > 0);
+ assert(numTriangles > 0);
+ m_numTriangles = numTriangles;
+ m_numVertices = numVertices;
+ m_triangles = triangles;
+ m_vertexCount = 0;
+ m_triangleCount = 0;
+ m_itNumTFans = 0;
+ m_itDegree = 0;
+ m_itConfig = 0;
+ m_itOperation = 0;
+ m_itIndex = 0;
+ if (m_numVertices > m_maxNumVertices)
+ {
+ m_maxNumVertices = m_numVertices;
+ delete [] m_visitedVerticesValence;
+ delete [] m_visitedVertices;
+ m_visitedVerticesValence = new long [m_numVertices];
+ m_visitedVertices = new long [m_numVertices];
+ }
+
+ if (m_decodeTrianglesOrder && m_tempTrianglesSize < m_numTriangles)
+ {
+ delete [] m_tempTriangles;
+ m_tempTrianglesSize = m_numTriangles;
+ m_tempTriangles = new T [3*m_tempTrianglesSize];
+ }
+
+ m_ctfans.SetStreamType(m_streamType);
+ m_ctfans.Allocate(m_numVertices, m_numTriangles);
+ m_tfans.Allocate(2 * m_numVertices, 8 * m_numVertices);
+
+ // compute vertex-to-triangle adjacency information
+ m_vertexToTriangle.AllocateNumNeighborsArray(numVertices);
+ long * numNeighbors = m_vertexToTriangle.GetNumNeighborsBuffer();
+ for(long i = 0; i < numVertices; ++i)
+ {
+ numNeighbors[i] = maxSizeV2T;
+ }
+ m_vertexToTriangle.AllocateNeighborsArray();
+ m_vertexToTriangle.ClearNeighborsArray();
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode TriangleListDecoder<T>::Decompress()
+ {
+ for(long focusVertex = 0; focusVertex < m_numVertices; ++focusVertex)
+ {
+ if (focusVertex == m_vertexCount)
+ {
+ m_vertexCount++; // insert focusVertex
+ }
+ CompueLocalConnectivityInfo(focusVertex);
+ DecompressTFAN(focusVertex);
+ }
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode TriangleListDecoder<T>::Reorder()
+ {
+ if (m_decodeTrianglesOrder)
+ {
+ unsigned long itTriangleIndex = 0;
+ long prevTriangleIndex = 0;
+ long t;
+ memcpy(m_tempTriangles, m_triangles, m_numTriangles * 3 * sizeof(T));
+ for(long i = 0; i < m_numTriangles; ++i)
+ {
+ t = m_ctfans.ReadTriangleIndex(itTriangleIndex) + prevTriangleIndex;
+ assert( t >= 0 && t < m_numTriangles);
+ memcpy(m_triangles + 3 * t, m_tempTriangles + 3 * i, sizeof(T) * 3);
+ prevTriangleIndex = t + 1;
+ }
+ }
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode TriangleListDecoder<T>::CompueLocalConnectivityInfo(const long focusVertex)
+ {
+ long t = 0;
+ long p, v;
+ m_numConqueredTriangles = 0;
+ m_numVisitedVertices = 0;
+ for(long i = m_vertexToTriangle.Begin(focusVertex); (t >= 0) && (i < m_vertexToTriangle.End(focusVertex)); ++i)
+ {
+ t = m_vertexToTriangle.GetNeighbor(i);
+ if ( t >= 0)
+ {
+ ++m_numConqueredTriangles;
+ p = 3*t;
+ // extract visited vertices
+ for(long k = 0; k < 3; ++k)
+ {
+ v = m_triangles[p+k];
+ if (v > focusVertex) // vertices are insertices by increasing traversal order
+ {
+ bool foundOrInserted = false;
+ for (long j = 0; j < m_numVisitedVertices; ++j)
+ {
+ if (v == m_visitedVertices[j])
+ {
+ m_visitedVerticesValence[j]++;
+ foundOrInserted = true;
+ break;
+ }
+ else if (v < m_visitedVertices[j])
+ {
+ ++m_numVisitedVertices;
+ for (long h = m_numVisitedVertices-1; h > j; --h)
+ {
+ m_visitedVertices[h] = m_visitedVertices[h-1];
+ m_visitedVerticesValence[h] = m_visitedVerticesValence[h-1];
+ }
+ m_visitedVertices[j] = v;
+ m_visitedVerticesValence[j] = 1;
+ foundOrInserted = true;
+ break;
+ }
+ }
+ if (!foundOrInserted)
+ {
+ m_visitedVertices[m_numVisitedVertices] = v;
+ m_visitedVerticesValence[m_numVisitedVertices] = 1;
+ m_numVisitedVertices++;
+ }
+ }
+ }
+ }
+ }
+ // re-order visited vertices by taking into account their valence (i.e., # of conquered triangles incident to each vertex)
+ // in order to avoid config. 9
+ if (m_numVisitedVertices > 2)
+ {
+ long y;
+ for(long x = 1; x < m_numVisitedVertices; ++x)
+ {
+
+ if (m_visitedVerticesValence[x] == 1)
+ {
+ y = x;
+ while( (y > 0) && (m_visitedVerticesValence[y] < m_visitedVerticesValence[y-1]) )
+ {
+ swap(m_visitedVerticesValence[y], m_visitedVerticesValence[y-1]);
+ swap(m_visitedVertices[y], m_visitedVertices[y-1]);
+ --y;
+ }
+ }
+ }
+ }
+ return O3DGC_OK;
+ }
+ template<class T>
+ O3DGCErrorCode TriangleListDecoder<T>::DecompressTFAN(const long focusVertex)
+ {
+ long ntfans;
+ long degree, config;
+ long op;
+ long index;
+ long k0, k1;
+ long b, c, t;
+
+ ntfans = m_ctfans.ReadNumTFans(m_itNumTFans);
+ if (ntfans > 0)
+ {
+ for(long f = 0; f != ntfans; f++)
+ {
+ m_tfans.AddTFAN();
+ degree = m_ctfans.ReadDegree(m_itDegree) +2 - m_numConqueredTriangles;
+ config = m_ctfans.ReadConfig(m_itConfig);
+ k0 = m_tfans.GetNumVertices();
+ m_tfans.AddVertex(focusVertex);
+ switch(config)
+ {
+ case 0:// ops: 1000001 vertices: -1 -2
+ m_tfans.AddVertex(m_visitedVertices[0]);
+ for(long u = 1; u < degree-1; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ m_tfans.AddVertex(m_visitedVertices[1]);
+ break;
+ case 1: // ops: 1xxxxxx1 vertices: -1 x x x x x -2
+ m_tfans.AddVertex(m_visitedVertices[0]);
+ for(long u = 1; u < degree-1; u++)
+ {
+ op = m_ctfans.ReadOperation(m_itOperation);
+ if (op == 1)
+ {
+ index = m_ctfans.ReadIndex(m_itIndex);
+ if ( index < 0)
+ {
+ m_tfans.AddVertex(m_visitedVertices[-index-1]);
+ }
+ else
+ {
+ m_tfans.AddVertex(index + focusVertex);
+ }
+ }
+ else
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ }
+ m_tfans.AddVertex(m_visitedVertices[1]);
+ break;
+ case 2: // ops: 00000001 vertices: -1
+ for(long u = 0; u < degree-1; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ m_tfans.AddVertex(m_visitedVertices[0]);
+ break;
+ case 3: // ops: 00000001 vertices: -2
+ for(long u=0; u < degree-1; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ m_tfans.AddVertex(m_visitedVertices[1]);
+ break;
+ case 4: // ops: 10000000 vertices: -1
+ m_tfans.AddVertex(m_visitedVertices[0]);
+ for(long u = 1; u < degree; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ break;
+ case 5: // ops: 10000000 vertices: -2
+ m_tfans.AddVertex(m_visitedVertices[1]);
+ for(long u = 1; u < degree; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ break;
+ case 6:// ops: 00000000 vertices:
+ for(long u = 0; u < degree; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ break;
+ case 7: // ops: 1000001 vertices: -2 -1
+ m_tfans.AddVertex(m_visitedVertices[1]);
+ for(long u = 1; u < degree-1; u++)
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ m_tfans.AddVertex(m_visitedVertices[0]);
+ break;
+ case 8: // ops: 1xxxxxx1 vertices: -2 x x x x x -1
+ m_tfans.AddVertex(m_visitedVertices[1]);
+ for(long u = 1; u < degree-1; u++)
+ {
+ op = m_ctfans.ReadOperation(m_itOperation);
+ if (op == 1)
+ {
+ index = m_ctfans.ReadIndex(m_itIndex);
+ if ( index < 0)
+ {
+ m_tfans.AddVertex(m_visitedVertices[-index-1]);
+ }
+ else
+ {
+ m_tfans.AddVertex(index + focusVertex);
+ }
+ }
+ else
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ }
+ m_tfans.AddVertex(m_visitedVertices[0]);
+ break;
+ case 9: // general case
+ for(long u = 0; u < degree; u++)
+ {
+ op = m_ctfans.ReadOperation(m_itOperation);
+ if (op == 1)
+ {
+ index = m_ctfans.ReadIndex(m_itIndex);
+ if ( index < 0)
+ {
+ m_tfans.AddVertex(m_visitedVertices[-index-1]);
+ }
+ else
+ {
+ m_tfans.AddVertex(index + focusVertex);
+ }
+ }
+ else
+ {
+ m_visitedVertices[m_numVisitedVertices++] = m_vertexCount;
+ m_tfans.AddVertex(m_vertexCount++);
+ }
+ }
+ break;
+
+ }
+ //logger.write_2_log("\t degree=%i \t cas = %i\n", degree, cas);
+ k1 = m_tfans.GetNumVertices();
+ b = m_tfans.GetVertex(k0+1);
+ for (long k = k0+2; k < k1; k++)
+ {
+ c = m_tfans.GetVertex(k);
+ t = m_triangleCount*3;
+
+ m_triangles[t++] = (T) focusVertex;
+ m_triangles[t++] = (T) b;
+ m_triangles[t ] = (T) c;
+
+ m_vertexToTriangle.AddNeighbor(focusVertex, m_triangleCount);
+ m_vertexToTriangle.AddNeighbor(b , m_triangleCount);
+ m_vertexToTriangle.AddNeighbor(c , m_triangleCount);
+ b=c;
+ m_triangleCount++;
+ }
+ }
+ }
+ return O3DGC_OK;
+ }
+}
+#endif //O3DGC_TRIANGLE_LIST_DECODER_INL
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.h
new file mode 100644
index 000000000..c09172273
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.h
@@ -0,0 +1,101 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_TRIANGLE_LIST_ENCODER_H
+#define O3DGC_TRIANGLE_LIST_ENCODER_H
+
+#include "o3dgcCommon.h"
+#include "o3dgcAdjacencyInfo.h"
+#include "o3dgcBinaryStream.h"
+#include "o3dgcFIFO.h"
+#include "o3dgcTriangleFans.h"
+
+namespace o3dgc
+{
+ //!
+ template <class T>
+ class TriangleListEncoder
+ {
+ public:
+ //! Constructor.
+ TriangleListEncoder(void);
+ //! Destructor.
+ ~TriangleListEncoder(void);
+ //!
+ O3DGCErrorCode Encode(const T * const triangles,
+ const unsigned long * const indexBufferIDs,
+ const long numTriangles,
+ const long numVertices,
+ BinaryStream & bstream);
+ O3DGCStreamType GetStreamType() const { return m_streamType; }
+ void SetStreamType(O3DGCStreamType streamType) { m_streamType = streamType; }
+ const long * GetInvVMap() const { return m_invVMap;}
+ const long * GetInvTMap() const { return m_invTMap;}
+ const long * GetVMap() const { return m_vmap;}
+ const long * GetTMap() const { return m_tmap;}
+ const AdjacencyInfo & GetVertexToTriangle() const { return m_vertexToTriangle;}
+
+ private:
+ O3DGCErrorCode Init(const T * const triangles,
+ long numTriangles,
+ long numVertices);
+ O3DGCErrorCode CompueLocalConnectivityInfo(const long focusVertex);
+ O3DGCErrorCode ProcessVertex( long focusVertex);
+ O3DGCErrorCode ComputeTFANDecomposition(const long focusVertex);
+ O3DGCErrorCode CompressTFAN(const long focusVertex);
+
+ long m_vertexCount;
+ long m_triangleCount;
+ long m_maxNumVertices;
+ long m_maxNumTriangles;
+ long m_numNonConqueredTriangles;
+ long m_numConqueredTriangles;
+ long m_numVisitedVertices;
+ long m_numTriangles;
+ long m_numVertices;
+ long m_maxSizeVertexToTriangle;
+ T const * m_triangles;
+ long * m_vtags;
+ long * m_ttags;
+ long * m_vmap;
+ long * m_invVMap;
+ long * m_tmap;
+ long * m_invTMap;
+ long * m_count;
+ long * m_nonConqueredTriangles;
+ long * m_nonConqueredEdges;
+ long * m_visitedVertices;
+ long * m_visitedVerticesValence;
+ FIFO<long> m_vfifo;
+ AdjacencyInfo m_vertexToTriangle;
+ AdjacencyInfo m_triangleToTriangle;
+ AdjacencyInfo m_triangleToTriangleInv;
+ TriangleFans m_tfans;
+ CompressedTriangleFans m_ctfans;
+ O3DGCStreamType m_streamType;
+ };
+}
+#include "o3dgcTriangleListEncoder.inl" // template implementation
+#endif // O3DGC_TRIANGLE_LIST_ENCODER_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.inl b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.inl
new file mode 100644
index 000000000..017dd86bf
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcTriangleListEncoder.inl
@@ -0,0 +1,719 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_TRIANGLE_LIST_ENCODER_INL
+#define O3DGC_TRIANGLE_LIST_ENCODER_INL
+
+namespace o3dgc
+{
+ // extract opposite edge
+ template <class T>
+ inline void CompueOppositeEdge(const long focusVertex,
+ const T * triangle,
+ long & a, long & b)
+ {
+ if ((long) triangle[0] == focusVertex)
+ {
+ a = triangle[1];
+ b = triangle[2];
+ }
+ else if ((long) triangle[1] == focusVertex)
+ {
+ a = triangle[2];
+ b = triangle[0];
+ }
+ else
+ {
+ a = triangle[0];
+ b = triangle[1];
+ }
+ }
+ inline bool IsCase0(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 1000001 vertices: -1 -2
+ if ((numIndices != 2) || (degree < 2)) {
+ return false;
+ }
+ if ((indices[0] != -1) ||(indices[1] != -2) ||
+ (ops[0] != 1) ||(ops[degree-1] != 1) ) return false;
+ for (long u = 1; u < degree-1; u++) {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase1(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 1xxxxxx1 indices: -1 x x x x x -2
+ if ((degree < 2) || (numIndices < 1))
+ {
+ return false;
+ }
+ if ((indices[0] != -1) ||(indices[numIndices-1] != -2) ||
+ (ops[0] != 1) ||(ops[degree-1] != 1) ) return false;
+ return true;
+ }
+ inline bool IsCase2(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 00000001 indices: -1
+ if ((degree < 2) || (numIndices!= 1))
+ {
+ return false;
+ }
+ if ((indices[0] != -1) || (ops[degree-1] != 1) ) return false;
+ for (long u = 0; u < degree-1; u++) {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase3(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 00000001 indices: -2
+ if ((degree < 2) || (numIndices!= 1))
+ {
+ return false;
+ }
+ if ((indices[0] != -2) || (ops[degree-1] != 1) ) return false;
+ for (long u = 0; u < degree-1; u++) {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase4(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 10000000 indices: -1
+ if ((degree < 2) || (numIndices!= 1))
+ {
+ return false;
+ }
+ if ((indices[0] != -1) || (ops[0] != 1) ) return false;
+ for (long u = 1; u < degree; u++)
+ {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase5(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 10000000 indices: -2
+ if ((degree < 2) || (numIndices!= 1))
+ {
+ return false;
+ }
+ if ((indices[0] != -2) || (ops[0] != 1) ) return false;
+ for (long u = 1; u < degree; u++) {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase6(long degree, long numIndices, const long * const ops, const long * const /*indices*/)
+ {
+ // ops: 0000000 indices:
+ if (numIndices!= 0)
+ {
+ return false;
+ }
+ for (long u = 0; u < degree; u++)
+ {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase7(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 1000001 indices: -2 -1
+ if ((numIndices!= 2) || (degree < 2))
+ {
+ return false;
+ }
+ if ((indices[0] != -2) ||(indices[1] != -1) ||
+ (ops[0] != 1) ||(ops[degree-1] != 1) ) return false;
+ for (long u = 1; u < degree-1; u++)
+ {
+ if (ops[u] != 0) return false;
+ }
+ return true;
+ }
+ inline bool IsCase8(long degree, long numIndices, const long * const ops, const long * const indices)
+ {
+ // ops: 1xxxxxx1 indices: -1 x x x x x -2
+ if ((degree < 2) || (numIndices < 1))
+ {
+ return false;
+ }
+ if ((indices[0] != -2) ||(indices[numIndices-1] != -1) ||
+ (ops[0] != 1) ||(ops[degree-1] != 1) ) return false;
+ return true;
+ }
+ template <class T>
+ TriangleListEncoder<T>::TriangleListEncoder(void)
+ {
+ m_vtags = 0;
+ m_ttags = 0;
+ m_tmap = 0;
+ m_vmap = 0;
+ m_count = 0;
+ m_invVMap = 0;
+ m_invTMap = 0;
+ m_nonConqueredTriangles = 0;
+ m_nonConqueredEdges = 0;
+ m_visitedVertices = 0;
+ m_visitedVerticesValence = 0;
+ m_vertexCount = 0;
+ m_triangleCount = 0;
+ m_maxNumVertices = 0;
+ m_maxNumTriangles = 0;
+ m_numTriangles = 0;
+ m_numVertices = 0;
+ m_triangles = 0;
+ m_maxSizeVertexToTriangle = 0;
+ m_streamType = O3DGC_STREAM_TYPE_UNKOWN;
+ }
+ template <class T>
+ TriangleListEncoder<T>::~TriangleListEncoder()
+ {
+ delete [] m_vtags;
+ delete [] m_vmap;
+ delete [] m_invVMap;
+ delete [] m_invTMap;
+ delete [] m_visitedVerticesValence;
+ delete [] m_visitedVertices;
+ delete [] m_ttags;
+ delete [] m_tmap;
+ delete [] m_count;
+ delete [] m_nonConqueredTriangles;
+ delete [] m_nonConqueredEdges;
+ }
+ template <class T>
+ O3DGCErrorCode TriangleListEncoder<T>::Init(const T * const triangles,
+ long numTriangles,
+ long numVertices)
+ {
+ assert(numVertices > 0);
+ assert(numTriangles > 0);
+
+ m_numTriangles = numTriangles;
+ m_numVertices = numVertices;
+ m_triangles = triangles;
+ m_vertexCount = 0;
+ m_triangleCount = 0;
+
+ if (m_numVertices > m_maxNumVertices)
+ {
+ delete [] m_vtags;
+ delete [] m_vmap;
+ delete [] m_invVMap;
+ delete [] m_visitedVerticesValence;
+ delete [] m_visitedVertices;
+ m_maxNumVertices = m_numVertices;
+ m_vtags = new long [m_numVertices];
+ m_vmap = new long [m_numVertices];
+ m_invVMap = new long [m_numVertices];
+ m_visitedVerticesValence = new long [m_numVertices];
+ m_visitedVertices = new long [m_numVertices];
+ }
+
+ if (m_numTriangles > m_maxNumTriangles)
+ {
+ delete [] m_ttags;
+ delete [] m_tmap;
+ delete [] m_invTMap;
+ delete [] m_nonConqueredTriangles;
+ delete [] m_nonConqueredEdges;
+ delete [] m_count;
+ m_maxNumTriangles = m_numTriangles;
+ m_ttags = new long [m_numTriangles];
+ m_tmap = new long [m_numTriangles];
+ m_invTMap = new long [m_numTriangles];
+ m_count = new long [m_numTriangles+1];
+ m_nonConqueredTriangles = new long [m_numTriangles];
+ m_nonConqueredEdges = new long [2*m_numTriangles];
+ }
+
+ memset(m_vtags , 0x00, sizeof(long) * m_numVertices );
+ memset(m_vmap , 0xFF, sizeof(long) * m_numVertices );
+ memset(m_invVMap, 0xFF, sizeof(long) * m_numVertices );
+ memset(m_ttags , 0x00, sizeof(long) * m_numTriangles);
+ memset(m_tmap , 0xFF, sizeof(long) * m_numTriangles);
+ memset(m_invTMap, 0xFF, sizeof(long) * m_numTriangles);
+ memset(m_count , 0x00, sizeof(long) * (m_numTriangles+1));
+
+ m_vfifo.Allocate(m_numVertices);
+ m_ctfans.SetStreamType(m_streamType);
+ m_ctfans.Allocate(m_numVertices, m_numTriangles);
+
+ // compute vertex-to-triangle adjacency information
+ m_vertexToTriangle.AllocateNumNeighborsArray(numVertices);
+ m_vertexToTriangle.ClearNumNeighborsArray();
+ long * numNeighbors = m_vertexToTriangle.GetNumNeighborsBuffer();
+ for(long i = 0, t = 0; i < m_numTriangles; ++i, t+=3)
+ {
+ ++numNeighbors[ triangles[t ] ];
+ ++numNeighbors[ triangles[t+1] ];
+ ++numNeighbors[ triangles[t+2] ];
+ }
+ m_maxSizeVertexToTriangle = 0;
+ for(long i = 0; i < numVertices; ++i)
+ {
+ if (m_maxSizeVertexToTriangle < numNeighbors[i])
+ {
+ m_maxSizeVertexToTriangle = numNeighbors[i];
+ }
+ }
+ m_vertexToTriangle.AllocateNeighborsArray();
+ m_vertexToTriangle.ClearNeighborsArray();
+ for(long i = 0, t = 0; i < m_numTriangles; ++i, t+=3)
+ {
+ m_vertexToTriangle.AddNeighbor(triangles[t ], i);
+ m_vertexToTriangle.AddNeighbor(triangles[t+1], i);
+ m_vertexToTriangle.AddNeighbor(triangles[t+2], i);
+ }
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode TriangleListEncoder<T>::Encode(const T * const triangles,
+ const unsigned long * const indexBufferIDs,
+ const long numTriangles,
+ const long numVertices,
+ BinaryStream & bstream)
+ {
+ assert(numVertices > 0);
+ assert(numTriangles > 0);
+
+ Init(triangles, numTriangles, numVertices);
+ unsigned char mask = 0;
+ bool encodeTrianglesOrder = (indexBufferIDs != 0);
+
+
+ if (encodeTrianglesOrder)
+ {
+ long numBufferIDs = 0;
+ for (long t = 0; t < numTriangles; t++)
+ {
+ if (numBufferIDs <= (long) indexBufferIDs[t])
+ {
+ ++numBufferIDs;
+ assert(numBufferIDs <= numTriangles);
+ }
+ ++m_count[indexBufferIDs[t]+1];
+ }
+ for (long i = 2; i <= numBufferIDs; i++)
+ {
+ m_count[i] += m_count[i-1];
+ }
+ mask += 2; // preserved triangles order
+ }
+ bstream.WriteUChar(mask, m_streamType);
+ bstream.WriteUInt32(m_maxSizeVertexToTriangle, m_streamType);
+
+ long v0;
+ for (long v = 0; v < m_numVertices; v++)
+ {
+ if (!m_vtags[v])
+ {
+ m_vfifo.PushBack(v);
+ m_vtags[v] = 1;
+ m_vmap[v] = m_vertexCount++;
+ m_invVMap[m_vmap[v]] = v;
+ while (m_vfifo.GetSize() > 0 )
+ {
+ v0 = m_vfifo.PopFirst();
+ ProcessVertex(v0);
+ }
+ }
+ }
+ if (encodeTrianglesOrder)
+ {
+ long t, prev = 0;
+ long pred;
+ for (long i = 0; i < numTriangles; ++i)
+ {
+ t = m_invTMap[i];
+ m_tmap[t] = m_count[ indexBufferIDs[t] ]++;
+ pred = m_tmap[t] - prev;
+ m_ctfans.PushTriangleIndex(pred);
+ prev = m_tmap[t] + 1;
+ }
+ for (long t = 0; t < numTriangles; ++t)
+ {
+ m_invTMap[m_tmap[t]] = t;
+ }
+ }
+ m_ctfans.Save(bstream, encodeTrianglesOrder, m_streamType);
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode TriangleListEncoder<T>::CompueLocalConnectivityInfo(const long focusVertex)
+ {
+ long t, v, p;
+ m_numNonConqueredTriangles = 0;
+ m_numConqueredTriangles = 0;
+ m_numVisitedVertices = 0;
+ for(long i = m_vertexToTriangle.Begin(focusVertex); i < m_vertexToTriangle.End(focusVertex); ++i)
+ {
+ t = m_vertexToTriangle.GetNeighbor(i);
+
+ if ( m_ttags[t] == 0) // non-processed triangle
+ {
+ m_nonConqueredTriangles[m_numNonConqueredTriangles] = t;
+ CompueOppositeEdge( focusVertex,
+ m_triangles + (3*t),
+ m_nonConqueredEdges[m_numNonConqueredTriangles*2],
+ m_nonConqueredEdges[m_numNonConqueredTriangles*2+1]);
+ ++m_numNonConqueredTriangles;
+ }
+ else // triangle already processed
+ {
+ m_numConqueredTriangles++;
+ p = 3*t;
+ // extract visited vertices
+ for(long k = 0; k < 3; ++k)
+ {
+ v = m_triangles[p+k];
+ if (m_vmap[v] > m_vmap[focusVertex]) // vertices are insertices by increasing traversal order
+ {
+ bool foundOrInserted = false;
+ for (long j = 0; j < m_numVisitedVertices; ++j)
+ {
+
+ if (m_vmap[v] == m_visitedVertices[j])
+ {
+ m_visitedVerticesValence[j]++;
+ foundOrInserted = true;
+ break;
+ }
+ else if (m_vmap[v] < m_visitedVertices[j])
+ {
+ ++m_numVisitedVertices;
+ for (long h = m_numVisitedVertices-1; h > j; --h)
+ {
+ m_visitedVertices[h] = m_visitedVertices[h-1];
+ m_visitedVerticesValence[h] = m_visitedVerticesValence[h-1];
+ }
+ m_visitedVertices[j] = m_vmap[v];
+ m_visitedVerticesValence[j] = 1;
+ foundOrInserted = true;
+ break;
+ }
+ }
+ if (!foundOrInserted)
+ {
+ m_visitedVertices[m_numVisitedVertices] = m_vmap[v];
+ m_visitedVerticesValence[m_numVisitedVertices] = 1;
+ m_numVisitedVertices++;
+ }
+ }
+ }
+ }
+ }
+ // re-order visited vertices by taking into account their valence (i.e., # of conquered triangles incident to each vertex)
+ // in order to avoid config. 9
+ if (m_numVisitedVertices > 2)
+ {
+ long y;
+ for(long x = 1; x < m_numVisitedVertices; ++x)
+ {
+
+ if (m_visitedVerticesValence[x] == 1)
+ {
+ y = x;
+ while( (y > 0) && (m_visitedVerticesValence[y] < m_visitedVerticesValence[y-1]) )
+ {
+ swap(m_visitedVerticesValence[y], m_visitedVerticesValence[y-1]);
+ swap(m_visitedVertices[y], m_visitedVertices[y-1]);
+ --y;
+ }
+ }
+ }
+ }
+ if (m_numNonConqueredTriangles > 0)
+ {
+ // compute triangle-to-triangle adjacency information
+ m_triangleToTriangle.AllocateNumNeighborsArray(m_numNonConqueredTriangles);
+ m_triangleToTriangle.ClearNumNeighborsArray();
+ m_triangleToTriangleInv.AllocateNumNeighborsArray(m_numNonConqueredTriangles);
+ m_triangleToTriangleInv.ClearNumNeighborsArray();
+ long * const numNeighbors = m_triangleToTriangle.GetNumNeighborsBuffer();
+ long * const invNumNeighbors = m_triangleToTriangleInv.GetNumNeighborsBuffer();
+ for(long i = 0; i < m_numNonConqueredTriangles; ++i)
+ {
+ for(long j = i+1; j < m_numNonConqueredTriangles; ++j)
+ {
+ if (m_nonConqueredEdges[2*i+1] == m_nonConqueredEdges[2*j]) // edge i is connected to edge j
+ {
+ ++numNeighbors[i];
+ ++invNumNeighbors[j];
+ }
+ if (m_nonConqueredEdges[2*i] == m_nonConqueredEdges[2*j+1]) // edge i is connected to edge j
+ {
+ ++numNeighbors[j];
+ ++invNumNeighbors[i];
+ }
+ }
+ }
+ m_triangleToTriangle.AllocateNeighborsArray();
+ m_triangleToTriangle.ClearNeighborsArray();
+ m_triangleToTriangleInv.AllocateNeighborsArray();
+ m_triangleToTriangleInv.ClearNeighborsArray();
+ for(long i = 0; i < m_numNonConqueredTriangles; ++i)
+ {
+ for(long j = 1; j < m_numNonConqueredTriangles; ++j)
+ {
+ if (m_nonConqueredEdges[2*i+1] == m_nonConqueredEdges[2*j]) // edge i is connected to edge j
+ {
+ m_triangleToTriangle.AddNeighbor(i, j);
+ m_triangleToTriangleInv.AddNeighbor(j, i);
+ }
+ if (m_nonConqueredEdges[2*i] == m_nonConqueredEdges[2*j+1]) // edge i is connected to edge j
+ {
+ m_triangleToTriangle.AddNeighbor(j, i);
+ m_triangleToTriangleInv.AddNeighbor(i, j);
+ }
+ }
+ }
+ }
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode TriangleListEncoder<T>::ComputeTFANDecomposition(const long focusVertex)
+ {
+ long processedTriangles = 0;
+ long minNumInputEdges;
+ long numInputEdges;
+ long indexSeedTriangle;
+ long seedTriangle;
+ long currentIndex;
+ long currentTriangle;
+ long i0, i1, index;
+
+ m_tfans.Clear();
+ while (processedTriangles != m_numNonConqueredTriangles)
+ {
+ // find non processed triangle with lowest number of inputs
+ minNumInputEdges = m_numTriangles;
+ indexSeedTriangle = -1;
+ for(long i = 0; i < m_numNonConqueredTriangles; ++i)
+ {
+ numInputEdges = m_triangleToTriangleInv.GetNumNeighbors(i);
+ if ( !m_ttags[m_nonConqueredTriangles[i]] &&
+ numInputEdges < minNumInputEdges )
+ {
+ minNumInputEdges = numInputEdges;
+ indexSeedTriangle = i;
+ if (minNumInputEdges == 0) // found boundary triangle
+ {
+ break;
+ }
+ }
+ }
+ assert(indexSeedTriangle >= 0);
+ seedTriangle = m_nonConqueredTriangles[indexSeedTriangle];
+ m_tfans.AddTFAN();
+ m_tfans.AddVertex( focusVertex );
+ m_tfans.AddVertex( m_nonConqueredEdges[indexSeedTriangle*2] );
+ m_tfans.AddVertex( m_nonConqueredEdges[indexSeedTriangle*2 + 1] );
+ m_ttags[ seedTriangle ] = 1; // mark triangle as processed
+ m_tmap[seedTriangle] = m_triangleCount++;
+ m_invTMap[m_tmap[seedTriangle]] = seedTriangle;
+ ++processedTriangles;
+ currentIndex = indexSeedTriangle;
+ currentTriangle = seedTriangle;
+ do
+ {
+ // find next triangle
+ i0 = m_triangleToTriangle.Begin(currentIndex);
+ i1 = m_triangleToTriangle.End(currentIndex);
+ currentIndex = -1;
+ for(long i = i0; i < i1; ++i)
+ {
+ index = m_triangleToTriangle.GetNeighbor(i);
+ currentTriangle = m_nonConqueredTriangles[index];
+ if ( !m_ttags[currentTriangle] )
+ {
+ currentIndex = index;
+ m_tfans.AddVertex( m_nonConqueredEdges[currentIndex*2+1] );
+ m_ttags[currentTriangle] = 1; // mark triangle as processed
+ m_tmap [currentTriangle] = m_triangleCount++;
+ m_invTMap[m_tmap [currentTriangle]] = currentTriangle;
+ ++processedTriangles;
+ break;
+ }
+ }
+ } while (currentIndex != -1);
+ }
+
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode TriangleListEncoder<T>::CompressTFAN(const long focusVertex)
+ {
+ m_ctfans.PushNumTFans(m_tfans.GetNumTFANs());
+
+ const long ntfans = m_tfans.GetNumTFANs();
+ long degree;
+ long k0, k1;
+ long v0;
+ long ops[O3DGC_MAX_TFAN_SIZE];
+ long indices[O3DGC_MAX_TFAN_SIZE];
+
+ long numOps;
+ long numIndices;
+ long pos;
+ long found;
+
+ if (m_tfans.GetNumTFANs() > 0)
+ {
+ for(long f = 0; f != ntfans; f++)
+ {
+ degree = m_tfans.GetTFANSize(f) - 1;
+ m_ctfans.PushDegree(degree-2+ m_numConqueredTriangles);
+ numOps = 0;
+ numIndices = 0;
+ k0 = 1 + m_tfans.Begin(f);
+ k1 = m_tfans.End(f);
+ for(long k = k0; k < k1; k++)
+ {
+ v0 = m_tfans.GetVertex(k);
+ if (m_vtags[v0] == 0)
+ {
+ ops[numOps++] = 0;
+ m_vtags[v0] = 1;
+ m_vmap[v0] = m_vertexCount++;
+ m_invVMap[m_vmap[v0]] = v0;
+ m_vfifo.PushBack(v0);
+ m_visitedVertices[m_numVisitedVertices++] = m_vmap[v0];
+ }
+ else
+ {
+ ops[numOps++] = 1;
+ pos = 0;
+ found = 0;
+ for(long u=0; u < m_numVisitedVertices; ++u)
+ {
+ pos++;
+ if (m_visitedVertices[u] == m_vmap[v0])
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 1)
+ {
+ indices[numIndices++] = -pos;
+ }
+ else
+ {
+ indices[numIndices++] = m_vmap[v0] - m_vmap[focusVertex];
+ }
+ }
+ }
+ //-----------------------------------------------
+ if (IsCase0(degree, numIndices, ops, indices))
+ {
+ // ops: 1000001 vertices: -1 -2
+ m_ctfans.PushConfig(0);
+ }
+ else if (IsCase1(degree, numIndices, ops, indices))
+ {
+ // ops: 1xxxxxx1 vertices: -1 x x x x x -2
+ long u = 1;
+ for(u = 1; u < degree-1; u++)
+ {
+ m_ctfans.PushOperation(ops[u]);
+ }
+ for(u =1; u < numIndices-1; u++)
+ {
+ m_ctfans.PushIndex(indices[u]);
+ }
+ m_ctfans.PushConfig(1);
+ }
+ else if (IsCase2(degree, numIndices, ops, indices))
+ {
+ // ops: 00000001 vertices: -1
+ m_ctfans.PushConfig(2);
+ }
+ else if (IsCase3(degree, numIndices, ops, indices))
+ {
+ // ops: 00000001 vertices: -2
+ m_ctfans.PushConfig(3);
+ }
+ else if (IsCase4(degree, numIndices, ops, indices))
+ {
+ // ops: 10000000 vertices: -1
+ m_ctfans.PushConfig(4);
+ }
+ else if (IsCase5(degree, numIndices, ops, indices))
+ {
+ // ops: 10000000 vertices: -2
+ m_ctfans.PushConfig(5);
+ }
+ else if (IsCase6(degree, numIndices, ops, indices))
+ {
+ // ops: 00000000 vertices:
+ m_ctfans.PushConfig(6);
+ }
+ else if (IsCase7(degree, numIndices, ops, indices))
+ {
+ // ops: 1000001 vertices: -1 -2
+ m_ctfans.PushConfig(7);
+ }
+ else if (IsCase8(degree, numIndices, ops, indices))
+ {
+ // ops: 1xxxxxx1 vertices: -2 x x x x x -1
+ long u = 1;
+ for(u =1; u < degree-1; u++)
+ {
+ m_ctfans.PushOperation(ops[u]);
+ }
+ for(u =1; u < numIndices-1; u++)
+ {
+ m_ctfans.PushIndex(indices[u]);
+ }
+ m_ctfans.PushConfig(8);
+ }
+ else
+ {
+ long u = 0;
+ for(u =0; u < degree; u++)
+ {
+ m_ctfans.PushOperation(ops[u]);
+ }
+ for(u =0; u < numIndices; u++)
+ {
+ m_ctfans.PushIndex(indices[u]);
+ }
+ m_ctfans.PushConfig(9);
+ }
+ }
+ }
+ return O3DGC_OK;
+ }
+ template <class T>
+ O3DGCErrorCode TriangleListEncoder<T>::ProcessVertex(const long focusVertex)
+ {
+ CompueLocalConnectivityInfo(focusVertex);
+ ComputeTFANDecomposition(focusVertex);
+ CompressTFAN(focusVertex);
+ return O3DGC_OK;
+ }
+}
+#endif //O3DGC_TRIANGLE_LIST_ENCODER_INL
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.h b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.h
new file mode 100644
index 000000000..08d3ed564
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.h
@@ -0,0 +1,184 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_VECTOR_H
+#define O3DGC_VECTOR_H
+
+#include "o3dgcCommon.h"
+
+namespace o3dgc
+{
+ const unsigned long O3DGC_DEFAULT_VECTOR_SIZE = 32;
+
+ //!
+ template < typename T > class Vector
+ {
+ public:
+ //! Constructor.
+ Vector()
+ {
+ m_allocated = 0;
+ m_size = 0;
+ m_buffer = 0;
+ };
+ //! Destructor.
+ ~Vector(void)
+ {
+ delete [] m_buffer;
+ };
+ T & operator[](unsigned long i)
+ {
+ return m_buffer[i];
+ }
+ const T & operator[](unsigned long i) const
+ {
+ return m_buffer[i];
+ }
+ void Allocate(unsigned long size)
+ {
+ if (size > m_allocated)
+ {
+ m_allocated = size;
+ T * tmp = new T [m_allocated];
+ if (m_size > 0)
+ {
+ memcpy(tmp, m_buffer, m_size * sizeof(T) );
+ delete [] m_buffer;
+ }
+ m_buffer = tmp;
+ }
+ };
+ void PushBack(const T & value)
+ {
+ if (m_size == m_allocated)
+ {
+ m_allocated *= 2;
+ if (m_allocated < O3DGC_DEFAULT_VECTOR_SIZE)
+ {
+ m_allocated = O3DGC_DEFAULT_VECTOR_SIZE;
+ }
+ T * tmp = new T [m_allocated];
+ if (m_size > 0)
+ {
+ memcpy(tmp, m_buffer, m_size * sizeof(T) );
+ delete [] m_buffer;
+ }
+ m_buffer = tmp;
+ }
+ assert(m_size < m_allocated);
+ m_buffer[m_size++] = value;
+ }
+ const T * GetBuffer() const { return m_buffer;};
+ T * GetBuffer() { return m_buffer;};
+ unsigned long GetSize() const { return m_size;};
+ void SetSize(unsigned long size)
+ {
+ assert(size <= m_allocated);
+ m_size = size;
+ };
+ unsigned long GetAllocatedSize() const { return m_allocated;};
+ void Clear(){ m_size = 0;};
+
+ private:
+ T * m_buffer;
+ unsigned long m_allocated;
+ unsigned long m_size;
+ };
+
+
+
+
+ //! Vector dim 3.
+ template < typename T > class Vec3
+ {
+ public:
+ T & operator[](unsigned long i) { return m_data[i];}
+ const T & operator[](unsigned long i) const { return m_data[i];}
+ T & X();
+ T & Y();
+ T & Z();
+ const T & X() const;
+ const T & Y() const;
+ const T & Z() const;
+ double GetNorm() const;
+ void operator= (const Vec3 & rhs);
+ void operator+=(const Vec3 & rhs);
+ void operator-=(const Vec3 & rhs);
+ void operator-=(T a);
+ void operator+=(T a);
+ void operator/=(T a);
+ void operator*=(T a);
+ Vec3 operator^ (const Vec3 & rhs) const;
+ T operator* (const Vec3 & rhs) const;
+ Vec3 operator+ (const Vec3 & rhs) const;
+ Vec3 operator- (const Vec3 & rhs) const;
+ Vec3 operator- () const;
+ Vec3 operator* (T rhs) const;
+ Vec3 operator/ (T rhs) const;
+ Vec3();
+ Vec3(T a);
+ Vec3(T x, T y, T z);
+ Vec3(const Vec3 & rhs);
+ ~Vec3(void);
+
+ private:
+ T m_data[3];
+ };
+ //! Vector dim 2.
+ template < typename T > class Vec2
+ {
+ public:
+ T & operator[](unsigned long i) { return m_data[i];}
+ const T & operator[](unsigned long i) const { return m_data[i];}
+ T & X();
+ T & Y();
+ const T & X() const;
+ const T & Y() const;
+ double GetNorm() const;
+ void operator= (const Vec2 & rhs);
+ void operator+=(const Vec2 & rhs);
+ void operator-=(const Vec2 & rhs);
+ void operator-=(T a);
+ void operator+=(T a);
+ void operator/=(T a);
+ void operator*=(T a);
+ T operator^ (const Vec2 & rhs) const;
+ T operator* (const Vec2 & rhs) const;
+ Vec2 operator+ (const Vec2 & rhs) const;
+ Vec2 operator- (const Vec2 & rhs) const;
+ Vec2 operator- () const;
+ Vec2 operator* (T rhs) const;
+ Vec2 operator/ (T rhs) const;
+ Vec2();
+ Vec2(T a);
+ Vec2(T x, T y);
+ Vec2(const Vec2 & rhs);
+ ~Vec2(void);
+
+ private:
+ T m_data[2];
+ };
+}
+#include "o3dgcVector.inl" // template implementation
+#endif // O3DGC_VECTOR_H
+
diff --git a/src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.inl b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.inl
new file mode 100644
index 000000000..5549b00ce
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/Open3DGC/o3dgcVector.inl
@@ -0,0 +1,317 @@
+/*
+Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc.
+
+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
+#ifndef O3DGC_VECTOR_INL
+#define O3DGC_VECTOR_INL
+namespace o3dgc
+{
+ template <typename T>
+ inline Vec3<T> operator*(T lhs, const Vec3<T> & rhs)
+ {
+ return Vec3<T>(lhs * rhs.X(), lhs * rhs.Y(), lhs * rhs.Z());
+ }
+ template <typename T>
+ inline T & Vec3<T>::X()
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline T & Vec3<T>::Y()
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline T & Vec3<T>::Z()
+ {
+ return m_data[2];
+ }
+ template <typename T>
+ inline const T & Vec3<T>::X() const
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline const T & Vec3<T>::Y() const
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline const T & Vec3<T>::Z() const
+ {
+ return m_data[2];
+ }
+ template <typename T>
+ inline double Vec3<T>::GetNorm() const
+ {
+ double a = (double) (m_data[0]);
+ double b = (double) (m_data[1]);
+ double c = (double) (m_data[2]);
+ return sqrt(a*a+b*b+c*c);
+ }
+ template <typename T>
+ inline void Vec3<T>::operator= (const Vec3 & rhs)
+ {
+ this->m_data[0] = rhs.m_data[0];
+ this->m_data[1] = rhs.m_data[1];
+ this->m_data[2] = rhs.m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::operator+=(const Vec3 & rhs)
+ {
+ this->m_data[0] += rhs.m_data[0];
+ this->m_data[1] += rhs.m_data[1];
+ this->m_data[2] += rhs.m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::operator-=(const Vec3 & rhs)
+ {
+ this->m_data[0] -= rhs.m_data[0];
+ this->m_data[1] -= rhs.m_data[1];
+ this->m_data[2] -= rhs.m_data[2];
+ }
+ template <typename T>
+ inline void Vec3<T>::operator-=(T a)
+ {
+ this->m_data[0] -= a;
+ this->m_data[1] -= a;
+ this->m_data[2] -= a;
+ }
+ template <typename T>
+ inline void Vec3<T>::operator+=(T a)
+ {
+ this->m_data[0] += a;
+ this->m_data[1] += a;
+ this->m_data[2] += a;
+ }
+ template <typename T>
+ inline void Vec3<T>::operator/=(T a)
+ {
+ this->m_data[0] /= a;
+ this->m_data[1] /= a;
+ this->m_data[2] /= a;
+ }
+ template <typename T>
+ inline void Vec3<T>::operator*=(T a)
+ {
+ this->m_data[0] *= a;
+ this->m_data[1] *= a;
+ this->m_data[2] *= a;
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator^ (const Vec3<T> & rhs) const
+ {
+ return Vec3<T>(m_data[1] * rhs.m_data[2] - m_data[2] * rhs.m_data[1],
+ m_data[2] * rhs.m_data[0] - m_data[0] * rhs.m_data[2],
+ m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]);
+ }
+ template <typename T>
+ inline T Vec3<T>::operator*(const Vec3<T> & rhs) const
+ {
+ return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1] + m_data[2] * rhs.m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator+(const Vec3<T> & rhs) const
+ {
+ return Vec3<T>(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1],m_data[2] + rhs.m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator-(const Vec3<T> & rhs) const
+ {
+ return Vec3<T>(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1],m_data[2] - rhs.m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator-() const
+ {
+ return Vec3<T>(-m_data[0],-m_data[1],-m_data[2]);
+ }
+
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator*(T rhs) const
+ {
+ return Vec3<T>(rhs * this->m_data[0], rhs * this->m_data[1], rhs * this->m_data[2]);
+ }
+ template <typename T>
+ inline Vec3<T> Vec3<T>::operator/ (T rhs) const
+ {
+ return Vec3<T>(m_data[0] / rhs, m_data[1] / rhs, m_data[2] / rhs);
+ }
+ template <typename T>
+ inline Vec3<T>::Vec3(T a)
+ {
+ m_data[0] = m_data[1] = m_data[2] = a;
+ }
+ template <typename T>
+ inline Vec3<T>::Vec3(T x, T y, T z)
+ {
+ m_data[0] = x;
+ m_data[1] = y;
+ m_data[2] = z;
+ }
+ template <typename T>
+ inline Vec3<T>::Vec3(const Vec3 & rhs)
+ {
+ m_data[0] = rhs.m_data[0];
+ m_data[1] = rhs.m_data[1];
+ m_data[2] = rhs.m_data[2];
+ }
+ template <typename T>
+ inline Vec3<T>::~Vec3(void){};
+
+ template <typename T>
+ inline Vec3<T>::Vec3() {}
+
+ template <typename T>
+ inline Vec2<T> operator*(T lhs, const Vec2<T> & rhs)
+ {
+ return Vec2<T>(lhs * rhs.X(), lhs * rhs.Y());
+ }
+ template <typename T>
+ inline T & Vec2<T>::X()
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline T & Vec2<T>::Y()
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline const T & Vec2<T>::X() const
+ {
+ return m_data[0];
+ }
+ template <typename T>
+ inline const T & Vec2<T>::Y() const
+ {
+ return m_data[1];
+ }
+ template <typename T>
+ inline double Vec2<T>::GetNorm() const
+ {
+ double a = (double) (m_data[0]);
+ double b = (double) (m_data[1]);
+ return sqrt(a*a+b*b);
+ }
+ template <typename T>
+ inline void Vec2<T>::operator= (const Vec2 & rhs)
+ {
+ this->m_data[0] = rhs.m_data[0];
+ this->m_data[1] = rhs.m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::operator+=(const Vec2 & rhs)
+ {
+ this->m_data[0] += rhs.m_data[0];
+ this->m_data[1] += rhs.m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::operator-=(const Vec2 & rhs)
+ {
+ this->m_data[0] -= rhs.m_data[0];
+ this->m_data[1] -= rhs.m_data[1];
+ }
+ template <typename T>
+ inline void Vec2<T>::operator-=(T a)
+ {
+ this->m_data[0] -= a;
+ this->m_data[1] -= a;
+ }
+ template <typename T>
+ inline void Vec2<T>::operator+=(T a)
+ {
+ this->m_data[0] += a;
+ this->m_data[1] += a;
+ }
+ template <typename T>
+ inline void Vec2<T>::operator/=(T a)
+ {
+ this->m_data[0] /= a;
+ this->m_data[1] /= a;
+ }
+ template <typename T>
+ inline void Vec2<T>::operator*=(T a)
+ {
+ this->m_data[0] *= a;
+ this->m_data[1] *= a;
+ }
+ template <typename T>
+ inline T Vec2<T>::operator^ (const Vec2<T> & rhs) const
+ {
+ return m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0];
+ }
+ template <typename T>
+ inline T Vec2<T>::operator*(const Vec2<T> & rhs) const
+ {
+ return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator+(const Vec2<T> & rhs) const
+ {
+ return Vec2<T>(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator-(const Vec2<T> & rhs) const
+ {
+ return Vec2<T>(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator-() const
+ {
+ return Vec2<T>(-m_data[0],-m_data[1]) ;
+ }
+
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator*(T rhs) const
+ {
+ return Vec2<T>(rhs * this->m_data[0], rhs * this->m_data[1]);
+ }
+ template <typename T>
+ inline Vec2<T> Vec2<T>::operator/ (T rhs) const
+ {
+ return Vec2<T>(m_data[0] / rhs, m_data[1] / rhs);
+ }
+ template <typename T>
+ inline Vec2<T>::Vec2(T a)
+ {
+ m_data[0] = m_data[1] = a;
+ }
+ template <typename T>
+ inline Vec2<T>::Vec2(T x, T y)
+ {
+ m_data[0] = x;
+ m_data[1] = y;
+ }
+ template <typename T>
+ inline Vec2<T>::Vec2(const Vec2 & rhs)
+ {
+ m_data[0] = rhs.m_data[0];
+ m_data[1] = rhs.m_data[1];
+ }
+ template <typename T>
+ inline Vec2<T>::~Vec2(void){};
+
+ template <typename T>
+ inline Vec2<T>::Vec2() {}
+}
+#endif //O3DGC_VECTOR_INL
+
diff --git a/src/3rdparty/assimp/contrib/clipper/clipper.cpp b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
index c8c62bc2a..074f22b21 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 *
* *
*******************************************************************************/
@@ -43,6 +43,7 @@
#include <vector>
#include <algorithm>
#include <stdexcept>
+#include <cassert>
#include <cstring>
#include <cstdlib>
#include <ostream>
@@ -2365,6 +2366,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
//ok, so far it looks like we're still in range of the horizontal edge
if ( e->xcurr == horzEdge->xtop && !eMaxPair )
{
+ assert(horzEdge->nextInLML);
if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange))
{
//if output polygons share an edge, they'll need joining later ...
@@ -2429,6 +2431,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
if ( horzEdge->outIdx >= 0 )
IntersectEdges( horzEdge, eMaxPair,
IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth);
+ assert(eMaxPair);
if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error");
DeleteFromAEL(eMaxPair);
DeleteFromAEL(horzEdge);
diff --git a/src/3rdparty/assimp/contrib/clipper/clipper.hpp b/src/3rdparty/assimp/contrib/clipper/clipper.hpp
index 3d6510dff..7cdac6c3f 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/openddlparser/CMakeLists.txt b/src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt
index a39d0219f..9e903ca3f 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt
+++ b/src/3rdparty/assimp/contrib/openddlparser/CMakeLists.txt
@@ -3,18 +3,40 @@ 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 ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} )
SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
+option( DDL_USE_CPP11 "Set to ON to use C++11 features ( always on on windows )." ON )
+option( DDL_DEBUG_OUTPUT "Set to ON to use output debug texts" OFF )
+option( DDL_STATIC_LIBRARY "Set to ON to build static libary of OpenDDL Parser." ON )
+option( COVERALLS "Generate coveralls data" OFF )
+
+if ( DDL_USE_CPP11 )
+ if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+ set( OPENDDL_CXXFLAGS -std=c++0x )
+ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set( OPENDDL_CXXFLAGS --std=c++11 )
+ endif()
+else( DDL_USE_CPP11 )
+ add_definitions( -DOPENDDL_NO_USE_CPP11 )
+endif( DDL_USE_CPP11)
+
if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
find_package(Threads)
else()
add_definitions( -D_CRT_SECURE_NO_WARNINGS )
endif()
+if ( DDL_STATIC_LIBRARY )
+ add_definitions( -DOPENDDL_STATIC_LIBARY )
+endif()
+
add_definitions( -DOPENDDLPARSER_BUILD )
-add_definitions( -DOPENDDL_NO_USE_CPP11 )
add_definitions( -D_VARIADIC_MAX=10 )
+add_definitions( -DGTEST_HAS_PTHREAD=0 )
+if ( DDL_DEBUG_OUTPUT )
+ add_definitions( -DDDL_DEBUG_HEADER_NAME)
+endif()
INCLUDE_DIRECTORIES(
./
@@ -24,9 +46,10 @@ INCLUDE_DIRECTORIES(
)
link_directories(
- ./
+ ${CMAKE_HOME_DIRECTORY}/lib
)
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
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 )
@@ -40,18 +63,38 @@ if( WIN32 AND NOT CYGWIN )
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")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS}")
elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS} -Wwrite-strings")
+endif()
+
+if (COVERALLS)
+ include(Coveralls)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
endif()
+# Include the doc component.
+FIND_PACKAGE( doxygen )
+IF ( DOXYGEN_FOUND )
+ CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY )
+ ADD_CUSTOM_TARGET( doc ALL ${DOXYGEN_EXECUTABLE} doc/doxygenfile
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Generating API documentation with Doxygen" VERBATIM )
+ENDIF ( DOXYGEN_FOUND )
+
SET ( openddl_parser_src
+ code/OpenDDLCommon.cpp
+ code/OpenDDLExport.cpp
code/OpenDDLParser.cpp
+ code/OpenDDLStream.cpp
code/DDLNode.cpp
code/Value.cpp
+ include/openddlparser/OpenDDLCommon.h
+ include/openddlparser/OpenDDLExport.h
include/openddlparser/OpenDDLParser.h
include/openddlparser/OpenDDLParserUtils.h
- include/openddlparser/OpenDDLCommon.h
+ include/openddlparser/OpenDDLStream.h
include/openddlparser/DDLNode.h
include/openddlparser/Value.h
README.md
@@ -59,6 +102,69 @@ SET ( openddl_parser_src
SOURCE_GROUP( code FILES ${openddl_parser_src} )
-ADD_LIBRARY( openddl_parser SHARED
- ${openddl_parser_src}
+if ( DDL_STATIC_LIBRARY )
+ ADD_LIBRARY( openddl_parser STATIC
+ ${openddl_parser_src}
+ )
+else()
+ ADD_LIBRARY( openddl_parser SHARED
+ ${openddl_parser_src}
+ )
+endif()
+
+SET ( GTEST_PATH contrib/gtest-1.7.0 )
+
+SET ( gtest_src
+ ${GTEST_PATH}/src/gtest-death-test.cc
+ ${GTEST_PATH}/src/gtest-filepath.cc
+ ${GTEST_PATH}/src/gtest-internal-inl.h
+ ${GTEST_PATH}/src/gtest-port.cc
+ ${GTEST_PATH}/src/gtest-printers.cc
+ ${GTEST_PATH}/src/gtest-test-part.cc
+ ${GTEST_PATH}/src/gtest-typed-test.cc
+ ${GTEST_PATH}/src/gtest.cc
+ ${GTEST_PATH}/src/gtest_main.cc
+)
+
+SET( openddl_parser_unittest_src
+ test/UnitTestCommon.h
+ test/DDLNodeTest.cpp
+ test/OpenDDLCommonTest.cpp
+ test/OpenDDLExportTest.cpp
+ test/OpenDDLParserTest.cpp
+ test/OpenDDLParserUtilsTest.cpp
+ test/OpenDDLStreamTest.cpp
+ test/OpenDDLIntegrationTest.cpp
+ test/ValueTest.cpp
+ test/OpenDDLDefectsTest.cpp
+)
+
+SOURCE_GROUP( code FILES ${openddl_parser_unittest_src} )
+SOURCE_GROUP( gtest FILES ${gtest_src} )
+
+ADD_EXECUTABLE( openddl_parser_unittest
+ ${gtest_src}
+ ${openddl_parser_unittest_src}
+)
+
+target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} )
+
+SET( openddl_parser_demo_src
+ demo/main.cpp
)
+
+if (COVERALLS)
+ set(COVERAGE_SRCS ${gtest_src} ${openddl_parser_unittest_src} )
+
+ # Create the coveralls target.
+ coveralls_setup(
+ "${COVERAGE_SRCS}" # The source files.
+ ON # If we should upload.
+ "${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
+endif()
+
+ADD_EXECUTABLE( openddl_parser_demo
+ ${openddl_parser_demo_src}
+)
+
+target_link_libraries( openddl_parser_demo openddl_parser )
diff --git a/src/3rdparty/assimp/contrib/openddlparser/CREDITS b/src/3rdparty/assimp/contrib/openddlparser/CREDITS
index a2b01eb13..d3936af83 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/CREDITS
+++ b/src/3rdparty/assimp/contrib/openddlparser/CREDITS
@@ -12,5 +12,8 @@ Improvements value interface, serveral bugfixes.
- Henry Read ( henrya2 ):
Static build option, Interface improvements
+- (wise86-android)
+fix several mem-leaks
+
- Paul Holland ( pkholland ):
Bugfixes.
diff --git a/src/3rdparty/assimp/contrib/openddlparser/README.md b/src/3rdparty/assimp/contrib/openddlparser/README.md
index 619747d23..a48ea1be0 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/README.md
+++ b/src/3rdparty/assimp/contrib/openddlparser/README.md
@@ -11,7 +11,7 @@ Current coverity check status:
<img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5606/badge.svg"/>
</a>
-
+Current test coverage:[![Coverage Status](https://coveralls.io/repos/github/kimkulling/openddl-parser/badge.svg?branch=master)](https://coveralls.io/github/kimkulling/openddl-parser?branch=cpp_coveralls)
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:
@@ -25,7 +25,7 @@ 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 ).
+This command will generate a build environment for your preferred build tool ( 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
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp
index 0cc95bdfc..a7c557fc5 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/DDLNode.cpp
@@ -68,8 +68,8 @@ DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx,
}
DDLNode::~DDLNode() {
- releaseDataType<Property>( m_properties );
- releaseDataType<Value>( m_value );
+ delete m_properties;
+ delete m_value;
releaseReferencedNames( m_references );
delete m_dtArrayList;
@@ -77,6 +77,9 @@ DDLNode::~DDLNode() {
if( s_allocatedNodes[ m_idx ] == this ) {
s_allocatedNodes[ m_idx ] = ddl_nullptr;
}
+ for ( size_t i = 0; i<m_children.size(); i++ ){
+ delete m_children[ i ];
+ }
}
void DDLNode::attachParent( DDLNode *parent ) {
@@ -91,9 +94,8 @@ void DDLNode::attachParent( DDLNode *parent ) {
}
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( ddl_nullptr != m_parent ) {
+ DDLNodeIt 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 );
}
@@ -126,6 +128,8 @@ const std::string &DDLNode::getName() const {
}
void DDLNode::setProperties( Property *prop ) {
+ if(m_properties!=ddl_nullptr)
+ delete m_properties;
m_properties = prop;
}
@@ -187,6 +191,10 @@ Reference *DDLNode::getReferences() const {
return m_references;
}
+void DDLNode::dump(IOStreamBase &/*stream*/) {
+ // Todo!
+}
+
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 );
@@ -197,7 +205,7 @@ DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLN
void DDLNode::releaseNodes() {
if( s_allocatedNodes.size() > 0 ) {
- for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+ for( DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
if( *it ) {
delete *it;
}
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
index 13a96f7a8..5c341a780 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp
@@ -22,6 +22,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <openddlparser/OpenDDLCommon.h>
#include <openddlparser/DDLNode.h>
+#include <openddlparser/Value.h>
BEGIN_ODDLPARSER_NS
@@ -84,7 +85,14 @@ Name::~Name() {
m_id = ddl_nullptr;
}
-Reference::Reference()
+Name::Name( const Name &name ){
+ m_type=name.m_type;
+ m_id=new Text(name.m_id->m_buffer,name.m_id->m_len);
+}
+
+
+
+ Reference::Reference()
: m_numRefs( 0 )
, m_referencedName( ddl_nullptr ) {
// empty
@@ -96,8 +104,16 @@ Reference::Reference( size_t numrefs, Name **names )
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;
+ m_referencedName[ i ] = names[i];
+ }
+ }
+}
+Reference::Reference(const Reference &ref) {
+ m_numRefs=ref.m_numRefs;
+ if(m_numRefs!=0){
+ m_referencedName = new Name*[m_numRefs];
+ for ( size_t i = 0; i < m_numRefs; i++ ) {
+ m_referencedName[i] = new Name(*ref.m_referencedName[i]);
}
}
}
@@ -107,6 +123,7 @@ Reference::~Reference() {
delete m_referencedName[ i ];
}
m_numRefs = 0;
+ delete [] m_referencedName;
m_referencedName = ddl_nullptr;
}
@@ -135,21 +152,30 @@ Property::Property( Text *id )
}
Property::~Property() {
- m_key = ddl_nullptr;
- m_value = ddl_nullptr;
- m_ref = ddl_nullptr;;
- m_next = ddl_nullptr;;
+ delete m_key;
+ if(m_value!=ddl_nullptr)
+ delete m_value;
+ if(m_ref!=ddl_nullptr)
+ delete(m_ref);
+ if(m_next!=ddl_nullptr)
+ delete m_next;
}
DataArrayList::DataArrayList()
: m_numItems( 0 )
, m_dataList( ddl_nullptr )
-, m_next( ddl_nullptr ) {
+, m_next( ddl_nullptr )
+, m_refs(ddl_nullptr)
+, m_numRefs(0){
// empty
}
DataArrayList::~DataArrayList() {
- // empty
+ delete m_dataList;
+ if(m_next!=ddl_nullptr)
+ delete m_next;
+ if(m_refs!=ddl_nullptr)
+ delete m_refs;
}
size_t DataArrayList::size() {
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
index 2e73ea470..e45fb041a 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLExport.cpp
@@ -29,60 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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;
@@ -189,10 +135,9 @@ bool OpenDDLExport::writeToStream( const std::string &statement ) {
}
bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
- bool success( true );
writeNodeHeader( node, statement );
if (node->hasProperties()) {
- success |= writeProperties( node, statement );
+ writeProperties( node, statement );
}
writeLineEnd( statement );
@@ -280,7 +225,7 @@ bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std:
statement += "[";
char buffer[ 256 ];
::memset( buffer, '\0', 256 * sizeof( char ) );
- sprintf( buffer, "%d", int(numItems) );
+ sprintf( buffer, "%d", static_cast<int>( numItems ) );
statement += buffer;
statement += "]";
}
@@ -414,11 +359,10 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement )
}
DataArrayList *nextDataArrayList = al ;
- Value *nextValue( nextDataArrayList->m_dataList );
while (ddl_nullptr != nextDataArrayList) {
if (ddl_nullptr != nextDataArrayList) {
statement += "{ ";
- nextValue = nextDataArrayList->m_dataList;
+ Value *nextValue( nextDataArrayList->m_dataList );
size_t idx( 0 );
while (ddl_nullptr != nextValue) {
if (idx > 0) {
@@ -437,3 +381,4 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement )
}
END_ODDLPARSER_NS
+
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
index 6f471be36..caa281364 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLParser.cpp
@@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <iostream>
#include <sstream>
#include <algorithm>
+#include <memory>
#include <math.h>
#ifdef _WIN32
@@ -36,7 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
BEGIN_ODDLPARSER_NS
-static const char *Version = "0.3.0";
+static const char *Version = "0.4.0";
namespace Grammar {
static const char *OpenBracketToken = "{";
@@ -49,7 +50,7 @@ namespace Grammar {
static const char *BoolFalse = "false";
static const char *CommaSeparator = ",";
- static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+ static const char *PrimitiveTypeToken[ Value::ddl_types_max ] = {
"bool",
"int8",
"int16",
@@ -74,8 +75,8 @@ const char *getTypeToken( Value::ValueType 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));
+ std::string full( in );
+ std::string part( full.substr( 0, 50 ) );
stream << part;
callback( ddl_error_msg, stream.str() );
}
@@ -85,6 +86,7 @@ static bool isIntegerType( Value::ValueType integerType ) {
integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
return false;
}
+
return true;
}
@@ -105,7 +107,7 @@ static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) {
const std::string type( id->m_buffer );
DDLNode *parent( parser->top() );
DDLNode *node = DDLNode::create( type, "", parent );
-
+
return node;
}
@@ -193,10 +195,11 @@ size_t OpenDDLParser::getBufferSize() const {
void OpenDDLParser::clear() {
m_buffer.resize( 0 );
if( ddl_nullptr != m_context ) {
- m_context->m_root = ddl_nullptr;
+ delete m_context;
+ m_context=ddl_nullptr;
}
- DDLNode::releaseNodes();
+// DDLNode::releaseNodes();
}
bool OpenDDLParser::parse() {
@@ -212,11 +215,11 @@ bool OpenDDLParser::parse() {
// do the main parsing
char *current( &m_buffer[ 0 ] );
- char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 );
+ 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) {
+ if ( current == ddl_nullptr ) {
return false;
}
pos = current - &m_buffer[ 0 ];
@@ -245,7 +248,7 @@ 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
@@ -271,21 +274,26 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
} else {
std::cerr << "nullptr returned by creating DDLNode." << std::endl;
}
+ delete id;
- Name *name(ddl_nullptr);
- in = OpenDDLParser::parseName(in, end, &name);
+ Name *name_(ddl_nullptr);
+ in = OpenDDLParser::parseName(in, end, &name_);
+ std::unique_ptr<Name> name(name_);
if( ddl_nullptr != name && ddl_nullptr != node ) {
const std::string nodeName( name->m_id->m_buffer );
node->setName( nodeName );
}
- Property *first(ddl_nullptr);
+
+ std::unique_ptr<Property> first;
in = lookForNextToken(in, end);
if (*in == Grammar::OpenPropertyToken[0]) {
in++;
- Property *prop(ddl_nullptr), *prev(ddl_nullptr);
+ std::unique_ptr<Property> prop, prev;
while (*in != Grammar::ClosePropertyToken[0] && in != end) {
- in = OpenDDLParser::parseProperty(in, end, &prop);
+ Property *prop_(ddl_nullptr);
+ in = OpenDDLParser::parseProperty(in, end, &prop_);
+ prop.reset(prop_);
in = lookForNextToken(in, end);
if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) {
@@ -295,20 +303,20 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
if (ddl_nullptr != prop && *in != Grammar::CommaSeparator[0]) {
if (ddl_nullptr == first) {
- first = prop;
+ first = std::move(prop);
}
if (ddl_nullptr != prev) {
- prev->m_next = prop;
+ prev->m_next = prop.release();
}
- prev = prop;
+ prev = std::move(prop);
}
}
- in++;
+ ++in;
}
// set the properties
- if (ddl_nullptr != first && ddl_nullptr != node) {
- node->setProperties(first);
+ if (first && ddl_nullptr != node) {
+ node->setProperties(first.release());
}
}
@@ -322,19 +330,18 @@ char *OpenDDLParser::parseStructure( char *in, char *end ) {
bool error( false );
in = lookForNextToken( in, end );
- if( *in == '{' ) {
+ if( *in == *Grammar::OpenBracketToken) {
// loop over all children ( data and nodes )
do {
in = parseStructureBody( in, end, error );
if(in == ddl_nullptr){
return ddl_nullptr;
}
- } while ( *in != '}' );
- in++;
+ } while ( *in != *Grammar::CloseBracketToken);
+ ++in;
} else {
- in++;
+ ++in;
logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
- error = true;
return ddl_nullptr;
}
in = lookForNextToken( in, end );
@@ -373,7 +380,7 @@ static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayLi
char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
if( !isNumeric( *in ) && !isCharacter( *in ) ) {
- in++;
+ ++in;
}
in = lookForNextToken( in, end );
@@ -431,7 +438,6 @@ DDLNode *OpenDDLParser::popNode() {
DDLNode *topNode( top() );
m_stack.pop_back();
-
return topNode;
}
@@ -467,7 +473,14 @@ void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
char *c( &buffer[readIdx] );
// check for a comment
- if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
+ if (isCommentOpenTag(c, end)) {
+ ++readIdx;
+ while (!isCommentCloseTag(&buffer[readIdx], end)) {
+ ++readIdx;
+ }
+ ++readIdx;
+ ++readIdx;
+ } else if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
newBuffer.push_back( buffer[ readIdx ] );
} else {
if( isComment<char>( c, end ) ) {
@@ -529,14 +542,17 @@ char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) {
// 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 != '$' ) {
+ 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;
+ *id = new Text( start, len );
return in;
}
@@ -552,7 +568,7 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
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;
+ type = static_cast<Value::ValueType>( i );
break;
}
}
@@ -567,14 +583,14 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
bool ok( true );
if( *in == Grammar::OpenArrayToken[ 0 ] ) {
ok = false;
- in++;
+ ++in;
char *start( in );
while ( in != end ) {
- in++;
+ ++in;
if( *in == Grammar::CloseArrayToken[ 0 ] ) {
len = ::atoi( start );
ok = true;
- in++;
+ ++in;
break;
}
}
@@ -623,10 +639,10 @@ char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean )
char *start( in );
size_t len( 0 );
while( !isSeparator( *in ) && in != end ) {
- in++;
- len++;
+ ++in;
+ ++len;
}
- len++;
+ ++len;
int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
if( 0 != res ) {
res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
@@ -657,7 +673,7 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer,
in = lookForNextToken( in, end );
char *start( in );
while( !isSeparator( *in ) && in != end ) {
- in++;
+ ++in;
}
if( isNumeric( *start ) ) {
@@ -671,29 +687,29 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer,
*integer = ValueAllocator::allocPrimData( integerType );
switch( integerType ) {
case Value::ddl_int8:
- ( *integer )->setInt8( (int8) value );
- break;
+ ( *integer )->setInt8( (int8) value );
+ break;
case Value::ddl_int16:
- ( *integer )->setInt16( ( int16 ) value );
- break;
+ ( *integer )->setInt16( ( int16 ) value );
+ break;
case Value::ddl_int32:
- ( *integer )->setInt32( ( int32 ) value );
- break;
+ ( *integer )->setInt32( ( int32 ) value );
+ break;
case Value::ddl_int64:
- ( *integer )->setInt64( ( int64 ) value );
- break;
+ ( *integer )->setInt64( ( int64 ) value );
+ break;
case Value::ddl_unsigned_int8:
- ( *integer )->setUnsignedInt8( (uint8) uvalue );
- break;
+ ( *integer )->setUnsignedInt8( (uint8) uvalue );
+ break;
case Value::ddl_unsigned_int16:
- ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
- break;
+ ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
+ break;
case Value::ddl_unsigned_int32:
- ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
- break;
+ ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
+ break;
case Value::ddl_unsigned_int64:
- ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
- break;
+ ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
+ break;
default:
break;
}
@@ -711,7 +727,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating
in = lookForNextToken( in, end );
char *start( in );
while( !isSeparator( *in ) && in != end ) {
- in++;
+ ++in;
}
// parse the float value
@@ -732,8 +748,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating
}
if( ok ) {
- if(floatType == Value::ddl_double)
- {
+ if ( floatType == Value::ddl_double ) {
const double value( atof( start ) );
*floating = ValueAllocator::allocPrimData( Value::ddl_double );
( *floating )->setDouble( value );
@@ -757,17 +772,17 @@ char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData
size_t len( 0 );
char *start( in );
if( *start == '\"' ) {
- start++;
- in++;
+ ++start;
+ ++in;
while( *in != '\"' && in != end ) {
- in++;
- len++;
+ ++in;
+ ++len;
}
*stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
::strncpy( ( char* ) ( *stringData )->m_data, start, len );
( *stringData )->m_data[len] = '\0';
- in++;
+ ++in;
}
return in;
@@ -791,12 +806,12 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
return in;
}
- in++;
+ ++in;
if( *in != 'x' && *in != 'X' ) {
return in;
}
- in++;
+ ++in;
bool ok( true );
char *start( in );
int pos( 0 );
@@ -805,8 +820,8 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
ok = false;
break;
}
- pos++;
- in++;
+ ++pos;
+ ++in;
}
if( !ok ) {
@@ -816,9 +831,9 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
int value( 0 );
while( pos > 0 ) {
int v = hex2Decimal( *start );
- pos--;
+ --pos;
value = ( value << 4 ) | v;
- start++;
+ ++start;
}
*data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
@@ -841,7 +856,7 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
if( ddl_nullptr != id ) {
in = lookForNextToken( in, end );
if( *in == '=' ) {
- in++;
+ ++in;
in = getNextToken( in, end );
Value *primData( ddl_nullptr );
if( isInteger( in, end ) ) {
@@ -862,6 +877,8 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
( *prop )->m_ref = ref;
}
}
+ } else {
+ delete id;
}
}
@@ -878,7 +895,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
in = lookForNextToken( in, end );
if( *in == '{' ) {
- in++;
+ ++in;
Value *current( ddl_nullptr ), *prev( ddl_nullptr );
while( '}' != *in ) {
current = ddl_nullptr;
@@ -934,7 +951,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
prev->setNext( current );
prev = current;
}
- numValues++;
+ ++numValues;
}
in = getNextSeparator( in, end );
@@ -942,7 +959,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
break;
}
}
- in++;
+ ++in;
}
return in;
@@ -972,7 +989,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty
in = lookForNextToken( in, end );
if( *in == Grammar::OpenBracketToken[ 0 ] ) {
- in++;
+ ++in;
Value *currentValue( ddl_nullptr );
Reference *refs( ddl_nullptr );
DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
@@ -995,7 +1012,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty
}
} while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
in = lookForNextToken( in, end );
- in++;
+ ++in;
}
return in;
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLStream.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLStream.cpp
new file mode 100644
index 000000000..7ea8331bd
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/OpenDDLStream.cpp
@@ -0,0 +1,96 @@
+/*-----------------------------------------------------------------------------------------------
+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/OpenDDLStream.h>
+
+BEGIN_ODDLPARSER_NS
+
+StreamFormatterBase::StreamFormatterBase() {
+ // empty
+}
+
+StreamFormatterBase::~StreamFormatterBase() {
+ // empty
+}
+
+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;
+}
+
+bool IOStreamBase::isOpen() const {
+ return ( ddl_nullptr != m_file );
+}
+
+size_t IOStreamBase::read( size_t sizeToRead, std::string &statement ) {
+ if (ddl_nullptr == m_file) {
+ return 0;
+ }
+
+ statement.resize(sizeToRead);
+ const size_t readBytes = ::fread( &statement[0], 1, sizeToRead, m_file );
+
+ return readBytes;
+}
+
+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);
+}
+
+END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp b/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp
index 3e251c508..b5a35e722 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp
+++ b/src/3rdparty/assimp/contrib/openddlparser/code/Value.cpp
@@ -110,7 +110,17 @@ Value::Value( ValueType type )
}
Value::~Value() {
- // empty
+ if(m_data!=ddl_nullptr) {
+ if (m_type == ddl_ref ) {
+ Reference *tmp = (Reference *) m_data;
+ if (tmp != ddl_nullptr)
+ delete tmp;
+ }else
+ delete[] m_data;
+
+ }
+ if(m_next!=ddl_nullptr)
+ delete m_next;
}
void Value::setBool( bool value ) {
@@ -273,13 +283,7 @@ void Value::setRef( Reference *ref ) {
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 );
- }
+ m_data = (unsigned char*) new Reference(*ref);
}
}
}
@@ -290,7 +294,7 @@ Reference *Value::getRef() const {
return (Reference*) m_data;
}
-void Value::dump() {
+void Value::dump( IOStreamBase &/*stream*/ ) {
switch( m_type ) {
case ddl_none:
std::cout << "None" << std::endl;
@@ -350,7 +354,7 @@ Value *Value::getNext() const {
return m_next;
}
-size_t Value::size(){
+size_t Value::size() const{
size_t result=1;
Value *n=m_next;
while( n!=ddl_nullptr) {
@@ -366,7 +370,6 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
}
Value *data = new Value( type );
- data->m_type = type;
switch( type ) {
case Value::ddl_bool:
data->m_size = sizeof( bool );
@@ -405,10 +408,10 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
data->m_size = sizeof( double );
break;
case Value::ddl_string:
- data->m_size = sizeof( char );
+ data->m_size = sizeof( char )*(len+1);
break;
case Value::ddl_ref:
- data->m_size = sizeof( char );
+ data->m_size = 0;
break;
case Value::ddl_none:
case Value::ddl_types_max:
@@ -417,12 +420,8 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
}
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 ];
+ ::memset(data->m_data,0,data->m_size);
}
return data;
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
index 137135604..915bd3041 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/DDLNode.h
@@ -29,6 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
BEGIN_ODDLPARSER_NS
+// Forward declarations
+class IOStreamBase;
class Value;
class OpenDDLParser;
@@ -53,6 +55,9 @@ public:
/// @brief The child-node-list type.
typedef std::vector<DDLNode*> DllNodeList;
+ /// @brief The child-node-list iterator.
+ typedef std::vector<DDLNode*>::iterator DDLNodeIt;
+
public:
/// @brief The class destructor.
~DDLNode();
@@ -81,7 +86,7 @@ public:
const std::string &getType() const;
/// Set the name of the DDLNode instance.
- /// @param type [in] The name.
+ /// @param name [in] The name.
void setName( const std::string &name );
/// @brief Returns the name of the DDLNode instance.
@@ -89,7 +94,7 @@ public:
const std::string &getName() const;
/// @brief Set a new property set.
- /// @param prop [in] The first element of the 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.
@@ -97,7 +102,7 @@ public:
Property *getProperties() const;
/// @brief Looks for a given property.
- /// @param name [in] The name for the property to look for.
+ /// @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 );
@@ -106,12 +111,12 @@ public:
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.
+ /// @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.
+ /// @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.
@@ -119,7 +124,7 @@ public:
Value *getValue() const;
/// @brief Set a new DataArrayList.
- /// @param val [in] The DataArrayList instance.
+ /// @param dtArrayList [in] The DataArrayList instance.
void setDataArrayList( DataArrayList *dtArrayList );
/// @brief Returns the DataArrayList.
@@ -127,17 +132,21 @@ public:
DataArrayList *getDataArrayList() const;
/// @brief Set a new Reference set.
- /// @param val [in] The first value instance of the Reference set.
+ /// @param refs [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 Will dump the node into the stream.
+ /// @param stream [in] The stream to write to.
+ void dump(IOStreamBase &stream);
+
/// @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.
+ /// @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 );
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
index d3e0fb458..bec62cc9d 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
@@ -148,12 +148,12 @@ struct DLL_ODDLPARSER_EXPORT Name {
/// @param type [in] The name type.
/// @param id [in] The id.
Name( NameType type, Text *id );
-
+ Name( const Name &name );
/// @brief The destructor.
~Name();
private:
- Name( const Name & ) ddl_no_copy;
+
Name &operator = ( const Name& ) ddl_no_copy;
};
@@ -164,7 +164,7 @@ struct DLL_ODDLPARSER_EXPORT Reference {
/// @brief The default constructor.
Reference();
-
+ Reference( const Reference &ref );
/// @brief The constructor with an array of ref names.
/// @param numrefs [in] The number of ref names.
/// @param names [in] The ref names.
@@ -178,7 +178,6 @@ struct DLL_ODDLPARSER_EXPORT Reference {
size_t sizeInBytes();
private:
- Reference( const Reference & ) ddl_no_copy;
Reference &operator = ( const Reference & ) ddl_no_copy;
};
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
index 8ede537d9..020d662a0 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLExport.h
@@ -23,37 +23,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/OpenDDLStream.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;
-};
+// Forward declarations
+class IOStreamBase;
//-------------------------------------------------------------------------------------------------
///
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
index efeab6026..ef7f3a72e 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParser.h
@@ -39,6 +39,20 @@ struct Identifier;
struct Reference;
struct Property;
+template<class T>
+inline
+bool isEmbeddedCommentOpenTag( T *in, T *end ) {
+ if ( in == end ) {
+ return false;
+ }
+
+ if ( in == '/' && in+1 == '*' ) {
+ return true;
+ }
+
+ return false;
+}
+
/// @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.
@@ -47,7 +61,7 @@ struct Property;
template<class T>
inline
T *lookForNextToken( T *in, T *end ) {
- while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+ while( ( in != end ) && ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) ) {
in++;
}
return in;
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
index 778a1b46e..64897436e 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
@@ -84,7 +84,7 @@ static const unsigned char chartype_table[ 256 ] = {
template<class T>
inline
bool isNumeric( const T in ) {
- return ( chartype_table[ static_cast<int>( in ) ] == 1 );
+ return ( chartype_table[ static_cast<size_t>( in ) ] == 1 );
}
template<class T>
@@ -98,7 +98,7 @@ inline
bool isInteger( T *in, T *end ) {
if( in != end ) {
if( *in == '-' ) {
- in++;
+ ++in;
}
}
@@ -108,7 +108,7 @@ bool isInteger( T *in, T *end ) {
if( !result ) {
break;
}
- in++;
+ ++in;
}
return result;
@@ -119,7 +119,7 @@ inline
bool isFloat( T *in, T *end ) {
if( in != end ) {
if( *in == '-' ) {
- in++;
+ ++in;
}
}
@@ -134,12 +134,12 @@ bool isFloat( T *in, T *end ) {
if( !result ) {
return false;
}
- in++;
+ ++in;
}
// check for 1<.>0f
if( *in == '.' ) {
- in++;
+ ++in;
} else {
return false;
}
@@ -150,7 +150,7 @@ bool isFloat( T *in, T *end ) {
if( !result ) {
return false;
}
- in++;
+ ++in;
}
return result;
@@ -208,7 +208,7 @@ template<class T>
inline
static T *getNextSeparator( T *in, T *end ) {
while( !isSeparator( *in ) || in == end ) {
- in++;
+ ++in;
}
return in;
}
@@ -250,5 +250,33 @@ bool isComment( T *in, T *end ) {
return false;
}
+template<class T>
+inline
+bool isCommentOpenTag(T *in, T *end ) {
+ if (*in == '/') {
+ if (in + 1 != end) {
+ if (*(in + 1) == '*') {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+template<class T>
+inline
+bool isCommentCloseTag(T *in, T *end) {
+ if (*in == '*') {
+ if (in + 1 != end) {
+ if (*(in + 1) == '/') {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
END_ODDLPARSER_NS
diff --git a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h
new file mode 100644
index 000000000..93370da03
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/OpenDDLStream.h
@@ -0,0 +1,89 @@
+/*-----------------------------------------------------------------------------------------------
+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
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup IOStreamBase
+/// @brief This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
+public:
+ /// @brief The class constructor.
+ StreamFormatterBase();
+
+ /// @brief The class destructor, virtual.
+ virtual ~StreamFormatterBase();
+
+ /// @brief Will format the sring and return the new formatted result.
+ /// @param statement [in] The string to reformat.
+ /// @return The reformatted result.
+ 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:
+ /// @brief The class constructor with the formatter.
+ /// @param formatter [in] The formatter to use.
+ explicit IOStreamBase(StreamFormatterBase *formatter = ddl_nullptr);
+
+ /// @brief The class destructor, virtual.
+ virtual ~IOStreamBase();
+
+ /// @brief Will open the stream.
+ /// @param name [in] The name for the stream.
+ /// @return true, if the stream was opened successfully, false if not.
+ virtual bool open(const std::string &name);
+
+ /// @brief Will close the stream.
+ /// @return true, if the stream was closed successfully, false if not.
+ virtual bool close();
+
+ /// @brief Returns true, if the stream is open.
+ /// @return true, if the stream is open, false if not.
+ virtual bool isOpen() const;
+
+ /// @brief Will read a string from the stream.
+ /// @param sizeToRead [in] The size to read in bytes.
+ /// @param statement [out] The read statements.
+ /// @return The bytes read from the stream.
+ virtual size_t read( size_t sizeToRead, std::string &statement );
+
+ /// @brief Will write a string into the stream.
+ /// @param statement [in] The string to write.
+ /// @return The bytes written into the stream.
+ virtual size_t write(const std::string &statement);
+
+private:
+ StreamFormatterBase *m_formatter;
+ FILE *m_file;
+};
+
+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
index 242ec8781..77c6da06b 100644
--- a/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h
+++ b/src/3rdparty/assimp/contrib/openddlparser/include/openddlparser/Value.h
@@ -28,8 +28,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
BEGIN_ODDLPARSER_NS
+// Forward declarations
struct ValueAllocator;
+class IOStreamBase;
+
///------------------------------------------------------------------------------------------------
/// @brief This class implements a value.
///
@@ -213,7 +216,7 @@ public:
double getDouble() const;
/// @brief Assigns a std::string to the value.
- /// @param value [in] The value.
+ /// @param str [in] The value.
void setString( const std::string &str );
/// @brief Returns the std::string value.
@@ -229,7 +232,8 @@ public:
Reference *getRef() const;
/// @brief Dumps the value.
- void dump();
+ /// @param stream [in] The stream to write in.
+ void dump( IOStreamBase &stream );
/// @brief Assigns the next value.
/// @param next [n] The next value.
@@ -241,7 +245,7 @@ public:
/// @brief Gets the length of the array.
/// @return The number of items in the array.
- size_t size();
+ size_t size() const;
ValueType m_type;
size_t m_size;
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.cc b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.cc
index 4080445a7..c94e11c03 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.cc
@@ -1,4 +1,4 @@
-/*
+/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
@@ -88,7 +88,7 @@ void Triangle::Clear()
points_[0]=points_[1]=points_[2] = NULL;
}
-void Triangle::ClearNeighbor(Triangle *triangle )
+void Triangle::ClearNeighbor(const Triangle *triangle )
{
if( neighbors_[0] == triangle )
{
@@ -96,14 +96,14 @@ void Triangle::ClearNeighbor(Triangle *triangle )
}
else if( neighbors_[1] == triangle )
{
- neighbors_[1] = NULL;
+ neighbors_[1] = NULL;
}
else
{
neighbors_[2] = NULL;
}
}
-
+
void Triangle::ClearNeighbors()
{
neighbors_[0] = NULL;
@@ -116,13 +116,9 @@ void Triangle::ClearDelunayEdges()
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
}
-Point* Triangle::OppositePoint(Triangle& t, Point& p)
+Point* Triangle::OppositePoint(Triangle& t, const Point& p)
{
Point *cw = t.PointCW(p);
- //double x = cw->x;
- //double y = cw->y;
- //x = p.x;
- //y = p.y;
return PointCW(*cw);
}
@@ -164,8 +160,7 @@ int Triangle::Index(const Point* p)
return 2;
}
assert(0);
-
- return 0;
+ return -1;
}
int Triangle::EdgeIndex(const Point* p1, const Point* p2)
@@ -192,7 +187,7 @@ int Triangle::EdgeIndex(const Point* p1, const Point* p2)
return -1;
}
-void Triangle::MarkConstrainedEdge(const int index)
+void Triangle::MarkConstrainedEdge(int index)
{
constrained_edge[index] = true;
}
@@ -215,7 +210,7 @@ void Triangle::MarkConstrainedEdge(Point* p, Point* q)
}
// The point counter-clockwise to given point
-Point* Triangle::PointCW(Point& point)
+Point* Triangle::PointCW(const Point& point)
{
if (&point == points_[0]) {
return points_[2];
@@ -225,12 +220,11 @@ Point* Triangle::PointCW(Point& point)
return points_[1];
}
assert(0);
-
- return 0;
+ return NULL;
}
// The point counter-clockwise to given point
-Point* Triangle::PointCCW(Point& point)
+Point* Triangle::PointCCW(const Point& point)
{
if (&point == points_[0]) {
return points_[1];
@@ -240,12 +234,11 @@ Point* Triangle::PointCCW(Point& point)
return points_[0];
}
assert(0);
-
- return 0;
+ return NULL;
}
// The neighbor clockwise to given point
-Triangle* Triangle::NeighborCW(Point& point)
+Triangle* Triangle::NeighborCW(const Point& point)
{
if (&point == points_[0]) {
return neighbors_[1];
@@ -256,7 +249,7 @@ Triangle* Triangle::NeighborCW(Point& point)
}
// The neighbor counter-clockwise to given point
-Triangle* Triangle::NeighborCCW(Point& point)
+Triangle* Triangle::NeighborCCW(const Point& point)
{
if (&point == points_[0]) {
return neighbors_[2];
@@ -266,7 +259,7 @@ Triangle* Triangle::NeighborCCW(Point& point)
return neighbors_[1];
}
-bool Triangle::GetConstrainedEdgeCCW(Point& p)
+bool Triangle::GetConstrainedEdgeCCW(const Point& p)
{
if (&p == points_[0]) {
return constrained_edge[2];
@@ -276,7 +269,7 @@ bool Triangle::GetConstrainedEdgeCCW(Point& p)
return constrained_edge[1];
}
-bool Triangle::GetConstrainedEdgeCW(Point& p)
+bool Triangle::GetConstrainedEdgeCW(const Point& p)
{
if (&p == points_[0]) {
return constrained_edge[1];
@@ -286,7 +279,7 @@ bool Triangle::GetConstrainedEdgeCW(Point& p)
return constrained_edge[0];
}
-void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce)
{
if (&p == points_[0]) {
constrained_edge[2] = ce;
@@ -297,7 +290,7 @@ void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
}
}
-void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce)
{
if (&p == points_[0]) {
constrained_edge[1] = ce;
@@ -308,7 +301,7 @@ void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
}
}
-bool Triangle::GetDelunayEdgeCCW(Point& p)
+bool Triangle::GetDelunayEdgeCCW(const Point& p)
{
if (&p == points_[0]) {
return delaunay_edge[2];
@@ -318,7 +311,7 @@ bool Triangle::GetDelunayEdgeCCW(Point& p)
return delaunay_edge[1];
}
-bool Triangle::GetDelunayEdgeCW(Point& p)
+bool Triangle::GetDelunayEdgeCW(const Point& p)
{
if (&p == points_[0]) {
return delaunay_edge[1];
@@ -328,7 +321,7 @@ bool Triangle::GetDelunayEdgeCW(Point& p)
return delaunay_edge[0];
}
-void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCCW(const Point& p, bool e)
{
if (&p == points_[0]) {
delaunay_edge[2] = e;
@@ -339,7 +332,7 @@ void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
}
}
-void Triangle::SetDelunayEdgeCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
{
if (&p == points_[0]) {
delaunay_edge[1] = e;
@@ -351,7 +344,7 @@ void Triangle::SetDelunayEdgeCW(Point& p, bool e)
}
// The neighbor across to given point
-Triangle& Triangle::NeighborAcross(Point& opoint)
+Triangle& Triangle::NeighborAcross(const Point& opoint)
{
if (&opoint == points_[0]) {
return *neighbors_[0];
@@ -370,4 +363,3 @@ void Triangle::DebugPrint()
}
}
-
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
index 4f691838f..d3660f716 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/shapes.h
@@ -113,7 +113,7 @@ struct Point {
/// Convert this point into a unit point. Returns the Length.
double Normalize()
{
- double len = Length();
+ const double len = Length();
x /= len;
y /= len;
return len;
@@ -162,50 +162,50 @@ bool constrained_edge[3];
/// Flags to determine if an edge is a Delauney edge
bool delaunay_edge[3];
-Point* GetPoint(const int& index);
-Point* PointCW(Point& point);
-Point* PointCCW(Point& point);
-Point* OppositePoint(Triangle& t, Point& p);
+Point* GetPoint(int index);
+Point* PointCW(const Point& point);
+Point* PointCCW(const Point& point);
+Point* OppositePoint(Triangle& t, const Point& p);
-Triangle* GetNeighbor(const int& index);
+Triangle* GetNeighbor(int index);
void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
void MarkNeighbor(Triangle& t);
-void MarkConstrainedEdge(const int index);
+void MarkConstrainedEdge(int index);
void MarkConstrainedEdge(Edge& edge);
void MarkConstrainedEdge(Point* p, Point* q);
int Index(const Point* p);
int EdgeIndex(const Point* p1, const Point* p2);
-Triangle* NeighborCW(Point& point);
-Triangle* NeighborCCW(Point& point);
-bool GetConstrainedEdgeCCW(Point& p);
-bool GetConstrainedEdgeCW(Point& p);
-void SetConstrainedEdgeCCW(Point& p, bool ce);
-void SetConstrainedEdgeCW(Point& p, bool ce);
-bool GetDelunayEdgeCCW(Point& p);
-bool GetDelunayEdgeCW(Point& p);
-void SetDelunayEdgeCCW(Point& p, bool e);
-void SetDelunayEdgeCW(Point& p, bool e);
-
-bool Contains(Point* p);
+Triangle* NeighborCW(const Point& point);
+Triangle* NeighborCCW(const Point& point);
+bool GetConstrainedEdgeCCW(const Point& p);
+bool GetConstrainedEdgeCW(const Point& p);
+void SetConstrainedEdgeCCW(const Point& p, bool ce);
+void SetConstrainedEdgeCW(const Point& p, bool ce);
+bool GetDelunayEdgeCCW(const Point& p);
+bool GetDelunayEdgeCW(const Point& p);
+void SetDelunayEdgeCCW(const Point& p, bool e);
+void SetDelunayEdgeCW(const Point& p, bool e);
+
+bool Contains(const Point* p);
bool Contains(const Edge& e);
-bool Contains(Point* p, Point* q);
+bool Contains(const Point* p, const Point* q);
void Legalize(Point& point);
void Legalize(Point& opoint, Point& npoint);
/**
* Clears all references to all other triangles and points
*/
void Clear();
-void ClearNeighbor(Triangle *triangle );
+void ClearNeighbor(const Triangle *triangle);
void ClearNeighbors();
void ClearDelunayEdges();
inline bool IsInterior();
inline void IsInterior(bool b);
-Triangle& NeighborAcross(Point& opoint);
+Triangle& NeighborAcross(const Point& opoint);
void DebugPrint();
@@ -258,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
inline bool operator !=(const Point& a, const Point& b)
{
- return a.x != b.x || a.y != b.y;
+ return !(a.x == b.x) && !(a.y == b.y);
}
/// Peform the dot product on two vectors.
@@ -282,22 +282,22 @@ inline Point Cross(const Point& a, double s)
/// Perform the cross product on a scalar and a point. In 2D this produces
/// a point.
-inline Point Cross(const double s, const Point& a)
+inline Point Cross(double s, const Point& a)
{
return Point(-s * a.y, s * a.x);
}
-inline Point* Triangle::GetPoint(const int& index)
+inline Point* Triangle::GetPoint(int index)
{
return points_[index];
}
-inline Triangle* Triangle::GetNeighbor(const int& index)
+inline Triangle* Triangle::GetNeighbor(int index)
{
return neighbors_[index];
}
-inline bool Triangle::Contains(Point* p)
+inline bool Triangle::Contains(const Point* p)
{
return p == points_[0] || p == points_[1] || p == points_[2];
}
@@ -307,7 +307,7 @@ inline bool Triangle::Contains(const Edge& e)
return Contains(e.p) && Contains(e.q);
}
-inline bool Triangle::Contains(Point* p, Point* q)
+inline bool Triangle::Contains(const Point* p, const Point* q)
{
return Contains(p) && Contains(q);
}
@@ -325,5 +325,3 @@ inline void Triangle::IsInterior(bool b)
}
#endif
-
-
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h
index f123fedaf..2424c712c 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/common/utils.h
@@ -1,4 +1,4 @@
-/*
+/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
@@ -28,18 +28,26 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
+
#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>
+
+// C99 removes M_PI from math.h
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327
+#endif
namespace p2t {
-const double PI = 3.1415926535897932384626433832795029;
-const double PI_2 = 2 * PI;
-const double PI_3div4 = 3 * PI / 4;
-const double EPSILON = 1e-15;
+const double PI_3div4 = 3 * M_PI / 4;
+const double PI_div2 = 1.57079632679489661923;
+const double EPSILON = 1e-12;
enum Orientation { CW, CCW, COLLINEAR };
@@ -53,7 +61,7 @@ enum Orientation { CW, CCW, COLLINEAR };
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
* </pre>
*/
-Orientation Orient2d(Point& pa, Point& pb, Point& pc)
+Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
{
double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x);
@@ -66,6 +74,7 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc)
return CW;
}
+/*
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
{
double pdx = pd.x;
@@ -97,7 +106,22 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
return true;
}
+*/
+
+bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point& pd)
+{
+ double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);
+ if (oadb >= -EPSILON) {
+ return false;
+ }
+
+ double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);
+ if (oadc <= EPSILON) {
+ return false;
+ }
+ return true;
}
-#endif
+}
+#endif
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/poly2tri.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/poly2tri.h
index 487755e2e..ba5cc159e 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/poly2tri.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/poly2tri.h
@@ -1,4 +1,4 @@
-/*
+/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
@@ -36,4 +36,3 @@
#include "sweep/cdt.h"
#endif
-
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.cc b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.cc
index 019df4a6e..9739babce 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.cc
@@ -39,7 +39,7 @@ AdvancingFront::AdvancingFront(Node& head, Node& tail)
search_node_ = &head;
}
-Node* AdvancingFront::LocateNode(const double& x)
+Node* AdvancingFront::LocateNode(double x)
{
Node* node = search_node_;
@@ -61,7 +61,7 @@ Node* AdvancingFront::LocateNode(const double& x)
return NULL;
}
-Node* AdvancingFront::FindSearchNode(const double& x)
+Node* AdvancingFront::FindSearchNode(double x)
{
(void)x; // suppress compiler warnings "unused parameter 'x'"
// TODO: implement BST index
@@ -106,4 +106,3 @@ AdvancingFront::~AdvancingFront()
}
}
-
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.h
index bab73d449..3bfec5368 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/advancing_front.h
@@ -74,7 +74,7 @@ Node* search();
void set_search(Node* node);
/// Locate insertion point along advancing front
-Node* LocateNode(const double& x);
+Node* LocateNode(double x);
Node* LocatePoint(const Point* point);
@@ -82,7 +82,7 @@ private:
Node* head_, *tail_, *search_node_;
-Node* FindSearchNode(const double& x);
+Node* FindSearchNode(double x);
};
inline Node* AdvancingFront::head()
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.cc b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.cc
index d7838257c..b79f5a8de 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.cc
@@ -1,4 +1,4 @@
-/*
+/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
@@ -32,13 +32,13 @@
namespace p2t {
-CDT::CDT(std::vector<Point*> polyline)
+CDT::CDT(const std::vector<Point*>& polyline)
{
sweep_context_ = new SweepContext(polyline);
sweep_ = new Sweep;
}
-void CDT::AddHole(std::vector<Point*> polyline)
+void CDT::AddHole(const std::vector<Point*>& polyline)
{
sweep_context_->AddHole(polyline);
}
@@ -69,4 +69,3 @@ CDT::~CDT()
}
}
-
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.h
index 3e6f02408..4a9a292d3 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/cdt.h
@@ -1,4 +1,4 @@
-/*
+/*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
@@ -28,7 +28,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
+
#ifndef CDT_H
#define CDT_H
@@ -37,11 +37,11 @@
#include "sweep.h"
/**
- *
+ *
* @author Mason Green <mason.green@gmail.com>
*
*/
-
+
namespace p2t {
class CDT
@@ -50,40 +50,40 @@ public:
/**
* Constructor - add polyline with non repeating points
- *
+ *
* @param polyline
*/
- CDT(std::vector<Point*> polyline);
-
+ CDT(const std::vector<Point*>& polyline);
+
/**
* Destructor - clean up memory
*/
~CDT();
-
+
/**
* Add a hole
- *
+ *
* @param polyline
*/
- void AddHole(std::vector<Point*> polyline);
-
+ void AddHole(const std::vector<Point*>& polyline);
+
/**
* Add a steiner point
- *
+ *
* @param point
*/
void AddPoint(Point* point);
-
+
/**
* Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
*/
void Triangulate();
-
+
/**
* Get CDT triangles
*/
std::vector<Triangle*> GetTriangles();
-
+
/**
* Get triangle map
*/
@@ -94,7 +94,7 @@ public:
/**
* Internals
*/
-
+
SweepContext* sweep_context_;
Sweep* sweep_;
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc
index ed7c49ac4..826905ceb 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.cc
@@ -49,7 +49,7 @@ void Sweep::Triangulate(SweepContext& tcx)
void Sweep::SweepPoints(SweepContext& tcx)
{
- for (int i = 1; i < tcx.point_count(); i++) {
+ for (size_t i = 1; i < tcx.point_count(); i++) {
Point& point = *tcx.GetPoint(i);
Node* node = &PointEvent(tcx, point);
for (unsigned int i = 0; i < point.edge_list.size(); i++) {
@@ -117,7 +117,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
throw std::runtime_error("EdgeEvent - collinear points not supported");
if( triangle->Contains(&eq, p1)) {
triangle->MarkConstrainedEdge(&eq, p1 );
- // We are modifying the constraint maybe it would be better to
+ // We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p1;
triangle = &triangle->NeighborAcross(point);
@@ -137,7 +137,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
if( triangle->Contains(&eq, p2)) {
triangle->MarkConstrainedEdge(&eq, p2 );
- // We are modifying the constraint maybe it would be better to
+ // We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p2;
triangle = &triangle->NeighborAcross(point);
@@ -166,7 +166,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
{
- int index = triangle.EdgeIndex(&ep, &eq);
+ const int index = triangle.EdgeIndex(&ep, &eq);
if (index != -1) {
triangle.MarkConstrainedEdge(index);
@@ -230,8 +230,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
Node* node = n.next;
while (node->next) {
- double angle = HoleAngle(*node);
- if (angle > PI_2 || angle < -PI_2) break;
+ // if HoleAngle exceeds 90 degrees then break.
+ if (LargeHole_DontFill(node)) break;
Fill(tcx, *node);
node = node->next;
}
@@ -240,29 +240,81 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
node = n.prev;
while (node->prev) {
- double angle = HoleAngle(*node);
- if (angle > PI_2 || angle < -PI_2) break;
+ // if HoleAngle exceeds 90 degrees then break.
+ if (LargeHole_DontFill(node)) break;
Fill(tcx, *node);
node = node->prev;
}
// Fill right basins
if (n.next && n.next->next) {
- double angle = BasinAngle(n);
+ const double angle = BasinAngle(n);
if (angle < PI_3div4) {
FillBasin(tcx, n);
}
}
}
-double Sweep::BasinAngle(Node& node)
+// True if HoleAngle exceeds 90 degrees.
+bool Sweep::LargeHole_DontFill(const Node* node) const {
+
+ const Node* nextNode = node->next;
+ const Node* prevNode = node->prev;
+ if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
+ return false;
+
+ // Check additional points on front.
+ const Node* next2Node = nextNode->next;
+ // "..Plus.." because only want angles on same side as point being added.
+ if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
+ return false;
+
+ const Node* prev2Node = prevNode->prev;
+ // "..Plus.." because only want angles on same side as point being added.
+ if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
+ return false;
+
+ return true;
+}
+
+bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const {
+ const double angle = Angle(origin, pa, pb);
+ return ((angle > PI_div2) || (angle < -PI_div2));
+}
+
+bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const {
+ const double angle = Angle(origin, pa, pb);
+ return (angle > PI_div2) || (angle < 0);
+}
+
+double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const {
+ /* Complex plane
+ * ab = cosA +i*sinA
+ * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+ * atan2(y,x) computes the principal value of the argument function
+ * applied to the complex number x+iy
+ * Where x = ax*bx + ay*by
+ * y = ax*by - ay*bx
+ */
+ const double px = origin->x;
+ const double py = origin->y;
+ const double ax = pa->x- px;
+ const double ay = pa->y - py;
+ const double bx = pb->x - px;
+ const double by = pb->y - py;
+ const double x = ax * by - ay * bx;
+ const double y = ax * bx + ay * by;
+ return atan2(x, y);
+}
+
+double Sweep::BasinAngle(const Node& node) const
{
- double ax = node.point->x - node.next->next->point->x;
- double ay = node.point->y - node.next->next->point->y;
+ const double ax = node.point->x - node.next->next->point->x;
+ const double ay = node.point->y - node.next->next->point->y;
return atan2(ay, ax);
}
-double Sweep::HoleAngle(Node& node)
+double Sweep::HoleAngle(const Node& node) const
{
/* Complex plane
* ab = cosA +i*sinA
@@ -272,10 +324,10 @@ double Sweep::HoleAngle(Node& node)
* Where x = ax*bx + ay*by
* y = ax*by - ay*bx
*/
- double ax = node.next->point->x - node.point->x;
- double ay = node.next->point->y - node.point->y;
- double bx = node.prev->point->x - node.point->x;
- double by = node.prev->point->y - node.point->y;
+ const double ax = node.next->point->x - node.point->x;
+ const double ay = node.next->point->y - node.point->y;
+ const double bx = node.prev->point->x - node.point->x;
+ const double by = node.prev->point->y - node.point->y;
return atan2(ax * by - ay * bx, ax * bx + ay * by);
}
@@ -340,43 +392,43 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
return false;
}
-bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd)
+bool Sweep::Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const
{
- double adx = pa.x - pd.x;
- double ady = pa.y - pd.y;
- double bdx = pb.x - pd.x;
- double bdy = pb.y - pd.y;
+ const double adx = pa.x - pd.x;
+ const double ady = pa.y - pd.y;
+ const double bdx = pb.x - pd.x;
+ const double bdy = pb.y - pd.y;
- double adxbdy = adx * bdy;
- double bdxady = bdx * ady;
- double oabd = adxbdy - bdxady;
+ const double adxbdy = adx * bdy;
+ const double bdxady = bdx * ady;
+ const double oabd = adxbdy - bdxady;
if (oabd <= 0)
return false;
- double cdx = pc.x - pd.x;
- double cdy = pc.y - pd.y;
+ const double cdx = pc.x - pd.x;
+ const double cdy = pc.y - pd.y;
- double cdxady = cdx * ady;
- double adxcdy = adx * cdy;
- double ocad = cdxady - adxcdy;
+ const double cdxady = cdx * ady;
+ const double adxcdy = adx * cdy;
+ const double ocad = cdxady - adxcdy;
if (ocad <= 0)
return false;
- double bdxcdy = bdx * cdy;
- double cdxbdy = cdx * bdy;
+ const double bdxcdy = bdx * cdy;
+ const double cdxbdy = cdx * bdy;
- double alift = adx * adx + ady * ady;
- double blift = bdx * bdx + bdy * bdy;
- double clift = cdx * cdx + cdy * cdy;
+ const double alift = adx * adx + ady * ady;
+ const double blift = bdx * bdx + bdy * bdy;
+ const double clift = cdx * cdx + cdy * cdy;
- double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
+ const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
return det > 0;
}
-void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op)
+void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const
{
Triangle* n1, *n2, *n3, *n4;
n1 = t.NeighborCCW(p);
@@ -708,11 +760,8 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
} else if (o2d == CCW) {
// Left
return *ot.PointCW(op);
- } else{
- //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
- // ASSIMP_CHANGE (aramis_acg)
- throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
}
+ throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
}
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
@@ -740,7 +789,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
Sweep::~Sweep() {
// Clean up memory
- for(unsigned int i = 0; i < nodes_.size(); i++) {
+ for(size_t i = 0; i < nodes_.size(); i++) {
delete nodes_[i];
}
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.h
index bd98adfc5..ad429fd96 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep.h
@@ -33,7 +33,7 @@
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
* International Journal of Geographical Information Science
*
- * "FlipScan" Constrained Edge Algorithm invented by Thomas hln, thahlen@gmail.com
+ * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com
*/
#ifndef SWEEP_H
@@ -49,17 +49,17 @@ struct Point;
struct Edge;
class Triangle;
-class Sweep
+class Sweep
{
public:
/**
* Triangulate
- *
+ *
* @param tcx
*/
void Triangulate(SweepContext& tcx);
-
+
/**
* Destructor - clean up memory
*/
@@ -69,7 +69,7 @@ private:
/**
* Start sweeping the Y-sorted point set from bottom to top
- *
+ *
* @param tcx
*/
void SweepPoints(SweepContext& tcx);
@@ -86,8 +86,8 @@ private:
Node& PointEvent(SweepContext& tcx, Point& point);
/**
- *
- *
+ *
+ *
* @param tcx
* @param edge
* @param node
@@ -98,7 +98,7 @@ private:
/**
* Creates a new front triangle and legalize it
- *
+ *
* @param tcx
* @param point
* @param node
@@ -142,7 +142,7 @@ private:
* @param d - point opposite a
* @return true if d is inside circle, false if on circle edge
*/
- bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);
+ bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const;
/**
* Rotates a triangle pair one vertex CW
@@ -158,7 +158,7 @@ private:
* n4 n4
* </pre>
*/
- void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);
+ void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const;
/**
* Fills holes in the Advancing Front
@@ -169,17 +169,24 @@ private:
*/
void FillAdvancingFront(SweepContext& tcx, Node& n);
+ // Decision-making about when to Fill hole.
+ // Contributed by ToolmakerSteve2
+ bool LargeHole_DontFill(const Node* node) const;
+ bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
+ bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
+ double Angle(const Point* origin, const Point* pa, const Point* pb) const;
+
/**
*
* @param node - middle node
* @return the angle between 3 front nodes
*/
- double HoleAngle(Node& node);
+ double HoleAngle(const Node& node) const;
/**
* The basin angle is decided against the horizontal line [1,0]
*/
- double BasinAngle(Node& node);
+ double BasinAngle(const Node& node) const;
/**
* Fills a basin that has formed on the Advancing Front to the right
@@ -228,22 +235,22 @@ private:
/**
* After a flip we have two triangles and know that only one will still be
* intersecting the edge. So decide which to contiune with and legalize the other
- *
+ *
* @param tcx
* @param o - should be the result of an orient2d( eq, op, ep )
* @param t - triangle 1
* @param ot - triangle 2
- * @param p - a point shared by both triangles
+ * @param p - a point shared by both triangles
* @param op - another point shared by both triangles
* @return returns the triangle still intersecting the edge
*/
Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op);
/**
- * When we need to traverse from one triangle to the next we need
+ * When we need to traverse from one triangle to the next we need
* the point in current triangle that is the opposite point to the next
- * triangle.
- *
+ * triangle.
+ *
* @param ep
* @param eq
* @param ot
@@ -254,10 +261,10 @@ private:
/**
* Scan part of the FlipScan algorithm<br>
- * When a triangle pair isn't flippable we will scan for the next
- * point that is inside the flip triangle scan area. When found
+ * When a triangle pair isn't flippable we will scan for the next
+ * point that is inside the flip triangle scan area. When found
* we generate a new flipEdgeEvent
- *
+ *
* @param tcx
* @param ep - last point on the edge we are traversing
* @param eq - first point on the edge we are traversing
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 235e1eb05..a9f1fdf8e 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.cc
@@ -34,17 +34,18 @@
namespace p2t {
-SweepContext::SweepContext(std::vector<Point*> polyline)
+SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyline),
+ front_(0),
+ head_(0),
+ tail_(0),
+ af_head_(0),
+ af_middle_(0),
+ af_tail_(0)
{
- basin = Basin();
- edge_event = EdgeEvent();
-
- points_ = polyline;
-
InitEdges(points_);
}
-void SweepContext::AddHole(std::vector<Point*> polyline)
+void SweepContext::AddHole(const std::vector<Point*>& polyline)
{
InitEdges(polyline);
for(unsigned int i = 0; i < polyline.size(); i++) {
@@ -56,12 +57,12 @@ void SweepContext::AddPoint(Point* point) {
points_.push_back(point);
}
-std::vector<Triangle*> SweepContext::GetTriangles()
+std::vector<Triangle*> &SweepContext::GetTriangles()
{
return triangles_;
}
-std::list<Triangle*> SweepContext::GetMap()
+std::list<Triangle*> &SweepContext::GetMap()
{
return map_;
}
@@ -94,16 +95,16 @@ void SweepContext::InitTriangulation()
}
-void SweepContext::InitEdges(std::vector<Point*> polyline)
+void SweepContext::InitEdges(const std::vector<Point*>& polyline)
{
- int num_points = polyline.size();
- for (int i = 0; i < num_points; i++) {
- int j = i < num_points - 1 ? i + 1 : 0;
+ size_t num_points = polyline.size();
+ for (size_t i = 0; i < num_points; i++) {
+ size_t j = i < num_points - 1 ? i + 1 : 0;
edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
}
}
-Point* SweepContext::GetPoint(const int& index)
+Point* SweepContext::GetPoint(size_t index)
{
return points_[index];
}
@@ -113,13 +114,13 @@ void SweepContext::AddToMap(Triangle* triangle)
map_.push_back(triangle);
}
-Node& SweepContext::LocateNode(Point& point)
+Node& SweepContext::LocateNode(const Point& point)
{
// TODO implement search tree
return *front_->LocateNode(point.x);
}
-void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)
+void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
{
(void) nodes;
@@ -164,12 +165,20 @@ void SweepContext::RemoveFromMap(Triangle* triangle)
void SweepContext::MeshClean(Triangle& triangle)
{
- if (!triangle.IsInterior()) {
- triangle.IsInterior(true);
- triangles_.push_back(&triangle);
- for (int i = 0; i < 3; i++) {
- if (!triangle.constrained_edge[i])
- MeshClean(*triangle.GetNeighbor(i));
+ std::vector<Triangle *> triangles;
+ triangles.push_back(&triangle);
+
+ while(!triangles.empty()){
+ Triangle *t = triangles.back();
+ triangles.pop_back();
+
+ if (t != NULL && !t->IsInterior()) {
+ t->IsInterior(true);
+ triangles_.push_back(t);
+ for (int i = 0; i < 3; i++) {
+ if (!t->constrained_edge[i])
+ triangles.push_back(t->GetNeighbor(i));
+ }
}
}
}
diff --git a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.h b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.h
index 1010c0e8a..ba0d06581 100644
--- a/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.h
+++ b/src/3rdparty/assimp/contrib/poly2tri/poly2tri/sweep/sweep_context.h
@@ -52,47 +52,47 @@ class SweepContext {
public:
/// Constructor
-SweepContext(std::vector<Point*> polyline);
+SweepContext(const std::vector<Point*>& polyline);
/// Destructor
~SweepContext();
void set_head(Point* p1);
-Point* head();
+Point* head() const;
void set_tail(Point* p1);
-Point* tail();
+Point* tail() const;
-int point_count();
+size_t point_count() const;
-Node& LocateNode(Point& point);
+Node& LocateNode(const Point& point);
void RemoveNode(Node* node);
-void CreateAdvancingFront(std::vector<Node*> nodes);
+void CreateAdvancingFront(const std::vector<Node*>& nodes);
/// Try to map a node to all sides of this triangle that don't have a neighbor
void MapTriangleToNodes(Triangle& t);
void AddToMap(Triangle* triangle);
-Point* GetPoint(const int& index);
+Point* GetPoint(size_t index);
Point* GetPoints();
void RemoveFromMap(Triangle* triangle);
-void AddHole(std::vector<Point*> polyline);
+void AddHole(const std::vector<Point*>& polyline);
void AddPoint(Point* point);
-AdvancingFront* front();
+AdvancingFront* front() const;
void MeshClean(Triangle& triangle);
-std::vector<Triangle*> GetTriangles();
-std::list<Triangle*> GetMap();
+std::vector<Triangle*> &GetTriangles();
+std::list<Triangle*> &GetMap();
std::vector<Edge*> edge_list;
@@ -147,16 +147,16 @@ Point* tail_;
Node *af_head_, *af_middle_, *af_tail_;
void InitTriangulation();
-void InitEdges(std::vector<Point*> polyline);
+void InitEdges(const std::vector<Point*>& polyline);
};
-inline AdvancingFront* SweepContext::front()
+inline AdvancingFront* SweepContext::front() const
{
return front_;
}
-inline int SweepContext::point_count()
+inline size_t SweepContext::point_count() const
{
return points_.size();
}
@@ -166,7 +166,7 @@ inline void SweepContext::set_head(Point* p1)
head_ = p1;
}
-inline Point* SweepContext::head()
+inline Point* SweepContext::head() const
{
return head_;
}
@@ -176,7 +176,7 @@ inline void SweepContext::set_tail(Point* p1)
tail_ = p1;
}
-inline Point* SweepContext::tail()
+inline Point* SweepContext::tail() const
{
return tail_;
}
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h
index 24e6044b3..655f4a385 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/allocators.h
@@ -179,7 +179,8 @@ public:
size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
- AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+ if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
+ return NULL;
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
@@ -194,14 +195,16 @@ public:
if (newSize == 0)
return NULL;
+ originalSize = RAPIDJSON_ALIGN(originalSize);
+ newSize = RAPIDJSON_ALIGN(newSize);
+
// 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) {
+ if (originalPtr == reinterpret_cast<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;
@@ -209,11 +212,13 @@ public:
}
// 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;
+ if (void* newBuffer = Malloc(newSize)) {
+ if (originalSize)
+ std::memcpy(newBuffer, originalPtr, originalSize);
+ return newBuffer;
+ }
+ else
+ return NULL;
}
//! Frees a memory block (concept Allocator)
@@ -227,15 +232,20 @@ private:
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
+ \return true if success.
*/
- void AddChunk(size_t capacity) {
+ bool 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;
+ ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
+ if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
+ chunk->capacity = capacity;
+ chunk->size = 0;
+ chunk->next = chunkHead_;
+ chunkHead_ = chunk;
+ return true;
+ }
+ else
+ return false;
}
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h
index 98053cbd5..93b091f64 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/document.h
@@ -20,40 +20,29 @@
#include "reader.h"
#include "internal/meta.h"
#include "internal/strfunc.h"
+#include "memorystream.h"
+#include "encodedstream.h"
#include <new> // placement new
+#include <limits>
-#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
+#ifdef _MSC_VER
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-#elif defined(__GNUC__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
#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
+#ifdef __clang__
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(c++98-compat)
#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
+#ifdef __GNUC__
+RAPIDJSON_DIAG_OFF(effc++)
+#if __GNUC__ >= 6
+RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
+#endif
+#endif // __GNUC__
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include <iterator> // std::iterator, std::random_access_iterator_tag
@@ -158,6 +147,7 @@ public:
Otherwise, the copy constructor is implicitly defined.
*/
GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+ Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
//! @name stepping
//@{
@@ -260,6 +250,7 @@ struct GenericStringRef {
typedef CharType Ch; //!< character type of the string
//! Create string reference from \c const character array
+#ifndef __clang__ // -Wdocumentation
/*!
This constructor implicitly creates a constant string reference from
a \c const character array. It has better performance than
@@ -282,11 +273,13 @@ struct GenericStringRef {
In such cases, the referenced string should be \b copied to the
GenericValue instead.
*/
+#endif
template<SizeType N>
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
: s(str), length(N-1) {}
//! Explicitly create string reference from \c const character pointer
+#ifndef __clang__ // -Wdocumentation
/*!
This constructor can be used to \b explicitly create a reference to
a constant string pointer.
@@ -305,18 +298,23 @@ struct GenericStringRef {
In such cases, the referenced string should be \b copied to the
GenericValue instead.
*/
+#endif
explicit GenericStringRef(const CharType* str)
- : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
+ : s(str), length(NotNullStrLen(str)) {}
//! Create constant string reference from pointer and length
+#ifndef __clang__ // -Wdocumentation
/*! \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.
*/
+#endif
GenericStringRef(const CharType* str, SizeType len)
- : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
+ : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }
+
+ GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
//! implicit conversion to plain CharType pointer
operator const Ch *() const { return s; }
@@ -325,13 +323,24 @@ struct GenericStringRef {
const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
private:
- //! Disallow copy-assignment
- GenericStringRef operator=(const GenericStringRef&);
+ SizeType NotNullStrLen(const CharType* str) {
+ RAPIDJSON_ASSERT(str != 0);
+ return internal::StrLen(str);
+ }
+
+ /// Empty string - used when passing in a NULL pointer
+ static const Ch emptyString[];
+
//! Disallow construction from non-const array
template<SizeType N>
GenericStringRef(CharType (&str)[N]) /* = delete */;
+ //! Copy assignment operator not permitted - immutable type
+ GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;
};
+template<typename CharType>
+const CharType GenericStringRef<CharType>::emptyString[] = { CharType() };
+
//! 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
@@ -346,7 +355,7 @@ private:
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const CharType* str) {
- return GenericStringRef<CharType>(str, internal::StrLen(str));
+ return GenericStringRef<CharType>(str);
}
//! Mark a character pointer as constant string
@@ -405,6 +414,127 @@ template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
} // namespace internal
///////////////////////////////////////////////////////////////////////////////
+// TypeHelper
+
+namespace internal {
+
+template <typename ValueType, typename T>
+struct TypeHelper {};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, bool> {
+ static bool Is(const ValueType& v) { return v.IsBool(); }
+ static bool Get(const ValueType& v) { return v.GetBool(); }
+ static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
+ static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, int> {
+ static bool Is(const ValueType& v) { return v.IsInt(); }
+ static int Get(const ValueType& v) { return v.GetInt(); }
+ static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
+ static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, unsigned> {
+ static bool Is(const ValueType& v) { return v.IsUint(); }
+ static unsigned Get(const ValueType& v) { return v.GetUint(); }
+ static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
+ static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, int64_t> {
+ static bool Is(const ValueType& v) { return v.IsInt64(); }
+ static int64_t Get(const ValueType& v) { return v.GetInt64(); }
+ static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
+ static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, uint64_t> {
+ static bool Is(const ValueType& v) { return v.IsUint64(); }
+ static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
+ static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
+ static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, double> {
+ static bool Is(const ValueType& v) { return v.IsDouble(); }
+ static double Get(const ValueType& v) { return v.GetDouble(); }
+ static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
+ static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, float> {
+ static bool Is(const ValueType& v) { return v.IsFloat(); }
+ static float Get(const ValueType& v) { return v.GetFloat(); }
+ static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
+ static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, const typename ValueType::Ch*> {
+ typedef const typename ValueType::Ch* StringType;
+ static bool Is(const ValueType& v) { return v.IsString(); }
+ static StringType Get(const ValueType& v) { return v.GetString(); }
+ static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
+ static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
+};
+
+#if RAPIDJSON_HAS_STDSTRING
+template<typename ValueType>
+struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
+ typedef std::basic_string<typename ValueType::Ch> StringType;
+ static bool Is(const ValueType& v) { return v.IsString(); }
+ static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }
+ static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
+};
+#endif
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::Array> {
+ typedef typename ValueType::Array ArrayType;
+ static bool Is(const ValueType& v) { return v.IsArray(); }
+ static ArrayType Get(ValueType& v) { return v.GetArray(); }
+ static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
+ static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::ConstArray> {
+ typedef typename ValueType::ConstArray ArrayType;
+ static bool Is(const ValueType& v) { return v.IsArray(); }
+ static ArrayType Get(const ValueType& v) { return v.GetArray(); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::Object> {
+ typedef typename ValueType::Object ObjectType;
+ static bool Is(const ValueType& v) { return v.IsObject(); }
+ static ObjectType Get(ValueType& v) { return v.GetObject(); }
+ static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
+ static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::ConstObject> {
+ typedef typename ValueType::ConstObject ObjectType;
+ static bool Is(const ValueType& v) { return v.IsObject(); }
+ static ObjectType Get(const ValueType& v) { return v.GetObject(); }
+};
+
+} // namespace internal
+
+// Forward declarations
+template <bool, typename> class GenericArray;
+template <bool, typename> class GenericObject;
+
+///////////////////////////////////////////////////////////////////////////////
// GenericValue
//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
@@ -431,17 +561,21 @@ public:
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.
+ typedef GenericArray<false, ValueType> Array;
+ typedef GenericArray<true, ValueType> ConstArray;
+ typedef GenericObject<false, ValueType> Object;
+ typedef GenericObject<true, ValueType> ConstObject;
//!@name Constructors and destructor.
//@{
//! Default constructor creates a null value.
- GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
+ GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.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
+ GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
+ rhs.data_.f.flags = kNullFlag; // give up contents
}
#endif
@@ -466,13 +600,13 @@ public:
\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] = {
+ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
+ static const uint16_t defaultFlags[7] = {
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
kNumberAnyFlag
};
- RAPIDJSON_ASSERT(type <= kNumberType);
- flags_ = defaultFlags[type];
+ RAPIDJSON_ASSERT(type >= kNullType && type <= kNumberType);
+ data_.f.flags = defaultFlags[type];
// Use ShortString to store empty string.
if (type == kStringType)
@@ -484,10 +618,50 @@ public:
\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().
+ \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
\see CopyFrom()
*/
- template< typename SourceAllocator >
- GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+ template <typename SourceAllocator>
+ GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
+ switch (rhs.GetType()) {
+ case kObjectType: {
+ SizeType count = rhs.data_.o.size;
+ Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
+ const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
+ for (SizeType i = 0; i < count; i++) {
+ new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
+ new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
+ }
+ data_.f.flags = kObjectFlag;
+ data_.o.size = data_.o.capacity = count;
+ SetMembersPointer(lm);
+ }
+ break;
+ case kArrayType: {
+ SizeType count = rhs.data_.a.size;
+ GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
+ const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer();
+ for (SizeType i = 0; i < count; i++)
+ new (&le[i]) GenericValue(re[i], allocator, copyConstStrings);
+ data_.f.flags = kArrayFlag;
+ data_.a.size = data_.a.capacity = count;
+ SetElementsPointer(le);
+ }
+ break;
+ case kStringType:
+ if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {
+ data_.f.flags = rhs.data_.f.flags;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ }
+ else
+ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+ break;
+ default:
+ data_.f.flags = rhs.data_.f.flags;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ break;
+ }
+ }
//! Constructor for boolean value.
/*! \param b Boolean value
@@ -497,118 +671,125 @@ public:
*/
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
template <typename T>
- explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
#else
explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
#endif
- : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
+ : data_() {
// safe-guard against failing SFINAE
RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+ data_.f.flags = b ? kTrueFlag : kFalseFlag;
}
//! Constructor for int value.
- explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
+ explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i;
- if (i >= 0)
- flags_ |= kUintFlag | kUint64Flag;
+ data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
}
//! Constructor for unsigned value.
- explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
+ explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u;
- if (!(u & 0x80000000))
- flags_ |= kIntFlag | kInt64Flag;
+ data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
}
//! Constructor for int64_t value.
- explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
+ explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i64;
+ data_.f.flags = kNumberInt64Flag;
if (i64 >= 0) {
- flags_ |= kNumberUint64Flag;
+ data_.f.flags |= kNumberUint64Flag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
- flags_ |= kUintFlag;
+ data_.f.flags |= kUintFlag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- flags_ |= kIntFlag;
+ data_.f.flags |= kIntFlag;
}
else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- flags_ |= kIntFlag;
+ data_.f.flags |= kIntFlag;
}
//! Constructor for uint64_t value.
- explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
+ explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u64;
+ data_.f.flags = kNumberUint64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
- flags_ |= kInt64Flag;
+ data_.f.flags |= kInt64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
- flags_ |= kUintFlag;
+ data_.f.flags |= kUintFlag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- flags_ |= kIntFlag;
+ data_.f.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; }
+ explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
+
+ //! Constructor for float value.
+ explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }
//! 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)); }
+ GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { 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); }
+ explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { 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); }
+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { 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); }
+ GenericValue(const Ch*s, Allocator& allocator) : data_() { 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); }
+ GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
#endif
+ //! Constructor for Array.
+ /*!
+ \param a An array obtained by \c GetArray().
+ \note \c Array is always pass-by-value.
+ \note the source array is moved into this value and the sourec array becomes empty.
+ */
+ GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
+ a.value_.data_ = Data();
+ a.value_.data_.f.flags = kArrayFlag;
+ }
+
+ //! Constructor for Object.
+ /*!
+ \param o An object obtained by \c GetObject().
+ \note \c Object is always pass-by-value.
+ \note the source object is moved into this value and the sourec object becomes empty.
+ */
+ GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
+ o.value_.data_ = Data();
+ o.value_.data_.f.flags = kObjectFlag;
+ }
+
//! Destructor.
/*! Need to destruct elements of array, members of object, or copy-string.
*/
~GenericValue() {
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
- switch(flags_) {
+ switch(data_.f.flags) {
case kArrayFlag:
- for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
- v->~GenericValue();
- Allocator::Free(data_.a.elements);
+ {
+ GenericValue* e = GetElementsPointer();
+ for (GenericValue* v = e; v != e + data_.a.size; ++v)
+ v->~GenericValue();
+ Allocator::Free(e);
+ }
break;
case kObjectFlag:
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
m->~Member();
- Allocator::Free(data_.o.members);
+ Allocator::Free(GetMembersPointer());
break;
case kCopyStringFlag:
- Allocator::Free(const_cast<Ch*>(data_.s.str));
+ Allocator::Free(const_cast<Ch*>(GetStringPointer()));
break;
default:
@@ -673,12 +854,13 @@ public:
\tparam SourceAllocator Allocator type of \c rhs
\param rhs Value to copy from (read-only)
\param allocator Allocator to use for copying
+ \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
*/
template <typename SourceAllocator>
- GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
- RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
+ GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
+ RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
this->~GenericValue();
- new (this) GenericValue(rhs, allocator);
+ new (this) GenericValue(rhs, allocator, copyConstStrings);
return *this;
}
@@ -758,7 +940,7 @@ public:
else
return data_.n.u64 == rhs.data_.n.u64;
- default: // kTrueType, kFalseType, kNullType
+ default:
return true;
}
}
@@ -806,20 +988,58 @@ public:
//!@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; }
+ Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); }
+ bool IsNull() const { return data_.f.flags == kNullFlag; }
+ bool IsFalse() const { return data_.f.flags == kFalseFlag; }
+ bool IsTrue() const { return data_.f.flags == kTrueFlag; }
+ bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
+ bool IsObject() const { return data_.f.flags == kObjectFlag; }
+ bool IsArray() const { return data_.f.flags == kArrayFlag; }
+ bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
+ bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
+ bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
+ bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
+ bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
+ bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
+ bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
+
+ // Checks whether a number can be losslessly converted to a double.
+ bool IsLosslessDouble() const {
+ if (!IsNumber()) return false;
+ if (IsUint64()) {
+ uint64_t u = GetUint64();
+ volatile double d = static_cast<double>(u);
+ return (d >= 0.0)
+ && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)()))
+ && (u == static_cast<uint64_t>(d));
+ }
+ if (IsInt64()) {
+ int64_t i = GetInt64();
+ volatile double d = static_cast<double>(i);
+ return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))
+ && (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))
+ && (i == static_cast<int64_t>(d));
+ }
+ return true; // double, int, uint are always lossless
+ }
+
+ // Checks whether a number is a float (possible lossy).
+ bool IsFloat() const {
+ if ((data_.f.flags & kDoubleFlag) == 0)
+ return false;
+ double d = GetDouble();
+ return d >= -3.4028234e38 && d <= 3.4028234e38;
+ }
+ // Checks whether a number can be losslessly converted to a float.
+ bool IsLosslessFloat() const {
+ if (!IsNumber()) return false;
+ double a = GetDouble();
+ if (a < static_cast<double>(-(std::numeric_limits<float>::max)())
+ || a > static_cast<double>((std::numeric_limits<float>::max)()))
+ return false;
+ double b = static_cast<double>(static_cast<float>(a));
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
//@}
@@ -833,7 +1053,7 @@ public:
//!@name Bool
//@{
- bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
//!< Set boolean value
/*! \post IsBool() == true */
GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
@@ -886,8 +1106,14 @@ public:
return member->value;
else {
RAPIDJSON_ASSERT(false); // see above note
- static GenericValue NullValue;
- return NullValue;
+
+ // This will generate -Wexit-time-destructors in clang
+ // static GenericValue NullValue;
+ // return NullValue;
+
+ // Use static buffer and placement-new to prevent destruction
+ static char buffer[sizeof(GenericValue)];
+ return *new (buffer) GenericValue();
}
}
template <typename SourceAllocator>
@@ -901,16 +1127,16 @@ public:
//! Const member iterator
/*! \pre IsObject() == true */
- ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
//! Const \em past-the-end member iterator
/*! \pre IsObject() == true */
- ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
//! Member iterator
/*! \pre IsObject() == true */
- MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
//! \em Past-the-end member iterator
/*! \pre IsObject() == true */
- MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
//! Check whether a member exists in the object.
/*!
@@ -998,8 +1224,8 @@ public:
\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)); }
+ MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }
+ ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }
#endif
//! Add a member (name-value pair) to the object.
@@ -1016,20 +1242,21 @@ public:
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString());
- Object& o = data_.o;
+ ObjectData& 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)));
+ SetMembersPointer(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)));
+ SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
}
}
- o.members[o.size].name.RawAssign(name);
- o.members[o.size].value.RawAssign(value);
+ Member* members = GetMembersPointer();
+ members[o.size].name.RawAssign(name);
+ members[o.size].value.RawAssign(value);
o.size++;
return *this;
}
@@ -1208,18 +1435,14 @@ public:
MemberIterator RemoveMember(MemberIterator m) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0);
- RAPIDJSON_ASSERT(data_.o.members != 0);
+ RAPIDJSON_ASSERT(GetMembersPointer() != 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();
- }
+ MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
+ if (data_.o.size > 1 && m != last)
+ *m = *last; // Move the last one to this place
+ else
+ m->~Member(); // Only one left, just destroy
--data_.o.size;
return m;
}
@@ -1249,7 +1472,7 @@ public:
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0);
- RAPIDJSON_ASSERT(data_.o.members != 0);
+ RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(first >= MemberBegin());
RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= MemberEnd());
@@ -1257,8 +1480,8 @@ public:
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);
+ std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
+ data_.o.size -= static_cast<SizeType>(last - first);
return pos;
}
@@ -1287,6 +1510,9 @@ public:
return false;
}
+ Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
+ ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
+
//@}
//!@name Array
@@ -1294,7 +1520,7 @@ public:
//! Set this value as an empty array.
/*! \post IsArray == true */
- GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+ 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; }
@@ -1311,8 +1537,9 @@ public:
*/
void Clear() {
RAPIDJSON_ASSERT(IsArray());
- for (SizeType i = 0; i < data_.a.size; ++i)
- data_.a.elements[i].~GenericValue();
+ GenericValue* e = GetElementsPointer();
+ for (GenericValue* v = e; v != e + data_.a.size; ++v)
+ v->~GenericValue();
data_.a.size = 0;
}
@@ -1324,16 +1551,16 @@ public:
GenericValue& operator[](SizeType index) {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(index < data_.a.size);
- return data_.a.elements[index];
+ return GetElementsPointer()[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; }
+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
//! \em Past-the-end element iterator
/*! \pre IsArray() == true */
- ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
//! Constant element iterator
/*! \pre IsArray() == true */
ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
@@ -1350,7 +1577,7 @@ public:
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));
+ SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
data_.a.capacity = newCapacity;
}
return *this;
@@ -1370,7 +1597,7 @@ public:
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);
+ GetElementsPointer()[data_.a.size++].RawAssign(value);
return *this;
}
@@ -1424,7 +1651,7 @@ public:
GenericValue& PopBack() {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(!Empty());
- data_.a.elements[--data_.a.size].~GenericValue();
+ GetElementsPointer()[--data_.a.size].~GenericValue();
return *this;
}
@@ -1450,35 +1677,48 @@ public:
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(data_.a.size > 0);
- RAPIDJSON_ASSERT(data_.a.elements != 0);
+ RAPIDJSON_ASSERT(GetElementsPointer() != 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);
+ std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
+ data_.a.size -= static_cast<SizeType>(last - first);
return pos;
}
+ Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
+ ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
+
//@}
//!@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; }
+ int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
+ unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
+ int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
+ //! Get the value as double type.
+ /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
+ */
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)
+ if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
+ if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
+ if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
+ if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
+ RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
+ }
+
+ //! Get the value as float type.
+ /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
+ */
+ float GetFloat() const {
+ return static_cast<float>(GetDouble());
}
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
@@ -1486,18 +1726,19 @@ public:
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; }
+ GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }
//@}
//!@name String
//@{
- const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
//! 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); }
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.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.
@@ -1524,7 +1765,7 @@ public:
\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; }
+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); }
//! Set this value as a string by copying from source string.
/*! \param s source string.
@@ -1532,7 +1773,15 @@ public:
\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); }
+ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
+
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string reference
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }
#if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string.
@@ -1542,11 +1791,35 @@ public:
\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); }
+ GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
#endif
//@}
+ //!@name Array
+ //@{
+
+ //! Templated version for checking whether this value is type T.
+ /*!
+ \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
+ */
+ template <typename T>
+ bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
+
+ template <typename T>
+ T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
+
+ template <typename T>
+ T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
+
+ template<typename T>
+ ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
+
+ template<typename T>
+ ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
+
+ //@}
+
//! 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.
@@ -1562,35 +1835,35 @@ public:
case kTrueType: return handler.Bool(true);
case kObjectType:
- if (!handler.StartObject())
+ if (RAPIDJSON_UNLIKELY(!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))
+ if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
return false;
- if (!m->value.Accept(handler))
+ if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
return false;
}
return handler.EndObject(data_.o.size);
case kArrayType:
- if (!handler.StartArray())
+ if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
return false;
- for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
- if (!v->Accept(handler))
+ for (const GenericValue* v = Begin(); v != End(); ++v)
+ if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
return false;
return handler.EndArray(data_.a.size);
case kStringType:
- return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
+ return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
default:
RAPIDJSON_ASSERT(GetType() == kNumberType);
- if (IsInt()) return handler.Int(data_.n.i.i);
+ if (IsDouble()) return handler.Double(data_.n.d);
+ else 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);
+ else return handler.Uint64(data_.n.u64);
}
}
@@ -1599,16 +1872,16 @@ private:
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,
+ kBoolFlag = 0x0008,
+ kNumberFlag = 0x0010,
+ kIntFlag = 0x0020,
+ kUintFlag = 0x0040,
+ kInt64Flag = 0x0080,
+ kUint64Flag = 0x0100,
+ kDoubleFlag = 0x0200,
+ kStringFlag = 0x0400,
+ kCopyFlag = 0x0800,
+ kInlineStrFlag = 0x1000,
// Initial flags of different types.
kNullFlag = kNullType,
@@ -1626,16 +1899,27 @@ private:
kObjectFlag = kObjectType,
kArrayFlag = kArrayType,
- kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
+ kTypeMask = 0x07
};
static const SizeType kDefaultArrayCapacity = 16;
static const SizeType kDefaultObjectCapacity = 16;
+ struct Flag {
+#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
+ char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer
+#elif RAPIDJSON_64BIT
+ char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
+#else
+ char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
+#endif
+ uint16_t flags;
+ };
+
struct String {
- const Ch* str;
SizeType length;
- unsigned hashcode; //!< reserved
+ SizeType hashcode; //!< reserved
+ const Ch* str;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
@@ -1644,15 +1928,15 @@ private:
// 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).
+ // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
+ // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
struct ShortString {
- enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+ enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / 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]); }
+ inline static bool Usable(SizeType len) { return (MaxSize >= len); }
+ inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
+ inline SizeType GetLength() const { return static_cast<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.
@@ -1681,69 +1965,79 @@ private:
double d;
}; // 8 bytes
- struct Object {
- Member* members;
+ struct ObjectData {
SizeType size;
SizeType capacity;
+ Member* members;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
- struct Array {
- GenericValue* elements;
+ struct ArrayData {
SizeType size;
SizeType capacity;
+ GenericValue* elements;
}; // 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
+ ObjectData o;
+ ArrayData a;
+ Flag f;
+ }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+ RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
+ RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
+ RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
+ RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
+ RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
+ RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
// Initialize this value as array with initial data, without calling destructor.
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
- flags_ = kArrayFlag;
+ data_.f.flags = kArrayFlag;
if (count) {
- data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
- std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
+ GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
+ SetElementsPointer(e);
+ std::memcpy(e, values, count * sizeof(GenericValue));
}
else
- data_.a.elements = NULL;
+ SetElementsPointer(0);
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;
+ data_.f.flags = kObjectFlag;
if (count) {
- data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
- std::memcpy(data_.o.members, members, count * sizeof(Member));
+ Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
+ SetMembersPointer(m);
+ std::memcpy(m, members, count * sizeof(Member));
}
else
- data_.o.members = NULL;
+ SetMembersPointer(0);
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_.f.flags = kConstStringFlag;
+ SetStringPointer(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;
+ Ch* str = 0;
+ if (ShortString::Usable(s.length)) {
+ data_.f.flags = kShortStringFlag;
data_.ss.SetLength(s.length);
str = data_.ss.str;
} else {
- flags_ = kCopyStringFlag;
+ data_.f.flags = kCopyStringFlag;
data_.s.length = s.length;
- str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
- data_.s.str = str;
+ str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
+ SetStringPointer(str);
}
std::memcpy(str, s, s.length * sizeof(Ch));
str[s.length] = '\0';
@@ -1752,8 +2046,8 @@ private:
//! Assignment without calling destructor
void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
data_ = rhs.data_;
- flags_ = rhs.flags_;
- rhs.flags_ = kNullFlag;
+ // data_.f.flags = rhs.data_.f.flags;
+ rhs.data_.f.flags = kNullFlag;
}
template <typename SourceAllocator>
@@ -1773,7 +2067,6 @@ private:
}
Data data_;
- unsigned flags_;
};
//! GenericValue with UTF8 encoding
@@ -1808,7 +2101,7 @@ public:
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
}
//! Constructor
@@ -1821,7 +2114,7 @@ public:
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
@@ -1869,7 +2162,7 @@ public:
//! Exchange the contents of this document with those of another.
/*!
- \param other Another document.
+ \param rhs Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
@@ -1882,6 +2175,10 @@ public:
return *this;
}
+ // Allow Swap with ValueType.
+ // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names.
+ using ValueType::Swap;
+
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
@@ -1896,6 +2193,21 @@ public:
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+ //! Populate this document by a generator which produces SAX events.
+ /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
+ \param g Generator functor which sends SAX events to the parameter.
+ \return The document itself for fluent API.
+ */
+ template <typename Generator>
+ GenericDocument& Populate(Generator& g) {
+ ClearStackOnExit scope(*this);
+ if (g(*this)) {
+ 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;
+ }
+
//!@name Parse from stream
//!@{
@@ -1973,7 +2285,7 @@ public:
\param str Read-only zero-terminated string to be parsed.
*/
template <unsigned parseFlags, typename SourceEncoding>
- GenericDocument& Parse(const Ch* str) {
+ GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<SourceEncoding> s(str);
return ParseStream<parseFlags, SourceEncoding>(s);
@@ -1994,6 +2306,42 @@ public:
GenericDocument& Parse(const Ch* str) {
return Parse<kParseDefaultFlags>(str);
}
+
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
+ EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
+ ParseStream<parseFlags, SourceEncoding>(is);
+ return *this;
+ }
+
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str, size_t length) {
+ return Parse<parseFlags, Encoding>(str, length);
+ }
+
+ GenericDocument& Parse(const Ch* str, size_t length) {
+ return Parse<kParseDefaultFlags>(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
+ // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
+ return Parse<parseFlags, SourceEncoding>(str.c_str());
+ }
+
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const std::basic_string<Ch>& str) {
+ return Parse<parseFlags, Encoding>(str.c_str());
+ }
+
+ GenericDocument& Parse(const std::basic_string<Ch>& str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+#endif // RAPIDJSON_HAS_STDSTRING
+
//!@}
//!@name Handling parse errors
@@ -2008,6 +2356,19 @@ public:
//! Get the position of last parsing error in input, 0 otherwise.
size_t GetErrorOffset() const { return parseResult_.Offset(); }
+ //! Implicit conversion to get the last parse result
+#ifndef __clang // -Wdocumentation
+ /*! \return \ref ParseResult of the last parse operation
+
+ \code
+ Document doc;
+ ParseResult ok = doc.Parse(json);
+ if (!ok)
+ printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
+ \endcode
+ */
+#endif
+ operator ParseResult() const { return parseResult_; }
//!@}
//! Get the allocator of this document.
@@ -2031,9 +2392,10 @@ private:
};
// callers of the following private Handler functions
- template <typename,typename,typename> friend class GenericReader; // for parsing
+ // template <typename,typename,typename> friend class GenericReader; // for parsing
template <typename, typename> friend class GenericValue; // for deep copying
+public:
// 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; }
@@ -2043,6 +2405,14 @@ private:
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 RawNumber(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 String(const Ch* str, SizeType length, bool copy) {
if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
@@ -2057,7 +2427,7 @@ private:
bool EndObject(SizeType memberCount) {
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
- stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
+ stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
return true;
}
@@ -2098,39 +2468,146 @@ private:
//! 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;
- }
-}
+//! Helper class for accessing Value of array type.
+/*!
+ Instance of this helper class is obtained by \c GenericValue::GetArray().
+ In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
+*/
+template <bool Const, typename ValueT>
+class GenericArray {
+public:
+ typedef GenericArray<true, ValueT> ConstArray;
+ typedef GenericArray<false, ValueT> Array;
+ typedef ValueT PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef ValueType* ValueIterator; // This may be const or non-const iterator
+ typedef const ValueT* ConstValueIterator;
+ typedef typename ValueType::AllocatorType AllocatorType;
+ typedef typename ValueType::StringRefType StringRefType;
+
+ template <typename, typename>
+ friend class GenericValue;
+
+ GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
+ GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
+ ~GenericArray() {}
+
+ SizeType Size() const { return value_.Size(); }
+ SizeType Capacity() const { return value_.Capacity(); }
+ bool Empty() const { return value_.Empty(); }
+ void Clear() const { value_.Clear(); }
+ ValueType& operator[](SizeType index) const { return value_[index]; }
+ ValueIterator Begin() const { return value_.Begin(); }
+ ValueIterator End() const { return value_.End(); }
+ GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
+ GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+ GenericArray PopBack() const { value_.PopBack(); return *this; }
+ ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
+
+#if RAPIDJSON_HAS_CXX11_RANGE_FOR
+ ValueIterator begin() const { return value_.Begin(); }
+ ValueIterator end() const { return value_.End(); }
+#endif
-RAPIDJSON_NAMESPACE_END
+private:
+ GenericArray();
+ GenericArray(ValueType& value) : value_(value) {}
+ ValueType& value_;
+};
-#if defined(_MSC_VER) || defined(__GNUC__)
-RAPIDJSON_DIAG_POP
+//! Helper class for accessing Value of object type.
+/*!
+ Instance of this helper class is obtained by \c GenericValue::GetObject().
+ In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
+*/
+template <bool Const, typename ValueT>
+class GenericObject {
+public:
+ typedef GenericObject<true, ValueT> ConstObject;
+ typedef GenericObject<false, ValueT> Object;
+ typedef ValueT PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator
+ typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
+ typedef typename ValueType::AllocatorType AllocatorType;
+ typedef typename ValueType::StringRefType StringRefType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename ValueType::Ch Ch;
+
+ template <typename, typename>
+ friend class GenericValue;
+
+ GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
+ GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
+ ~GenericObject() {}
+
+ SizeType MemberCount() const { return value_.MemberCount(); }
+ bool ObjectEmpty() const { return value_.ObjectEmpty(); }
+ template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
+ template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
+#if RAPIDJSON_HAS_STDSTRING
+ ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
+#endif
+ MemberIterator MemberBegin() const { return value_.MemberBegin(); }
+ MemberIterator MemberEnd() const { return value_.MemberEnd(); }
+ bool HasMember(const Ch* name) const { return value_.HasMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
+#endif
+ template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
+ MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
+ template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
+#endif
+ GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#if RAPIDJSON_HAS_STDSTRING
+ GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#endif
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ void RemoveAllMembers() { value_.RemoveAllMembers(); }
+ bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
+#endif
+ template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
+ MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
+ MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
+ bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
+#endif
+ template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
+
+#if RAPIDJSON_HAS_CXX11_RANGE_FOR
+ MemberIterator begin() const { return value_.MemberBegin(); }
+ MemberIterator end() const { return value_.MemberEnd(); }
+#endif
+
+private:
+ GenericObject();
+ GenericObject(ValueType& value) : value_(value) {}
+ ValueType& value_;
+};
+
+RAPIDJSON_NAMESPACE_END
+RAPIDJSON_DIAG_POP
#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
index fd3bfaf13..223601c05 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodedstream.h
@@ -15,13 +15,19 @@
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
#define RAPIDJSON_ENCODEDSTREAM_H_
-#include "rapidjson.h"
+#include "stream.h"
+#include "memorystream.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
//! Input byte stream wrapper with a statically bound encoding.
@@ -57,10 +63,38 @@ private:
Ch current_;
};
+//! Specialized for UTF8 MemoryStream.
+template <>
+class EncodedInputStream<UTF8<>, MemoryStream> {
+public:
+ typedef UTF8<>::Ch Ch;
+
+ EncodedInputStream(MemoryStream& is) : is_(is) {
+ if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
+ if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
+ if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
+ }
+ Ch Peek() const { return is_.Peek(); }
+ Ch Take() { return is_.Take(); }
+ size_t Tell() const { return is_.Tell(); }
+
+ // Not implemented
+ void Put(Ch) {}
+ void Flush() {}
+ Ch* PutBegin() { return 0; }
+ size_t PutEnd(Ch*) { return 0; }
+
+ MemoryStream& is_;
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+};
+
//! 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.
+ \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
*/
template <typename Encoding, typename OutputByteStream>
class EncodedOutputStream {
@@ -142,7 +176,7 @@ private:
// FF FE UTF-16LE
// EF BB BF UTF-8
- const unsigned char* c = (const unsigned char *)is_->Peek4();
+ const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
if (!c)
return;
@@ -166,7 +200,7 @@ private:
// 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);
+ int 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;
@@ -193,7 +227,7 @@ private:
//! 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.
+ \tparam OutputByteStream type of output byte stream to be wrapped.
*/
template <typename CharType, typename OutputByteStream>
class AutoUTFOutputStream {
@@ -254,6 +288,10 @@ private:
RAPIDJSON_NAMESPACE_END
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h
index 90b46ed32..0df1c3435 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/encodings.h
@@ -120,19 +120,45 @@ struct UTF8 {
}
}
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ PutUnsafe(os, 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 COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define TAIL() COPY(); TRANS(0x70)
- Ch c = is.Take();
+ typename InputStream::Ch c = is.Take();
if (!(c & 0x80)) {
- *codepoint = (unsigned char)c;
+ *codepoint = static_cast<unsigned char>(c);
return true;
}
- unsigned char type = GetRange((unsigned char)c);
- *codepoint = (0xFF >> type) & (unsigned char)c;
+ unsigned char type = GetRange(static_cast<unsigned char>(c));
+ if (type >= 32) {
+ *codepoint = 0;
+ } else {
+ *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
+ }
bool result = true;
switch (type) {
case 2: TAIL(); return result;
@@ -152,7 +178,7 @@ struct UTF8 {
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 TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define TAIL() COPY(); TRANS(0x70)
Ch c;
COPY();
@@ -160,7 +186,7 @@ struct UTF8 {
return true;
bool result = true;
- switch (GetRange((unsigned char)c)) {
+ switch (GetRange(static_cast<unsigned char>(c))) {
case 2: TAIL(); return result;
case 3: TAIL(); TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result;
@@ -196,12 +222,12 @@ struct UTF8 {
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;
+ typename InputByteStream::Ch c = Take(is);
+ if (static_cast<unsigned char>(c) != 0xEFu) return c;
c = is.Take();
- if ((unsigned char)c != 0xBBu) return c;
+ if (static_cast<unsigned char>(c) != 0xBBu) return c;
c = is.Take();
- if ((unsigned char)c != 0xBFu) return c;
+ if (static_cast<unsigned char>(c) != 0xBFu) return c;
c = is.Take();
return c;
}
@@ -209,13 +235,15 @@ struct UTF8 {
template <typename InputByteStream>
static Ch Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- return is.Take();
+ return static_cast<Ch>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
}
template <typename OutputByteStream>
@@ -255,22 +283,38 @@ struct UTF16 {
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
- os.Put((v & 0x3FF) | 0xDC00);
+ os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
+ }
+ }
+
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(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
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>((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();
+ typename InputStream::Ch c = is.Take();
if (c < 0xD800 || c > 0xDFFF) {
- *codepoint = c;
+ *codepoint = static_cast<unsigned>(c);
return true;
}
else if (c <= 0xDBFF) {
- *codepoint = (c & 0x3FF) << 10;
+ *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
c = is.Take();
- *codepoint |= (c & 0x3FF);
+ *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
*codepoint += 0x10000;
return c >= 0xDC00 && c <= 0xDFFF;
}
@@ -281,8 +325,8 @@ struct UTF16 {
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());
+ typename InputStream::Ch c;
+ os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
if (c < 0xD800 || c > 0xDFFF)
return true;
else if (c <= 0xDBFF) {
@@ -300,28 +344,29 @@ struct UTF16LE : UTF16<CharType> {
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;
+ return static_cast<uint16_t>(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;
+ unsigned c = static_cast<uint8_t>(is.Take());
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ return static_cast<CharType>(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(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
}
};
@@ -332,28 +377,29 @@ struct UTF16BE : UTF16<CharType> {
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;
+ return static_cast<uint16_t>(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;
+ unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<uint8_t>(is.Take());
+ return static_cast<CharType>(c);
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(0xFEu); os.Put(0xFFu);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
}
};
@@ -382,6 +428,13 @@ struct UTF32 {
os.Put(codepoint);
}
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ PutUnsafe(os, codepoint);
+ }
+
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
@@ -406,32 +459,35 @@ struct UTF32LE : UTF32<CharType> {
static CharType TakeBOM(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is);
- return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+ return static_cast<uint32_t>(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;
+ unsigned c = static_cast<uint8_t>(is.Take());
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
+ return static_cast<CharType>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
}
};
@@ -442,32 +498,35 @@ struct UTF32BE : UTF32<CharType> {
static CharType TakeBOM(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is);
- return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+ return static_cast<uint32_t>(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;
+ unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
+ return static_cast<CharType>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(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);
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
}
};
@@ -491,31 +550,37 @@ struct ASCII {
os.Put(static_cast<Ch>(codepoint & 0xFF));
}
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
+ }
+
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
- unsigned char c = static_cast<unsigned char>(is.Take());
+ uint8_t c = static_cast<uint8_t>(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);
+ uint8_t c = static_cast<uint8_t>(is.Take());
+ os.Put(static_cast<typename OutputStream::Ch>(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;
+ uint8_t c = static_cast<uint8_t>(Take(is));
+ return static_cast<Ch>(c);
}
template <typename InputByteStream>
static Ch Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- return is.Take();
+ return static_cast<Ch>(is.Take());
}
template <typename OutputByteStream>
@@ -555,21 +620,28 @@ struct AutoUTF {
#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) {
+ static RAPIDJSON_FORCEINLINE 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 OutputStream>
+ static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
template <typename InputStream>
- RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+ static RAPIDJSON_FORCEINLINE 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) {
+ static RAPIDJSON_FORCEINLINE 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);
@@ -586,7 +658,7 @@ 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) {
+ static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
@@ -594,31 +666,50 @@ struct Transcoder {
return true;
}
+ template<typename InputStream, typename OutputStream>
+ static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::EncodeUnsafe(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) {
+ static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Transcode(is, os); // Since source/target encoding is different, must transcode.
}
};
+// Forward declaration.
+template<typename Stream>
+inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
+
//! 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) {
+ static RAPIDJSON_FORCEINLINE 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) {
+ static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
+ PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ static RAPIDJSON_FORCEINLINE 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)
+#if defined(__GNUC__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP
#endif
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h
index d5f9caab8..2db838bff 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/en.h
@@ -12,11 +12,17 @@
// 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__
+#ifndef RAPIDJSON_ERROR_EN_H_
+#define RAPIDJSON_ERROR_EN_H_
#include "error.h"
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(covered-switch-default)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
//! Maps error code of parsing into error message.
@@ -32,7 +38,7 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
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 kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
@@ -55,11 +61,14 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
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.");
+ default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
RAPIDJSON_NAMESPACE_END
-#endif // RAPIDJSON_ERROR_EN_H__
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#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
index f9094fb95..9311d2f03 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/error/error.h
@@ -12,11 +12,16 @@
// 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__
+#ifndef RAPIDJSON_ERROR_ERROR_H_
+#define RAPIDJSON_ERROR_ERROR_H_
#include "../rapidjson.h"
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
/*! \file error.h */
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
@@ -99,7 +104,9 @@ enum ParseErrorCode {
\see GenericReader::Parse, GenericDocument::Parse
*/
struct ParseResult {
-
+ //!! Unspecified boolean type
+ typedef bool (ParseResult::*BooleanType)() const;
+public:
//! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {}
//! Constructor to set an error.
@@ -110,8 +117,8 @@ struct ParseResult {
//! 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(); }
+ //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
+ operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
//! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; }
@@ -119,6 +126,10 @@ struct ParseResult {
bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
+ bool operator!=(const ParseResult& that) const { return !(*this == that); }
+ bool operator!=(ParseErrorCode code) const { return !(*this == code); }
+ friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
+
//! Reset error code.
void Clear() { Set(kParseErrorNone); }
//! Update error code and offset.
@@ -143,4 +154,8 @@ typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
RAPIDJSON_NAMESPACE_END
-#endif // RAPIDJSON_ERROR_ERROR_H__
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#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
index 3913eb74b..b56ea13b3 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filereadstream.h
@@ -15,9 +15,16 @@
#ifndef RAPIDJSON_FILEREADSTREAM_H_
#define RAPIDJSON_FILEREADSTREAM_H_
-#include "rapidjson.h"
+#include "stream.h"
#include <cstdio>
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(missing-noreturn)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
//! File byte stream for input using fread().
@@ -85,4 +92,8 @@ private:
RAPIDJSON_NAMESPACE_END
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
#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
index afd7e19b8..6378dd60e 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/filewritestream.h
@@ -15,9 +15,14 @@
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
#define RAPIDJSON_FILEWRITESTREAM_H_
-#include "rapidjson.h"
+#include "stream.h"
#include <cstdio>
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(unreachable-code)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
//! Wrapper of C file stream for input using fread().
@@ -92,4 +97,8 @@ inline void PutN(FileWriteStream& stream, char c, size_t n) {
RAPIDJSON_NAMESPACE_END
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/fwd.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/fwd.h
new file mode 100644
index 000000000..e8104e841
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/fwd.h
@@ -0,0 +1,151 @@
+// 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_FWD_H_
+#define RAPIDJSON_FWD_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// encodings.h
+
+template<typename CharType> struct UTF8;
+template<typename CharType> struct UTF16;
+template<typename CharType> struct UTF16BE;
+template<typename CharType> struct UTF16LE;
+template<typename CharType> struct UTF32;
+template<typename CharType> struct UTF32BE;
+template<typename CharType> struct UTF32LE;
+template<typename CharType> struct ASCII;
+template<typename CharType> struct AutoUTF;
+
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder;
+
+// allocators.h
+
+class CrtAllocator;
+
+template <typename BaseAllocator>
+class MemoryPoolAllocator;
+
+// stream.h
+
+template <typename Encoding>
+struct GenericStringStream;
+
+typedef GenericStringStream<UTF8<char> > StringStream;
+
+template <typename Encoding>
+struct GenericInsituStringStream;
+
+typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
+
+// stringbuffer.h
+
+template <typename Encoding, typename Allocator>
+class GenericStringBuffer;
+
+typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
+
+// filereadstream.h
+
+class FileReadStream;
+
+// filewritestream.h
+
+class FileWriteStream;
+
+// memorybuffer.h
+
+template <typename Allocator>
+struct GenericMemoryBuffer;
+
+typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
+
+// memorystream.h
+
+struct MemoryStream;
+
+// reader.h
+
+template<typename Encoding, typename Derived>
+struct BaseReaderHandler;
+
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
+class GenericReader;
+
+typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
+
+// writer.h
+
+template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
+class Writer;
+
+// prettywriter.h
+
+template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
+class PrettyWriter;
+
+// document.h
+
+template <typename Encoding, typename Allocator>
+struct GenericMember;
+
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator;
+
+template<typename CharType>
+struct GenericStringRef;
+
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
+
+template <typename Encoding, typename Allocator, typename StackAllocator>
+class GenericDocument;
+
+typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
+
+// pointer.h
+
+template <typename ValueType, typename Allocator>
+class GenericPointer;
+
+typedef GenericPointer<Value, CrtAllocator> Pointer;
+
+// schema.h
+
+template <typename SchemaDocumentType>
+class IGenericRemoteSchemaDocumentProvider;
+
+template <typename ValueT, typename Allocator>
+class GenericSchemaDocument;
+
+typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
+typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
+
+template <
+ typename SchemaDocumentType,
+ typename OutputHandler,
+ typename StateAllocator>
+class GenericSchemaValidator;
+
+typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSONFWD_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
index 4477cf5d1..9d3e88c99 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/biginteger.h
@@ -240,7 +240,7 @@ private:
uint64_t r = 0;
for (const char* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
- r = r * 10u + (unsigned)(*p - '0');
+ r = r * 10u + static_cast<unsigned>(*p - '0');
}
return r;
}
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h
index 7a55ee31c..29abf8046 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/diyfp.h
@@ -21,7 +21,7 @@
#include "../rapidjson.h"
-#if defined(_MSC_VER) && defined(_M_AMD64)
+#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
#include <intrin.h>
#pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128)
@@ -35,8 +35,13 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
struct DiyFp {
- DiyFp() {}
+ DiyFp() : f(), e() {}
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
@@ -242,6 +247,11 @@ inline DiyFp GetCachedPower10(int exp, int *outExp) {
RAPIDJSON_DIAG_POP
#endif
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
} // namespace internal
RAPIDJSON_NAMESPACE_END
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h
index d04ae21cc..bf2e9b2e5 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/dtoa.h
@@ -29,6 +29,7 @@ namespace internal {
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
#endif
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
@@ -40,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin
}
}
-inline unsigned CountDecimalDigit32(uint32_t n) {
+inline int 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;
@@ -62,7 +63,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
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]
+ int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0;
while (kappa > 0) {
@@ -101,7 +102,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
kappa--;
if (p2 < delta) {
*K += kappa;
- GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast<int>(kappa)]);
+ int index = -kappa;
+ GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0));
return;
}
}
@@ -145,10 +147,10 @@ inline char* WriteExponent(int K, char* buffer) {
return buffer;
}
-inline char* Prettify(char* buffer, int length, int k) {
+inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
- if (length <= kk && kk <= 21) {
+ if (0 <= k && kk <= 21) {
// 1234e7 -> 12340000000
for (int i = length; i < kk; i++)
buffer[i] = '0';
@@ -160,7 +162,16 @@ inline char* Prettify(char* buffer, int length, int k) {
// 1234e-2 -> 12.34
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
buffer[kk] = '.';
- return &buffer[length + 1];
+ if (0 > k + maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[kk + 2]; // Reserve one zero
+ }
+ else
+ return &buffer[length + 1];
}
else if (-6 < kk && kk <= 0) {
// 1234e-6 -> 0.001234
@@ -170,7 +181,23 @@ inline char* Prettify(char* buffer, int length, int k) {
buffer[1] = '.';
for (int i = 2; i < offset; i++)
buffer[i] = '0';
- return &buffer[length + offset];
+ if (length - kk > maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = maxDecimalPlaces + 1; i > 2; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[3]; // Reserve one zero
+ }
+ else
+ return &buffer[length + offset];
+ }
+ else if (kk < -maxDecimalPlaces) {
+ // Truncate to zero
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
}
else if (length == 1) {
// 1e30
@@ -186,7 +213,8 @@ inline char* Prettify(char* buffer, int length, int k) {
}
}
-inline char* dtoa(double value, char* buffer) {
+inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
+ RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
Double d(value);
if (d.IsZero()) {
if (d.Sign())
@@ -203,7 +231,7 @@ inline char* dtoa(double value, char* buffer) {
}
int length, K;
Grisu2(value, buffer, &length, &K);
- return Prettify(buffer, length, K);
+ return Prettify(buffer, length, K, maxDecimalPlaces);
}
}
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h
index 2fdaf54b3..c2684ba2a 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/ieee754.h
@@ -40,6 +40,7 @@ public:
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
+ bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
@@ -47,13 +48,13 @@ public:
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
- static unsigned EffectiveSignificandSize(int order) {
+ static int EffectiveSignificandSize(int order) {
if (order >= -1021)
return 53;
else if (order <= -1074)
return 0;
else
- return (unsigned)order + 1074;
+ return order + 1074;
}
private:
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/regex.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/regex.h
new file mode 100644
index 000000000..e1a2faae5
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/regex.h
@@ -0,0 +1,734 @@
+// 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_REGEX_H_
+#define RAPIDJSON_INTERNAL_REGEX_H_
+
+#include "../allocators.h"
+#include "../stream.h"
+#include "stack.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(implicit-fallthrough)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#if __GNUC__ >= 7
+RAPIDJSON_DIAG_OFF(implicit-fallthrough)
+#endif
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+#ifndef RAPIDJSON_REGEX_VERBOSE
+#define RAPIDJSON_REGEX_VERBOSE 0
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// DecodedStream
+
+template <typename SourceStream, typename Encoding>
+class DecodedStream {
+public:
+ DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
+ unsigned Peek() { return codepoint_; }
+ unsigned Take() {
+ unsigned c = codepoint_;
+ if (c) // No further decoding when '\0'
+ Decode();
+ return c;
+ }
+
+private:
+ void Decode() {
+ if (!Encoding::Decode(ss_, &codepoint_))
+ codepoint_ = 0;
+ }
+
+ SourceStream& ss_;
+ unsigned codepoint_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericRegex
+
+static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
+static const SizeType kRegexInvalidRange = ~SizeType(0);
+
+template <typename Encoding, typename Allocator>
+class GenericRegexSearch;
+
+//! Regular expression engine with subset of ECMAscript grammar.
+/*!
+ Supported regular expression syntax:
+ - \c ab Concatenation
+ - \c a|b Alternation
+ - \c a? Zero or one
+ - \c a* Zero or more
+ - \c a+ One or more
+ - \c a{3} Exactly 3 times
+ - \c a{3,} At least 3 times
+ - \c a{3,5} 3 to 5 times
+ - \c (ab) Grouping
+ - \c ^a At the beginning
+ - \c a$ At the end
+ - \c . Any character
+ - \c [abc] Character classes
+ - \c [a-c] Character class range
+ - \c [a-z0-9_] Character class combination
+ - \c [^abc] Negated character classes
+ - \c [^a-c] Negated character class range
+ - \c [\b] Backspace (U+0008)
+ - \c \\| \\\\ ... Escape characters
+ - \c \\f Form feed (U+000C)
+ - \c \\n Line feed (U+000A)
+ - \c \\r Carriage return (U+000D)
+ - \c \\t Tab (U+0009)
+ - \c \\v Vertical tab (U+000B)
+
+ \note This is a Thompson NFA engine, implemented with reference to
+ Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
+ https://swtch.com/~rsc/regexp/regexp1.html
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericRegex {
+public:
+ typedef Encoding EncodingType;
+ typedef typename Encoding::Ch Ch;
+ template <typename, typename> friend class GenericRegexSearch;
+
+ GenericRegex(const Ch* source, Allocator* allocator = 0) :
+ states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
+ anchorBegin_(), anchorEnd_()
+ {
+ GenericStringStream<Encoding> ss(source);
+ DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
+ Parse(ds);
+ }
+
+ ~GenericRegex() {}
+
+ bool IsValid() const {
+ return root_ != kRegexInvalidState;
+ }
+
+private:
+ enum Operator {
+ kZeroOrOne,
+ kZeroOrMore,
+ kOneOrMore,
+ kConcatenation,
+ kAlternation,
+ kLeftParenthesis
+ };
+
+ static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.'
+ static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
+ static const unsigned kRangeNegationFlag = 0x80000000;
+
+ struct Range {
+ unsigned start; //
+ unsigned end;
+ SizeType next;
+ };
+
+ struct State {
+ SizeType out; //!< Equals to kInvalid for matching state
+ SizeType out1; //!< Equals to non-kInvalid for split
+ SizeType rangeStart;
+ unsigned codepoint;
+ };
+
+ struct Frag {
+ Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
+ SizeType start;
+ SizeType out; //!< link-list of all output states
+ SizeType minIndex;
+ };
+
+ State& GetState(SizeType index) {
+ RAPIDJSON_ASSERT(index < stateCount_);
+ return states_.template Bottom<State>()[index];
+ }
+
+ const State& GetState(SizeType index) const {
+ RAPIDJSON_ASSERT(index < stateCount_);
+ return states_.template Bottom<State>()[index];
+ }
+
+ Range& GetRange(SizeType index) {
+ RAPIDJSON_ASSERT(index < rangeCount_);
+ return ranges_.template Bottom<Range>()[index];
+ }
+
+ const Range& GetRange(SizeType index) const {
+ RAPIDJSON_ASSERT(index < rangeCount_);
+ return ranges_.template Bottom<Range>()[index];
+ }
+
+ template <typename InputStream>
+ void Parse(DecodedStream<InputStream, Encoding>& ds) {
+ Allocator allocator;
+ Stack<Allocator> operandStack(&allocator, 256); // Frag
+ Stack<Allocator> operatorStack(&allocator, 256); // Operator
+ Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
+
+ *atomCountStack.template Push<unsigned>() = 0;
+
+ unsigned codepoint;
+ while (ds.Peek() != 0) {
+ switch (codepoint = ds.Take()) {
+ case '^':
+ anchorBegin_ = true;
+ break;
+
+ case '$':
+ anchorEnd_ = true;
+ break;
+
+ case '|':
+ while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+ *operatorStack.template Push<Operator>() = kAlternation;
+ *atomCountStack.template Top<unsigned>() = 0;
+ break;
+
+ case '(':
+ *operatorStack.template Push<Operator>() = kLeftParenthesis;
+ *atomCountStack.template Push<unsigned>() = 0;
+ break;
+
+ case ')':
+ while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+ if (operatorStack.Empty())
+ return;
+ operatorStack.template Pop<Operator>(1);
+ atomCountStack.template Pop<unsigned>(1);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '?':
+ if (!Eval(operandStack, kZeroOrOne))
+ return;
+ break;
+
+ case '*':
+ if (!Eval(operandStack, kZeroOrMore))
+ return;
+ break;
+
+ case '+':
+ if (!Eval(operandStack, kOneOrMore))
+ return;
+ break;
+
+ case '{':
+ {
+ unsigned n, m;
+ if (!ParseUnsigned(ds, &n))
+ return;
+
+ if (ds.Peek() == ',') {
+ ds.Take();
+ if (ds.Peek() == '}')
+ m = kInfinityQuantifier;
+ else if (!ParseUnsigned(ds, &m) || m < n)
+ return;
+ }
+ else
+ m = n;
+
+ if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
+ return;
+ ds.Take();
+ }
+ break;
+
+ case '.':
+ PushOperand(operandStack, kAnyCharacterClass);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '[':
+ {
+ SizeType range;
+ if (!ParseRange(ds, &range))
+ return;
+ SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
+ GetState(s).rangeStart = range;
+ *operandStack.template Push<Frag>() = Frag(s, s, s);
+ }
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '\\': // Escape character
+ if (!CharacterEscape(ds, &codepoint))
+ return; // Unsupported escape character
+ // fall through to default
+
+ default: // Pattern character
+ PushOperand(operandStack, codepoint);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ }
+ }
+
+ while (!operatorStack.Empty())
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+
+ // Link the operand to matching state.
+ if (operandStack.GetSize() == sizeof(Frag)) {
+ Frag* e = operandStack.template Pop<Frag>(1);
+ Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
+ root_ = e->start;
+
+#if RAPIDJSON_REGEX_VERBOSE
+ printf("root: %d\n", root_);
+ for (SizeType i = 0; i < stateCount_ ; i++) {
+ State& s = GetState(i);
+ printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
+ }
+ printf("\n");
+#endif
+ }
+ }
+
+ SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
+ State* s = states_.template Push<State>();
+ s->out = out;
+ s->out1 = out1;
+ s->codepoint = codepoint;
+ s->rangeStart = kRegexInvalidRange;
+ return stateCount_++;
+ }
+
+ void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
+ SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
+ *operandStack.template Push<Frag>() = Frag(s, s, s);
+ }
+
+ void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
+ if (*atomCountStack.template Top<unsigned>())
+ *operatorStack.template Push<Operator>() = kConcatenation;
+ (*atomCountStack.template Top<unsigned>())++;
+ }
+
+ SizeType Append(SizeType l1, SizeType l2) {
+ SizeType old = l1;
+ while (GetState(l1).out != kRegexInvalidState)
+ l1 = GetState(l1).out;
+ GetState(l1).out = l2;
+ return old;
+ }
+
+ void Patch(SizeType l, SizeType s) {
+ for (SizeType next; l != kRegexInvalidState; l = next) {
+ next = GetState(l).out;
+ GetState(l).out = s;
+ }
+ }
+
+ bool Eval(Stack<Allocator>& operandStack, Operator op) {
+ switch (op) {
+ case kConcatenation:
+ RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
+ {
+ Frag e2 = *operandStack.template Pop<Frag>(1);
+ Frag e1 = *operandStack.template Pop<Frag>(1);
+ Patch(e1.out, e2.start);
+ *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
+ }
+ return true;
+
+ case kAlternation:
+ if (operandStack.GetSize() >= sizeof(Frag) * 2) {
+ Frag e2 = *operandStack.template Pop<Frag>(1);
+ Frag e1 = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(e1.start, e2.start, 0);
+ *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
+ return true;
+ }
+ return false;
+
+ case kZeroOrOne:
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
+ return true;
+ }
+ return false;
+
+ case kZeroOrMore:
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ Patch(e.out, s);
+ *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
+ return true;
+ }
+ return false;
+
+ default:
+ RAPIDJSON_ASSERT(op == kOneOrMore);
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ Patch(e.out, s);
+ *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
+ RAPIDJSON_ASSERT(n <= m);
+ RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
+
+ if (n == 0) {
+ if (m == 0) // a{0} not support
+ return false;
+ else if (m == kInfinityQuantifier)
+ Eval(operandStack, kZeroOrMore); // a{0,} -> a*
+ else {
+ Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
+ for (unsigned i = 0; i < m - 1; i++)
+ CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
+ for (unsigned i = 0; i < m - 1; i++)
+ Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
+ }
+ return true;
+ }
+
+ for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
+ CloneTopOperand(operandStack);
+
+ if (m == kInfinityQuantifier)
+ Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
+ else if (m > n) {
+ CloneTopOperand(operandStack); // a{3,5} -> a a a a
+ Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
+ for (unsigned i = n; i < m - 1; i++)
+ CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
+ for (unsigned i = n; i < m; i++)
+ Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
+ }
+
+ for (unsigned i = 0; i < n - 1; i++)
+ Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
+
+ return true;
+ }
+
+ static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
+
+ void CloneTopOperand(Stack<Allocator>& operandStack) {
+ const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
+ SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
+ State* s = states_.template Push<State>(count);
+ memcpy(s, &GetState(src.minIndex), count * sizeof(State));
+ for (SizeType j = 0; j < count; j++) {
+ if (s[j].out != kRegexInvalidState)
+ s[j].out += count;
+ if (s[j].out1 != kRegexInvalidState)
+ s[j].out1 += count;
+ }
+ *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
+ stateCount_ += count;
+ }
+
+ template <typename InputStream>
+ bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
+ unsigned r = 0;
+ if (ds.Peek() < '0' || ds.Peek() > '9')
+ return false;
+ while (ds.Peek() >= '0' && ds.Peek() <= '9') {
+ if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
+ return false; // overflow
+ r = r * 10 + (ds.Take() - '0');
+ }
+ *u = r;
+ return true;
+ }
+
+ template <typename InputStream>
+ bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
+ bool isBegin = true;
+ bool negate = false;
+ int step = 0;
+ SizeType start = kRegexInvalidRange;
+ SizeType current = kRegexInvalidRange;
+ unsigned codepoint;
+ while ((codepoint = ds.Take()) != 0) {
+ if (isBegin) {
+ isBegin = false;
+ if (codepoint == '^') {
+ negate = true;
+ continue;
+ }
+ }
+
+ switch (codepoint) {
+ case ']':
+ if (start == kRegexInvalidRange)
+ return false; // Error: nothing inside []
+ if (step == 2) { // Add trailing '-'
+ SizeType r = NewRange('-');
+ RAPIDJSON_ASSERT(current != kRegexInvalidRange);
+ GetRange(current).next = r;
+ }
+ if (negate)
+ GetRange(start).start |= kRangeNegationFlag;
+ *range = start;
+ return true;
+
+ case '\\':
+ if (ds.Peek() == 'b') {
+ ds.Take();
+ codepoint = 0x0008; // Escape backspace character
+ }
+ else if (!CharacterEscape(ds, &codepoint))
+ return false;
+ // fall through to default
+
+ default:
+ switch (step) {
+ case 1:
+ if (codepoint == '-') {
+ step++;
+ break;
+ }
+ // fall through to step 0 for other characters
+
+ case 0:
+ {
+ SizeType r = NewRange(codepoint);
+ if (current != kRegexInvalidRange)
+ GetRange(current).next = r;
+ if (start == kRegexInvalidRange)
+ start = r;
+ current = r;
+ }
+ step = 1;
+ break;
+
+ default:
+ RAPIDJSON_ASSERT(step == 2);
+ GetRange(current).end = codepoint;
+ step = 0;
+ }
+ }
+ }
+ return false;
+ }
+
+ SizeType NewRange(unsigned codepoint) {
+ Range* r = ranges_.template Push<Range>();
+ r->start = r->end = codepoint;
+ r->next = kRegexInvalidRange;
+ return rangeCount_++;
+ }
+
+ template <typename InputStream>
+ bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
+ unsigned codepoint;
+ switch (codepoint = ds.Take()) {
+ case '^':
+ case '$':
+ case '|':
+ case '(':
+ case ')':
+ case '?':
+ case '*':
+ case '+':
+ case '.':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case '\\':
+ *escapedCodepoint = codepoint; return true;
+ case 'f': *escapedCodepoint = 0x000C; return true;
+ case 'n': *escapedCodepoint = 0x000A; return true;
+ case 'r': *escapedCodepoint = 0x000D; return true;
+ case 't': *escapedCodepoint = 0x0009; return true;
+ case 'v': *escapedCodepoint = 0x000B; return true;
+ default:
+ return false; // Unsupported escape character
+ }
+ }
+
+ Stack<Allocator> states_;
+ Stack<Allocator> ranges_;
+ SizeType root_;
+ SizeType stateCount_;
+ SizeType rangeCount_;
+
+ static const unsigned kInfinityQuantifier = ~0u;
+
+ // For SearchWithAnchoring()
+ bool anchorBegin_;
+ bool anchorEnd_;
+};
+
+template <typename RegexType, typename Allocator = CrtAllocator>
+class GenericRegexSearch {
+public:
+ typedef typename RegexType::EncodingType Encoding;
+ typedef typename Encoding::Ch Ch;
+
+ GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
+ regex_(regex), allocator_(allocator), ownAllocator_(0),
+ state0_(allocator, 0), state1_(allocator, 0), stateSet_()
+ {
+ RAPIDJSON_ASSERT(regex_.IsValid());
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
+ stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
+ state0_.template Reserve<SizeType>(regex_.stateCount_);
+ state1_.template Reserve<SizeType>(regex_.stateCount_);
+ }
+
+ ~GenericRegexSearch() {
+ Allocator::Free(stateSet_);
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ template <typename InputStream>
+ bool Match(InputStream& is) {
+ return SearchWithAnchoring(is, true, true);
+ }
+
+ bool Match(const Ch* s) {
+ GenericStringStream<Encoding> is(s);
+ return Match(is);
+ }
+
+ template <typename InputStream>
+ bool Search(InputStream& is) {
+ return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
+ }
+
+ bool Search(const Ch* s) {
+ GenericStringStream<Encoding> is(s);
+ return Search(is);
+ }
+
+private:
+ typedef typename RegexType::State State;
+ typedef typename RegexType::Range Range;
+
+ template <typename InputStream>
+ bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
+ DecodedStream<InputStream, Encoding> ds(is);
+
+ state0_.Clear();
+ Stack<Allocator> *current = &state0_, *next = &state1_;
+ const size_t stateSetSize = GetStateSetSize();
+ std::memset(stateSet_, 0, stateSetSize);
+
+ bool matched = AddState(*current, regex_.root_);
+ unsigned codepoint;
+ while (!current->Empty() && (codepoint = ds.Take()) != 0) {
+ std::memset(stateSet_, 0, stateSetSize);
+ next->Clear();
+ matched = false;
+ for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
+ const State& sr = regex_.GetState(*s);
+ if (sr.codepoint == codepoint ||
+ sr.codepoint == RegexType::kAnyCharacterClass ||
+ (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
+ {
+ matched = AddState(*next, sr.out) || matched;
+ if (!anchorEnd && matched)
+ return true;
+ }
+ if (!anchorBegin)
+ AddState(*next, regex_.root_);
+ }
+ internal::Swap(current, next);
+ }
+
+ return matched;
+ }
+
+ size_t GetStateSetSize() const {
+ return (regex_.stateCount_ + 31) / 32 * 4;
+ }
+
+ // Return whether the added states is a match state
+ bool AddState(Stack<Allocator>& l, SizeType index) {
+ RAPIDJSON_ASSERT(index != kRegexInvalidState);
+
+ const State& s = regex_.GetState(index);
+ if (s.out1 != kRegexInvalidState) { // Split
+ bool matched = AddState(l, s.out);
+ return AddState(l, s.out1) || matched;
+ }
+ else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
+ stateSet_[index >> 5] |= (1u << (index & 31));
+ *l.template PushUnsafe<SizeType>() = index;
+ }
+ return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
+ }
+
+ bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
+ bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
+ while (rangeIndex != kRegexInvalidRange) {
+ const Range& r = regex_.GetRange(rangeIndex);
+ if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
+ return yes;
+ rangeIndex = r.next;
+ }
+ return !yes;
+ }
+
+ const RegexType& regex_;
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ Stack<Allocator> state0_;
+ Stack<Allocator> state1_;
+ uint32_t* stateSet_;
+};
+
+typedef GenericRegex<UTF8<> > Regex;
+typedef GenericRegexSearch<Regex> RegexSearch;
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_REGEX_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h
index 344785dcd..5c5398c35 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/stack.h
@@ -15,9 +15,14 @@
#ifndef RAPIDJSON_INTERNAL_STACK_H_
#define RAPIDJSON_INTERNAL_STACK_H_
-#include "../rapidjson.h"
+#include "../allocators.h"
#include "swap.h"
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@@ -33,7 +38,6 @@ 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
@@ -108,11 +112,22 @@ public:
// 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) {
+ RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
// Expand the stack if needed
- if (stackTop_ + sizeof(T) * count >= stackEnd_)
+ if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
Expand<T>(count);
+ }
+
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+ Reserve<T>(count);
+ return PushUnsafe<T>(count);
+ }
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
+ RAPIDJSON_ASSERT(stackTop_);
+ RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
T* ret = reinterpret_cast<T*>(stackTop_);
stackTop_ += sizeof(T) * count;
return ret;
@@ -132,7 +147,22 @@ public:
}
template<typename T>
- T* Bottom() { return (T*)stack_; }
+ const T* Top() const {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ T* End() { return reinterpret_cast<T*>(stackTop_); }
+
+ template<typename T>
+ const T* End() const { return reinterpret_cast<T*>(stackTop_); }
+
+ template<typename T>
+ T* Bottom() { return reinterpret_cast<T*>(stack_); }
+
+ template<typename T>
+ const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
bool HasAllocator() const {
return allocator_ != 0;
@@ -142,6 +172,7 @@ public:
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_); }
@@ -153,7 +184,7 @@ private:
size_t newCapacity;
if (stack_ == 0) {
if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
newCapacity = initialCapacity_;
} else {
newCapacity = GetCapacity();
@@ -168,7 +199,7 @@ private:
void Resize(size_t newCapacity) {
const size_t size = GetSize(); // Backup the current size
- stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
+ stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
stackTop_ = stack_ + size;
stackEnd_ = stack_ + newCapacity;
}
@@ -193,4 +224,8 @@ private:
} // namespace internal
RAPIDJSON_NAMESPACE_END
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
#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
index 84405065a..226439a76 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strfunc.h
@@ -15,7 +15,8 @@
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
#define RAPIDJSON_INTERNAL_STRFUNC_H_
-#include "../rapidjson.h"
+#include "../stream.h"
+#include <cwchar>
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@@ -28,11 +29,40 @@ namespace internal {
*/
template <typename Ch>
inline SizeType StrLen(const Ch* s) {
+ RAPIDJSON_ASSERT(s != 0);
const Ch* p = s;
while (*p) ++p;
return SizeType(p - s);
}
+template <>
+inline SizeType StrLen(const char* s) {
+ return SizeType(std::strlen(s));
+}
+
+template <>
+inline SizeType StrLen(const wchar_t* s) {
+ return SizeType(std::wcslen(s));
+}
+
+//! Returns number of code points in a encoded string.
+template<typename Encoding>
+bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
+ RAPIDJSON_ASSERT(s != 0);
+ RAPIDJSON_ASSERT(outCount != 0);
+ GenericStringStream<Encoding> is(s);
+ const typename Encoding::Ch* end = s + length;
+ SizeType count = 0;
+ while (is.src_ < end) {
+ unsigned codepoint;
+ if (!Encoding::Decode(is, &codepoint))
+ return false;
+ count++;
+ }
+ *outCount = count;
+ return true;
+}
+
} // namespace internal
RAPIDJSON_NAMESPACE_END
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h
index a1b821197..adf49e349 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/strtod.h
@@ -15,7 +15,6 @@
#ifndef RAPIDJSON_STRTOD_
#define RAPIDJSON_STRTOD_
-#include "../rapidjson.h"
#include "ieee754.h"
#include "biginteger.h"
#include "diyfp.h"
@@ -141,15 +140,15 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
significand++;
size_t remaining = length - i;
- const unsigned kUlpShift = 3;
- const unsigned kUlp = 1 << kUlpShift;
- int error = (remaining == 0) ? 0 : kUlp / 2;
+ const int kUlpShift = 3;
+ const int kUlp = 1 << kUlpShift;
+ int64_t error = (remaining == 0) ? 0 : kUlp / 2;
DiyFp v(significand, 0);
v = v.Normalize();
error <<= -v.e;
- const int dExp = (int)decimalPosition - (int)i + exp;
+ const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
int actualExp;
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
@@ -178,17 +177,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
v = v.Normalize();
error <<= oldExp - v.e;
- const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
- unsigned precisionSize = 64 - effectiveSignificandSize;
+ const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
+ int precisionSize = 64 - effectiveSignificandSize;
if (precisionSize + kUlpShift >= 64) {
- unsigned scaleExp = (precisionSize + kUlpShift) - 63;
+ int scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp;
v.e += scaleExp;
- error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
+ error = (error >> scaleExp) + 1 + kUlp;
precisionSize -= scaleExp;
}
- DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
+ DiyFp rounded(v.f >> precisionSize, v.e + 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)) {
@@ -206,7 +205,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
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;
+ const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
Double a(approx);
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
if (cmp < 0)
@@ -246,8 +245,8 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
// Trim right-most digits
const int kMaxDecimalDigit = 780;
- if ((int)length > kMaxDecimalDigit) {
- int delta = (int(length) - kMaxDecimalDigit);
+ if (static_cast<int>(length) > kMaxDecimalDigit) {
+ int delta = (static_cast<int>(length) - kMaxDecimalDigit);
exp += delta;
decimalPosition -= static_cast<unsigned>(delta);
length = kMaxDecimalDigit;
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h
index 0590921f1..666e49f97 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/internal/swap.h
@@ -17,6 +17,11 @@
#include "../rapidjson.h"
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@@ -34,4 +39,8 @@ inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
} // namespace internal
RAPIDJSON_NAMESPACE_END
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
#endif // RAPIDJSON_INTERNAL_SWAP_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/istreamwrapper.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/istreamwrapper.h
new file mode 100644
index 000000000..8639c8c3c
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/istreamwrapper.h
@@ -0,0 +1,115 @@
+// 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_ISTREAMWRAPPER_H_
+#define RAPIDJSON_ISTREAMWRAPPER_H_
+
+#include "stream.h"
+#include <iosfwd>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
+/*!
+ The classes can be wrapped including but not limited to:
+
+ - \c std::istringstream
+ - \c std::stringstream
+ - \c std::wistringstream
+ - \c std::wstringstream
+ - \c std::ifstream
+ - \c std::fstream
+ - \c std::wifstream
+ - \c std::wfstream
+
+ \tparam StreamType Class derived from \c std::basic_istream.
+*/
+
+template <typename StreamType>
+class BasicIStreamWrapper {
+public:
+ typedef typename StreamType::char_type Ch;
+ BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
+
+ Ch Peek() const {
+ typename StreamType::int_type c = stream_.peek();
+ return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : static_cast<Ch>('\0');
+ }
+
+ Ch Take() {
+ typename StreamType::int_type c = stream_.get();
+ if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
+ count_++;
+ return static_cast<Ch>(c);
+ }
+ else
+ return '\0';
+ }
+
+ // tellg() may return -1 when failed. So we count by ourself.
+ size_t Tell() const { return count_; }
+
+ 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 {
+ RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
+ int i;
+ bool hasError = false;
+ for (i = 0; i < 4; ++i) {
+ typename StreamType::int_type c = stream_.get();
+ if (c == StreamType::traits_type::eof()) {
+ hasError = true;
+ stream_.clear();
+ break;
+ }
+ peekBuffer_[i] = static_cast<Ch>(c);
+ }
+ for (--i; i >= 0; --i)
+ stream_.putback(peekBuffer_[i]);
+ return !hasError ? peekBuffer_ : 0;
+ }
+
+private:
+ BasicIStreamWrapper(const BasicIStreamWrapper&);
+ BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
+
+ StreamType& stream_;
+ size_t count_; //!< Number of characters read. Note:
+ mutable Ch peekBuffer_[4];
+};
+
+typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
+typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
+
+#if defined(__clang__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ISTREAMWRAPPER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h
index 2484b2185..39bee1dec 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorybuffer.h
@@ -15,7 +15,7 @@
#ifndef RAPIDJSON_MEMORYBUFFER_H_
#define RAPIDJSON_MEMORYBUFFER_H_
-#include "rapidjson.h"
+#include "stream.h"
#include "internal/stack.h"
RAPIDJSON_NAMESPACE_BEGIN
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h
index 99feae5d7..1d71d8a4f 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/memorystream.h
@@ -15,7 +15,13 @@
#ifndef RAPIDJSON_MEMORYSTREAM_H_
#define RAPIDJSON_MEMORYSTREAM_H_
-#include "rapidjson.h"
+#include "stream.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(missing-noreturn)
+#endif
RAPIDJSON_NAMESPACE_BEGIN
@@ -36,8 +42,8 @@ struct MemoryStream {
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_++; }
+ Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
+ Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
@@ -58,4 +64,8 @@ struct MemoryStream {
RAPIDJSON_NAMESPACE_END
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
#endif // RAPIDJSON_MEMORYBUFFER_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
index a26fff4bf..3d4477b9a 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h
@@ -89,14 +89,14 @@
#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:
+// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler would give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#ifdef __cplusplus
+#if defined(__cplusplus) && !defined(_M_ARM)
extern "C" {
#endif
# include <wchar.h>
-#ifdef __cplusplus
+#if defined(__cplusplus) && !defined(_M_ARM)
}
#endif
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/ostreamwrapper.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/ostreamwrapper.h
new file mode 100644
index 000000000..6f4667c08
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/ostreamwrapper.h
@@ -0,0 +1,81 @@
+// 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_OSTREAMWRAPPER_H_
+#define RAPIDJSON_OSTREAMWRAPPER_H_
+
+#include "stream.h"
+#include <iosfwd>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
+/*!
+ The classes can be wrapped including but not limited to:
+
+ - \c std::ostringstream
+ - \c std::stringstream
+ - \c std::wpstringstream
+ - \c std::wstringstream
+ - \c std::ifstream
+ - \c std::fstream
+ - \c std::wofstream
+ - \c std::wfstream
+
+ \tparam StreamType Class derived from \c std::basic_ostream.
+*/
+
+template <typename StreamType>
+class BasicOStreamWrapper {
+public:
+ typedef typename StreamType::char_type Ch;
+ BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
+
+ void Put(Ch c) {
+ stream_.put(c);
+ }
+
+ void Flush() {
+ stream_.flush();
+ }
+
+ // 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:
+ BasicOStreamWrapper(const BasicOStreamWrapper&);
+ BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
+
+ StreamType& stream_;
+};
+
+typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
+typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_OSTREAMWRAPPER_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h
index 5d2aa8d63..0f377efec 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/pointer.h
@@ -18,6 +18,16 @@
#include "document.h"
#include "internal/itoa.h"
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(switch-enum)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
@@ -71,7 +81,7 @@ 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
+ typedef typename ValueType::Ch Ch; //!< Character type from Value
//! A token is the basic units of internal representation.
/*!
@@ -96,7 +106,7 @@ public:
//@{
//! Default constructor.
- GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+ GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
//! Constructor that parses a string or URI fragment representation.
/*!
@@ -155,7 +165,7 @@ public:
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) {
+ GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs;
}
@@ -230,7 +240,7 @@ public:
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);
+ return Append(name, internal::StrLen(name), allocator);
}
#if RAPIDJSON_HAS_STDSTRING
@@ -253,17 +263,18 @@ public:
*/
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;
+ char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
+ SizeType length = static_cast<SizeType>(end - buffer);
buffer[length] = '\0';
if (sizeof(Ch) == 1) {
- Token token = { (Ch*)buffer, length, index };
+ Token token = { reinterpret_cast<Ch*>(buffer), length, index };
return Append(token, allocator);
}
else {
Ch name[21];
for (size_t i = 0; i <= length; i++)
- name[i] = buffer[i];
+ name[i] = static_cast<Ch>(buffer[i]);
Token token = { name, length, index };
return Append(token, allocator);
}
@@ -271,7 +282,7 @@ public:
//! Append a token by value, and return a new Pointer
/*!
- \param value Value (either Uint or String) to be appended.
+ \param token token to be appended.
\param allocator Allocator for the newly return Pointer.
\return A new Pointer with appended token.
*/
@@ -299,6 +310,9 @@ public:
//@}
+ //! Get the allocator of this pointer.
+ Allocator& GetAllocator() { return *allocator_; }
+
//!@name Tokens
//@{
@@ -390,7 +404,7 @@ public:
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->PushBack(ValueType().Move(), allocator);
v = &((*v)[v->Size() - 1]);
exist = false;
}
@@ -408,7 +422,7 @@ public:
if (t->index >= v->Size()) {
v->Reserve(t->index + 1, allocator);
while (t->index >= v->Size())
- v->PushBack(Value().Move(), allocator);
+ v->PushBack(ValueType().Move(), allocator);
exist = false;
}
v = &((*v)[t->index]);
@@ -416,7 +430,7 @@ public:
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->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
exist = false;
}
@@ -435,7 +449,6 @@ public:
//! 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.
*/
@@ -452,9 +465,18 @@ public:
//! 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.
+ \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
\return Pointer to the value if it can be resolved. Otherwise null.
+
+ \note
+ There are only 3 situations when a value cannot be resolved:
+ 1. A value in the path is not an array nor object.
+ 2. An object value does not contain the token.
+ 3. A token is out of range of an array value.
+
+ Use unresolvedTokenIndex to retrieve the token index.
*/
- ValueType* Get(ValueType& root) const {
+ ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root;
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
@@ -463,18 +485,23 @@ public:
{
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
if (m == v->MemberEnd())
- return 0;
+ break;
v = &m->value;
}
- break;
+ continue;
case kArrayType:
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
- return 0;
+ break;
v = &((*v)[t->index]);
- break;
+ continue;
default:
- return 0;
+ break;
}
+
+ // Error: unresolved token
+ if (unresolvedTokenIndex)
+ *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
+ return 0;
}
return v;
}
@@ -484,7 +511,9 @@ public:
\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)); }
+ const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
+ return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
+ }
//@}
@@ -525,7 +554,7 @@ public:
//! 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
+ \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&))
@@ -555,7 +584,7 @@ public:
//! 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
+ \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&))
@@ -601,7 +630,7 @@ public:
//! 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
+ \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&))
@@ -637,7 +666,7 @@ public:
//! 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
+ \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&))
@@ -729,7 +758,7 @@ private:
*/
Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
if (!allocator_) // allocator is independently owned.
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ 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)
@@ -738,8 +767,12 @@ private:
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));
+ if (rhs.tokenCount_ > 0) {
+ std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
+ }
+ if (nameBufferSize > 0) {
+ std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
+ }
// Adjust pointers to name buffer
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
@@ -759,11 +792,13 @@ private:
}
//! Parse a JSON String or its URI fragment representation into tokens.
+#ifndef __clang__ // -Wdocumentation
/*!
\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.
*/
+#endif
void Parse(const Ch* source, size_t length) {
RAPIDJSON_ASSERT(source != NULL);
RAPIDJSON_ASSERT(nameBuffer_ == 0);
@@ -771,7 +806,7 @@ private:
// Create own allocator if user did not supply.
if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
// Count number of '/' as tokenCount
tokenCount_ = 0;
@@ -857,7 +892,7 @@ private:
*name++ = c;
}
- token->length = name - token->name;
+ token->length = static_cast<SizeType>(name - token->name);
if (token->length == 0)
isNumber = false;
*name++ = '\0'; // Null terminator
@@ -944,6 +979,8 @@ private:
*/
class PercentDecodeStream {
public:
+ typedef typename ValueType::Ch Ch;
+
//! Constructor
/*!
\param source Start of the stream
@@ -959,11 +996,11 @@ private:
src_++;
Ch c = 0;
for (int j = 0; j < 2; j++) {
- c <<= 4;
+ c = static_cast<Ch>(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;
+ if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
+ else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
+ else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
else {
valid_ = false;
return 0;
@@ -973,7 +1010,7 @@ private:
return c;
}
- size_t Tell() const { return src_ - head_; }
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
bool IsValid() const { return valid_; }
private:
@@ -992,8 +1029,8 @@ private:
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]);
+ os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
+ os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
}
private:
OutputStream& os_;
@@ -1041,23 +1078,23 @@ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, c
//////////////////////////////////////////////////////////////////////////////
template <typename T>
-typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
- return pointer.Get(root);
+typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
+ return pointer.Get(root, unresolvedTokenIndex);
}
template <typename T>
-const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer) {
- return pointer.Get(root);
+const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
+ return pointer.Get(root, unresolvedTokenIndex);
}
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);
+typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
}
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);
+const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1310,4 +1347,12 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
RAPIDJSON_NAMESPACE_END
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
#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
index 416dd492e..98dfb3060 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/prettywriter.h
@@ -22,8 +22,21 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
+//! Combination of PrettyWriter format flags.
+/*! \see PrettyWriter::SetFormatOptions
+ */
+enum PrettyFormatOptions {
+ kFormatDefault = 0, //!< Default pretty formatting.
+ kFormatSingleLineArray = 1 //!< Format arrays on a single line.
+};
+
//! Writer with indentation and spacing.
/*!
\tparam OutputStream Type of ouptut os.
@@ -31,10 +44,10 @@ RAPIDJSON_NAMESPACE_BEGIN
\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> {
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public:
- typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+ typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
typedef typename Base::Ch Ch;
//! Constructor
@@ -42,8 +55,17 @@ public:
\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) {}
+ explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
+
+
+ explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ PrettyWriter(PrettyWriter&& rhs) :
+ Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
+#endif
//! Set custom indentation.
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
@@ -57,6 +79,14 @@ public:
return *this;
}
+ //! Set pretty writer formatting options.
+ /*! \param options Formatting options.
+ */
+ PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
+ formatOptions_ = options;
+ return *this;
+ }
+
/*! @name Implementation of Handler
\see Handler
*/
@@ -70,7 +100,15 @@ public:
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
+ bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
+ RAPIDJSON_ASSERT(str != 0);
+ (void)copy;
+ PrettyPrefix(kNumberType);
+ return Base::WriteString(str, length);
+ }
+
bool String(const Ch* str, SizeType length, bool copy = false) {
+ RAPIDJSON_ASSERT(str != 0);
(void)copy;
PrettyPrefix(kStringType);
return Base::WriteString(str, length);
@@ -89,11 +127,19 @@ public:
}
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool Key(const std::basic_string<Ch>& str) {
+ return Key(str.data(), SizeType(str.size()));
+ }
+#endif
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);
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
+ RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
+ RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
+
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
if (!empty) {
@@ -104,7 +150,7 @@ public:
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
- Base::os_->Flush();
+ Base::Flush();
return true;
}
@@ -120,7 +166,7 @@ public:
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) {
+ if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
Base::os_->Put('\n');
WriteIndent();
}
@@ -128,7 +174,7 @@ public:
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
- Base::os_->Flush();
+ Base::Flush();
return true;
}
@@ -142,6 +188,22 @@ public:
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
//@}
+
+ //! Write a raw JSON value.
+ /*!
+ For user to write a stringified JSON as a value.
+
+ \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
+ \param length Length of the json.
+ \param type Type of the root of json.
+ \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
+ */
+ bool RawValue(const Ch* json, size_t length, Type type) {
+ RAPIDJSON_ASSERT(json != 0);
+ PrettyPrefix(type);
+ return Base::WriteRawValue(json, length);
+ }
+
protected:
void PrettyPrefix(Type type) {
(void)type;
@@ -151,11 +213,14 @@ protected:
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');
+ if (formatOptions_ & kFormatSingleLineArray)
+ Base::os_->Put(' ');
}
- else
+
+ if (!(formatOptions_ & kFormatSingleLineArray)) {
Base::os_->Put('\n');
- WriteIndent();
+ WriteIndent();
+ }
}
else { // in object
if (level->valueCount > 0) {
@@ -186,11 +251,12 @@ protected:
void WriteIndent() {
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
- PutN(*Base::os_, indentChar_, count);
+ PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
}
Ch indentChar_;
unsigned indentCharCount_;
+ PrettyFormatOptions formatOptions_;
private:
// Prohibit copy constructor & assignment operator.
@@ -200,6 +266,10 @@ private:
RAPIDJSON_NAMESPACE_END
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h
index b83f8e22f..5716fdc06 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/rapidjson.h
@@ -49,6 +49,11 @@
// token stringification
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
#define RAPIDJSON_DO_STRINGIFY(x) #x
+
+// token concatenation
+#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
//!@endcond
/*! \def RAPIDJSON_MAJOR_VERSION
@@ -68,8 +73,8 @@
\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_MINOR_VERSION 1
+#define RAPIDJSON_PATCH_VERSION 0
#define RAPIDJSON_VERSION_STRING \
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
@@ -120,6 +125,31 @@
#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
+
+///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_NO_INT64DEFINE
/*! \def RAPIDJSON_NO_INT64DEFINE
@@ -134,7 +164,7 @@
*/
#ifndef RAPIDJSON_NO_INT64DEFINE
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
#include "msinttypes/stdint.h"
#include "msinttypes/inttypes.h"
#else
@@ -153,9 +183,9 @@
#ifndef RAPIDJSON_FORCEINLINE
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#if defined(_MSC_VER) && !defined(NDEBUG)
+#if defined(_MSC_VER) && defined(NDEBUG)
#define RAPIDJSON_FORCEINLINE __forceinline
-#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
+#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
#else
#define RAPIDJSON_FORCEINLINE
@@ -211,6 +241,8 @@
# 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(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
# define RAPIDJSON_ENDIAN
# else
@@ -223,7 +255,7 @@
//! Whether using 64-bit architecture
#ifndef RAPIDJSON_64BIT
-#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__)
+#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
#define RAPIDJSON_64BIT 1
#else
#define RAPIDJSON_64BIT 0
@@ -238,7 +270,8 @@
\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.
+ alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
+ User can customize by defining the RAPIDJSON_ALIGN function macro.
*/
#ifndef RAPIDJSON_ALIGN
#if RAPIDJSON_64BIT == 1
@@ -262,17 +295,47 @@
#endif
///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+// RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+//! Use only lower 48-bit address for some pointers.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+
+ This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
+ The higher 16-bit can be used for storing other data.
+ \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
+*/
+#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
+#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
+#else
+#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
+#endif
+#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
+#if RAPIDJSON_64BIT != 1
+#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
+#endif
+#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
+#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
+#else
+#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
+#define RAPIDJSON_GETPOINTER(type, p) (p)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD
/*! \def RAPIDJSON_SIMD
\ingroup RAPIDJSON_CONFIG
- \brief Enable SSE2/SSE4.2 optimization.
+ \brief Enable SSE2/SSE4.2/Neon optimization.
RapidJSON supports optimized implementations for some parsing operations
- based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
- processors.
+ based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
+ or ARM compatible processors.
- To enable these optimizations, two different symbols can be defined;
+ To enable these optimizations, three different symbols can be defined;
\code
// Enable SSE2 optimization.
#define RAPIDJSON_SSE2
@@ -281,13 +344,17 @@
#define RAPIDJSON_SSE42
\endcode
- \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+ // Enable ARM Neon optimization.
+ #define RAPIDJSON_NEON
+ \endcode
+
+ \c RAPIDJSON_SSE42 takes precedence over SSE2, 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)
+ || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
#define RAPIDJSON_SIMD
#endif
@@ -347,25 +414,33 @@ RAPIDJSON_NAMESPACE_END
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_STATIC_ASSERT
-// Adopt from boost
+// Prefer C++11 static_assert, if available
#ifndef RAPIDJSON_STATIC_ASSERT
+#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
+#define RAPIDJSON_STATIC_ASSERT(x) \
+ static_assert(x, RAPIDJSON_STRINGIFY(x))
+#endif // C++11
+#endif // RAPIDJSON_STATIC_ASSERT
+
+// Adopt C++03 implementation from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+#ifndef __clang__
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#endif
RAPIDJSON_NAMESPACE_BEGIN
template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
-template<int x> struct StaticAssertTest {};
+template <size_t 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
+#ifndef __clang__
//!@endcond
+#endif
/*! \def RAPIDJSON_STATIC_ASSERT
\brief (Internal) macro to check for conditions at compile-time
@@ -376,6 +451,35 @@ RAPIDJSON_NAMESPACE_END
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif // RAPIDJSON_STATIC_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
+
+//! Compiler branching hint for expression with high probability to be true.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+ \param x Boolean expression likely to be true.
+*/
+#ifndef RAPIDJSON_LIKELY
+#if defined(__GNUC__) || defined(__clang__)
+#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
+#else
+#define RAPIDJSON_LIKELY(x) (x)
+#endif
+#endif
+
+//! Compiler branching hint for expression with low probability to be true.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+ \param x Boolean expression unlikely to be true.
+*/
+#ifndef RAPIDJSON_UNLIKELY
+#if defined(__GNUC__) || defined(__clang__)
+#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define RAPIDJSON_UNLIKELY(x) (x)
+#endif
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -438,8 +542,12 @@ RAPIDJSON_NAMESPACE_END
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__)
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \
+#if __has_feature(cxx_rvalue_references) && \
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1600)
@@ -470,6 +578,17 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
#endif
+#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1700)
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
+#else
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
+
//!@endcond
///////////////////////////////////////////////////////////////////////////////
@@ -477,7 +596,7 @@ RAPIDJSON_NAMESPACE_END
#ifndef RAPIDJSON_NEW
///! customization point for global \c new
-#define RAPIDJSON_NEW(x) new x
+#define RAPIDJSON_NEW(TypeName) new TypeName
#endif
#ifndef RAPIDJSON_DELETE
///! customization point for global \c delete
@@ -485,10 +604,7 @@ RAPIDJSON_NAMESPACE_END
#endif
///////////////////////////////////////////////////////////////////////////////
-// Allocators and Encodings
-
-#include "allocators.h"
-#include "encodings.h"
+// Type
/*! \namespace rapidjson
\brief main RapidJSON namespace
@@ -496,148 +612,6 @@ RAPIDJSON_NAMESPACE_END
*/
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
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h
index 6fb29e908..120c31115 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/reader.h
@@ -1,5 +1,5 @@
// 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
@@ -7,9 +7,9 @@
//
// 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
+// 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_
@@ -17,11 +17,13 @@
/*! \file reader.h */
-#include "rapidjson.h"
-#include "encodings.h"
+#include "allocators.h"
+#include "stream.h"
+#include "encodedstream.h"
#include "internal/meta.h"
#include "internal/stack.h"
#include "internal/strtod.h"
+#include <limits>
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
#include <intrin.h>
@@ -31,6 +33,8 @@
#include <nmmintrin.h>
#elif defined(RAPIDJSON_SSE2)
#include <emmintrin.h>
+#elif defined(RAPIDJSON_NEON)
+#include <arm_neon.h>
#endif
#ifdef _MSC_VER
@@ -39,6 +43,13 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_DIAG_OFF(4702) // unreachable code
#endif
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(old-style-cast)
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+#endif
+
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
@@ -49,7 +60,7 @@ RAPIDJSON_DIAG_OFF(effc++)
#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
RAPIDJSON_MULTILINEMACRO_BEGIN \
- if (HasParseError()) { return value; } \
+ if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
RAPIDJSON_MULTILINEMACRO_END
#endif
#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
@@ -120,7 +131,7 @@ RAPIDJSON_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// ParseFlag
-/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
\ingroup RAPIDJSON_CONFIG
\brief User-defined kParseDefaultFlags definition.
@@ -141,6 +152,9 @@ enum ParseFlag {
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.
+ kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
+ kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
+ kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
};
@@ -149,7 +163,7 @@ enum ParseFlag {
/*! \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 functions return true if no error occurs. If they return false,
the event publisher should terminate the process.
\code
concept Handler {
@@ -162,6 +176,8 @@ concept Handler {
bool Int64(int64_t i);
bool Uint64(uint64_t i);
bool Double(double d);
+ /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
+ bool RawNumber(const Ch* str, SizeType length, bool copy);
bool String(const Ch* str, SizeType length, bool copy);
bool StartObject();
bool Key(const Ch* str, SizeType length, bool copy);
@@ -192,6 +208,8 @@ struct BaseReaderHandler {
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(); }
+ /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
+ bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
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); }
@@ -249,10 +267,17 @@ 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')
+ typename InputStream::Ch c;
+ while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
s.Take();
}
+inline const char* SkipWhitespace(const char* p, const char* end) {
+ while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ return p;
+}
+
#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) {
@@ -263,7 +288,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
return p;
// 16-byte align to the next boundary
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
while (p != nextAligned)
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p;
@@ -272,23 +297,37 @@ inline const char *SkipWhitespace_SIMD(const char* 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]);
+ const __m128i w = _mm_loadu_si128(reinterpret_cast<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
- }
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
+ if (r != 16) // some of characters is non-whitespace
+ return p + r;
}
}
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ // The middle of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
+
+ for (; p <= end - 16; p += 16) {
+ const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
+ const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
+ if (r != 16) // some of characters is non-whitespace
+ return p + r;
+ }
+
+ return SkipWhitespace(p, end);
+}
+
#elif defined(RAPIDJSON_SSE2)
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
@@ -300,7 +339,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
return p;
// 16-byte align to the next boundary
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
while (p != nextAligned)
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p;
@@ -308,24 +347,58 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
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"};
+ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
+ static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
+ #undef C16
- 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]);
+ const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
+ const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
+ const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
+ const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
for (;; p += 16) {
- const __m128i s = _mm_load_si128((const __m128i *)p);
+ const __m128i s = _mm_load_si128(reinterpret_cast<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 = static_cast<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
+ }
+ }
+}
+
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
+ static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
+ #undef C16
+
+ const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
+ const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
+ const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
+ const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
+
+ for (; p <= end - 16; p += 16) {
+ const __m128i s = _mm_loadu_si128(reinterpret_cast<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);
+ unsigned short r = static_cast<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;
@@ -336,13 +409,100 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
#endif
}
}
+
+ return SkipWhitespace(p, end);
+}
+
+#elif defined(RAPIDJSON_NEON)
+
+//! Skip whitespace with ARM Neon 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) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ const uint8x16_t w0 = vmovq_n_u8(' ');
+ const uint8x16_t w1 = vmovq_n_u8('\n');
+ const uint8x16_t w2 = vmovq_n_u8('\r');
+ const uint8x16_t w3 = vmovq_n_u8('\t');
+
+ for (;; p += 16) {
+ const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
+ uint8x16_t x = vceqq_u8(s, w0);
+ x = vorrq_u8(x, vceqq_u8(s, w1));
+ x = vorrq_u8(x, vceqq_u8(s, w2));
+ x = vorrq_u8(x, vceqq_u8(s, w3));
+
+ x = vmvnq_u8(x); // Negate
+ x = vrev64q_u8(x); // Rev in 64
+ uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
+ uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
+
+ if (low == 0) {
+ if (high != 0) {
+ int lz =__builtin_clzll(high);;
+ return p + 8 + (lz >> 3);
+ }
+ } else {
+ int lz = __builtin_clzll(low);;
+ return p + (lz >> 3);
+ }
+ }
+}
+
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ const uint8x16_t w0 = vmovq_n_u8(' ');
+ const uint8x16_t w1 = vmovq_n_u8('\n');
+ const uint8x16_t w2 = vmovq_n_u8('\r');
+ const uint8x16_t w3 = vmovq_n_u8('\t');
+
+ for (; p <= end - 16; p += 16) {
+ const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
+ uint8x16_t x = vceqq_u8(s, w0);
+ x = vorrq_u8(x, vceqq_u8(s, w1));
+ x = vorrq_u8(x, vceqq_u8(s, w2));
+ x = vorrq_u8(x, vceqq_u8(s, w3));
+
+ x = vmvnq_u8(x); // Negate
+ x = vrev64q_u8(x); // Rev in 64
+ uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
+ uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
+
+ if (low == 0) {
+ if (high != 0) {
+ int lz = __builtin_clzll(high);
+ return p + 8 + (lz >> 3);
+ }
+ } else {
+ int lz = __builtin_clzll(low);
+ return p + (lz >> 3);
+ }
+ }
+
+ return SkipWhitespace(p, end);
}
-#endif // RAPIDJSON_SSE2
+#endif // RAPIDJSON_NEON
#ifdef RAPIDJSON_SIMD
//! Template function specialization for InsituStringStream
-template<> inline void SkipWhitespace(InsituStringStream& is) {
+template<> inline void SkipWhitespace(InsituStringStream& is) {
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
}
@@ -350,23 +510,27 @@ template<> inline void SkipWhitespace(InsituStringStream& is) {
template<> inline void SkipWhitespace(StringStream& is) {
is.src_ = SkipWhitespace_SIMD(is.src_);
}
+
+template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
+ is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
+}
#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
+/*! 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
+ 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
+ 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.
@@ -402,7 +566,7 @@ public:
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- if (is.Peek() == '\0') {
+ if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
}
@@ -414,7 +578,7 @@ public:
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- if (is.Peek() != '\0') {
+ if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
}
@@ -436,9 +600,86 @@ public:
return Parse<kParseDefaultFlags>(is, handler);
}
+ //! Initialize JSON text token-by-token parsing
+ /*!
+ */
+ void IterativeParseInit() {
+ parseResult_.Clear();
+ state_ = IterativeParsingStartState;
+ }
+
+ //! Parse one token from JSON text
+ /*! \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>
+ bool IterativeParseNext(InputStream& is, Handler& handler) {
+ while (RAPIDJSON_LIKELY(is.Peek() != '\0')) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+
+ Token t = Tokenize(is.Peek());
+ IterativeParsingState n = Predict(state_, t);
+ IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);
+
+ // If we've finished or hit an error...
+ if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) {
+ // Report errors.
+ if (d == IterativeParsingErrorState) {
+ HandleError(state_, is);
+ return false;
+ }
+
+ // Transition to the finish state.
+ RAPIDJSON_ASSERT(d == IterativeParsingFinishState);
+ state_ = d;
+
+ // If StopWhenDone is not set...
+ if (!(parseFlags & kParseStopWhenDoneFlag)) {
+ // ... and extra non-whitespace data is found...
+ SkipWhitespaceAndComments<parseFlags>(is);
+ if (is.Peek() != '\0') {
+ // ... this is considered an error.
+ HandleError(state_, is);
+ return false;
+ }
+ }
+
+ // Success! We are done!
+ return true;
+ }
+
+ // Transition to the new state.
+ state_ = d;
+
+ // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
+ if (!IsIterativeParsingDelimiterState(n))
+ return true;
+ }
+
+ // We reached the end of file.
+ stack_.Clear();
+
+ if (state_ != IterativeParsingFinishState) {
+ HandleError(state_, is);
+ return false;
+ }
+
+ return true;
+ }
+
+ //! Check if token-by-token parsing JSON text is complete
+ /*! \return Whether the JSON has been fully decoded.
+ */
+ RAPIDJSON_FORCEINLINE bool IterativeParseComplete() {
+ return IsIterativeParsingCompleteState(state_);
+ }
+
//! 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(); }
@@ -470,29 +711,23 @@ private:
SkipWhitespace(is);
if (parseFlags & kParseCommentsFlag) {
- while (is.Peek() == '/') {
- is.Take();
-
- if (is.Peek() == '*') {
- is.Take();
+ while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
+ if (Consume(is, '*')) {
while (true) {
- if (is.Peek() == '\0')
+ if (RAPIDJSON_UNLIKELY(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() == '/')
+ else if (Consume(is, '*')) {
+ if (Consume(is, '/'))
break;
}
+ else
+ is.Take();
}
- } else if (is.Peek() == '/') {
- is.Take();
- while (is.Peek() != '\0' && is.Take() != '\n') { }
- } else {
- RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
}
+ else if (RAPIDJSON_LIKELY(Consume(is, '/')))
+ while (is.Peek() != '\0' && is.Take() != '\n') {}
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
SkipWhitespace(is);
}
@@ -504,22 +739,21 @@ private:
void ParseObject(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == '{');
is.Take(); // Skip '{'
-
- if (!handler.StartObject())
+
+ if (RAPIDJSON_UNLIKELY(!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
+ if (Consume(is, '}')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return;
}
for (SizeType memberCount = 0;;) {
- if (is.Peek() != '"')
+ if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
ParseString<parseFlags>(is, handler, true);
@@ -528,7 +762,7 @@ private:
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (is.Take() != ':')
+ if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is);
@@ -542,18 +776,28 @@ private:
++memberCount;
- switch (is.Take()) {
+ switch (is.Peek()) {
case ',':
+ is.Take();
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
break;
- case '}':
- if (!handler.EndObject(memberCount))
+ case '}':
+ is.Take();
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return;
- default:
- RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
- break;
+ default:
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
+ }
+
+ if (parseFlags & kParseTrailingCommasFlag) {
+ if (is.Peek() == '}') {
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ is.Take();
+ return;
+ }
}
}
}
@@ -563,16 +807,15 @@ private:
void ParseArray(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == '[');
is.Take(); // Skip '['
-
- if (!handler.StartArray())
+
+ if (RAPIDJSON_UNLIKELY(!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
+ if (Consume(is, ']')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return;
}
@@ -585,18 +828,25 @@ private:
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))
+ if (Consume(is, ',')) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ }
+ else if (Consume(is, ']')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+
+ if (parseFlags & kParseTrailingCommasFlag) {
+ if (is.Peek() == ']') {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ is.Take();
return;
- default:
- RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
- break;
+ }
}
}
}
@@ -606,12 +856,12 @@ private:
RAPIDJSON_ASSERT(is.Peek() == 'n');
is.Take();
- if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
- if (!handler.Null())
+ if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Null()))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
}
else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
}
template<unsigned parseFlags, typename InputStream, typename Handler>
@@ -619,12 +869,12 @@ private:
RAPIDJSON_ASSERT(is.Peek() == 't');
is.Take();
- if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
- if (!handler.Bool(true))
+ if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
}
else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
}
template<unsigned parseFlags, typename InputStream, typename Handler>
@@ -632,20 +882,30 @@ private:
RAPIDJSON_ASSERT(is.Peek() == 'f');
is.Take();
- if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
- if (!handler.Bool(false))
+ if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
}
else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
+ if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
+ is.Take();
+ return true;
+ }
+ else
+ return false;
}
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
template<typename InputStream>
- unsigned ParseHex4(InputStream& is) {
+ unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
unsigned codepoint = 0;
for (int i = 0; i < 4; i++) {
- Ch c = is.Take();
+ Ch c = is.Peek();
codepoint <<= 4;
codepoint += static_cast<unsigned>(c);
if (c >= '0' && c <= '9')
@@ -655,9 +915,10 @@ private:
else if (c >= 'a' && c <= 'f')
codepoint -= 'a' - 10;
else {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
}
+ is.Take();
}
return codepoint;
}
@@ -672,7 +933,14 @@ private:
*stack_.template Push<Ch>() = c;
++length_;
}
+
+ RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
+ length_ += count;
+ return stack_.template Push<Ch>(count);
+ }
+
size_t Length() const { return length_; }
+
Ch* Pop() {
return stack_.template Pop<Ch>(length_);
}
@@ -691,6 +959,9 @@ private:
internal::StreamLocalCopy<InputStream> copy(is);
InputStream& s(copy.s);
+ RAPIDJSON_ASSERT(s.Peek() == '\"');
+ s.Take(); // Skip '\"'
+
bool success = false;
if (parseFlags & kParseInsituFlag) {
typename InputStream::Ch *head = s.PutBegin();
@@ -698,7 +969,7 @@ private:
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;
+ const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
}
else {
@@ -709,7 +980,7 @@ private:
const typename TargetEncoding::Ch* const str = stackStream.Pop();
success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
}
- if (!success)
+ if (RAPIDJSON_UNLIKELY(!success))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
}
@@ -720,74 +991,421 @@ private:
//!@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, 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 (;;) {
+ // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
+ if (!(parseFlags & kParseValidateEncodingFlag))
+ ScanCopyUnescapedString(is, os);
+
Ch c = is.Peek();
- if (c == '\\') { // Escape
+ if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
+ size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
is.Take();
- Ch e = is.Take();
- if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
- os.Put(escape[(unsigned char)e]);
+ Ch e = is.Peek();
+ if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
+ is.Take();
+ os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
}
- else if (e == 'u') { // Unicode
- unsigned codepoint = ParseHex4(is);
+ else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
+ is.Take();
+ unsigned codepoint = ParseHex4(is, escapeOffset);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
+ if (RAPIDJSON_UNLIKELY(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);
+ if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
+ unsigned codepoint2 = ParseHex4(is, escapeOffset);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
- RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+ if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
}
TEncoding::Encode(os, codepoint);
}
else
- RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
}
- else if (c == '"') { // Closing double quote
+ else if (RAPIDJSON_UNLIKELY(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))
+ else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+ if (c == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
+ else
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
}
+ else {
+ size_t offset = is.Tell();
+ if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
+ !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
+ !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
+ }
+ }
+ }
+
+ template<typename InputStream, typename OutputStream>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
+ // Do nothing for generic version
+ }
+
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+ // StringStream -> StackStream<char>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
+ const char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ return;
+ }
+ else
+ os.Put(*p++);
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ SizeType length;
+ #ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+ #else
+ length = static_cast<SizeType>(__builtin_ffs(r) - 1);
+ #endif
+ if (length != 0) {
+ char* q = reinterpret_cast<char*>(os.Push(length));
+ for (size_t i = 0; i < length; i++)
+ q[i] = p[i];
+
+ p += length;
+ }
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
+ }
+
+ is.src_ = p;
+ }
+
+ // InsituStringStream -> InsituStringStream
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
+ RAPIDJSON_ASSERT(&is == &os);
+ (void)os;
+
+ if (is.src_ == is.dst_) {
+ SkipUnescapedString(is);
+ return;
+ }
+
+ char* p = is.src_;
+ char *q = is.dst_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ is.dst_ = q;
+ return;
+ }
+ else
+ *q++ = *p++;
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16, q += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ size_t length;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+#else
+ length = static_cast<size_t>(__builtin_ffs(r) - 1);
+#endif
+ for (const char* pend = p + length; p != pend; )
+ *q++ = *p++;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
}
+
+ is.src_ = p;
+ is.dst_ = q;
}
- template<typename InputStream, bool backup>
+ // When read/write pointers are the same for insitu stream, just skip unescaped characters
+ static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
+ RAPIDJSON_ASSERT(is.src_ == is.dst_);
+ char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ for (; p != nextAligned; p++)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = is.dst_ = p;
+ return;
+ }
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ size_t length;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+#else
+ length = static_cast<size_t>(__builtin_ffs(r) - 1);
+#endif
+ p += length;
+ break;
+ }
+ }
+
+ is.src_ = is.dst_ = p;
+ }
+#elif defined(RAPIDJSON_NEON)
+ // StringStream -> StackStream<char>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
+ const char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ return;
+ }
+ else
+ os.Put(*p++);
+
+ // The rest of string using SIMD
+ const uint8x16_t s0 = vmovq_n_u8('"');
+ const uint8x16_t s1 = vmovq_n_u8('\\');
+ const uint8x16_t s2 = vmovq_n_u8('\b');
+ const uint8x16_t s3 = vmovq_n_u8(32);
+
+ for (;; p += 16) {
+ const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
+ uint8x16_t x = vceqq_u8(s, s0);
+ x = vorrq_u8(x, vceqq_u8(s, s1));
+ x = vorrq_u8(x, vceqq_u8(s, s2));
+ x = vorrq_u8(x, vcltq_u8(s, s3));
+
+ x = vrev64q_u8(x); // Rev in 64
+ uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
+ uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
+
+ SizeType length = 0;
+ bool escaped = false;
+ if (low == 0) {
+ if (high != 0) {
+ unsigned lz = (unsigned)__builtin_clzll(high);;
+ length = 8 + (lz >> 3);
+ escaped = true;
+ }
+ } else {
+ unsigned lz = (unsigned)__builtin_clzll(low);;
+ length = lz >> 3;
+ escaped = true;
+ }
+ if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
+ if (length != 0) {
+ char* q = reinterpret_cast<char*>(os.Push(length));
+ for (size_t i = 0; i < length; i++)
+ q[i] = p[i];
+
+ p += length;
+ }
+ break;
+ }
+ vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
+ }
+
+ is.src_ = p;
+ }
+
+ // InsituStringStream -> InsituStringStream
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
+ RAPIDJSON_ASSERT(&is == &os);
+ (void)os;
+
+ if (is.src_ == is.dst_) {
+ SkipUnescapedString(is);
+ return;
+ }
+
+ char* p = is.src_;
+ char *q = is.dst_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ is.dst_ = q;
+ return;
+ }
+ else
+ *q++ = *p++;
+
+ // The rest of string using SIMD
+ const uint8x16_t s0 = vmovq_n_u8('"');
+ const uint8x16_t s1 = vmovq_n_u8('\\');
+ const uint8x16_t s2 = vmovq_n_u8('\b');
+ const uint8x16_t s3 = vmovq_n_u8(32);
+
+ for (;; p += 16, q += 16) {
+ const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
+ uint8x16_t x = vceqq_u8(s, s0);
+ x = vorrq_u8(x, vceqq_u8(s, s1));
+ x = vorrq_u8(x, vceqq_u8(s, s2));
+ x = vorrq_u8(x, vcltq_u8(s, s3));
+
+ x = vrev64q_u8(x); // Rev in 64
+ uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
+ uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
+
+ SizeType length = 0;
+ bool escaped = false;
+ if (low == 0) {
+ if (high != 0) {
+ unsigned lz = (unsigned)__builtin_clzll(high);
+ length = 8 + (lz >> 3);
+ escaped = true;
+ }
+ } else {
+ unsigned lz = (unsigned)__builtin_clzll(low);
+ length = lz >> 3;
+ escaped = true;
+ }
+ if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
+ for (const char* pend = p + length; p != pend; ) {
+ *q++ = *p++;
+ }
+ break;
+ }
+ vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
+ }
+
+ is.src_ = p;
+ is.dst_ = q;
+ }
+
+ // When read/write pointers are the same for insitu stream, just skip unescaped characters
+ static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
+ RAPIDJSON_ASSERT(is.src_ == is.dst_);
+ char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ for (; p != nextAligned; p++)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = is.dst_ = p;
+ return;
+ }
+
+ // The rest of string using SIMD
+ const uint8x16_t s0 = vmovq_n_u8('"');
+ const uint8x16_t s1 = vmovq_n_u8('\\');
+ const uint8x16_t s2 = vmovq_n_u8('\b');
+ const uint8x16_t s3 = vmovq_n_u8(32);
+
+ for (;; p += 16) {
+ const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
+ uint8x16_t x = vceqq_u8(s, s0);
+ x = vorrq_u8(x, vceqq_u8(s, s1));
+ x = vorrq_u8(x, vceqq_u8(s, s2));
+ x = vorrq_u8(x, vcltq_u8(s, s3));
+
+ x = vrev64q_u8(x); // Rev in 64
+ uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
+ uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
+
+ if (low == 0) {
+ if (high != 0) {
+ int lz = __builtin_clzll(high);
+ p += 8 + (lz >> 3);
+ break;
+ }
+ } else {
+ int lz = __builtin_clzll(low);
+ p += lz >> 3;
+ break;
+ }
+ }
+
+ is.src_ = is.dst_ = p;
+ }
+#endif // RAPIDJSON_NEON
+
+ template<typename InputStream, bool backup, bool pushOnTake>
class NumberStream;
template<typename InputStream>
- class NumberStream<InputStream, false> {
+ class NumberStream<InputStream, false, false> {
public:
+ typedef typename InputStream::Ch Ch;
+
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(); }
+ RAPIDJSON_FORCEINLINE void Push(char) {}
+
size_t Tell() { return is.Tell(); }
size_t Length() { return 0; }
const char* Pop() { return 0; }
@@ -799,17 +1417,20 @@ private:
};
template<typename InputStream>
- class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
- typedef NumberStream<InputStream, false> Base;
+ class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
+ typedef NumberStream<InputStream, false, false> Base;
public:
- NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
- ~NumberStream() {}
+ NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
RAPIDJSON_FORCEINLINE Ch TakePush() {
- stackStream.Put((char)Base::is.Peek());
+ stackStream.Put(static_cast<char>(Base::is.Peek()));
return Base::is.Take();
}
+ RAPIDJSON_FORCEINLINE void Push(char c) {
+ stackStream.Put(c);
+ }
+
size_t Length() { return stackStream.Length(); }
const char* Pop() {
@@ -821,34 +1442,48 @@ private:
StackStream<char> stackStream;
};
+ template<typename InputStream>
+ class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
+ typedef NumberStream<InputStream, true, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
+
+ RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
+ };
+
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);
+ NumberStream<InputStream,
+ ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
+ ((parseFlags & kParseInsituFlag) == 0) :
+ ((parseFlags & kParseFullPrecisionFlag) != 0),
+ (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
+ (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
+
+ size_t startOffset = s.Tell();
+ double d = 0.0;
+ bool useNanOrInf = false;
// Parse minus
- bool minus = false;
- if (s.Peek() == '-') {
- minus = true;
- s.Take();
- }
+ bool minus = Consume(s, '-');
// Parse int: zero / ( digit1-9 *DIGIT )
unsigned i = 0;
uint64_t i64 = 0;
bool use64bit = false;
int significandDigit = 0;
- if (s.Peek() == '0') {
+ if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
i = 0;
s.TakePush();
}
- else if (s.Peek() >= '1' && s.Peek() <= '9') {
+ else if (RAPIDJSON_LIKELY(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') {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
+ if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
i64 = i;
use64bit = true;
break;
@@ -858,9 +1493,9 @@ private:
significandDigit++;
}
else
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (i >= 429496729) { // 2^32 - 1 = 4294967295
- if (i != 429496729 || s.Peek() > '5') {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
+ if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
i64 = i;
use64bit = true;
break;
@@ -870,18 +1505,41 @@ private:
significandDigit++;
}
}
+ // Parse NaN or Infinity here
+ else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
+ if (Consume(s, 'N')) {
+ if (Consume(s, 'a') && Consume(s, 'N')) {
+ d = std::numeric_limits<double>::quiet_NaN();
+ useNanOrInf = true;
+ }
+ }
+ else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {
+ if (Consume(s, 'n') && Consume(s, 'f')) {
+ d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
+ useNanOrInf = true;
+
+ if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
+ && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+ }
+ }
+ }
+
+ if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+ }
+ }
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;
+ if (minus)
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
+ if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
+ d = static_cast<double>(i64);
useDouble = true;
break;
}
@@ -889,10 +1547,10 @@ private:
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;
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
+ if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
+ d = static_cast<double>(i64);
useDouble = true;
break;
}
@@ -903,9 +1561,9 @@ private:
// 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());
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
d = d * 10 + (s.TakePush() - '0');
}
}
@@ -913,11 +1571,10 @@ private:
// Parse frac = decimal-point 1*DIGIT
int expFrac = 0;
size_t decimalPosition;
- if (s.Peek() == '.') {
- s.Take();
+ if (Consume(s, '.')) {
decimalPosition = s.Length();
- if (!(s.Peek() >= '0' && s.Peek() <= '9'))
+ if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
if (!useDouble) {
@@ -925,8 +1582,8 @@ private:
// Use i64 to store significand in 64-bit architecture
if (!use64bit)
i64 = i;
-
- while (s.Peek() >= '0' && s.Peek() <= '9') {
+
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
break;
else {
@@ -937,19 +1594,19 @@ private:
}
}
- d = (double)i64;
+ d = static_cast<double>(i64);
#else
// Use double to store significand in 32-bit architecture
- d = use64bit ? (double)i64 : (double)i;
+ d = static_cast<double>(use64bit ? i64 : i);
#endif
useDouble = true;
}
- while (s.Peek() >= '0' && s.Peek() <= '9') {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
if (significandDigit < 17) {
d = d * 10.0 + (s.TakePush() - '0');
--expFrac;
- if (d > 0.0)
+ if (RAPIDJSON_LIKELY(d > 0.0))
significandDigit++;
}
else
@@ -961,38 +1618,35 @@ private:
// Parse exp = e [ minus / plus ] 1*DIGIT
int exp = 0;
- if (s.Peek() == 'e' || s.Peek() == 'E') {
+ if (Consume(s, 'e') || Consume(s, 'E')) {
if (!useDouble) {
- d = use64bit ? i64 : i;
+ d = static_cast<double>(use64bit ? i64 : i);
useDouble = true;
}
- s.Take();
bool expMinus = false;
- if (s.Peek() == '+')
- s.Take();
- else if (s.Peek() == '-') {
- s.Take();
+ if (Consume(s, '+'))
+ ;
+ else if (Consume(s, '-'))
expMinus = true;
- }
- if (s.Peek() >= '0' && s.Peek() <= '9') {
- exp = s.Take() - '0';
+ if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = static_cast<int>(s.Take() - '0');
if (expMinus) {
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- exp = exp * 10 + (s.Take() - '0');
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = exp * 10 + static_cast<int>(s.Take() - '0');
if (exp >= 214748364) { // Issue #313: prevent overflow exponent
- while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent
+ while (RAPIDJSON_UNLIKELY(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());
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = exp * 10 + static_cast<int>(s.Take() - '0');
+ if (RAPIDJSON_UNLIKELY(exp > maxExp))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
}
}
}
@@ -1005,34 +1659,63 @@ private:
// 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);
+ if (parseFlags & kParseNumbersAsStringsFlag) {
+ if (parseFlags & kParseInsituFlag) {
+ s.Pop(); // Pop stack no matter if it will be used or not.
+ typename InputStream::Ch* head = is.PutBegin();
+ const size_t length = s.Tell() - startOffset;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ // unable to insert the \0 character here, it will erase the comma after this number
+ const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
+ cont = handler.RawNumber(str, SizeType(length), false);
}
else {
- if (minus)
- cont = handler.Int(static_cast<int32_t>(~i + 1));
- else
- cont = handler.Uint(i);
+ SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
+ StringStream srcStream(s.Pop());
+ StackStream<typename TargetEncoding::Ch> dstStream(stack_);
+ while (numCharsToCopy--) {
+ Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
+ }
+ dstStream.Put('\0');
+ const typename TargetEncoding::Ch* str = dstStream.Pop();
+ const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
+ cont = handler.RawNumber(str, SizeType(length), true);
}
}
- if (!cont)
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ else {
+ 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 (useNanOrInf) {
+ cont = handler.Double(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 (RAPIDJSON_UNLIKELY(!cont))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
}
// Parse any JSON value
@@ -1045,10 +1728,10 @@ private:
case '"': ParseString<parseFlags>(is, handler); break;
case '{': ParseObject<parseFlags>(is, handler); break;
case '[': ParseArray <parseFlags>(is, handler); break;
- default :
+ default :
ParseNumber<parseFlags>(is, handler);
break;
-
+
}
}
@@ -1056,27 +1739,29 @@ private:
// States
enum IterativeParsingState {
- IterativeParsingStartState = 0,
- IterativeParsingFinishState,
- IterativeParsingErrorState,
+ IterativeParsingFinishState = 0, // sink states at top
+ IterativeParsingErrorState, // sink states at top
+ IterativeParsingStartState,
// Object states
IterativeParsingObjectInitialState,
IterativeParsingMemberKeyState,
- IterativeParsingKeyValueDelimiterState,
IterativeParsingMemberValueState,
- IterativeParsingMemberDelimiterState,
IterativeParsingObjectFinishState,
// Array states
IterativeParsingArrayInitialState,
IterativeParsingElementState,
- IterativeParsingElementDelimiterState,
IterativeParsingArrayFinishState,
// Single value state
IterativeParsingValueState,
-
+
+ // Delimiter states (at bottom)
+ IterativeParsingElementDelimiterState,
+ IterativeParsingMemberDelimiterState,
+ IterativeParsingKeyValueDelimiterState,
+
cIterativeParsingStateCount
};
@@ -1120,9 +1805,9 @@ private:
#undef N
#undef N16
//!@endcond
-
- if (sizeof(Ch) == 1 || unsigned(c) < 256)
- return (Token)tokenMap[(unsigned char)c];
+
+ if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
+ return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
else
return NumberToken;
}
@@ -1130,6 +1815,18 @@ private:
RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
// current state x one lookahead token -> new state
static const char G[cIterativeParsingStateCount][kTokenCount] = {
+ // 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
+ },
// Start
{
IterativeParsingArrayInitialState, // Left bracket
@@ -1144,18 +1841,6 @@ private:
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
@@ -1184,20 +1869,6 @@ private:
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
@@ -1212,20 +1883,6 @@ private:
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,
@@ -1260,10 +1917,22 @@ private:
IterativeParsingErrorState, // Null
IterativeParsingErrorState // 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
+ },
// ElementDelimiter
{
IterativeParsingArrayInitialState, // Left bracket(push Element state)
- IterativeParsingErrorState, // Right bracket
+ IterativeParsingArrayFinishState, // Right bracket
IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
@@ -1274,21 +1943,37 @@ private:
IterativeParsingElementState, // Null
IterativeParsingElementState // Number
},
- // ArrayFinish(sink state)
+ // MemberDelimiter
{
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
+ 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
},
- // Single Value (sink state)
+ // KeyValueDelimiter
{
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- }
+ 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
+ },
}; // End of G
- return (IterativeParsingState)G[state][token];
+ return static_cast<IterativeParsingState>(G[state][token]);
}
// Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
@@ -1365,6 +2050,11 @@ private:
case IterativeParsingObjectFinishState:
{
+ // Transit from delimiter is only allowed when trailing commas are enabled
+ if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
+ return IterativeParsingErrorState;
+ }
// Get member count.
SizeType c = *stack_.template Pop<SizeType>(1);
// If the object is not empty, count the last member.
@@ -1390,6 +2080,11 @@ private:
case IterativeParsingArrayFinishState:
{
+ // Transit from delimiter is only allowed when trailing commas are enabled
+ if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
+ return IterativeParsingErrorState;
+ }
// Get element count.
SizeType c = *stack_.template Pop<SizeType>(1);
// If the array is not empty, count the last element.
@@ -1441,7 +2136,7 @@ private:
// 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;
@@ -1449,49 +2144,60 @@ private:
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;
- }
+ case IterativeParsingKeyValueDelimiterState:
+ case IterativeParsingArrayInitialState:
+ case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
+ default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
+ }
}
+ RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) {
+ return s >= IterativeParsingElementDelimiterState;
+ }
+
+ RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) {
+ return s <= IterativeParsingErrorState;
+ }
+
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_;
+ IterativeParsingState state_;
}; // class GenericReader
//! Reader with UTF8 encoding and default allocator.
@@ -1499,6 +2205,11 @@ typedef GenericReader<UTF8<>, UTF8<> > Reader;
RAPIDJSON_NAMESPACE_END
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/schema.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/schema.h
new file mode 100644
index 000000000..abcf1a102
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/schema.h
@@ -0,0 +1,2016 @@
+// 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_SCHEMA_H_
+#define RAPIDJSON_SCHEMA_H_
+
+#include "document.h"
+#include "pointer.h"
+#include <cmath> // abs, floor
+
+#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
+#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
+#else
+#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
+#endif
+
+#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
+#define RAPIDJSON_SCHEMA_USE_STDREGEX 1
+#else
+#define RAPIDJSON_SCHEMA_USE_STDREGEX 0
+#endif
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+#include "internal/regex.h"
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+#include <regex>
+#endif
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX
+#define RAPIDJSON_SCHEMA_HAS_REGEX 1
+#else
+#define RAPIDJSON_SCHEMA_HAS_REGEX 0
+#endif
+
+#ifndef RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_SCHEMA_VERBOSE 0
+#endif
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#include "stringbuffer.h"
+#endif
+
+RAPIDJSON_DIAG_PUSH
+
+#if defined(__GNUC__)
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_OFF(weak-vtables)
+RAPIDJSON_DIAG_OFF(exit-time-destructors)
+RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
+RAPIDJSON_DIAG_OFF(variadic-macros)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Verbose Utilities
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+
+namespace internal {
+
+inline void PrintInvalidKeyword(const char* keyword) {
+ printf("Fail keyword: %s\n", keyword);
+}
+
+inline void PrintInvalidKeyword(const wchar_t* keyword) {
+ wprintf(L"Fail keyword: %ls\n", keyword);
+}
+
+inline void PrintInvalidDocument(const char* document) {
+ printf("Fail document: %s\n\n", document);
+}
+
+inline void PrintInvalidDocument(const wchar_t* document) {
+ wprintf(L"Fail document: %ls\n\n", document);
+}
+
+inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
+ printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
+}
+
+inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
+ wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
+}
+
+} // namespace internal
+
+#endif // RAPIDJSON_SCHEMA_VERBOSE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_INVALID_KEYWORD_RETURN
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
+#else
+#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
+#endif
+
+#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
+RAPIDJSON_MULTILINEMACRO_BEGIN\
+ context.invalidKeyword = keyword.GetString();\
+ RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
+ return false;\
+RAPIDJSON_MULTILINEMACRO_END
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+
+template <typename ValueType, typename Allocator>
+class GenericSchemaDocument;
+
+namespace internal {
+
+template <typename SchemaDocumentType>
+class Schema;
+
+///////////////////////////////////////////////////////////////////////////////
+// ISchemaValidator
+
+class ISchemaValidator {
+public:
+ virtual ~ISchemaValidator() {}
+ virtual bool IsValid() const = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ISchemaStateFactory
+
+template <typename SchemaType>
+class ISchemaStateFactory {
+public:
+ virtual ~ISchemaStateFactory() {}
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
+ virtual void* CreateHasher() = 0;
+ virtual uint64_t GetHashCode(void* hasher) = 0;
+ virtual void DestroryHasher(void* hasher) = 0;
+ virtual void* MallocState(size_t size) = 0;
+ virtual void FreeState(void* p) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Hasher
+
+// For comparison of compound value
+template<typename Encoding, typename Allocator>
+class Hasher {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
+
+ bool Null() { return WriteType(kNullType); }
+ bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
+ bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
+ bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
+ bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
+ bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
+ bool Double(double d) {
+ Number n;
+ if (d < 0) n.u.i = static_cast<int64_t>(d);
+ else n.u.u = static_cast<uint64_t>(d);
+ n.d = d;
+ return WriteNumber(n);
+ }
+
+ bool RawNumber(const Ch* str, SizeType len, bool) {
+ WriteBuffer(kNumberType, str, len * sizeof(Ch));
+ return true;
+ }
+
+ bool String(const Ch* str, SizeType len, bool) {
+ WriteBuffer(kStringType, str, len * sizeof(Ch));
+ return true;
+ }
+
+ bool StartObject() { return true; }
+ bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
+ bool EndObject(SizeType memberCount) {
+ uint64_t h = Hash(0, kObjectType);
+ uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
+ for (SizeType i = 0; i < memberCount; i++)
+ h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ bool StartArray() { return true; }
+ bool EndArray(SizeType elementCount) {
+ uint64_t h = Hash(0, kArrayType);
+ uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
+ for (SizeType i = 0; i < elementCount; i++)
+ h = Hash(h, e[i]); // Use hash to achieve element order sensitive
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
+
+ uint64_t GetHashCode() const {
+ RAPIDJSON_ASSERT(IsValid());
+ return *stack_.template Top<uint64_t>();
+ }
+
+private:
+ static const size_t kDefaultSize = 256;
+ struct Number {
+ union U {
+ uint64_t u;
+ int64_t i;
+ }u;
+ double d;
+ };
+
+ bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
+
+ bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
+
+ bool WriteBuffer(Type type, const void* data, size_t len) {
+ // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
+ uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
+ const unsigned char* d = static_cast<const unsigned char*>(data);
+ for (size_t i = 0; i < len; i++)
+ h = Hash(h, d[i]);
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ static uint64_t Hash(uint64_t h, uint64_t d) {
+ static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
+ h ^= d;
+ h *= kPrime;
+ return h;
+ }
+
+ Stack<Allocator> stack_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// SchemaValidationContext
+
+template <typename SchemaDocumentType>
+struct SchemaValidationContext {
+ typedef Schema<SchemaDocumentType> SchemaType;
+ typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
+ typedef typename SchemaType::ValueType ValueType;
+ typedef typename ValueType::Ch Ch;
+
+ enum PatternValidatorType {
+ kPatternValidatorOnly,
+ kPatternValidatorWithProperty,
+ kPatternValidatorWithAdditionalProperty
+ };
+
+ SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) :
+ factory(f),
+ schema(s),
+ valueSchema(),
+ invalidKeyword(),
+ hasher(),
+ arrayElementHashCodes(),
+ validators(),
+ validatorCount(),
+ patternPropertiesValidators(),
+ patternPropertiesValidatorCount(),
+ patternPropertiesSchemas(),
+ patternPropertiesSchemaCount(),
+ valuePatternValidatorType(kPatternValidatorOnly),
+ propertyExist(),
+ inArray(false),
+ valueUniqueness(false),
+ arrayUniqueness(false)
+ {
+ }
+
+ ~SchemaValidationContext() {
+ if (hasher)
+ factory.DestroryHasher(hasher);
+ if (validators) {
+ for (SizeType i = 0; i < validatorCount; i++)
+ factory.DestroySchemaValidator(validators[i]);
+ factory.FreeState(validators);
+ }
+ if (patternPropertiesValidators) {
+ for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
+ factory.DestroySchemaValidator(patternPropertiesValidators[i]);
+ factory.FreeState(patternPropertiesValidators);
+ }
+ if (patternPropertiesSchemas)
+ factory.FreeState(patternPropertiesSchemas);
+ if (propertyExist)
+ factory.FreeState(propertyExist);
+ }
+
+ SchemaValidatorFactoryType& factory;
+ const SchemaType* schema;
+ const SchemaType* valueSchema;
+ const Ch* invalidKeyword;
+ void* hasher; // Only validator access
+ void* arrayElementHashCodes; // Only validator access this
+ ISchemaValidator** validators;
+ SizeType validatorCount;
+ ISchemaValidator** patternPropertiesValidators;
+ SizeType patternPropertiesValidatorCount;
+ const SchemaType** patternPropertiesSchemas;
+ SizeType patternPropertiesSchemaCount;
+ PatternValidatorType valuePatternValidatorType;
+ PatternValidatorType objectPatternValidatorType;
+ SizeType arrayElementIndex;
+ bool* propertyExist;
+ bool inArray;
+ bool valueUniqueness;
+ bool arrayUniqueness;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Schema
+
+template <typename SchemaDocumentType>
+class Schema {
+public:
+ typedef typename SchemaDocumentType::ValueType ValueType;
+ typedef typename SchemaDocumentType::AllocatorType AllocatorType;
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+ typedef SchemaValidationContext<SchemaDocumentType> Context;
+ typedef Schema<SchemaDocumentType> SchemaType;
+ typedef GenericValue<EncodingType, AllocatorType> SValue;
+ friend class GenericSchemaDocument<ValueType, AllocatorType>;
+
+ Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
+ allocator_(allocator),
+ typeless_(schemaDocument->GetTypeless()),
+ enum_(),
+ enumCount_(),
+ not_(),
+ type_((1 << kTotalSchemaType) - 1), // typeless
+ validatorCount_(),
+ properties_(),
+ additionalPropertiesSchema_(),
+ patternProperties_(),
+ patternPropertyCount_(),
+ propertyCount_(),
+ minProperties_(),
+ maxProperties_(SizeType(~0)),
+ additionalProperties_(true),
+ hasDependencies_(),
+ hasRequired_(),
+ hasSchemaDependencies_(),
+ additionalItemsSchema_(),
+ itemsList_(),
+ itemsTuple_(),
+ itemsTupleCount_(),
+ minItems_(),
+ maxItems_(SizeType(~0)),
+ additionalItems_(true),
+ uniqueItems_(false),
+ pattern_(),
+ minLength_(0),
+ maxLength_(~SizeType(0)),
+ exclusiveMinimum_(false),
+ exclusiveMaximum_(false)
+ {
+ typedef typename SchemaDocumentType::ValueType ValueType;
+ typedef typename ValueType::ConstValueIterator ConstValueIterator;
+ typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
+
+ if (!value.IsObject())
+ return;
+
+ if (const ValueType* v = GetMember(value, GetTypeString())) {
+ type_ = 0;
+ if (v->IsString())
+ AddType(*v);
+ else if (v->IsArray())
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
+ AddType(*itr);
+ }
+
+ if (const ValueType* v = GetMember(value, GetEnumString()))
+ if (v->IsArray() && v->Size() > 0) {
+ enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
+ typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
+ char buffer[256 + 24];
+ MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
+ EnumHasherType h(&hasherAllocator, 256);
+ itr->Accept(h);
+ enum_[enumCount_++] = h.GetHashCode();
+ }
+ }
+
+ if (schemaDocument) {
+ AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
+ AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
+ AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
+ }
+
+ if (const ValueType* v = GetMember(value, GetNotString())) {
+ schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
+ notValidatorIndex_ = validatorCount_;
+ validatorCount_++;
+ }
+
+ // Object
+
+ const ValueType* properties = GetMember(value, GetPropertiesString());
+ const ValueType* required = GetMember(value, GetRequiredString());
+ const ValueType* dependencies = GetMember(value, GetDependenciesString());
+ {
+ // Gather properties from properties/required/dependencies
+ SValue allProperties(kArrayType);
+
+ if (properties && properties->IsObject())
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
+ AddUniqueElement(allProperties, itr->name);
+
+ if (required && required->IsArray())
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
+ if (itr->IsString())
+ AddUniqueElement(allProperties, *itr);
+
+ if (dependencies && dependencies->IsObject())
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
+ AddUniqueElement(allProperties, itr->name);
+ if (itr->value.IsArray())
+ for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
+ if (i->IsString())
+ AddUniqueElement(allProperties, *i);
+ }
+
+ if (allProperties.Size() > 0) {
+ propertyCount_ = allProperties.Size();
+ properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
+ for (SizeType i = 0; i < propertyCount_; i++) {
+ new (&properties_[i]) Property();
+ properties_[i].name = allProperties[i];
+ properties_[i].schema = typeless_;
+ }
+ }
+ }
+
+ if (properties && properties->IsObject()) {
+ PointerType q = p.Append(GetPropertiesString(), allocator_);
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
+ SizeType index;
+ if (FindPropertyIndex(itr->name, &index))
+ schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
+ }
+ }
+
+ if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
+ PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
+ patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
+ patternPropertyCount_ = 0;
+
+ for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
+ new (&patternProperties_[patternPropertyCount_]) PatternProperty();
+ patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
+ schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
+ patternPropertyCount_++;
+ }
+ }
+
+ if (required && required->IsArray())
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
+ if (itr->IsString()) {
+ SizeType index;
+ if (FindPropertyIndex(*itr, &index)) {
+ properties_[index].required = true;
+ hasRequired_ = true;
+ }
+ }
+
+ if (dependencies && dependencies->IsObject()) {
+ PointerType q = p.Append(GetDependenciesString(), allocator_);
+ hasDependencies_ = true;
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
+ SizeType sourceIndex;
+ if (FindPropertyIndex(itr->name, &sourceIndex)) {
+ if (itr->value.IsArray()) {
+ properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
+ std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
+ for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
+ SizeType targetIndex;
+ if (FindPropertyIndex(*targetItr, &targetIndex))
+ properties_[sourceIndex].dependencies[targetIndex] = true;
+ }
+ }
+ else if (itr->value.IsObject()) {
+ hasSchemaDependencies_ = true;
+ schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
+ properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
+ validatorCount_++;
+ }
+ }
+ }
+ }
+
+ if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
+ if (v->IsBool())
+ additionalProperties_ = v->GetBool();
+ else if (v->IsObject())
+ schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
+ }
+
+ AssignIfExist(minProperties_, value, GetMinPropertiesString());
+ AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
+
+ // Array
+ if (const ValueType* v = GetMember(value, GetItemsString())) {
+ PointerType q = p.Append(GetItemsString(), allocator_);
+ if (v->IsObject()) // List validation
+ schemaDocument->CreateSchema(&itemsList_, q, *v, document);
+ else if (v->IsArray()) { // Tuple validation
+ itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
+ SizeType index = 0;
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
+ schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
+ }
+ }
+
+ AssignIfExist(minItems_, value, GetMinItemsString());
+ AssignIfExist(maxItems_, value, GetMaxItemsString());
+
+ if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
+ if (v->IsBool())
+ additionalItems_ = v->GetBool();
+ else if (v->IsObject())
+ schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
+ }
+
+ AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
+
+ // String
+ AssignIfExist(minLength_, value, GetMinLengthString());
+ AssignIfExist(maxLength_, value, GetMaxLengthString());
+
+ if (const ValueType* v = GetMember(value, GetPatternString()))
+ pattern_ = CreatePattern(*v);
+
+ // Number
+ if (const ValueType* v = GetMember(value, GetMinimumString()))
+ if (v->IsNumber())
+ minimum_.CopyFrom(*v, *allocator_);
+
+ if (const ValueType* v = GetMember(value, GetMaximumString()))
+ if (v->IsNumber())
+ maximum_.CopyFrom(*v, *allocator_);
+
+ AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
+ AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
+
+ if (const ValueType* v = GetMember(value, GetMultipleOfString()))
+ if (v->IsNumber() && v->GetDouble() > 0.0)
+ multipleOf_.CopyFrom(*v, *allocator_);
+ }
+
+ ~Schema() {
+ AllocatorType::Free(enum_);
+ if (properties_) {
+ for (SizeType i = 0; i < propertyCount_; i++)
+ properties_[i].~Property();
+ AllocatorType::Free(properties_);
+ }
+ if (patternProperties_) {
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
+ patternProperties_[i].~PatternProperty();
+ AllocatorType::Free(patternProperties_);
+ }
+ AllocatorType::Free(itemsTuple_);
+#if RAPIDJSON_SCHEMA_HAS_REGEX
+ if (pattern_) {
+ pattern_->~RegexType();
+ AllocatorType::Free(pattern_);
+ }
+#endif
+ }
+
+ bool BeginValue(Context& context) const {
+ if (context.inArray) {
+ if (uniqueItems_)
+ context.valueUniqueness = true;
+
+ if (itemsList_)
+ context.valueSchema = itemsList_;
+ else if (itemsTuple_) {
+ if (context.arrayElementIndex < itemsTupleCount_)
+ context.valueSchema = itemsTuple_[context.arrayElementIndex];
+ else if (additionalItemsSchema_)
+ context.valueSchema = additionalItemsSchema_;
+ else if (additionalItems_)
+ context.valueSchema = typeless_;
+ else
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
+ }
+ else
+ context.valueSchema = typeless_;
+
+ context.arrayElementIndex++;
+ }
+ return true;
+ }
+
+ RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
+ if (context.patternPropertiesValidatorCount > 0) {
+ bool otherValid = false;
+ SizeType count = context.patternPropertiesValidatorCount;
+ if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
+ otherValid = context.patternPropertiesValidators[--count]->IsValid();
+
+ bool patternValid = true;
+ for (SizeType i = 0; i < count; i++)
+ if (!context.patternPropertiesValidators[i]->IsValid()) {
+ patternValid = false;
+ break;
+ }
+
+ if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
+ if (!patternValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+ else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
+ if (!patternValid || !otherValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+ else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+
+ if (enum_) {
+ const uint64_t h = context.factory.GetHashCode(context.hasher);
+ for (SizeType i = 0; i < enumCount_; i++)
+ if (enum_[i] == h)
+ goto foundEnum;
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
+ foundEnum:;
+ }
+
+ if (allOf_.schemas)
+ for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
+ if (!context.validators[i]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
+
+ if (anyOf_.schemas) {
+ for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
+ if (context.validators[i]->IsValid())
+ goto foundAny;
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
+ foundAny:;
+ }
+
+ if (oneOf_.schemas) {
+ bool oneValid = false;
+ for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
+ if (context.validators[i]->IsValid()) {
+ if (oneValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
+ else
+ oneValid = true;
+ }
+ if (!oneValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
+ }
+
+ if (not_ && context.validators[notValidatorIndex_]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
+
+ return true;
+ }
+
+ bool Null(Context& context) const {
+ if (!(type_ & (1 << kNullSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+ return CreateParallelValidator(context);
+ }
+
+ bool Bool(Context& context, bool) const {
+ if (!(type_ & (1 << kBooleanSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+ return CreateParallelValidator(context);
+ }
+
+ bool Int(Context& context, int i) const {
+ if (!CheckInt(context, i))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Uint(Context& context, unsigned u) const {
+ if (!CheckUint(context, u))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Int64(Context& context, int64_t i) const {
+ if (!CheckInt(context, i))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Uint64(Context& context, uint64_t u) const {
+ if (!CheckUint(context, u))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Double(Context& context, double d) const {
+ if (!(type_ & (1 << kNumberSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
+ return false;
+
+ if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
+ return false;
+
+ if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
+ return false;
+
+ return CreateParallelValidator(context);
+ }
+
+ bool String(Context& context, const Ch* str, SizeType length, bool) const {
+ if (!(type_ & (1 << kStringSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
+ SizeType count;
+ if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
+ if (count < minLength_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
+ if (count > maxLength_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
+ }
+ }
+
+ if (pattern_ && !IsPatternMatch(pattern_, str, length))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
+
+ return CreateParallelValidator(context);
+ }
+
+ bool StartObject(Context& context) const {
+ if (!(type_ & (1 << kObjectSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (hasDependencies_ || hasRequired_) {
+ context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
+ std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
+ }
+
+ if (patternProperties_) { // pre-allocate schema array
+ SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
+ context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
+ context.patternPropertiesSchemaCount = 0;
+ std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
+ }
+
+ return CreateParallelValidator(context);
+ }
+
+ bool Key(Context& context, const Ch* str, SizeType len, bool) const {
+ if (patternProperties_) {
+ context.patternPropertiesSchemaCount = 0;
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
+ if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
+ context.valueSchema = typeless_;
+ }
+ }
+
+ SizeType index;
+ if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
+ if (context.patternPropertiesSchemaCount > 0) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
+ context.valueSchema = typeless_;
+ context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
+ }
+ else
+ context.valueSchema = properties_[index].schema;
+
+ if (context.propertyExist)
+ context.propertyExist[index] = true;
+
+ return true;
+ }
+
+ if (additionalPropertiesSchema_) {
+ if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
+ context.valueSchema = typeless_;
+ context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
+ }
+ else
+ context.valueSchema = additionalPropertiesSchema_;
+ return true;
+ }
+ else if (additionalProperties_) {
+ context.valueSchema = typeless_;
+ return true;
+ }
+
+ if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
+
+ return true;
+ }
+
+ bool EndObject(Context& context, SizeType memberCount) const {
+ if (hasRequired_)
+ for (SizeType index = 0; index < propertyCount_; index++)
+ if (properties_[index].required)
+ if (!context.propertyExist[index])
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
+
+ if (memberCount < minProperties_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
+
+ if (memberCount > maxProperties_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
+
+ if (hasDependencies_) {
+ for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
+ if (context.propertyExist[sourceIndex]) {
+ if (properties_[sourceIndex].dependencies) {
+ for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
+ if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
+ }
+ else if (properties_[sourceIndex].dependenciesSchema)
+ if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
+ }
+ }
+
+ return true;
+ }
+
+ bool StartArray(Context& context) const {
+ if (!(type_ & (1 << kArraySchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ context.arrayElementIndex = 0;
+ context.inArray = true;
+
+ return CreateParallelValidator(context);
+ }
+
+ bool EndArray(Context& context, SizeType elementCount) const {
+ context.inArray = false;
+
+ if (elementCount < minItems_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
+
+ if (elementCount > maxItems_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
+
+ return true;
+ }
+
+ // Generate functions for string literal according to Ch
+#define RAPIDJSON_STRING_(name, ...) \
+ static const ValueType& Get##name##String() {\
+ static const Ch s[] = { __VA_ARGS__, '\0' };\
+ static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
+ return v;\
+ }
+
+ RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
+ RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
+ RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
+ RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
+ RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
+ RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
+ RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
+ RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
+ RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
+ RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
+ RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
+ RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
+ RAPIDJSON_STRING_(Not, 'n', 'o', 't')
+ RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
+ RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
+ RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
+ RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
+ RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
+ RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
+
+#undef RAPIDJSON_STRING_
+
+private:
+ enum SchemaValueType {
+ kNullSchemaType,
+ kBooleanSchemaType,
+ kObjectSchemaType,
+ kArraySchemaType,
+ kStringSchemaType,
+ kNumberSchemaType,
+ kIntegerSchemaType,
+ kTotalSchemaType
+ };
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+ typedef internal::GenericRegex<EncodingType> RegexType;
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+ typedef std::basic_regex<Ch> RegexType;
+#else
+ typedef char RegexType;
+#endif
+
+ struct SchemaArray {
+ SchemaArray() : schemas(), count() {}
+ ~SchemaArray() { AllocatorType::Free(schemas); }
+ const SchemaType** schemas;
+ SizeType begin; // begin index of context.validators
+ SizeType count;
+ };
+
+ template <typename V1, typename V2>
+ void AddUniqueElement(V1& a, const V2& v) {
+ for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
+ if (*itr == v)
+ return;
+ V1 c(v, *allocator_);
+ a.PushBack(c, *allocator_);
+ }
+
+ static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
+ typename ValueType::ConstMemberIterator itr = value.FindMember(name);
+ return itr != value.MemberEnd() ? &(itr->value) : 0;
+ }
+
+ static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
+ if (const ValueType* v = GetMember(value, name))
+ if (v->IsBool())
+ out = v->GetBool();
+ }
+
+ static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
+ if (const ValueType* v = GetMember(value, name))
+ if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
+ out = static_cast<SizeType>(v->GetUint64());
+ }
+
+ void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
+ if (const ValueType* v = GetMember(value, name)) {
+ if (v->IsArray() && v->Size() > 0) {
+ PointerType q = p.Append(name, allocator_);
+ out.count = v->Size();
+ out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
+ memset(out.schemas, 0, sizeof(Schema*)* out.count);
+ for (SizeType i = 0; i < out.count; i++)
+ schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
+ out.begin = validatorCount_;
+ validatorCount_ += out.count;
+ }
+ }
+ }
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType& value) {
+ if (value.IsString()) {
+ RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString());
+ if (!r->IsValid()) {
+ r->~RegexType();
+ AllocatorType::Free(r);
+ r = 0;
+ }
+ return r;
+ }
+ return 0;
+ }
+
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
+ GenericRegexSearch<RegexType> rs(*pattern);
+ return rs.Search(str);
+ }
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType& value) {
+ if (value.IsString())
+ try {
+ return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
+ }
+ catch (const std::regex_error&) {
+ }
+ return 0;
+ }
+
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
+ std::match_results<const Ch*> r;
+ return std::regex_search(str, str + length, r, *pattern);
+ }
+#else
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType&) { return 0; }
+
+ static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
+#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
+
+ void AddType(const ValueType& type) {
+ if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
+ else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
+ else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
+ else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
+ else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
+ else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
+ else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
+ }
+
+ bool CreateParallelValidator(Context& context) const {
+ if (enum_ || context.arrayUniqueness)
+ context.hasher = context.factory.CreateHasher();
+
+ if (validatorCount_) {
+ RAPIDJSON_ASSERT(context.validators == 0);
+ context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
+ context.validatorCount = validatorCount_;
+
+ if (allOf_.schemas)
+ CreateSchemaValidators(context, allOf_);
+
+ if (anyOf_.schemas)
+ CreateSchemaValidators(context, anyOf_);
+
+ if (oneOf_.schemas)
+ CreateSchemaValidators(context, oneOf_);
+
+ if (not_)
+ context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
+
+ if (hasSchemaDependencies_) {
+ for (SizeType i = 0; i < propertyCount_; i++)
+ if (properties_[i].dependenciesSchema)
+ context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
+ }
+ }
+
+ return true;
+ }
+
+ void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
+ for (SizeType i = 0; i < schemas.count; i++)
+ context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
+ }
+
+ // O(n)
+ bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
+ SizeType len = name.GetStringLength();
+ const Ch* str = name.GetString();
+ for (SizeType index = 0; index < propertyCount_; index++)
+ if (properties_[index].name.GetStringLength() == len &&
+ (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
+ {
+ *outIndex = index;
+ return true;
+ }
+ return false;
+ }
+
+ bool CheckInt(Context& context, int64_t i) const {
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull()) {
+ if (minimum_.IsInt64()) {
+ if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ }
+ else if (minimum_.IsUint64()) {
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
+ }
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!maximum_.IsNull()) {
+ if (maximum_.IsInt64()) {
+ if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ }
+ else if (maximum_.IsUint64()) { }
+ /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!multipleOf_.IsNull()) {
+ if (multipleOf_.IsUint64()) {
+ if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ }
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckUint(Context& context, uint64_t i) const {
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull()) {
+ if (minimum_.IsUint64()) {
+ if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ }
+ else if (minimum_.IsInt64())
+ /* do nothing */; // i >= 0 > minimum.Getint64()
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!maximum_.IsNull()) {
+ if (maximum_.IsUint64()) {
+ if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ }
+ else if (maximum_.IsInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!multipleOf_.IsNull()) {
+ if (multipleOf_.IsUint64()) {
+ if (i % multipleOf_.GetUint64() != 0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ }
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckDoubleMinimum(Context& context, double d) const {
+ if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ return true;
+ }
+
+ bool CheckDoubleMaximum(Context& context, double d) const {
+ if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ return true;
+ }
+
+ bool CheckDoubleMultipleOf(Context& context, double d) const {
+ double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
+ double q = std::floor(a / b);
+ double r = a - q * b;
+ if (r > 0.0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ return true;
+ }
+
+ struct Property {
+ Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
+ ~Property() { AllocatorType::Free(dependencies); }
+ SValue name;
+ const SchemaType* schema;
+ const SchemaType* dependenciesSchema;
+ SizeType dependenciesValidatorIndex;
+ bool* dependencies;
+ bool required;
+ };
+
+ struct PatternProperty {
+ PatternProperty() : schema(), pattern() {}
+ ~PatternProperty() {
+ if (pattern) {
+ pattern->~RegexType();
+ AllocatorType::Free(pattern);
+ }
+ }
+ const SchemaType* schema;
+ RegexType* pattern;
+ };
+
+ AllocatorType* allocator_;
+ const SchemaType* typeless_;
+ uint64_t* enum_;
+ SizeType enumCount_;
+ SchemaArray allOf_;
+ SchemaArray anyOf_;
+ SchemaArray oneOf_;
+ const SchemaType* not_;
+ unsigned type_; // bitmask of kSchemaType
+ SizeType validatorCount_;
+ SizeType notValidatorIndex_;
+
+ Property* properties_;
+ const SchemaType* additionalPropertiesSchema_;
+ PatternProperty* patternProperties_;
+ SizeType patternPropertyCount_;
+ SizeType propertyCount_;
+ SizeType minProperties_;
+ SizeType maxProperties_;
+ bool additionalProperties_;
+ bool hasDependencies_;
+ bool hasRequired_;
+ bool hasSchemaDependencies_;
+
+ const SchemaType* additionalItemsSchema_;
+ const SchemaType* itemsList_;
+ const SchemaType** itemsTuple_;
+ SizeType itemsTupleCount_;
+ SizeType minItems_;
+ SizeType maxItems_;
+ bool additionalItems_;
+ bool uniqueItems_;
+
+ RegexType* pattern_;
+ SizeType minLength_;
+ SizeType maxLength_;
+
+ SValue minimum_;
+ SValue maximum_;
+ SValue multipleOf_;
+ bool exclusiveMinimum_;
+ bool exclusiveMaximum_;
+};
+
+template<typename Stack, typename Ch>
+struct TokenHelper {
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
+ *documentStack.template Push<Ch>() = '/';
+ char buffer[21];
+ size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
+ for (size_t i = 0; i < length; i++)
+ *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
+ }
+};
+
+// Partial specialized version for char to prevent buffer copying.
+template <typename Stack>
+struct TokenHelper<Stack, char> {
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
+ if (sizeof(SizeType) == 4) {
+ char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
+ *buffer++ = '/';
+ const char* end = internal::u32toa(index, buffer);
+ documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
+ }
+ else {
+ char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
+ *buffer++ = '/';
+ const char* end = internal::u64toa(index, buffer);
+ documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
+ }
+ }
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// IGenericRemoteSchemaDocumentProvider
+
+template <typename SchemaDocumentType>
+class IGenericRemoteSchemaDocumentProvider {
+public:
+ typedef typename SchemaDocumentType::Ch Ch;
+
+ virtual ~IGenericRemoteSchemaDocumentProvider() {}
+ virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericSchemaDocument
+
+//! JSON schema document.
+/*!
+ A JSON schema document is a compiled version of a JSON schema.
+ It is basically a tree of internal::Schema.
+
+ \note This is an immutable class (i.e. its instance cannot be modified after construction).
+ \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding.
+ \tparam Allocator Allocator type for allocating memory of this document.
+*/
+template <typename ValueT, typename Allocator = CrtAllocator>
+class GenericSchemaDocument {
+public:
+ typedef ValueT ValueType;
+ typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
+ typedef Allocator AllocatorType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+ typedef internal::Schema<GenericSchemaDocument> SchemaType;
+ typedef GenericPointer<ValueType, Allocator> PointerType;
+ friend class internal::Schema<GenericSchemaDocument>;
+ template <typename, typename, typename>
+ friend class GenericSchemaValidator;
+
+ //! Constructor.
+ /*!
+ Compile a JSON document into schema document.
+
+ \param document A JSON document as source.
+ \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
+ \param allocator An optional allocator instance for allocating memory. Can be null.
+ */
+ explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
+ remoteProvider_(remoteProvider),
+ allocator_(allocator),
+ ownAllocator_(),
+ root_(),
+ typeless_(),
+ schemaMap_(allocator, kInitialSchemaMapSize),
+ schemaRef_(allocator, kInitialSchemaRefSize)
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
+
+ typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
+ new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
+
+ // Generate root schema, it will call CreateSchema() to create sub-schemas,
+ // And call AddRefSchema() if there are $ref.
+ CreateSchemaRecursive(&root_, PointerType(), document, document);
+
+ // Resolve $ref
+ while (!schemaRef_.Empty()) {
+ SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
+ if (const SchemaType* s = GetSchema(refEntry->target)) {
+ if (refEntry->schema)
+ *refEntry->schema = s;
+
+ // Create entry in map if not exist
+ if (!GetSchema(refEntry->source)) {
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
+ }
+ }
+ else if (refEntry->schema)
+ *refEntry->schema = typeless_;
+
+ refEntry->~SchemaRefEntry();
+ }
+
+ RAPIDJSON_ASSERT(root_ != 0);
+
+ schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
+ remoteProvider_(rhs.remoteProvider_),
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ root_(rhs.root_),
+ typeless_(rhs.typeless_),
+ schemaMap_(std::move(rhs.schemaMap_)),
+ schemaRef_(std::move(rhs.schemaRef_))
+ {
+ rhs.remoteProvider_ = 0;
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.typeless_ = 0;
+ }
+#endif
+
+ //! Destructor
+ ~GenericSchemaDocument() {
+ while (!schemaMap_.Empty())
+ schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
+
+ if (typeless_) {
+ typeless_->~SchemaType();
+ Allocator::Free(typeless_);
+ }
+
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ //! Get the root schema.
+ const SchemaType& GetRoot() const { return *root_; }
+
+private:
+ //! Prohibit copying
+ GenericSchemaDocument(const GenericSchemaDocument&);
+ //! Prohibit assignment
+ GenericSchemaDocument& operator=(const GenericSchemaDocument&);
+
+ struct SchemaRefEntry {
+ SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
+ PointerType source;
+ PointerType target;
+ const SchemaType** schema;
+ };
+
+ struct SchemaEntry {
+ SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
+ ~SchemaEntry() {
+ if (owned) {
+ schema->~SchemaType();
+ Allocator::Free(schema);
+ }
+ }
+ PointerType pointer;
+ SchemaType* schema;
+ bool owned;
+ };
+
+ void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
+ if (schema)
+ *schema = typeless_;
+
+ if (v.GetType() == kObjectType) {
+ const SchemaType* s = GetSchema(pointer);
+ if (!s)
+ CreateSchema(schema, pointer, v, document);
+
+ for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
+ CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
+ }
+ else if (v.GetType() == kArrayType)
+ for (SizeType i = 0; i < v.Size(); i++)
+ CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
+ }
+
+ void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
+ RAPIDJSON_ASSERT(pointer.IsValid());
+ if (v.IsObject()) {
+ if (!HandleRefSchema(pointer, schema, v, document)) {
+ SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
+ if (schema)
+ *schema = s;
+ }
+ }
+ }
+
+ bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
+ static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
+ static const ValueType kRefValue(kRefString, 4);
+
+ typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
+ if (itr == v.MemberEnd())
+ return false;
+
+ if (itr->value.IsString()) {
+ SizeType len = itr->value.GetStringLength();
+ if (len > 0) {
+ const Ch* s = itr->value.GetString();
+ SizeType i = 0;
+ while (i < len && s[i] != '#') // Find the first #
+ i++;
+
+ if (i > 0) { // Remote reference, resolve immediately
+ if (remoteProvider_) {
+ if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) {
+ PointerType pointer(&s[i], len - i, allocator_);
+ if (pointer.IsValid()) {
+ if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
+ if (schema)
+ *schema = sc;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ else if (s[i] == '#') { // Local reference, defer resolution
+ PointerType pointer(&s[i], len - i, allocator_);
+ if (pointer.IsValid()) {
+ if (const ValueType* nv = pointer.Get(document))
+ if (HandleRefSchema(source, schema, *nv, document))
+ return true;
+
+ new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ const SchemaType* GetSchema(const PointerType& pointer) const {
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
+ if (pointer == target->pointer)
+ return target->schema;
+ return 0;
+ }
+
+ PointerType GetPointer(const SchemaType* schema) const {
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
+ if (schema == target->schema)
+ return target->pointer;
+ return PointerType();
+ }
+
+ const SchemaType* GetTypeless() const { return typeless_; }
+
+ static const size_t kInitialSchemaMapSize = 64;
+ static const size_t kInitialSchemaRefSize = 64;
+
+ IRemoteSchemaDocumentProviderType* remoteProvider_;
+ Allocator *allocator_;
+ Allocator *ownAllocator_;
+ const SchemaType* root_; //!< Root schema.
+ SchemaType* typeless_;
+ internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
+ internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
+};
+
+//! GenericSchemaDocument using Value type.
+typedef GenericSchemaDocument<Value> SchemaDocument;
+//! IGenericRemoteSchemaDocumentProvider using SchemaDocument.
+typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericSchemaValidator
+
+//! JSON Schema Validator.
+/*!
+ A SAX style JSON schema validator.
+ It uses a \c GenericSchemaDocument to validate SAX events.
+ It delegates the incoming SAX events to an output handler.
+ The default output handler does nothing.
+ It can be reused multiple times by calling \c Reset().
+
+ \tparam SchemaDocumentType Type of schema document.
+ \tparam OutputHandler Type of output handler. Default handler does nothing.
+ \tparam StateAllocator Allocator for storing the internal validation states.
+*/
+template <
+ typename SchemaDocumentType,
+ typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
+ typename StateAllocator = CrtAllocator>
+class GenericSchemaValidator :
+ public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
+ public internal::ISchemaValidator
+{
+public:
+ typedef typename SchemaDocumentType::SchemaType SchemaType;
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename SchemaType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+
+ //! Constructor without output handler.
+ /*!
+ \param schemaDocument The schema document to conform to.
+ \param allocator Optional allocator for storing internal validation states.
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
+ \param documentStackCapacity Optional initial capacity of document path stack.
+ */
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(schemaDocument.GetRoot()),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ outputHandler_(0),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(0)
+#endif
+ {
+ }
+
+ //! Constructor with output handler.
+ /*!
+ \param schemaDocument The schema document to conform to.
+ \param allocator Optional allocator for storing internal validation states.
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
+ \param documentStackCapacity Optional initial capacity of document path stack.
+ */
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ OutputHandler& outputHandler,
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(schemaDocument.GetRoot()),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ outputHandler_(&outputHandler),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(0)
+#endif
+ {
+ }
+
+ //! Destructor.
+ ~GenericSchemaValidator() {
+ Reset();
+ RAPIDJSON_DELETE(ownStateAllocator_);
+ }
+
+ //! Reset the internal states.
+ void Reset() {
+ while (!schemaStack_.Empty())
+ PopSchema();
+ documentStack_.Clear();
+ valid_ = true;
+ }
+
+ //! Checks whether the current state is valid.
+ // Implementation of ISchemaValidator
+ virtual bool IsValid() const { return valid_; }
+
+ //! Gets the JSON pointer pointed to the invalid schema.
+ PointerType GetInvalidSchemaPointer() const {
+ return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
+ }
+
+ //! Gets the keyword of invalid schema.
+ const Ch* GetInvalidSchemaKeyword() const {
+ return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
+ }
+
+ //! Gets the JSON pointer pointed to the invalid value.
+ PointerType GetInvalidDocumentPointer() const {
+ return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
+ }
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
+RAPIDJSON_MULTILINEMACRO_BEGIN\
+ *documentStack_.template Push<Ch>() = '\0';\
+ documentStack_.template Pop<Ch>(1);\
+ internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
+RAPIDJSON_MULTILINEMACRO_END
+#else
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
+#endif
+
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
+ if (!valid_) return false; \
+ if (!BeginValue() || !CurrentSchema().method arg1) {\
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
+ return valid_ = false;\
+ }
+
+#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
+ for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
+ if (context->hasher)\
+ static_cast<HasherType*>(context->hasher)->method arg2;\
+ if (context->validators)\
+ for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
+ static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
+ if (context->patternPropertiesValidators)\
+ for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
+ static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
+ }
+
+#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
+ return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2)
+
+#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
+ RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
+
+ bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); }
+ bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
+ bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
+ bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
+ bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
+ bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
+ bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
+ bool RawNumber(const Ch* str, SizeType length, bool copy)
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
+ bool String(const Ch* str, SizeType length, bool copy)
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
+
+ bool StartObject() {
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
+ return valid_ = !outputHandler_ || outputHandler_->StartObject();
+ }
+
+ bool Key(const Ch* str, SizeType len, bool copy) {
+ if (!valid_) return false;
+ AppendToken(str, len);
+ if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
+ return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
+ }
+
+ bool EndObject(SizeType memberCount) {
+ if (!valid_) return false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
+ if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
+ }
+
+ bool StartArray() {
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
+ return valid_ = !outputHandler_ || outputHandler_->StartArray();
+ }
+
+ bool EndArray(SizeType elementCount) {
+ if (!valid_) return false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
+ if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
+ }
+
+#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
+#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
+#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
+#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
+
+ // Implementation of ISchemaStateFactory<SchemaType>
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
+ return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root,
+#if RAPIDJSON_SCHEMA_VERBOSE
+ depth_ + 1,
+#endif
+ &GetStateAllocator());
+ }
+
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) {
+ GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
+ v->~GenericSchemaValidator();
+ StateAllocator::Free(v);
+ }
+
+ virtual void* CreateHasher() {
+ return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
+ }
+
+ virtual uint64_t GetHashCode(void* hasher) {
+ return static_cast<HasherType*>(hasher)->GetHashCode();
+ }
+
+ virtual void DestroryHasher(void* hasher) {
+ HasherType* h = static_cast<HasherType*>(hasher);
+ h->~HasherType();
+ StateAllocator::Free(h);
+ }
+
+ virtual void* MallocState(size_t size) {
+ return GetStateAllocator().Malloc(size);
+ }
+
+ virtual void FreeState(void* p) {
+ StateAllocator::Free(p);
+ }
+
+private:
+ typedef typename SchemaType::Context Context;
+ typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
+ typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
+
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ const SchemaType& root,
+#if RAPIDJSON_SCHEMA_VERBOSE
+ unsigned depth,
+#endif
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(root),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ outputHandler_(0),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(depth)
+#endif
+ {
+ }
+
+ StateAllocator& GetStateAllocator() {
+ if (!stateAllocator_)
+ stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)();
+ return *stateAllocator_;
+ }
+
+ bool BeginValue() {
+ if (schemaStack_.Empty())
+ PushSchema(root_);
+ else {
+ if (CurrentContext().inArray)
+ internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
+
+ if (!CurrentSchema().BeginValue(CurrentContext()))
+ return false;
+
+ SizeType count = CurrentContext().patternPropertiesSchemaCount;
+ const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
+ typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
+ bool valueUniqueness = CurrentContext().valueUniqueness;
+ RAPIDJSON_ASSERT(CurrentContext().valueSchema);
+ PushSchema(*CurrentContext().valueSchema);
+
+ if (count > 0) {
+ CurrentContext().objectPatternValidatorType = patternValidatorType;
+ ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
+ SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
+ va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
+ for (SizeType i = 0; i < count; i++)
+ va[validatorCount++] = CreateSchemaValidator(*sa[i]);
+ }
+
+ CurrentContext().arrayUniqueness = valueUniqueness;
+ }
+ return true;
+ }
+
+ bool EndValue() {
+ if (!CurrentSchema().EndValue(CurrentContext()))
+ return false;
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+ GenericStringBuffer<EncodingType> sb;
+ schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
+
+ *documentStack_.template Push<Ch>() = '\0';
+ documentStack_.template Pop<Ch>(1);
+ internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
+#endif
+
+ uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
+
+ PopSchema();
+
+ if (!schemaStack_.Empty()) {
+ Context& context = CurrentContext();
+ if (context.valueUniqueness) {
+ HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
+ if (!a)
+ CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
+ for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
+ if (itr->GetUint64() == h)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
+ a->PushBack(h, GetStateAllocator());
+ }
+ }
+
+ // Remove the last token of document pointer
+ while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
+ ;
+
+ return true;
+ }
+
+ void AppendToken(const Ch* str, SizeType len) {
+ documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
+ *documentStack_.template PushUnsafe<Ch>() = '/';
+ for (SizeType i = 0; i < len; i++) {
+ if (str[i] == '~') {
+ *documentStack_.template PushUnsafe<Ch>() = '~';
+ *documentStack_.template PushUnsafe<Ch>() = '0';
+ }
+ else if (str[i] == '/') {
+ *documentStack_.template PushUnsafe<Ch>() = '~';
+ *documentStack_.template PushUnsafe<Ch>() = '1';
+ }
+ else
+ *documentStack_.template PushUnsafe<Ch>() = str[i];
+ }
+ }
+
+ RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); }
+
+ RAPIDJSON_FORCEINLINE void PopSchema() {
+ Context* c = schemaStack_.template Pop<Context>(1);
+ if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
+ a->~HashCodeArray();
+ StateAllocator::Free(a);
+ }
+ c->~Context();
+ }
+
+ const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
+ Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
+ const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
+
+ static const size_t kDefaultSchemaStackCapacity = 1024;
+ static const size_t kDefaultDocumentStackCapacity = 256;
+ const SchemaDocumentType* schemaDocument_;
+ const SchemaType& root_;
+ StateAllocator* stateAllocator_;
+ StateAllocator* ownStateAllocator_;
+ internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
+ internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
+ OutputHandler* outputHandler_;
+ bool valid_;
+#if RAPIDJSON_SCHEMA_VERBOSE
+ unsigned depth_;
+#endif
+};
+
+typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
+
+///////////////////////////////////////////////////////////////////////////////
+// SchemaValidatingReader
+
+//! A helper class for parsing with validation.
+/*!
+ This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate().
+
+ \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam SchemaDocumentType Type of schema document.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <
+ unsigned parseFlags,
+ typename InputStream,
+ typename SourceEncoding,
+ typename SchemaDocumentType = SchemaDocument,
+ typename StackAllocator = CrtAllocator>
+class SchemaValidatingReader {
+public:
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename InputStream::Ch Ch;
+
+ //! Constructor
+ /*!
+ \param is Input stream.
+ \param sd Schema document.
+ */
+ SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {}
+
+ template <typename Handler>
+ bool operator()(Handler& handler) {
+ GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
+ GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
+ parseResult_ = reader.template Parse<parseFlags>(is_, validator);
+
+ isValid_ = validator.IsValid();
+ if (isValid_) {
+ invalidSchemaPointer_ = PointerType();
+ invalidSchemaKeyword_ = 0;
+ invalidDocumentPointer_ = PointerType();
+ }
+ else {
+ invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
+ invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
+ invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
+ }
+
+ return parseResult_;
+ }
+
+ const ParseResult& GetParseResult() const { return parseResult_; }
+ bool IsValid() const { return isValid_; }
+ const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
+ const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
+ const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
+
+private:
+ InputStream& is_;
+ const SchemaDocumentType& sd_;
+
+ ParseResult parseResult_;
+ PointerType invalidSchemaPointer_;
+ const Ch* invalidSchemaKeyword_;
+ PointerType invalidDocumentPointer_;
+ bool isValid_;
+};
+
+RAPIDJSON_NAMESPACE_END
+RAPIDJSON_DIAG_POP
+
+#endif // RAPIDJSON_SCHEMA_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stream.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stream.h
new file mode 100644
index 000000000..fef82c252
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stream.h
@@ -0,0 +1,179 @@
+// 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.
+
+#include "rapidjson.h"
+
+#ifndef RAPIDJSON_STREAM_H_
+#define RAPIDJSON_STREAM_H_
+
+#include "encodings.h"
+
+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 };
+};
+
+//! Reserve n characters for writing to a stream.
+template<typename Stream>
+inline void PutReserve(Stream& stream, size_t count) {
+ (void)stream;
+ (void)count;
+}
+
+//! Write character to a stream, presuming buffer is reserved.
+template<typename Stream>
+inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
+ stream.Put(c);
+}
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+ PutReserve(stream, n);
+ for (size_t i = 0; i < n; i++)
+ PutUnsafe(stream, 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;
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STREAM_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h
index 1c9c80b79..4e38b82c3 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/stringbuffer.h
@@ -15,7 +15,8 @@
#ifndef RAPIDJSON_STRINGBUFFER_H_
#define RAPIDJSON_STRINGBUFFER_H_
-#include "rapidjson.h"
+#include "stream.h"
+#include "internal/stack.h"
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#include <utility> // std::move
@@ -23,6 +24,11 @@
#include "internal/stack.h"
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
//! Represents an in-memory output stream.
@@ -48,6 +54,7 @@ public:
#endif
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
void Flush() {}
void Clear() { stack_.Clear(); }
@@ -57,7 +64,10 @@ public:
stack_.ShrinkToFit();
stack_.template Pop<Ch>(1);
}
+
+ void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
void Pop(size_t count) { stack_.template Pop<Ch>(count); }
const Ch* GetString() const {
@@ -68,8 +78,12 @@ public:
return stack_.template Bottom<Ch>();
}
+ //! Get the size of string in bytes in the string buffer.
size_t GetSize() const { return stack_.GetSize(); }
+ //! Get the length of string in Ch in the string buffer.
+ size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }
+
static const size_t kDefaultCapacity = 256;
mutable internal::Stack<Allocator> stack_;
@@ -82,6 +96,16 @@ private:
//! String buffer with UTF8 encoding
typedef GenericStringBuffer<UTF8<> > StringBuffer;
+template<typename Encoding, typename Allocator>
+inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
+ stream.Reserve(count);
+}
+
+template<typename Encoding, typename Allocator>
+inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
+ stream.PutUnsafe(c);
+}
+
//! Implement specialized version of PutN() with memset() for better performance.
template<>
inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
@@ -90,4 +114,8 @@ inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
RAPIDJSON_NAMESPACE_END
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
#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
index 874faa881..e610ebb60 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h
+++ b/src/3rdparty/assimp/contrib/rapidjson/include/rapidjson/writer.h
@@ -15,7 +15,8 @@
#ifndef RAPIDJSON_WRITER_H_
#define RAPIDJSON_WRITER_H_
-#include "rapidjson.h"
+#include "stream.h"
+#include "internal/meta.h"
#include "internal/stack.h"
#include "internal/strfunc.h"
#include "internal/dtoa.h"
@@ -23,8 +24,16 @@
#include "stringbuffer.h"
#include <new> // placement new
-#if RAPIDJSON_HAS_STDSTRING
-#include <string>
+#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>
+#elif defined(RAPIDJSON_NEON)
+#include <arm_neon.h>
#endif
#ifdef _MSC_VER
@@ -32,8 +41,36 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#endif
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
+///////////////////////////////////////////////////////////////////////////////
+// WriteFlag
+
+/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kWriteDefaultFlags definition.
+
+ User can define this as any \c WriteFlag combinations.
+*/
+#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
+#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
+#endif
+
+//! Combination of writeFlags
+enum WriteFlag {
+ kWriteNoFlags = 0, //!< No flags are set.
+ kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
+ kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
+ kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
+};
+
//! JSON writer
/*! Writer implements the concept Handler.
It generates JSON text by events to an output os.
@@ -50,11 +87,13 @@ RAPIDJSON_NAMESPACE_BEGIN
\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>
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class Writer {
public:
typedef typename SourceEncoding::Ch Ch;
+ static const int kDefaultMaxDecimalPlaces = 324;
+
//! Constructor
/*! \param os Output stream.
\param stackAllocator User supplied allocator. If it is null, it will create a private one.
@@ -62,11 +101,18 @@ public:
*/
explicit
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
- os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+ os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
explicit
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
- os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+ os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Writer(Writer&& rhs) :
+ os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
+ rhs.os_ = 0;
+ }
+#endif
//! Reset the writer with a new stream.
/*!
@@ -100,29 +146,66 @@ public:
return hasRoot_ && level_stack_.Empty();
}
+ int GetMaxDecimalPlaces() const {
+ return maxDecimalPlaces_;
+ }
+
+ //! Sets the maximum number of decimal places for double output.
+ /*!
+ This setting truncates the output with specified number of decimal places.
+
+ For example,
+
+ \code
+ writer.SetMaxDecimalPlaces(3);
+ writer.StartArray();
+ writer.Double(0.12345); // "0.123"
+ writer.Double(0.0001); // "0.0"
+ writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
+ writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
+ writer.EndArray();
+ \endcode
+
+ The default setting does not truncate any decimal places. You can restore to this setting by calling
+ \code
+ writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
+ \endcode
+ */
+ void SetMaxDecimalPlaces(int maxDecimalPlaces) {
+ maxDecimalPlaces_ = maxDecimalPlaces;
+ }
+
/*!@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); }
+ bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
+ bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
+ bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
+ bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
+ bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
+ bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(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 Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
+ RAPIDJSON_ASSERT(str != 0);
+ (void)copy;
+ Prefix(kNumberType);
+ return EndValue(WriteString(str, length));
+ }
bool String(const Ch* str, SizeType length, bool copy = false) {
+ RAPIDJSON_ASSERT(str != 0);
(void)copy;
Prefix(kStringType);
- return WriteString(str, length);
+ return EndValue(WriteString(str, length));
}
#if RAPIDJSON_HAS_STDSTRING
@@ -138,16 +221,21 @@ public:
}
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool Key(const std::basic_string<Ch>& str)
+ {
+ return Key(str.data(), SizeType(str.size()));
+ }
+#endif
bool EndObject(SizeType memberCount = 0) {
(void)memberCount;
- RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
- RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
+ RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
+ RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
level_stack_.template Pop<Level>(1);
- bool ret = WriteEndObject();
- if (level_stack_.Empty()) // end of json text
- os_->Flush();
- return ret;
+ return EndValue(WriteEndObject());
}
bool StartArray() {
@@ -161,10 +249,7 @@ public:
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;
+ return EndValue(WriteEndArray());
}
//@}
@@ -172,11 +257,33 @@ public:
//@{
//! 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)); }
-
+ bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
+
//@}
+ //! Write a raw JSON value.
+ /*!
+ For user to write a stringified JSON as a value.
+
+ \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
+ \param length Length of the json.
+ \param type Type of the root of json.
+ */
+ bool RawValue(const Ch* json, size_t length, Type type) {
+ RAPIDJSON_ASSERT(json != 0);
+ Prefix(type);
+ return EndValue(WriteRawValue(json, length));
+ }
+
+ //! Flush the output stream.
+ /*!
+ Allows the user to flush the output stream immediately.
+ */
+ void Flush() {
+ os_->Flush();
+ }
+
protected:
//! Information for each nested level
struct Level {
@@ -188,15 +295,18 @@ protected:
static const size_t kDefaultLevelDepth = 32;
bool WriteNull() {
- os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
+ PutReserve(*os_, 4);
+ PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
}
bool WriteBool(bool b) {
if (b) {
- os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
+ PutReserve(*os_, 4);
+ PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
}
else {
- os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
+ PutReserve(*os_, 5);
+ PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
}
return true;
}
@@ -204,45 +314,69 @@ protected:
bool WriteInt(int i) {
char buffer[11];
const char* end = internal::i32toa(i, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p)
- os_->Put(*p);
+ PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
return true;
}
bool WriteUint(unsigned u) {
char buffer[10];
const char* end = internal::u32toa(u, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p)
- os_->Put(*p);
+ PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
return true;
}
bool WriteInt64(int64_t i64) {
char buffer[21];
const char* end = internal::i64toa(i64, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p)
- os_->Put(*p);
+ PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char* end = internal::u64toa(u64, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p)
- os_->Put(*p);
+ PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
return true;
}
bool WriteDouble(double d) {
+ if (internal::Double(d).IsNanOrInf()) {
+ if (!(writeFlags & kWriteNanAndInfFlag))
+ return false;
+ if (internal::Double(d).IsNan()) {
+ PutReserve(*os_, 3);
+ PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
+ return true;
+ }
+ if (internal::Double(d).Sign()) {
+ PutReserve(*os_, 9);
+ PutUnsafe(*os_, '-');
+ }
+ else
+ PutReserve(*os_, 8);
+ PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
+ PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
+ return true;
+ }
+
char buffer[25];
- char* end = internal::dtoa(d, buffer);
+ char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p)
- os_->Put(*p);
+ PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*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 typename OutputStream::Ch 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
@@ -255,22 +389,27 @@ protected:
#undef Z16
};
- os_->Put('\"');
+ if (TargetEncoding::supportUnicode)
+ PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
+ else
+ PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
+
+ PutUnsafe(*os_, '\"');
GenericStringStream<SourceEncoding> is(str);
- while (is.Tell() < length) {
+ while (ScanWriteUnescapedString(is, length)) {
const Ch c = is.Peek();
- if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
+ if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
// Unicode escaping
unsigned codepoint;
- if (!SourceEncoding::Decode(is, &codepoint))
+ if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
return false;
- os_->Put('\\');
- os_->Put('u');
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, '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]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
}
else {
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
@@ -278,45 +417,59 @@ protected:
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]);
+ PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead ) & 15]);
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, 'u');
+ PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail ) & 15]);
}
}
- else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
+ else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<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]);
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
+ if (escape[static_cast<unsigned char>(c)] == 'u') {
+ PutUnsafe(*os_, '0');
+ PutUnsafe(*os_, '0');
+ PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
+ PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
}
}
- else
- if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
- return false;
+ else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
+ Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
+ Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
+ return false;
}
- os_->Put('\"');
+ PutUnsafe(*os_, '\"');
return true;
}
+ bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+
bool WriteStartObject() { os_->Put('{'); return true; }
bool WriteEndObject() { os_->Put('}'); return true; }
bool WriteStartArray() { os_->Put('['); return true; }
bool WriteEndArray() { os_->Put(']'); return true; }
+ bool WriteRawValue(const Ch* json, size_t length) {
+ PutReserve(*os_, length);
+ for (size_t i = 0; i < length; i++) {
+ RAPIDJSON_ASSERT(json[i] != '\0');
+ PutUnsafe(*os_, json[i]);
+ }
+ return true;
+ }
+
void Prefix(Type type) {
(void)type;
- if (level_stack_.GetSize() != 0) { // this value is not at root
+ if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
Level* level = level_stack_.template Top<Level>();
if (level->valueCount > 0) {
if (level->inArray)
@@ -334,8 +487,16 @@ protected:
}
}
+ // Flush the value if it is the top level one.
+ bool EndValue(bool ret) {
+ if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
+ Flush();
+ return ret;
+ }
+
OutputStream* os_;
internal::Stack<StackAllocator> level_stack_;
+ int maxDecimalPlaces_;
bool hasRoot_;
private:
@@ -380,16 +541,171 @@ inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) {
+ if (internal::Double(d).IsNanOrInf()) {
+ // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
+ if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
+ return false;
+ if (internal::Double(d).IsNan()) {
+ PutReserve(*os_, 3);
+ PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
+ return true;
+ }
+ if (internal::Double(d).Sign()) {
+ PutReserve(*os_, 9);
+ PutUnsafe(*os_, '-');
+ }
+ else
+ PutReserve(*os_, 8);
+ PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
+ PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
+ return true;
+ }
+
char *buffer = os_->Push(25);
- char* end = internal::dtoa(d, buffer);
+ char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
os_->Pop(static_cast<size_t>(25 - (end - buffer)));
return true;
}
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+template<>
+inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
+ if (length < 16)
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+
+ if (!RAPIDJSON_LIKELY(is.Tell() < length))
+ return false;
+
+ const char* p = is.src_;
+ const char* end = is.head_ + length;
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
+ if (nextAligned > end)
+ return true;
+
+ while (p != nextAligned)
+ if (*p < 0x20 || *p == '\"' || *p == '\\') {
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+ else
+ os_->PutUnsafe(*p++);
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (; p != endAligned; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ SizeType len;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ len = offset;
+#else
+ len = static_cast<SizeType>(__builtin_ffs(r) - 1);
+#endif
+ char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
+ for (size_t i = 0; i < len; i++)
+ q[i] = p[i];
+
+ p += len;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
+ }
+
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+}
+#elif defined(RAPIDJSON_NEON)
+template<>
+inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
+ if (length < 16)
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+
+ if (!RAPIDJSON_LIKELY(is.Tell() < length))
+ return false;
+
+ const char* p = is.src_;
+ const char* end = is.head_ + length;
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
+ if (nextAligned > end)
+ return true;
+
+ while (p != nextAligned)
+ if (*p < 0x20 || *p == '\"' || *p == '\\') {
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+ else
+ os_->PutUnsafe(*p++);
+
+ // The rest of string using SIMD
+ const uint8x16_t s0 = vmovq_n_u8('"');
+ const uint8x16_t s1 = vmovq_n_u8('\\');
+ const uint8x16_t s2 = vmovq_n_u8('\b');
+ const uint8x16_t s3 = vmovq_n_u8(32);
+
+ for (; p != endAligned; p += 16) {
+ const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
+ uint8x16_t x = vceqq_u8(s, s0);
+ x = vorrq_u8(x, vceqq_u8(s, s1));
+ x = vorrq_u8(x, vceqq_u8(s, s2));
+ x = vorrq_u8(x, vcltq_u8(s, s3));
+
+ x = vrev64q_u8(x); // Rev in 64
+ uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
+ uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
+
+ SizeType len = 0;
+ bool escaped = false;
+ if (low == 0) {
+ if (high != 0) {
+ unsigned lz = (unsigned)__builtin_clzll(high);
+ len = 8 + (lz >> 3);
+ escaped = true;
+ }
+ } else {
+ unsigned lz = (unsigned)__builtin_clzll(low);
+ len = lz >> 3;
+ escaped = true;
+ }
+ if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
+ char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
+ for (size_t i = 0; i < len; i++)
+ q[i] = p[i];
+
+ p += len;
+ break;
+ }
+ vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
+ }
+
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+}
+#endif // RAPIDJSON_NEON
+
RAPIDJSON_NAMESPACE_END
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP
#endif
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/3rdparty/assimp/contrib/rapidjson/readme.md b/src/3rdparty/assimp/contrib/rapidjson/readme.md
index fb270fb96..b833a98e8 100644
--- a/src/3rdparty/assimp/contrib/rapidjson/readme.md
+++ b/src/3rdparty/assimp/contrib/rapidjson/readme.md
@@ -1,14 +1,14 @@
-![](doc/logo/rapidjson.png)
+![RapidJSON logo](doc/logo/rapidjson.png)
-![](https://img.shields.io/badge/release-v1.0.2-blue.png)
+![Release version](https://img.shields.io/badge/release-v1.1.0-blue.svg)
-## A fast JSON parser/generator for C++ with both SAX/DOM style API
+## 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 GitHub](https://github.com/Tencent/rapidjson/)
* RapidJSON Documentation
* [English](http://rapidjson.org/)
* [简体中文](http://rapidjson.org/zh-cn/)
@@ -20,12 +20,12 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
| :---------------: | :-----------------: | :-------------------: |
| ![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
+[lin-badge]: https://travis-ci.org/Tencent/rapidjson.svg?branch=master "Travis build status"
+[lin-link]: https://travis-ci.org/Tencent/rapidjson "Travis build status"
+[win-badge]: https://ci.appveyor.com/api/projects/status/l6qulgqahcayidrf/branch/master?svg=true "AppVeyor build status"
+[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson-0fdqj/branch/master "AppVeyor build status"
+[cov-badge]: https://coveralls.io/repos/Tencent/rapidjson/badge.svg?branch=master "Coveralls coverage"
+[cov-link]: https://coveralls.io/r/Tencent/rapidjson?branch=master "Coveralls coverage"
## Introduction
@@ -37,16 +37,26 @@ RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](
* 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 **memory-friendly**. Each JSON value occupies exactly 16 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
+JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in fully compliance with RFC7159/ECMA-404, with optional support of relaxed syntax. 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)
+* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159)
+* [Standard ECMA-404: The JSON Data Interchange Format](https://www.ecma-international.org/publications/standards/Ecma-404.htm)
+
+## Highlights in v1.1 (2016-8-25)
+
+* Added [JSON Pointer](doc/pointer.md)
+* Added [JSON Schema](doc/schema.md)
+* Added [relaxed JSON syntax](doc/dom.md) (comment, trailing comma, NaN/Infinity)
+* Iterating array/object with [C++11 Range-based for loop](doc/tutorial.md)
+* Reduce memory overhead of each `Value` from 24 bytes to 16 bytes in x86-64 architecture.
+
+For other changes please refer to [change log](CHANGELOG.md).
## Compatibility
@@ -63,9 +73,9 @@ Users can build and run the unit tests on their platform/compiler.
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
+* [CMake](https://cmake.org/) as a general build tool
+* (optional) [Doxygen](http://www.doxygen.org) to build documentation
+* (optional) [googletest](https://github.com/google/googletest) for unit and performance testing
To generate user documentation and run tests please proceed with the steps below:
@@ -74,7 +84,7 @@ To generate user documentation and run tests please proceed with the steps below
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`
+On successful 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
@@ -126,4 +136,25 @@ The following diagram shows the process.
![simpledom](doc/diagram/simpledom.png)
-More [examples](https://github.com/miloyip/rapidjson/tree/master/example) are available.
+More [examples](https://github.com/Tencent/rapidjson/tree/master/example) are available:
+
+* DOM API
+ * [tutorial](https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp): Basic usage of DOM API.
+
+* SAX API
+ * [simplereader](https://github.com/Tencent/rapidjson/blob/master/example/simplereader/simplereader.cpp): Dumps all SAX events while parsing a JSON by `Reader`.
+ * [condense](https://github.com/Tencent/rapidjson/blob/master/example/condense/condense.cpp): A command line tool to rewrite a JSON, with all whitespaces removed.
+ * [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp): A command line tool to rewrite a JSON with indents and newlines by `PrettyWriter`.
+ * [capitalize](https://github.com/Tencent/rapidjson/blob/master/example/capitalize/capitalize.cpp): A command line tool to capitalize strings in JSON.
+ * [messagereader](https://github.com/Tencent/rapidjson/blob/master/example/messagereader/messagereader.cpp): Parse a JSON message with SAX API.
+ * [serialize](https://github.com/Tencent/rapidjson/blob/master/example/serialize/serialize.cpp): Serialize a C++ object into JSON with SAX API.
+ * [jsonx](https://github.com/Tencent/rapidjson/blob/master/example/jsonx/jsonx.cpp): Implements a `JsonxWriter` which stringify SAX events into [JSONx](https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html) (a kind of XML) format. The example is a command line tool which converts input JSON into JSONx format.
+
+* Schema
+ * [schemavalidator](https://github.com/Tencent/rapidjson/blob/master/example/schemavalidator/schemavalidator.cpp) : A command line tool to validate a JSON with a JSON schema.
+
+* Advanced
+ * [prettyauto](https://github.com/Tencent/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): A modified version of [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp) to automatically handle JSON with any UTF encodings.
+ * [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread.
+ * [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key.
+ * [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkeydom/filterkeydom.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`.
diff --git a/src/3rdparty/assimp/contrib/unzip/crypt.h b/src/3rdparty/assimp/contrib/unzip/crypt.h
index 1362cfcd1..2aa99c284 100644
--- a/src/3rdparty/assimp/contrib/unzip/crypt.h
+++ b/src/3rdparty/assimp/contrib/unzip/crypt.h
@@ -32,7 +32,7 @@
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
-static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
@@ -45,13 +45,13 @@ static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
-static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
- int keyshift = (int)((*(pkeys+1)) >> 24);
+ register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
@@ -62,7 +62,7 @@ static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int
* Initialize the encryption keys and the random header according to
* the given password.
*/
-static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
diff --git a/src/3rdparty/assimp/contrib/unzip/ioapi.c b/src/3rdparty/assimp/contrib/unzip/ioapi.c
index b7200df75..f1bee23e6 100644
--- a/src/3rdparty/assimp/contrib/unzip/ioapi.c
+++ b/src/3rdparty/assimp/contrib/unzip/ioapi.c
@@ -10,11 +10,7 @@
#include <stdlib.h>
#include <string.h>
-# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
-# else
-# include "../zlib/zlib.h"
-# endif
+#include "zlib.h"
#include "ioapi.h"
@@ -33,40 +29,40 @@
#define SEEK_SET 0
#endif
-voidpf ZCALLBACK fopen_file_func (
+voidpf ZCALLBACK fopen_file_func OF((
voidpf opaque,
const char* filename,
- int mode);
+ int mode));
-uLong ZCALLBACK fread_file_func (
+uLong ZCALLBACK fread_file_func OF((
voidpf opaque,
voidpf stream,
void* buf,
- uLong size);
+ uLong size));
-uLong ZCALLBACK fwrite_file_func (
+uLong ZCALLBACK fwrite_file_func OF((
voidpf opaque,
voidpf stream,
const void* buf,
- uLong size);
+ uLong size));
-long ZCALLBACK ftell_file_func (
+long ZCALLBACK ftell_file_func OF((
voidpf opaque,
- voidpf stream);
+ voidpf stream));
-long ZCALLBACK fseek_file_func (
+long ZCALLBACK fseek_file_func OF((
voidpf opaque,
voidpf stream,
uLong offset,
- int origin);
+ int origin));
-int ZCALLBACK fclose_file_func (
+int ZCALLBACK fclose_file_func OF((
voidpf opaque,
- voidpf stream);
+ voidpf stream));
-int ZCALLBACK ferror_file_func (
+int ZCALLBACK ferror_file_func OF((
voidpf opaque,
- voidpf stream);
+ voidpf stream));
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
diff --git a/src/3rdparty/assimp/contrib/unzip/ioapi.h b/src/3rdparty/assimp/contrib/unzip/ioapi.h
index 06fdd15e9..7d457baab 100644
--- a/src/3rdparty/assimp/contrib/unzip/ioapi.h
+++ b/src/3rdparty/assimp/contrib/unzip/ioapi.h
@@ -35,13 +35,13 @@
extern "C" {
#endif
-typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
-typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
-typedef uLong (ZCALLBACK *write_file_func)(voidpf opaque, voidpf stream, const void* buf, uLong size);
-typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
-typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
-typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
-typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef struct zlib_filefunc_def_s
{
@@ -57,7 +57,7 @@ typedef struct zlib_filefunc_def_s
-void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def);
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
diff --git a/src/3rdparty/assimp/contrib/unzip/unzip.c b/src/3rdparty/assimp/contrib/unzip/unzip.c
index af00f7d6f..e8b62e763 100644
--- a/src/3rdparty/assimp/contrib/unzip/unzip.c
+++ b/src/3rdparty/assimp/contrib/unzip/unzip.c
@@ -38,7 +38,8 @@ woven in by Terry Thorsen 1/2003.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "./unzip.h"
+#include "zlib.h"
+#include "unzip.h"
#ifdef STDC
# include <stddef.h>
@@ -146,7 +147,7 @@ typedef struct
int encrypted;
# ifndef NOUNCRYPT
unsigned long keys[3]; /* keys defining the pseudo-random sequence */
- const unsigned long* pcrc_32_tab;
+ const z_crc_t* pcrc_32_tab;
# endif
} unz_s;
@@ -162,10 +163,10 @@ typedef struct
*/
-local int unzlocal_getByte (
+local int unzlocal_getByte OF((
const zlib_filefunc_def* pzlib_filefunc_def,
voidpf filestream,
- int *pi);
+ int *pi));
local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
const zlib_filefunc_def* pzlib_filefunc_def;
@@ -192,10 +193,10 @@ local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
/* ===========================================================================
Reads a long in LSB order from the given gz_stream. Sets
*/
-local int unzlocal_getShort (
+local int unzlocal_getShort OF((
const zlib_filefunc_def* pzlib_filefunc_def,
voidpf filestream,
- uLong *pX);
+ uLong *pX));
local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
const zlib_filefunc_def* pzlib_filefunc_def;
@@ -203,7 +204,7 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
uLong *pX;
{
uLong x ;
- int i;
+ int i = 0;
int err;
err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
@@ -220,10 +221,10 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
return err;
}
-local int unzlocal_getLong (
+local int unzlocal_getLong OF((
const zlib_filefunc_def* pzlib_filefunc_def,
voidpf filestream,
- uLong *pX);
+ uLong *pX));
local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
const zlib_filefunc_def* pzlib_filefunc_def;
@@ -231,7 +232,7 @@ local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
uLong *pX;
{
uLong x ;
- int i;
+ int i = 0;
int err;
err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
@@ -323,9 +324,9 @@ extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivit
Locate the Central directory of a zipfile (at the end, just before
the global comment)
*/
-local uLong unzlocal_SearchCentralDir (
+local uLong unzlocal_SearchCentralDir OF((
const zlib_filefunc_def* pzlib_filefunc_def,
- voidpf filestream);
+ voidpf filestream));
local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
const zlib_filefunc_def* pzlib_filefunc_def;
@@ -562,7 +563,7 @@ local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
/*
Get Info about the current file in the zipfile, with internal only info
*/
-local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
+local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
unz_file_info *pfile_info,
unz_file_info_internal
*pfile_info_internal,
@@ -571,7 +572,7 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
- uLong commentBufferSize);
+ uLong commentBufferSize));
local int unzlocal_GetCurrentFileInfoInternal (file,
pfile_info,
@@ -609,9 +610,13 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
if (err==UNZ_OK)
{
if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ {
err=UNZ_ERRNO;
+ }
else if (uMagic!=0x02014b50)
+ {
err=UNZ_BADZIPFILE;
+ }
}
if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
@@ -701,8 +706,9 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
lSeek += file_info.size_file_extra - uSizeRead;
}
else
+ {
lSeek+=file_info.size_file_extra;
-
+ }
if ((err==UNZ_OK) && (szComment!=NULL))
{
@@ -713,22 +719,22 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
uSizeRead = file_info.size_file_comment;
}
else
+ {
uSizeRead = commentBufferSize;
+ }
if (lSeek!=0)
{
- if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
- lSeek=0;
- else
+ if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)!=0)
err=UNZ_ERRNO;
}
if ((file_info.size_file_comment>0) && (commentBufferSize>0))
if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
err=UNZ_ERRNO;
- lSeek+=file_info.size_file_comment - uSizeRead;
}
else
- lSeek+=file_info.size_file_comment;
+ {
+ }
if ((err==UNZ_OK) && (pfile_info!=NULL))
*pfile_info=file_info;
@@ -988,7 +994,7 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
else if (uMagic!=0x04034b50)
err=UNZ_BADZIPFILE;
}
-
+
if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
err=UNZ_ERRNO;
/*
@@ -1119,7 +1125,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
if ((s->cur_file_info.compression_method!=0) &&
(s->cur_file_info.compression_method!=Z_DEFLATED))
- err=UNZ_BADZIPFILE;
+ return UNZ_BADZIPFILE;
pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
pfile_in_zip_read_info->crc32=0;
@@ -1541,6 +1547,7 @@ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
char *szComment;
uLong uSizeBuf;
{
+ int err=UNZ_OK;
unz_s* s;
uLong uReadThis ;
if (file==NULL)
diff --git a/src/3rdparty/assimp/contrib/unzip/unzip.h b/src/3rdparty/assimp/contrib/unzip/unzip.h
index e3b7f24ee..b247937c8 100644
--- a/src/3rdparty/assimp/contrib/unzip/unzip.h
+++ b/src/3rdparty/assimp/contrib/unzip/unzip.h
@@ -50,11 +50,7 @@ extern "C" {
#endif
#ifndef _ZLIB_H
-# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
-# else
-# include "../zlib/zlib.h"
-# endif
+#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
@@ -123,9 +119,9 @@ typedef struct unz_file_info_s
tm_unz tmu_date;
} unz_file_info;
-extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
const char* fileName2,
- int iCaseSensitivity);
+ int iCaseSensitivity));
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
@@ -136,7 +132,7 @@ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
*/
-extern unzFile ZEXPORT unzOpen (const char *path);
+extern unzFile ZEXPORT unzOpen OF((const char *path));
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
@@ -147,31 +143,31 @@ extern unzFile ZEXPORT unzOpen (const char *path);
of this unzip package.
*/
-extern unzFile ZEXPORT unzOpen2 (const char *path,
- zlib_filefunc_def* pzlib_filefunc_def);
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
/*
Open a Zip file, like unzOpen, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
*/
-extern int ZEXPORT unzClose (unzFile file);
+extern int ZEXPORT unzClose OF((unzFile file));
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzGetGlobalInfo (unzFile file,
- unz_global_info *pglobal_info);
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzGetGlobalComment (unzFile file,
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
- uLong uSizeBuf);
+ uLong uSizeBuf));
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
@@ -182,22 +178,22 @@ extern int ZEXPORT unzGetGlobalComment (unzFile file,
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
-extern int ZEXPORT unzGoToFirstFile (unzFile file);
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
-extern int ZEXPORT unzGoToNextFile (unzFile file);
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
-extern int ZEXPORT unzLocateFile (unzFile file,
+extern int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
- int iCaseSensitivity);
+ int iCaseSensitivity));
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
@@ -227,14 +223,14 @@ extern int ZEXPORT unzGoToFilePos(
/* ****************************************** */
-extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
unz_file_info *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
- uLong commentBufferSize);
+ uLong commentBufferSize));
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
@@ -253,24 +249,24 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
from it, and close it (you can close it before reading all the file)
*/
-extern int ZEXPORT unzOpenCurrentFile (unzFile file);
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
-extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file,
- const char* password);
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+ const char* password));
/*
Open for reading data the current file in the zipfile.
password is a crypting password
If there is no error, the return value is UNZ_OK.
*/
-extern int ZEXPORT unzOpenCurrentFile2 (unzFile file,
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
int* method,
int* level,
- int raw);
+ int raw));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
@@ -280,11 +276,11 @@ extern int ZEXPORT unzOpenCurrentFile2 (unzFile file,
but you CANNOT set method parameter as NULL
*/
-extern int ZEXPORT unzOpenCurrentFile3 (unzFile file,
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
int* method,
int* level,
int raw,
- const char* password);
+ const char* password));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
@@ -295,15 +291,15 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file,
*/
-extern int ZEXPORT unzCloseCurrentFile (unzFile file);
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
-extern int ZEXPORT unzReadCurrentFile (unzFile file,
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
voidp buf,
- unsigned len);
+ unsigned len));
/*
Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
@@ -315,19 +311,19 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file,
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
-extern z_off_t ZEXPORT unztell (unzFile file);
+extern z_off_t ZEXPORT unztell OF((unzFile file));
/*
Give the current position in uncompressed data
*/
-extern int ZEXPORT unzeof (unzFile file);
+extern int ZEXPORT unzeof OF((unzFile file));
/*
return 1 if the end of file was reached, 0 elsewhere
*/
-extern int ZEXPORT unzGetLocalExtrafield (unzFile file,
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
voidp buf,
- unsigned len);
+ unsigned len));
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
diff --git a/src/3rdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes b/src/3rdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes
new file mode 100644
index 000000000..364411a23
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes
@@ -0,0 +1,12 @@
+utf8 cpp library
+Release 2.3.4
+
+A minor bug fix release. Thanks to all who reported bugs.
+
+Note: Version 2.3.3 contained a regression, and therefore was removed.
+
+Changes from version 2.3.2
+- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';'
+- Bug fix [36]: replace_invalid() only works with back_inserter
+
+Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes
diff --git a/src/3rdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html b/src/3rdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html
new file mode 100644
index 000000000..6f2aacbe7
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html
@@ -0,0 +1,1789 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st November 2002), see www.w3.org">
+ <meta name="description" content=
+ "A simple, portable and lightweigt C++ library for easy handling of UTF-8 encoded strings">
+ <meta name="keywords" content="UTF-8 C++ portable utf8 unicode generic templates">
+ <meta name="author" content="Nemanja Trifunovic">
+ <title>
+ UTF8-CPP: UTF-8 with C++ in a Portable Way
+ </title>
+ <style type="text/css">
+ <!--
+ span.return_value {
+ color: brown;
+ }
+ span.keyword {
+ color: blue;
+ }
+ span.preprocessor {
+ color: navy;
+ }
+ span.literal {
+ color: olive;
+ }
+ span.comment {
+ color: green;
+ }
+ code {
+ font-weight: bold;
+ }
+ ul.toc {
+ list-style-type: none;
+ }
+ p.version {
+ font-size: small;
+ font-style: italic;
+ }
+ -->
+ </style>
+ </head>
+ <body>
+ <h1>
+ UTF8-CPP: UTF-8 with C++ in a Portable Way
+ </h1>
+ <p>
+ <a href="https://sourceforge.net/projects/utfcpp">The Sourceforge project page</a>
+ </p>
+ <div id="toc">
+ <h2>
+ Table of Contents
+ </h2>
+ <ul class="toc">
+ <li>
+ <a href="#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="#examples">Examples of Use</a>
+ <ul class="toc">
+ <li>
+ <a href=#introsample>Introductionary Sample </a>
+ </li>
+ <li>
+ <a href=#validfile>Checking if a file contains valid UTF-8 text</a>
+ </li>
+ <li>
+ <a href=#fixinvalid>Ensure that a string contains valid UTF-8 text</a>
+ </li>
+ </ul>
+ <li>
+ <a href="#reference">Reference</a>
+ <ul class="toc">
+ <li>
+ <a href="#funutf8">Functions From utf8 Namespace </a>
+ </li>
+ <li>
+ <a href="#typesutf8">Types From utf8 Namespace </a>
+ </li>
+ <li>
+ <a href="#fununchecked">Functions From utf8::unchecked Namespace </a>
+ </li>
+ <li>
+ <a href="#typesunchecked">Types From utf8::unchecked Namespace </a>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <a href="#points">Points of Interest</a>
+ </li>
+ <li>
+ <a href="#links">Links</a>
+ </li>
+ </ul>
+ </div>
+ <h2 id="introduction">
+ Introduction
+ </h2>
+ <p>
+ Many C++ developers miss an easy and portable way of handling Unicode encoded
+ strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic.
+ C++11 provides some support for Unicode on core language and library level:
+ u8, u, and U character and string literals, char16_t and char32_t character types,
+ u16string and u32string library classes, and codecvt support for conversions
+ between Unicode encoding forms.
+ In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply
+ roll out their own solutions.
+ </p>
+ <p>
+ In order to easily handle UTF-8 encoded Unicode strings, I came up with a small
+ generic library. For anybody used to work with STL algorithms and iterators, it should be
+ easy and natural to use. The code is freely available for any purpose - check out
+ the license at the beginning of the utf8.h file. If you run into
+ bugs or performance issues, please let me know and I'll do my best to address them.
+ </p>
+ <p>
+ The purpose of this article is not to offer an introduction to Unicode in general,
+ and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out
+ <a href="http://www.unicode.org/">Unicode Home Page</a> or some other source of
+ information for Unicode. Also, it is not my aim to advocate the use of UTF-8
+ encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from
+ C++, I am sure you have good reasons for it.
+ </p>
+ <h2 id="examples">
+ Examples of use
+ </h2>
+ <h3 id="introsample">
+ Introductionary Sample
+ </h3>
+ <p>
+ To illustrate the use of the library, let's start with a small but complete program
+ that opens a file containing UTF-8 encoded text, reads it line by line, checks each line
+ for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
+ </p>
+<pre>
+<span class="preprocessor">#include &lt;fstream&gt;</span>
+<span class="preprocessor">#include &lt;iostream&gt;</span>
+<span class="preprocessor">#include &lt;string&gt;</span>
+<span class="preprocessor">#include &lt;vector&gt;</span>
+<span class="preprocessor">#include "utf8.h"</span>
+<span class="keyword">using namespace</span> std;
+<span class="keyword">int</span> main(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)
+{
+ <span class="keyword">if</span> (argc != <span class="literal">2</span>) {
+ cout &lt;&lt; <span class="literal">"\nUsage: docsample filename\n"</span>;
+ <span class="keyword">return</span> <span class="literal">0</span>;
+ }
+
+ <span class="keyword">const char</span>* test_file_path = argv[1];
+ <span class="comment">// Open the test file (contains UTF-8 encoded text)</span>
+ ifstream fs8(test_file_path);
+ <span class="keyword">if</span> (!fs8.is_open()) {
+ cout &lt;&lt; <span class=
+"literal">"Could not open "</span> &lt;&lt; test_file_path &lt;&lt; endl;
+ <span class="keyword">return</span> <span class="literal">0</span>;
+ }
+
+ <span class="keyword">unsigned</span> line_count = <span class="literal">1</span>;
+ string line;
+ <span class="comment">// Play with all the lines in the file</span>
+ <span class="keyword">while</span> (getline(fs8, line)) {
+ <span class="comment">// check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)</span>
+ string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+ <span class="keyword">if</span> (end_it != line.end()) {
+ cout &lt;&lt; <span class=
+"literal">"Invalid UTF-8 encoding detected at line "</span> &lt;&lt; line_count &lt;&lt; <span
+ class="literal">"\n"</span>;
+ cout &lt;&lt; <span class=
+"literal">"This part is fine: "</span> &lt;&lt; string(line.begin(), end_it) &lt;&lt; <span
+ class="literal">"\n"</span>;
+ }
+
+ <span class="comment">// Get the line length (at least for the valid part)</span>
+ <span class="keyword">int</span> length = utf8::distance(line.begin(), end_it);
+ cout &lt;&lt; <span class=
+"literal">"Length of line "</span> &lt;&lt; line_count &lt;&lt; <span class=
+"literal">" is "</span> &lt;&lt; length &lt;&lt; <span class="literal">"\n"</span>;
+
+ <span class="comment">// Convert it to utf-16</span>
+ vector&lt;unsigned short&gt; utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+
+ <span class="comment">// And back to utf-8</span>
+ string utf8line;
+ utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+
+ <span class="comment">// Confirm that the conversion went OK:</span>
+ <span class="keyword">if</span> (utf8line != string(line.begin(), end_it))
+ cout &lt;&lt; <span class=
+"literal">"Error in UTF-16 conversion at line: "</span> &lt;&lt; line_count &lt;&lt; <span
+ class="literal">"\n"</span>;
+
+ line_count++;
+ }
+ <span class="keyword">return</span> <span class="literal">0</span>;
+}
+</pre>
+ <p>
+ In the previous code sample, for each line we performed
+ a detection of invalid UTF-8 sequences with <code>find_invalid</code>; the number
+ of characters (more precisely - the number of Unicode code points, including the end
+ of line and even BOM if there is one) in each line was
+ determined with a use of <code>utf8::distance</code>; finally, we have converted
+ each line to UTF-16 encoding with <code>utf8to16</code> and back to UTF-8 with
+ <code>utf16to8</code>.
+ </p>
+ <h3 id="validfile">Checking if a file contains valid UTF-8 text</h3>
+<p>
+Here is a function that checks whether the content of a file is valid UTF-8 encoded text without
+reading the content into the memory:
+</p>
+<pre>
+<span class="keyword">bool</span> valid_utf8_file(i<span class="keyword">const char</span>* file_name)
+{
+ ifstream ifs(file_name);
+ <span class="keyword">if</span> (!ifs)
+ <span class="keyword">return false</span>; <span class="comment">// even better, throw here</span>
+
+ istreambuf_iterator&lt;<span class="keyword">char</span>&gt; it(ifs.rdbuf());
+ istreambuf_iterator&lt;<span class="keyword">char</span>&gt; eos;
+
+ <span class="keyword">return</span> utf8::is_valid(it, eos);
+}
+</pre>
+<p>
+Because the function <code>utf8::is_valid()</code> works with input iterators, we were able
+to pass an <code>istreambuf_iterator</code> to it and read the content of the file directly
+without loading it to the memory first.</p>
+<p>
+Note that other functions that take input iterator arguments can be used in a similar way. For
+instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just
+do something like:
+</p>
+<pre>
+ utf8::utf8to16(it, eos, back_inserter(u16string));
+</pre>
+ <h3 id="fixinvalid">Ensure that a string contains valid UTF-8 text</h3>
+<p>
+If we have some text that "probably" contains UTF-8 encoded text and we want to
+replace any invalid UTF-8 sequence with a replacement character, something like
+the following function may be used:
+</p>
+<pre>
+<span class="keyword">void</span> fix_utf8_string(std::string&amp; str)
+{
+ std::string temp;
+ utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
+ str = temp;
+}
+</pre>
+<p>The function will replace any invalid UTF-8 sequence with a Unicode replacement character.
+There is an overloaded function that enables the caller to supply their own replacement character.
+</p>
+ <h2 id="reference">
+ Reference
+ </h2>
+ <h3 id="funutf8">
+ Functions From utf8 Namespace
+ </h3>
+ <h4>
+ utf8::append
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
+ to a UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator append(uint32_t cp, octet_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an output iterator.<br>
+ <code>cp</code>: a 32 bit integer representing a code point to append to the
+ sequence.<br>
+ <code>result</code>: an output iterator to the place in the sequence where to
+ append the code point.<br>
+ <span class="return_value">Return value</span>: an iterator pointing to the place
+ after the newly appended sequence.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
+class="literal">0</span>,<span class="literal">0</span>,<span class=
+"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
+<span class="keyword">unsigned char</span>* end = append(<span class=
+"literal">0x0448</span>, u);
+assert (u[<span class="literal">0</span>] == <span class=
+"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
+"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
+"literal">0</span>);
+</pre>
+ <p>
+ Note that <code>append</code> does not allocate any memory - it is the burden of
+ the caller to make sure there is enough memory allocated for the operation. To make
+ things more interesting, <code>append</code> can add anywhere between 1 and 4
+ octets to the sequence. In practice, you would most often want to use
+ <code>std::back_inserter</code> to ensure that the necessary memory is allocated.
+ </p>
+ <p>
+ In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
+ is thrown.
+ </p>
+ <h4>
+ utf8::next
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code
+ point and moves the iterator to the next position.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t next(octet_iterator&amp; it, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ beginning of the next code point.<br>
+ <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+ gets equal to <code>end</code> during the extraction of a code point, an
+ <code>utf8::not_enough_room</code> exception is thrown.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = next(w, twochars + <span class="literal">6</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars + <span class="literal">3</span>);
+</pre>
+ <p>
+ This function is typically used to iterate through a UTF-8 encoded string.
+ </p>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown.
+ </p>
+ <h4>
+ utf8::peek_next
+ </h4>
+ <p class="version">
+ Available in version 2.1 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code
+ point for the following sequence without changing the value of the iterator.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: an iterator pointing to the beginning of an UTF-8
+ encoded code point.<br>
+ <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+ gets equal to <code>end</code> during the extraction of a code point, an
+ <code>utf8::not_enough_room</code> exception is thrown.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = peek_next(w, twochars + <span class="literal">6</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown.
+ </p>
+ <h4>
+ utf8::prior
+ </h4>
+ <p class="version">
+ Available in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t prior(octet_iterator&amp; it, octet_iterator start);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: a bidirectional iterator.<br>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <code>start</code>: an iterator to the beginning of the sequence where the search
+ for the beginning of a code point is performed. It is a
+ safety measure to prevent passing the beginning of the string in the search for a
+ UTF-8 lead octet.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars + <span class=
+"literal">3</span>;
+<span class="keyword">int</span> cp = prior (w, twochars);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ This function has two purposes: one is two iterate backwards through a UTF-8
+ encoded string. Note that it is usually a better idea to iterate forward instead,
+ since <code>utf8::next</code> is faster. The second purpose is to find a beginning
+ of a UTF-8 sequence if we have a random position within a string. Note that in that
+ case <code>utf8::prior</code> may not detect an invalid UTF-8 sequence in some scenarios:
+ for instance if there are superfluous trail octets, it will just skip them.
+ </p>
+ <p>
+ <code>it</code> will typically point to the beginning of
+ a code point, and <code>start</code> will point to the
+ beginning of the string to ensure we don't go backwards too far. <code>it</code> is
+ decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
+ beginning with that octet is decoded to a 32 bit representation and returned.
+ </p>
+ <p>
+ In case <code>start</code> is reached before a UTF-8 lead octet is hit, or if an
+ invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
+ exception is thrown.
+ </p>
+ <p>In case <code>start</code> equals <code>it</code>, a <code>not_enough_room</code>
+ exception is thrown.
+ <h4>
+ utf8::previous
+ </h4>
+ <p class="version">
+ Deprecated in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t previous(octet_iterator&amp; it, octet_iterator pass_start);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: a random access iterator.<br>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <code>pass_start</code>: an iterator to the point in the sequence where the search
+ for the beginning of a code point is aborted if no result was reached. It is a
+ safety measure to prevent passing the beginning of the string in the search for a
+ UTF-8 lead octet.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars + <span class=
+"literal">3</span>;
+<span class="keyword">int</span> cp = previous (w, twochars - <span class=
+"literal">1</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ <code>utf8::previous</code> is deprecated, and <code>utf8::prior</code> should
+ be used instead, although the existing code can continue using this function.
+ The problem is the parameter <code>pass_start</code> that points to the position
+ just before the beginning of the sequence. Standard containers don't have the
+ concept of "pass start" and the function can not be used with their iterators.
+ </p>
+ <p>
+ <code>it</code> will typically point to the beginning of
+ a code point, and <code>pass_start</code> will point to the octet just before the
+ beginning of the string to ensure we don't go backwards too far. <code>it</code> is
+ decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
+ beginning with that octet is decoded to a 32 bit representation and returned.
+ </p>
+ <p>
+ In case <code>pass_start</code> is reached before a UTF-8 lead octet is hit, or if an
+ invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
+ exception is thrown
+ </p>
+ <h4>
+ utf8::advance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Advances an iterator by the specified number of code points within an UTF-8
+ sequence.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename distance_type&gt;
+<span class=
+"keyword">void</span> advance (octet_iterator&amp; it, distance_type n, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>distance_type</code>: an integral type convertible to <code>octet_iterator</code>'s difference type.<br>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ nth following code point.<br>
+ <code>n</code>: a positive integer that shows how many code points we want to
+ advance.<br>
+ <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+ gets equal to <code>end</code> during the extraction of a code point, an
+ <code>utf8::not_enough_room</code> exception is thrown.<br>
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars;
+advance (w, <span class="literal">2</span>, twochars + <span class="literal">6</span>);
+assert (w == twochars + <span class="literal">5</span>);
+</pre>
+ <p>
+ This function works only "forward". In case of a negative <code>n</code>, there is
+ no effect.
+ </p>
+ <p>
+ In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
+ is thrown.
+ </p>
+ <h4>
+ utf8::distance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the
+ number of code points between them.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class=
+"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
+ <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
+ point in the sequence we are trying to determine the length. It can be the
+ beginning of a new code point, or not.<br>
+ <span class="return_value">Return value</span> the distance between the iterators,
+ in code points.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+size_t dist = utf8::distance(twochars, twochars + <span class="literal">5</span>);
+assert (dist == <span class="literal">2</span>);
+</pre>
+ <p>
+ This function is used to find the length (in code points) of a UTF-8 encoded
+ string. The reason it is called <em>distance</em>, rather than, say,
+ <em>length</em> is mainly because developers are used that <em>length</em> is an
+ O(1) function. Computing the length of an UTF-8 string is a linear operation, and
+ it looked better to model it after <code>std::distance</code> algorithm.
+ </p>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown. If <code>last</code> does not point to the past-of-end of a UTF-8 seqence,
+ a <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::utf16to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-16 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, <span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>u16bit_iterator</code>: an input iterator.<br>
+ <code>octet_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned short</span> utf16string[] = {<span class=
+"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
+"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
+"literal">0xdd1e</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf16to8(utf16string, utf16string + <span class=
+"literal">5</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">10</span>);
+</pre>
+ <p>
+ In case of invalid UTF-16 sequence, a <code>utf8::invalid_utf16</code> exception is
+ thrown.
+ </p>
+ <h4>
+ utf8::utf8to16
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts an UTF-8 encoded string to UTF-16
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>u16bit_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
+ pass-the-end of the UTF-8 encoded string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-16 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-16 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
+vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
+"literal">9</span>, back_inserter(utf16result));
+assert (utf16result.size() == <span class="literal">4</span>);
+assert (utf16result[<span class="literal">2</span>] == <span class=
+"literal">0xd834</span>);
+assert (utf16result[<span class="literal">3</span>] == <span class=
+"literal">0xdd1e</span>);
+</pre>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
+ <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::utf32to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-32 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an output iterator.<br>
+ <code>u32bit_iterator</code>: an input iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">int</span> utf32string[] = {<span class=
+"literal">0x448</span>, <span class="literal">0x65E5</span>, <span class=
+"literal">0x10346</span>, <span class="literal">0</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf32to8(utf32string, utf32string + <span class=
+"literal">3</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">9</span>);
+</pre>
+ <p>
+ In case of invalid UTF-32 string, a <code>utf8::invalid_code_point</code> exception
+ is thrown.
+ </p>
+ <h4>
+ utf8::utf8to32
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-8 encoded string to UTF-32.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> u32bit_iterator&gt;
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>u32bit_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
+ to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-32 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-32 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+vector&lt;<span class="keyword">int</span>&gt; utf32result;
+utf8to32(twochars, twochars + <span class=
+"literal">5</span>, back_inserter(utf32result));
+assert (utf32result.size() == <span class="literal">2</span>);
+</pre>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
+ <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::find_invalid
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Detects an invalid sequence within a UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+ test for validity.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
+ for validity.<br>
+ <span class="return_value">Return value</span>: an iterator pointing to the first
+ invalid octet in the UTF-8 string. In case none were found, equals
+ <code>end</code>.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> utf_invalid[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
+<span class=
+"keyword">char</span>* invalid = find_invalid(utf_invalid, utf_invalid + <span class=
+"literal">6</span>);
+assert (invalid == utf_invalid + <span class="literal">5</span>);
+</pre>
+ <p>
+ This function is typically used to make sure a UTF-8 string is valid before
+ processing it with other functions. It is especially important to call it if before
+ doing any of the <em>unchecked</em> operations on it.
+ </p>
+ <h4>
+ utf8::is_valid
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Checks whether a sequence of octets is a valid UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class="keyword">bool</span> is_valid(octet_iterator start, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+ test for validity.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
+ for validity.<br>
+ <span class="return_value">Return value</span>: <code>true</code> if the sequence
+ is a valid UTF-8 string; <code>false</code> if not.
+ </p>
+ Example of use:
+<pre>
+<span class="keyword">char</span> utf_invalid[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
+<span class="keyword">bool</span> bvalid = is_valid(utf_invalid, utf_invalid + <span
+class="literal">6</span>);
+assert (bvalid == false);
+</pre>
+ <p>
+ <code>is_valid</code> is a shorthand for <code>find_invalid(start, end) ==
+ end;</code>. You may want to use it to make sure that a byte seqence is a valid
+ UTF-8 string without the need to know where it fails if it is not valid.
+ </p>
+ <h4>
+ utf8::replace_invalid
+ </h4>
+ <p class="version">
+ Available in version 2.0 and later.
+ </p>
+ <p>
+ Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> output_iterator&gt;
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> output_iterator&gt;
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>output_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+ look for invalid UTF-8 sequences.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to look
+ for invalid UTF-8 sequences.<br>
+ <code>out</code>: An output iterator to the range where the result of replacement
+ is stored.<br>
+ <code>replacement</code>: A Unicode code point for the replacement marker. The
+ version without this parameter assumes the value <code>0xfffd</code><br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the UTF-8 string with replaced invalid sequences.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> invalid_sequence[] = <span class=
+"literal">"a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z"</span>;
+vector&lt;<span class="keyword">char</span>&gt; replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), <span
+ class="literal">'?'</span>);
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+<span class="keyword">char</span>* fixed_invalid_sequence = <span class=
+"literal">"a????z"</span>;
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+</pre>
+ <p>
+ <code>replace_invalid</code> does not perform in-place replacement of invalid
+ sequences. Rather, it produces a copy of the original string with the invalid
+ sequences replaced with a replacement marker. Therefore, <code>out</code> must not
+ be in the <code>[start, end]</code> range.
+ </p>
+ <p>
+ If <code>end</code> does not point to the past-of-end of a UTF-8 sequence, a
+ <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::starts_with_bom
+ </h4>
+ <p class="version">
+ Available in version 2.3 and later. Relaces deprecated <code>is_bom()</code> function.
+ </p>
+ <p>
+ Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class="keyword">bool</span> starts_with_bom (octet_iterator it, octet_iterator end);
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: beginning of the octet sequence to check<br>
+ <code>end</code>: pass-end of the sequence to check<br>
+ <span class="return_value">Return value</span>: <code>true</code> if the sequence
+ starts with a UTF-8 byte order mark; <code>false</code> if not.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
+"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
+"literal">0xbf</span>};
+<span class="keyword">bool</span> bbom = starts_with_bom(byte_order_mark, byte_order_mark + <span class="keyword">sizeof</span>(byte_order_mark));
+assert (bbom == <span class="literal">true</span>);
+</pre>
+ <p>
+ The typical use of this function is to check the first three bytes of a file. If
+ they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
+ encoded text.
+ </p>
+ <h4>
+ utf8::is_bom
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later. Deprecated in version 2.3. <code>starts_with_bom()</code> should be used
+ instead.
+ </p>
+ <p>
+ Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM)
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class="keyword">bool</span> is_bom (octet_iterator it); <span class="comment"> // Deprecated</span>
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: beginning of the 3-octet sequence to check<br>
+ <span class="return_value">Return value</span>: <code>true</code> if the sequence
+ is UTF-8 byte order mark; <code>false</code> if not.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
+"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
+"literal">0xbf</span>};
+<span class="keyword">bool</span> bbom = is_bom(byte_order_mark);
+assert (bbom == <span class="literal">true</span>);
+</pre>
+ <p>
+ The typical use of this function is to check the first three bytes of a file. If
+ they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
+ encoded text.
+ </p>
+ <p>
+ If a sequence is
+ shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated
+ in favor of <code>starts_with_bom()</code>that takes the end of sequence as an argument.
+ </p>
+ <h3 id="typesutf8">
+ Types From utf8 Namespace
+ </h3>
+ <h4>utf8::exception
+ </h4>
+ <p class="version">
+ Available in version 2.3 and later.
+ </p>
+ <p>
+ Base class for the exceptions thrown by UTF CPP library functions.
+ </p>
+<pre>
+<span class="keyword">class</span> exception : <span class="keyword">public</span> std::exception {};
+</pre>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">try</span> {
+ code_that_uses_utf_cpp_library();
+}
+<span class="keyword">catch</span>(<span class="keyword">const</span> utf8::exception&amp; utfcpp_ex) {
+ cerr &lt;&lt; utfcpp_ex.what();
+}
+</pre>
+
+ <h4>utf8::invalid_code_point
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP functions such as <code>advance</code> and <code>next</code> if an UTF-8 sequence represents and invalid code point.
+ </p>
+
+<pre>
+<span class="keyword">class</span> invalid_code_point : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>:
+ uint32_t code_point() <span class="keyword">const</span>;
+};
+
+</pre>
+ <p>
+ Member function <code>code_point()</code> can be used to determine the invalid code point that
+ caused the exception to be thrown.
+ </p>
+ <h4>utf8::invalid_utf8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP functions such as <code>next</code> and <code>prior</code> if an invalid UTF-8 sequence
+ is detected during decoding.
+ </p>
+
+<pre>
+<span class="keyword">class</span> invalid_utf8 : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>:
+ uint8_t utf8_octet() <span class="keyword">const</span>;
+};
+</pre>
+
+ <p>
+ Member function <code>utf8_octet()</code> can be used to determine the beginning of the byte
+ sequence that caused the exception to be thrown.
+ </p>
+</pre>
+ <h4>utf8::invalid_utf16
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP function <code>utf16to8</code> if an invalid UTF-16 sequence
+ is detected during decoding.
+ </p>
+
+<pre>
+<span class="keyword">class</span> invalid_utf16 : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>:
+ uint16_t utf16_word() <span class="keyword">const</span>;
+};
+</pre>
+
+ <p>
+ Member function <code>utf16_word()</code> can be used to determine the UTF-16 code unit
+ that caused the exception to be thrown.
+ </p>
+ <h4>utf8::not_enough_room
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP functions such as <code>next</code> if the end of the decoded UTF-8 sequence
+ was reached before the code point was decoded.
+ </p>
+
+<pre>
+<span class="keyword">class</span> not_enough_room : <span class="keyword">public</span> exception {};
+</pre>
+ <h4>
+ utf8::iterator
+ </h4>
+ <p class="version">
+ Available in version 2.0 and later.
+ </p>
+ <p>
+ Adapts the underlying octet iterator to iterate over the sequence of code points,
+ rather than raw octets.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
+<span class="keyword">class</span> iterator;
+</pre>
+
+ <h5>Member functions</h5>
+ <dl>
+ <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
+ constructed with its default constructor.
+ <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it,
+ const octet_iterator&amp; range_start,
+ const octet_iterator&amp; range_end);</code> <dd> a constructor
+ that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
+ and sets the range in which the iterator is considered valid.
+ <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
+ underlying <code>octet_iterator</code>.
+ <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
+ the underlying <code>octet_iterator</code> is pointing to and returns the code point.
+ <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are equal.
+ <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are not equal.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
+ the iterator to the next UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
+ the iterator to the previous UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+ </dl>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; it(threechars, threechars, threechars + <span class="literal">9</span>);
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; it2 = it;
+assert (it2 == it);
+assert (*it == <span class="literal">0x10346</span>);
+assert (*(++it) == <span class="literal">0x65e5</span>);
+assert ((*it++) == <span class="literal">0x65e5</span>);
+assert (*it == <span class="literal">0x0448</span>);
+assert (it != it2);
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; endit (threechars + <span class="literal">9</span>, threechars, threechars + <span class="literal">9</span>);
+assert (++it == endit);
+assert (*(--it) == <span class="literal">0x0448</span>);
+assert ((*it--) == <span class="literal">0x0448</span>);
+assert (*it == <span class="literal">0x65e5</span>);
+assert (--it == utf8::iterator&lt;<span class="keyword">char</span>*&gt;(threechars, threechars, threechars + <span class="literal">9</span>));
+assert (*it == <span class="literal">0x10346</span>);
+</pre>
+ <p>
+ The purpose of <code>utf8::iterator</code> adapter is to enable easy iteration as well as the use of STL
+ algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of
+ <code>utf8::next()</code> and <code>utf8::prior()</code> functions.
+ </p>
+ <p>
+ Note that <code>utf8::iterator</code> adapter is a checked iterator. It operates on the range specified in
+ the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators
+ require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically,
+ the range will be determined by sequence container functions <code>begin</code> and <code>end</code>, i.e.:
+ </p>
+<pre>
+std::string s = <span class="literal">"example"</span>;
+utf8::iterator i (s.begin(), s.begin(), s.end());
+</pre>
+ <h3 id="fununchecked">
+ Functions From utf8::unchecked Namespace
+ </h3>
+ <h4>
+ utf8::unchecked::append
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
+ to a UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator append(uint32_t cp, octet_iterator result);
+
+</pre>
+ <p>
+ <code>cp</code>: A 32 bit integer representing a code point to append to the
+ sequence.<br>
+ <code>result</code>: An output iterator to the place in the sequence where to
+ append the code point.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the newly appended sequence.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
+class="literal">0</span>,<span class="literal">0</span>,<span class=
+"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
+<span class="keyword">unsigned char</span>* end = unchecked::append(<span class=
+"literal">0x0448</span>, u);
+assert (u[<span class="literal">0</span>] == <span class=
+"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
+"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
+"literal">0</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::append</code>. It does not
+ check for validity of the supplied code point, and may produce an invalid UTF-8
+ sequence.
+ </p>
+ <h4>
+ utf8::unchecked::next
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point
+ and moves the iterator to the next position.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t next(octet_iterator&amp; it);
+
+</pre>
+ <p>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ beginning of the next code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = unchecked::next(w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars + <span class="literal">3</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::next</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::peek_next
+ </h4>
+ <p class="version">
+ Available in version 2.1 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t peek_next(octet_iterator it);
+
+</pre>
+ <p>
+ <code>it</code>: an iterator pointing to the beginning of an UTF-8
+ encoded code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = unchecked::peek_next(w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::peek_next</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::prior
+ </h4>
+ <p class="version">
+ Available in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t prior(octet_iterator&amp; it);
+
+</pre>
+ <p>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
+<span class="keyword">int</span> cp = unchecked::prior (w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::prior</code>. It does not
+ check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+ </p>
+ <h4>
+ utf8::unchecked::previous (deprecated, see utf8::unchecked::prior)
+ </h4>
+ <p class="version">
+ Deprecated in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t previous(octet_iterator&amp; it);
+
+</pre>
+ <p>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
+<span class="keyword">int</span> cp = unchecked::previous (w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ The reason this function is deprecated is just the consistency with the "checked"
+ versions, where <code>prior</code> should be used instead of <code>previous</code>.
+ In fact, <code>unchecked::previous</code> behaves exactly the same as <code>
+ unchecked::prior</code>
+ </p>
+ <p>
+ This is a faster but less safe version of <code>utf8::previous</code>. It does not
+ check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+ </p>
+ <h4>
+ utf8::unchecked::advance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Advances an iterator by the specified number of code points within an UTF-8
+ sequence.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename distance_type&gt;
+<span class="keyword">void</span> advance (octet_iterator&amp; it, distance_type n);
+
+</pre>
+ <p>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ nth following code point.<br>
+ <code>n</code>: a positive integer that shows how many code points we want to
+ advance.<br>
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+unchecked::advance (w, <span class="literal">2</span>);
+assert (w == twochars + <span class="literal">5</span>);
+</pre>
+ <p>
+ This function works only "forward". In case of a negative <code>n</code>, there is
+ no effect.
+ </p>
+ <p>
+ This is a faster but less safe version of <code>utf8::advance</code>. It does not
+ check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+ </p>
+ <h4>
+ utf8::unchecked::distance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the
+ number of code points between them.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class=
+"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
+</pre>
+ <p>
+ <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
+ <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
+ point in the sequence we are trying to determine the length. It can be the
+ beginning of a new code point, or not.<br>
+ <span class="return_value">Return value</span> the distance between the iterators,
+ in code points.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+size_t dist = utf8::unchecked::distance(twochars, twochars + <span class=
+"literal">5</span>);
+assert (dist == <span class="literal">2</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::distance</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf16to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-16 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, <span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned short</span> utf16string[] = {<span class=
+"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
+"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
+"literal">0xdd1e</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+unchecked::utf16to8(utf16string, utf16string + <span class=
+"literal">5</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">10</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf16to8</code>. It does not
+ check for validity of the supplied UTF-16 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf8to16
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts an UTF-8 encoded string to UTF-16
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
+ pass-the-end of the UTF-8 encoded string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-16 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-16 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
+vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
+"literal">9</span>, back_inserter(utf16result));
+assert (utf16result.size() == <span class="literal">4</span>);
+assert (utf16result[<span class="literal">2</span>] == <span class=
+"literal">0xd834</span>);
+assert (utf16result[<span class="literal">3</span>] == <span class=
+"literal">0xdd1e</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf8to16</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf32to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-32 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> u32bit_iterator&gt;
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">int</span> utf32string[] = {<span class=
+"literal">0x448</span>, <span class="literal">0x65e5</span>, <span class=
+"literal">0x10346</span>, <span class="literal">0</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf32to8(utf32string, utf32string + <span class=
+"literal">3</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">9</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf32to8</code>. It does not
+ check for validity of the supplied UTF-32 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf8to32
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-8 encoded string to UTF-32.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
+ to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-32 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-32 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+vector&lt;<span class="keyword">int</span>&gt; utf32result;
+unchecked::utf8to32(twochars, twochars + <span class=
+"literal">5</span>, back_inserter(utf32result));
+assert (utf32result.size() == <span class="literal">2</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf8to32</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h3 id="typesunchecked">
+ Types From utf8::unchecked Namespace
+ </h3>
+ <h4>
+ utf8::iterator
+ </h4>
+ <p class="version">
+ Available in version 2.0 and later.
+ </p>
+ <p>
+ Adapts the underlying octet iterator to iterate over the sequence of code points,
+ rather than raw octets.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
+<span class="keyword">class</span> iterator;
+</pre>
+
+ <h5>Member functions</h5>
+ <dl>
+ <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
+ constructed with its default constructor.
+ <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it);
+ </code> <dd> a constructor
+ that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
+ <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
+ underlying <code>octet_iterator</code>.
+ <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
+ the underlying <code>octet_iterator</code> is pointing to and returns the code point.
+ <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are equal.
+ <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are not equal.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
+ the iterator to the next UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
+ the iterator to the previous UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+ </dl>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
+utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it(threechars);
+utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == <span class="literal">0x10346</span>);
+assert (*(++un_it) == <span class="literal">0x65e5</span>);
+assert ((*un_it++) == <span class="literal">0x65e5</span>);
+assert (*un_it == <span class="literal">0x0448</span>);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_endit (threechars + <span class="literal">9</span>);
+assert (++un_it == un_endit);
+assert (*(--un_it) == <span class="literal">0x0448</span>);
+assert ((*un_it--) == <span class="literal">0x0448</span>);
+assert (*un_it == <span class="literal">0x65e5</span>);
+assert (--un_it == utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt;(threechars));
+assert (*un_it == <span class="literal">0x10346</span>);
+</pre>
+ <p>
+ This is an unchecked version of <code>utf8::iterator</code>. It is faster in many cases, but offers
+ no validity or range checks.
+ </p>
+ <h2 id="points">
+ Points of interest
+ </h2>
+ <h4>
+ Design goals and decisions
+ </h4>
+ <p>
+ The library was designed to be:
+ </p>
+ <ol>
+ <li>
+ Generic: for better or worse, there are many C++ string classes out there, and
+ the library should work with as many of them as possible.
+ </li>
+ <li>
+ Portable: the library should be portable both accross different platforms and
+ compilers. The only non-portable code is a small section that declares unsigned
+ integers of different sizes: three typedefs. They can be changed by the users of
+ the library if they don't match their platform. The default setting should work
+ for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives.
+ </li>
+ <li>
+ Lightweight: follow the "pay only for what you use" guideline.
+ </li>
+ <li>
+ Unintrusive: avoid forcing any particular design or even programming style on the
+ user. This is a library, not a framework.
+ </li>
+ </ol>
+ <h4>
+ Alternatives
+ </h4>
+ <p>
+ In case you want to look into other means of working with UTF-8 strings from C++,
+ here is the list of solutions I am aware of:
+ </p>
+ <ol>
+ <li>
+ <a href="http://icu.sourceforge.net/">ICU Library</a>. It is very powerful,
+ complete, feature-rich, mature, and widely used. Also big, intrusive,
+ non-generic, and doesn't play well with the Standard Library. I definitelly
+ recommend looking at ICU even if you don't plan to use it.
+ </li>
+ <li>
+ C++11 language and library features. Still far from complete, and not widely
+ supported by compiler vendors.
+ </li>
+ <li>
+ <a href=
+ "http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html">Glib::ustring</a>.
+ A class specifically made to work with UTF-8 strings, and also feel like
+ <code>std::string</code>. If you prefer to have yet another string class in your
+ code, it may be worth a look. Be aware of the licensing issues, though.
+ </li>
+ <li>
+ Platform dependent solutions: Windows and POSIX have functions to convert strings
+ from one encoding to another. That is only a subset of what my library offers,
+ but if that is all you need it may be good enough.
+ </li>
+ </ol>
+ <h2 id="links">
+ Links
+ </h2>
+ <ol>
+ <li>
+ <a href="http://www.unicode.org/">The Unicode Consortium</a>.
+ </li>
+ <li>
+ <a href="http://icu.sourceforge.net/">ICU Library</a>.
+ </li>
+ <li>
+ <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8 at Wikipedia</a>
+ </li>
+ <li>
+ <a href="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ for
+ Unix/Linux</a>
+ </li>
+ </ol>
+ </body>
+</html>
diff --git a/src/3rdparty/assimp/contrib/utf8cpp/source/utf8.h b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8.h
new file mode 100644
index 000000000..82b13f59f
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8.h
@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/checked.h b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/checked.h
new file mode 100644
index 000000000..133115513
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/checked.h
@@ -0,0 +1,327 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_t cp;
+ public:
+ invalid_code_point(uint32_t cp) : cp(cp) {}
+ virtual const char* what() const throw() { return "Invalid code point"; }
+ uint32_t code_point() const {return cp;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_t u8;
+ public:
+ invalid_utf8 (uint8_t u) : u8(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-8"; }
+ uint8_t utf8_octet() const {return u8;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_t u16;
+ public:
+ invalid_utf16 (uint16_t u) : u16(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-16"; }
+ uint16_t utf16_word() const {return u16;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const throw() { return "Not enough space"; }
+ };
+
+ /// The library API - functions intended to be called by the users
+
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (!utf8::internal::is_code_point_valid(cp))
+ throw invalid_code_point(cp);
+
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ throw not_enough_room();
+ case internal::INVALID_LEAD:
+ out = utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it, octet_iterator end)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it, octet_iterator end)
+ {
+ return utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it, octet_iterator start)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ return utf8::peek_next(it, end);
+ }
+
+ /// Deprecated in versions that include "prior"
+ template <typename octet_iterator>
+ uint32_t previous(octet_iterator& it, octet_iterator pass_start)
+ {
+ octet_iterator end = it;
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == pass_start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ octet_iterator temp = it;
+ return utf8::next(temp, end);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n, octet_iterator end)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ if (utf8::internal::is_trail_surrogate(trail_surrogate))
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ else
+ throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::next(start, end);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start != end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it,
+ const octet_iterator& range_start,
+ const octet_iterator& range_end) :
+ it(octet_it), range_start(range_start), range_end(range_end)
+ {
+ if (it < range_start || it > range_end)
+ throw std::out_of_range("Invalid utf-8 iterator position");
+ }
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#endif //header guard
+
+
diff --git a/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/core.h b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/core.h
new file mode 100644
index 000000000..693d388c0
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/core.h
@@ -0,0 +1,329 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+namespace utf8
+{
+ // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+ // You may need to change them to match your system.
+ // These typedefs have the same names as ones from cstdint, or boost/cstdint
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+ // Unicode constants
+ // Leading (high) surrogates: 0xd800 - 0xdbff
+ // Trailing (low) surrogates: 0xdc00 - 0xdfff
+ const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
+ const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
+ const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+ const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+ const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
+ const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_t>(0xffff & oc);
+ }
+ template<typename octet_type>
+ inline bool is_trail(octet_type oc)
+ {
+ return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+ }
+
+ template <typename u16>
+ inline bool is_lead_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 cp)
+ {
+ return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+ }
+
+ template <typename octet_iterator>
+ inline typename std::iterator_traits<octet_iterator>::difference_type
+ sequence_length(octet_iterator lead_it)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// get_sequence_x functions decode utf-8 sequences of the length x
+ template <typename octet_iterator>
+ utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+ template <typename octet_iterator>
+ utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ // Save the original value of it so we can go back in case of failure
+ // Of course, it does not make much sense with i.e. stream iterators
+ octet_iterator original_it = it;
+
+ uint32_t cp = 0;
+ // Determine the sequence length based on the lead octet
+ typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+ const octet_difference_type length = utf8::internal::sequence_length(it);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+
+ //Deprecated in release 2.3
+ template <typename octet_iterator>
+ inline bool is_bom (octet_iterator it)
+ {
+ return (
+ (utf8::internal::mask8(*it++)) == bom[0] &&
+ (utf8::internal::mask8(*it++)) == bom[1] &&
+ (utf8::internal::mask8(*it)) == bom[2]
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h
new file mode 100644
index 000000000..cb2427166
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/utf8cpp/source/utf8/unchecked.h
@@ -0,0 +1,228 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it)
+ {
+ uint32_t cp = utf8::internal::mask8(*it);
+ typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+ switch (length) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it)
+ {
+ while (utf8::internal::is_trail(*(--it))) ;
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+
+ // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
+ template <typename octet_iterator>
+ inline uint32_t previous(octet_iterator& it)
+ {
+ return utf8::unchecked::prior(it);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::unchecked::next(start);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ public:
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/src/3rdparty/assimp/contrib/zip/README.md b/src/3rdparty/assimp/contrib/zip/README.md
new file mode 100644
index 000000000..24de5e61a
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/zip/README.md
@@ -0,0 +1,139 @@
+### A portable (OSX/Linux/Windows), simple zip library written in C
+This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
+
+[![Windows][win-badge]][win-link] [![OS X][osx-linux-badge]][osx-linux-link]
+
+[win-badge]: https://img.shields.io/appveyor/ci/kuba--/zip/master.svg?label=windows "AppVeyor build status"
+[win-link]: https://ci.appveyor.com/project/kuba--/zip "AppVeyor build status"
+[osx-linux-badge]: https://img.shields.io/travis/kuba--/zip/master.svg?label=linux/osx "Travis CI build status"
+[osx-linux-link]: https://travis-ci.org/kuba--/zip "Travis CI build status"
+
+# The Idea
+<img src="zip.png" name="zip" />
+... Some day, I was looking for zip library written in C for my project, but I could not find anything simple enough and lightweight.
+Everything what I tried required 'crazy mental gymnastics' to integrate or had some limitations or was too heavy.
+I hate frameworks, factories and adding new dependencies. If I must to install all those dependencies and link new library, I'm getting almost sick.
+I wanted something powerfull and small enough, so I could add just a few files and compile them into my project.
+And finally I found miniz.
+Miniz is a lossless, high performance data compression library in a single source file. I only needed simple interface to append buffers or files to the current zip-entry. Thanks to this feature I'm able to merge many files/buffers and compress them on-the-fly.
+
+It was the reason, why I decided to write zip module on top of the miniz. It required a little bit hacking and wrapping some functions, but I kept simplicity. So, you can grab these 3 files and compile them into your project. I hope that interface is also extremely simple, so you will not have any problems to understand it.
+
+# Examples
+
+* Create a new zip archive with default compression level.
+```c
+ struct zip_t *zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
+ {
+ zip_entry_open(zip, "foo-1.txt");
+ {
+ char *buf = "Some data here...";
+ zip_entry_write(zip, buf, strlen(buf));
+ }
+ zip_entry_close(zip);
+
+ zip_entry_open(zip, "foo-2.txt");
+ {
+ // merge 3 files into one entry and compress them on-the-fly.
+ zip_entry_fwrite(zip, "foo-2.1.txt");
+ zip_entry_fwrite(zip, "foo-2.2.txt");
+ zip_entry_fwrite(zip, "foo-2.3.txt");
+ }
+ zip_entry_close(zip);
+ }
+ zip_close(zip);
+```
+
+* Append to the existing zip archive.
+```c
+ struct zip_t *zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'a');
+ {
+ zip_entry_open(zip, "foo-3.txt");
+ {
+ char *buf = "Append some data here...";
+ zip_entry_write(zip, buf, strlen(buf));
+ }
+ zip_entry_close(zip);
+ }
+ zip_close(zip);
+```
+
+* Extract a zip archive into a folder.
+```c
+ int on_extract_entry(const char *filename, void *arg) {
+ static int i = 0;
+ int n = *(int *)arg;
+ printf("Extracted: %s (%d of %d)\n", filename, ++i, n);
+
+ return 0;
+ }
+
+ int arg = 2;
+ zip_extract("foo.zip", "/tmp", on_extract_entry, &arg);
+```
+
+* Extract a zip entry into memory.
+```c
+ void *buf = NULL;
+ size_t bufsize;
+
+ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
+ {
+ zip_entry_open(zip, "foo-1.txt");
+ {
+ zip_entry_read(zip, &buf, &bufsize);
+ }
+ zip_entry_close(zip);
+ }
+ zip_close(zip);
+
+ free(buf);
+```
+
+* Extract a zip entry into memory using callback.
+```c
+ struct buffer_t {
+ char *data;
+ size_t size;
+ };
+
+ static size_t on_extract(void *arg, unsigned long long offset, const void *data, size_t size) {
+ struct buffer_t *buf = (struct buffer_t *)arg;
+ buf->data = realloc(buf->data, buf->size + size + 1);
+ assert(NULL != buf->data);
+
+ memcpy(&(buf->data[buf->size]), data, size);
+ buf->size += size;
+ buf->data[buf->size] = 0;
+
+ return size;
+ }
+
+ struct buffer_t buf = {0};
+ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
+ {
+ zip_entry_open(zip, "foo-1.txt");
+ {
+ zip_entry_extract(zip, on_extract, &buf);
+ }
+ zip_entry_close(zip);
+ }
+ zip_close(zip);
+
+ free(buf.data);
+```
+
+
+* Extract a zip entry into a file.
+```c
+ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
+ {
+ zip_entry_open(zip, "foo-2.txt");
+ {
+ zip_entry_fread(zip, "foo-2.txt");
+ }
+ zip_entry_close(zip);
+ }
+ zip_close(zip);
+```
+
diff --git a/src/3rdparty/assimp/contrib/zip/UNLICENSE b/src/3rdparty/assimp/contrib/zip/UNLICENSE
new file mode 100644
index 000000000..ed7cccdf2
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/zip/UNLICENSE
@@ -0,0 +1,26 @@
+/*
+ This is free and unencumbered software released into the public domain.
+
+ Anyone is free to copy, modify, publish, use, compile, sell, or
+ distribute this software, either in source code form or as a compiled
+ binary, for any purpose, commercial or non-commercial, and by any
+ means.
+
+ In jurisdictions that recognize copyright laws, the author or authors
+ of this software dedicate any and all copyright interest in the
+ software to the public domain. We make this dedication for the benefit
+ of the public at large and to the detriment of our heirs and
+ successors. We intend this dedication to be an overt act of
+ relinquishment in perpetuity of all present and future rights to this
+ software under copyright law.
+
+ 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 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.
+
+ For more information, please refer to <http://unlicense.org/>
+*/
diff --git a/src/3rdparty/assimp/contrib/zip/src/miniz.h b/src/3rdparty/assimp/contrib/zip/src/miniz.h
new file mode 100644
index 000000000..916fb1ff8
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/zip/src/miniz.h
@@ -0,0 +1,4927 @@
+/*
+ miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
+ See "unlicense" statement at the end of this file.
+ Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013
+ Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
+
+ Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
+ MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
+
+ * Change History
+ 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!):
+ - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug
+ would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
+ (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
+ - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
+ - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
+ Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
+ - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
+ - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
+ - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
+ - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
+ - Merged MZ_FORCEINLINE fix from hdeanclark
+ - Fix <time.h> include before config #ifdef, thanks emil.brink
+ - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
+ set it to 1 for real-time compression).
+ - Merged in some compiler fixes from paulharris's github repro.
+ - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3.
+ - Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
+ - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
+ - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
+  - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
+ 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
+ 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
+ - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
+ - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
+ - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
+ "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
+ - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
+ - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
+ - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
+ - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
+ - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
+ 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
+ level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com> for the feedback/bug report.
+ 5/28/11 v1.11 - Added statement from unlicense.org
+ 5/27/11 v1.10 - Substantial compressor optimizations:
+ - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
+ - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
+ - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
+ - Refactored the compression code for better readability and maintainability.
+ - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
+ drop in throughput on some files).
+ 5/15/11 v1.09 - Initial stable release.
+
+ * Low-level Deflate/Inflate implementation notes:
+
+ Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
+ greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
+ approximately as well as zlib.
+
+ Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
+ coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
+ block large enough to hold the entire file.
+
+ The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.
+
+ * zlib-style API notes:
+
+ miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
+ zlib replacement in many apps:
+ The z_stream struct, optional memory allocation callbacks
+ deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
+ inflateInit/inflateInit2/inflate/inflateEnd
+ compress, compress2, compressBound, uncompress
+ CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
+ Supports raw deflate streams or standard zlib streams with adler-32 checking.
+
+ Limitations:
+ The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
+ I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
+ there are no guarantees that miniz.c pulls this off perfectly.
+
+ * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
+ Alex Evans. Supports 1-4 bytes/pixel images.
+
+ * ZIP archive API notes:
+
+ The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
+ get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
+ existing archives, create new archives, append new files to existing archives, or clone archive data from
+ one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
+ or you can specify custom file read/write callbacks.
+
+ - Archive reading: Just call this function to read a single file from a disk archive:
+
+ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
+ size_t *pSize, mz_uint zip_flags);
+
+ For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
+ directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.
+
+ - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:
+
+ int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
+
+ The locate operation can optionally check file comments too, which (as one example) can be used to identify
+ multiple versions of the same file in an archive. This function uses a simple linear search through the central
+ directory, so it's not very fast.
+
+ Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
+ retrieve detailed info on each file by calling mz_zip_reader_file_stat().
+
+ - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
+ to disk and builds an exact image of the central directory in memory. The central directory image is written
+ all at once at the end of the archive file when the archive is finalized.
+
+ The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
+ which can be useful when the archive will be read from optical media. Also, the writer supports placing
+ arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
+ readable by any ZIP tool.
+
+ - Archive appending: The simple way to add a single file to an archive is to call this function:
+
+ mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
+ const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+
+ The archive will be created if it doesn't already exist, otherwise it'll be appended to.
+ Note the appending is done in-place and is not an atomic operation, so if something goes wrong
+ during the operation it's possible the archive could be left without a central directory (although the local
+ file headers and file data will be fine, so the archive will be recoverable).
+
+ For more complex archive modification scenarios:
+ 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
+ preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
+ compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
+ you're done. This is safe but requires a bunch of temporary disk space or heap memory.
+
+ 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
+ append new files as needed, then finalize the archive which will write an updated central directory to the
+ original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
+ possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
+
+ - ZIP archive support limitations:
+ No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
+ Requires streams capable of seeking.
+
+ * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
+ below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
+
+ * Important: For best perf. be sure to customize the below macros for your target platform:
+ #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
+ #define MINIZ_LITTLE_ENDIAN 1
+ #define MINIZ_HAS_64BIT_REGISTERS 1
+
+ * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz
+ uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files
+ (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
+*/
+
+#ifndef MINIZ_HEADER_INCLUDED
+#define MINIZ_HEADER_INCLUDED
+
+#include <stdlib.h>
+
+// Defines to completely disable specific portions of miniz.c:
+// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
+
+// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
+//#define MINIZ_NO_STDIO
+
+// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
+// get/set file times, and the C run-time funcs that get/set times won't be called.
+// The current downside is the times written to your archives will be from 1979.
+//#define MINIZ_NO_TIME
+
+// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
+//#define MINIZ_NO_ARCHIVE_APIS
+
+// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
+//#define MINIZ_NO_ARCHIVE_WRITING_APIS
+
+// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
+//#define MINIZ_NO_ZLIB_APIS
+
+// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
+//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+
+// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
+// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
+// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
+// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
+//#define MINIZ_NO_MALLOC
+
+#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
+ // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
+ #define MINIZ_NO_TIME
+#endif
+
+#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
+ #include <time.h>
+#endif
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
+// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
+#define MINIZ_X86_OR_X64_CPU 1
+#endif
+
+#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
+// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
+#define MINIZ_LITTLE_ENDIAN 1
+#endif
+
+#if MINIZ_X86_OR_X64_CPU
+// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
+#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
+#endif
+
+#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
+// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
+#define MINIZ_HAS_64BIT_REGISTERS 1
+#endif
+
+#ifdef __APPLE__
+#define ftello64 ftello
+#define fseeko64 fseeko
+#define fopen64 fopen
+#define freopen64 freopen
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ------------------- zlib-style API Definitions.
+
+// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
+typedef unsigned long mz_ulong;
+
+// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
+void mz_free(void *p);
+
+#define MZ_ADLER32_INIT (1)
+// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
+mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
+
+#define MZ_CRC32_INIT (0)
+// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
+mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
+
+// Compression strategies.
+enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
+
+// Method
+#define MZ_DEFLATED 8
+
+#ifndef MINIZ_NO_ZLIB_APIS
+
+// Heap allocation callbacks.
+// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
+typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
+typedef void (*mz_free_func)(void *opaque, void *address);
+typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
+
+#define MZ_VERSION "9.1.15"
+#define MZ_VERNUM 0x91F0
+#define MZ_VER_MAJOR 9
+#define MZ_VER_MINOR 1
+#define MZ_VER_REVISION 15
+#define MZ_VER_SUBREVISION 0
+
+// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
+enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
+
+// Return status codes. MZ_PARAM_ERROR is non-standard.
+enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
+
+// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
+enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
+
+// Window bits
+#define MZ_DEFAULT_WINDOW_BITS 15
+
+struct mz_internal_state;
+
+// Compression/decompression stream struct.
+typedef struct mz_stream_s
+{
+ const unsigned char *next_in; // pointer to next byte to read
+ unsigned int avail_in; // number of bytes available at next_in
+ mz_ulong total_in; // total number of bytes consumed so far
+
+ unsigned char *next_out; // pointer to next byte to write
+ unsigned int avail_out; // number of bytes that can be written to next_out
+ mz_ulong total_out; // total number of bytes produced so far
+
+ char *msg; // error msg (unused)
+ struct mz_internal_state *state; // internal state, allocated by zalloc/zfree
+
+ mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc)
+ mz_free_func zfree; // optional heap free function (defaults to free)
+ void *opaque; // heap alloc function user pointer
+
+ int data_type; // data_type (unused)
+ mz_ulong adler; // adler32 of the source or uncompressed data
+ mz_ulong reserved; // not used
+} mz_stream;
+
+typedef mz_stream *mz_streamp;
+
+// Returns the version string of miniz.c.
+const char *mz_version(void);
+
+// mz_deflateInit() initializes a compressor with default options:
+// Parameters:
+// pStream must point to an initialized mz_stream struct.
+// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
+// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
+// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
+// Return values:
+// MZ_OK on success.
+// MZ_STREAM_ERROR if the stream is bogus.
+// MZ_PARAM_ERROR if the input parameters are bogus.
+// MZ_MEM_ERROR on out of memory.
+int mz_deflateInit(mz_streamp pStream, int level);
+
+// mz_deflateInit2() is like mz_deflate(), except with more control:
+// Additional parameters:
+// method must be MZ_DEFLATED
+// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
+// mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
+int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
+
+// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
+int mz_deflateReset(mz_streamp pStream);
+
+// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
+// Parameters:
+// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
+// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
+// Return values:
+// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
+// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
+// MZ_STREAM_ERROR if the stream is bogus.
+// MZ_PARAM_ERROR if one of the parameters is invalid.
+// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
+int mz_deflate(mz_streamp pStream, int flush);
+
+// mz_deflateEnd() deinitializes a compressor:
+// Return values:
+// MZ_OK on success.
+// MZ_STREAM_ERROR if the stream is bogus.
+int mz_deflateEnd(mz_streamp pStream);
+
+// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
+mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
+
+// Single-call compression functions mz_compress() and mz_compress2():
+// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
+int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
+int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
+
+// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
+mz_ulong mz_compressBound(mz_ulong source_len);
+
+// Initializes a decompressor.
+int mz_inflateInit(mz_streamp pStream);
+
+// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
+// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
+int mz_inflateInit2(mz_streamp pStream, int window_bits);
+
+// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
+// Parameters:
+// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
+// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
+// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
+// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
+// Return values:
+// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
+// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
+// MZ_STREAM_ERROR if the stream is bogus.
+// MZ_DATA_ERROR if the deflate stream is invalid.
+// MZ_PARAM_ERROR if one of the parameters is invalid.
+// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
+// with more input data, or with more room in the output buffer (except when using single call decompression, described above).
+int mz_inflate(mz_streamp pStream, int flush);
+
+// Deinitializes a decompressor.
+int mz_inflateEnd(mz_streamp pStream);
+
+// Single-call decompression.
+// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
+int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
+
+// Returns a string description of the specified error code, or NULL if the error code is invalid.
+const char *mz_error(int err);
+
+// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
+// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
+#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+ typedef unsigned char Byte;
+ typedef unsigned int uInt;
+ typedef mz_ulong uLong;
+ typedef Byte Bytef;
+ typedef uInt uIntf;
+ typedef char charf;
+ typedef int intf;
+ typedef void *voidpf;
+ typedef uLong uLongf;
+ typedef void *voidp;
+ typedef void *const voidpc;
+ #define Z_NULL 0
+ #define Z_NO_FLUSH MZ_NO_FLUSH
+ #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
+ #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
+ #define Z_FULL_FLUSH MZ_FULL_FLUSH
+ #define Z_FINISH MZ_FINISH
+ #define Z_BLOCK MZ_BLOCK
+ #define Z_OK MZ_OK
+ #define Z_STREAM_END MZ_STREAM_END
+ #define Z_NEED_DICT MZ_NEED_DICT
+ #define Z_ERRNO MZ_ERRNO
+ #define Z_STREAM_ERROR MZ_STREAM_ERROR
+ #define Z_DATA_ERROR MZ_DATA_ERROR
+ #define Z_MEM_ERROR MZ_MEM_ERROR
+ #define Z_BUF_ERROR MZ_BUF_ERROR
+ #define Z_VERSION_ERROR MZ_VERSION_ERROR
+ #define Z_PARAM_ERROR MZ_PARAM_ERROR
+ #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
+ #define Z_BEST_SPEED MZ_BEST_SPEED
+ #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
+ #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
+ #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
+ #define Z_FILTERED MZ_FILTERED
+ #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
+ #define Z_RLE MZ_RLE
+ #define Z_FIXED MZ_FIXED
+ #define Z_DEFLATED MZ_DEFLATED
+ #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
+ #define alloc_func mz_alloc_func
+ #define free_func mz_free_func
+ #define internal_state mz_internal_state
+ #define z_stream mz_stream
+ #define deflateInit mz_deflateInit
+ #define deflateInit2 mz_deflateInit2
+ #define deflateReset mz_deflateReset
+ #define deflate mz_deflate
+ #define deflateEnd mz_deflateEnd
+ #define deflateBound mz_deflateBound
+ #define compress mz_compress
+ #define compress2 mz_compress2
+ #define compressBound mz_compressBound
+ #define inflateInit mz_inflateInit
+ #define inflateInit2 mz_inflateInit2
+ #define inflate mz_inflate
+ #define inflateEnd mz_inflateEnd
+ #define uncompress mz_uncompress
+ #define crc32 mz_crc32
+ #define adler32 mz_adler32
+ #define MAX_WBITS 15
+ #define MAX_MEM_LEVEL 9
+ #define zError mz_error
+ #define ZLIB_VERSION MZ_VERSION
+ #define ZLIB_VERNUM MZ_VERNUM
+ #define ZLIB_VER_MAJOR MZ_VER_MAJOR
+ #define ZLIB_VER_MINOR MZ_VER_MINOR
+ #define ZLIB_VER_REVISION MZ_VER_REVISION
+ #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
+ #define zlibVersion mz_version
+ #define zlib_version mz_version()
+#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+
+#endif // MINIZ_NO_ZLIB_APIS
+
+// ------------------- Types and macros
+
+typedef unsigned char mz_uint8;
+typedef signed short mz_int16;
+typedef unsigned short mz_uint16;
+typedef unsigned int mz_uint32;
+typedef unsigned int mz_uint;
+typedef long long mz_int64;
+typedef unsigned long long mz_uint64;
+typedef int mz_bool;
+
+#define MZ_FALSE (0)
+#define MZ_TRUE (1)
+
+// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
+#ifdef _MSC_VER
+ #define MZ_MACRO_END while (0, 0)
+#else
+ #define MZ_MACRO_END while (0)
+#endif
+
+// ------------------- ZIP archive reading/writing
+
+#ifndef MINIZ_NO_ARCHIVE_APIS
+
+enum
+{
+ MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
+ MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
+ MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
+};
+
+typedef struct
+{
+ mz_uint32 m_file_index;
+ mz_uint32 m_central_dir_ofs;
+ mz_uint16 m_version_made_by;
+ mz_uint16 m_version_needed;
+ mz_uint16 m_bit_flag;
+ mz_uint16 m_method;
+#ifndef MINIZ_NO_TIME
+ time_t m_time;
+#endif
+ mz_uint32 m_crc32;
+ mz_uint64 m_comp_size;
+ mz_uint64 m_uncomp_size;
+ mz_uint16 m_internal_attr;
+ mz_uint32 m_external_attr;
+ mz_uint64 m_local_header_ofs;
+ mz_uint32 m_comment_size;
+ char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
+ char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
+} mz_zip_archive_file_stat;
+
+typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
+typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
+
+struct mz_zip_internal_state_tag;
+typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
+
+typedef enum
+{
+ MZ_ZIP_MODE_INVALID = 0,
+ MZ_ZIP_MODE_READING = 1,
+ MZ_ZIP_MODE_WRITING = 2,
+ MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
+} mz_zip_mode;
+
+typedef struct mz_zip_archive_tag
+{
+ mz_uint64 m_archive_size;
+ mz_uint64 m_central_directory_file_ofs;
+ mz_uint m_total_files;
+ mz_zip_mode m_zip_mode;
+
+ mz_uint m_file_offset_alignment;
+
+ mz_alloc_func m_pAlloc;
+ mz_free_func m_pFree;
+ mz_realloc_func m_pRealloc;
+ void *m_pAlloc_opaque;
+
+ mz_file_read_func m_pRead;
+ mz_file_write_func m_pWrite;
+ void *m_pIO_opaque;
+
+ mz_zip_internal_state *m_pState;
+
+} mz_zip_archive;
+
+typedef enum
+{
+ MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
+ MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
+ MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
+ MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
+} mz_zip_flags;
+
+// ZIP archive reading
+
+// Inits a ZIP archive reader.
+// These functions read and validate the archive's central directory.
+mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
+mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
+#endif
+
+// Returns the total number of files in the archive.
+mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
+
+// Returns detailed information about an archive file entry.
+mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
+
+// Determines if an archive file entry is a directory entry.
+mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
+mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
+
+// Retrieves the filename of an archive file entry.
+// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
+mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
+
+// Attempts to locates a file in the archive's central directory.
+// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
+// Returns -1 if the file cannot be found.
+int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
+
+// Extracts a archive file to a memory buffer using no memory allocation.
+mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
+mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
+
+// Extracts a archive file to a memory buffer.
+mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
+
+// Extracts a archive file to a dynamically allocated heap buffer.
+void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
+void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
+
+// Extracts a archive file using a callback function to output the file's data.
+mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
+
+#ifndef MINIZ_NO_STDIO
+// Extracts a archive file to a disk file and sets its last accessed and modified times.
+// This function only extracts files, not archive directory records.
+mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
+#endif
+
+// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
+mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
+
+// ZIP archive writing
+
+#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+// Inits a ZIP archive writer.
+mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
+mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
+#endif
+
+// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
+// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
+// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
+// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
+// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
+// the archive is finalized the file's central directory will be hosed.
+mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
+
+// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
+// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
+mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
+
+#ifndef MINIZ_NO_STDIO
+// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+#endif
+
+// Adds a file to an archive by fully cloning the data from another archive.
+// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
+mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
+
+// Finalizes the archive by writing the central directory records followed by the end of central directory record.
+// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
+// An archive must be manually finalized by calling this function for it to be valid.
+mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
+mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
+
+// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
+// Note for the archive to be valid, it must have been finalized before ending.
+mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
+
+// Misc. high-level helper functions:
+
+// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+
+// Reads a single file from an archive into a heap block.
+// Returns NULL on failure.
+void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
+
+// ------------------- Low-level Decompression API Definitions
+
+// Decompression flags used by tinfl_decompress().
+// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
+// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
+// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
+// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
+enum
+{
+ TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
+ TINFL_FLAG_HAS_MORE_INPUT = 2,
+ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
+ TINFL_FLAG_COMPUTE_ADLER32 = 8
+};
+
+// High level decompression functions:
+// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
+// On entry:
+// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
+// On return:
+// Function returns a pointer to the decompressed data, or NULL on failure.
+// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
+// The caller must call mz_free() on the returned block when it's no longer needed.
+void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
+
+// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
+// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
+#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
+// Returns 1 on success or 0 on failure.
+typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
+
+// Max size of LZ dictionary.
+#define TINFL_LZ_DICT_SIZE 32768
+
+// Return status.
+typedef enum
+{
+ TINFL_STATUS_BAD_PARAM = -3,
+ TINFL_STATUS_ADLER32_MISMATCH = -2,
+ TINFL_STATUS_FAILED = -1,
+ TINFL_STATUS_DONE = 0,
+ TINFL_STATUS_NEEDS_MORE_INPUT = 1,
+ TINFL_STATUS_HAS_MORE_OUTPUT = 2
+} tinfl_status;
+
+// Initializes the decompressor to its initial state.
+#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
+#define tinfl_get_adler32(r) (r)->m_check_adler32
+
+// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
+// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
+
+// Internal/private bits follow.
+enum
+{
+ TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
+ TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
+};
+
+typedef struct
+{
+ mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
+ mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
+} tinfl_huff_table;
+
+#if MINIZ_HAS_64BIT_REGISTERS
+ #define TINFL_USE_64BIT_BITBUF 1
+#endif
+
+#if TINFL_USE_64BIT_BITBUF
+ typedef mz_uint64 tinfl_bit_buf_t;
+ #define TINFL_BITBUF_SIZE (64)
+#else
+ typedef mz_uint32 tinfl_bit_buf_t;
+ #define TINFL_BITBUF_SIZE (32)
+#endif
+
+struct tinfl_decompressor_tag
+{
+ mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
+ tinfl_bit_buf_t m_bit_buf;
+ size_t m_dist_from_out_buf_start;
+ tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
+ mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
+};
+
+// ------------------- Low-level Compression API Definitions
+
+// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
+#define TDEFL_LESS_MEMORY 0
+
+// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
+// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
+enum
+{
+ TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
+};
+
+// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
+// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
+// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
+// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
+// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
+// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
+// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
+// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
+// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
+enum
+{
+ TDEFL_WRITE_ZLIB_HEADER = 0x01000,
+ TDEFL_COMPUTE_ADLER32 = 0x02000,
+ TDEFL_GREEDY_PARSING_FLAG = 0x04000,
+ TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
+ TDEFL_RLE_MATCHES = 0x10000,
+ TDEFL_FILTER_MATCHES = 0x20000,
+ TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
+ TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
+};
+
+// High level compression functions:
+// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
+// On entry:
+// pSrc_buf, src_buf_len: Pointer and size of source block to compress.
+// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
+// On return:
+// Function returns a pointer to the compressed data, or NULL on failure.
+// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
+// The caller must free() the returned block when it's no longer needed.
+void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
+
+// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
+// Returns 0 on failure.
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// Compresses an image to a compressed PNG file in memory.
+// On entry:
+// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4.
+// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
+// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
+// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
+// On return:
+// Function returns a pointer to the compressed data, or NULL on failure.
+// *pLen_out will be set to the size of the PNG image file.
+// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
+void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
+void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
+
+// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
+typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+
+// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
+
+// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
+#if TDEFL_LESS_MEMORY
+enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#else
+enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#endif
+
+// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
+typedef enum
+{
+ TDEFL_STATUS_BAD_PARAM = -2,
+ TDEFL_STATUS_PUT_BUF_FAILED = -1,
+ TDEFL_STATUS_OKAY = 0,
+ TDEFL_STATUS_DONE = 1,
+} tdefl_status;
+
+// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
+typedef enum
+{
+ TDEFL_NO_FLUSH = 0,
+ TDEFL_SYNC_FLUSH = 2,
+ TDEFL_FULL_FLUSH = 3,
+ TDEFL_FINISH = 4
+} tdefl_flush;
+
+// tdefl's compression state structure.
+typedef struct
+{
+ tdefl_put_buf_func_ptr m_pPut_buf_func;
+ void *m_pPut_buf_user;
+ mz_uint m_flags, m_max_probes[2];
+ int m_greedy_parsing;
+ mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
+ mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
+ mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
+ mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
+ tdefl_status m_prev_return_status;
+ const void *m_pIn_buf;
+ void *m_pOut_buf;
+ size_t *m_pIn_buf_size, *m_pOut_buf_size;
+ tdefl_flush m_flush;
+ const mz_uint8 *m_pSrc;
+ size_t m_src_buf_left, m_out_buf_ofs;
+ mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
+ mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+ mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+ mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+ mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
+ mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
+ mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
+ mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
+} tdefl_compressor;
+
+// Initializes the compressor.
+// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
+// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
+// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
+// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
+
+// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
+// tdefl_compress_buffer() always consumes the entire input buffer.
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
+
+// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
+#ifndef MINIZ_NO_ZLIB_APIS
+// Create tdefl_compress() flags given zlib-style compression parameters.
+// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
+// window_bits may be -15 (raw deflate) or 15 (zlib)
+// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
+#endif // #ifndef MINIZ_NO_ZLIB_APIS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_INCLUDED
+
+// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
+
+#ifndef MINIZ_HEADER_FILE_ONLY
+
+typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
+typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
+typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
+
+#include <string.h>
+#include <assert.h>
+
+#define MZ_ASSERT(x) assert(x)
+
+#ifdef MINIZ_NO_MALLOC
+ #define MZ_MALLOC(x) NULL
+ #define MZ_FREE(x) (void)x, ((void)0)
+ #define MZ_REALLOC(p, x) NULL
+#else
+ #define MZ_MALLOC(x) malloc(x)
+ #define MZ_FREE(x) free(x)
+ #define MZ_REALLOC(p, x) realloc(p, x)
+#endif
+
+#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
+#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
+#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+ #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
+ #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
+#else
+ #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
+ #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
+#endif
+
+#ifdef _MSC_VER
+ #define MZ_FORCEINLINE __forceinline
+#elif defined(__GNUC__)
+ #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
+#else
+ #define MZ_FORCEINLINE inline
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// ------------------- zlib-style API's
+
+mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
+{
+ mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
+ if (!ptr) return MZ_ADLER32_INIT;
+ while (buf_len) {
+ for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
+ s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
+ s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
+ }
+ for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
+ s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
+ }
+ return (s2 << 16) + s1;
+}
+
+// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
+mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
+{
+ static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
+ mz_uint32 crcu32 = (mz_uint32)crc;
+ if (!ptr) return MZ_CRC32_INIT;
+ crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
+ return ~crcu32;
+}
+
+void mz_free(void *p)
+{
+ MZ_FREE(p);
+}
+
+#ifndef MINIZ_NO_ZLIB_APIS
+
+static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
+static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
+static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }
+
+const char *mz_version(void)
+{
+ return MZ_VERSION;
+}
+
+int mz_deflateInit(mz_streamp pStream, int level)
+{
+ return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
+}
+
+int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
+{
+ tdefl_compressor *pComp;
+ mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
+
+ if (!pStream) return MZ_STREAM_ERROR;
+ if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;
+
+ pStream->data_type = 0;
+ pStream->adler = MZ_ADLER32_INIT;
+ pStream->msg = NULL;
+ pStream->reserved = 0;
+ pStream->total_in = 0;
+ pStream->total_out = 0;
+ if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
+ if (!pStream->zfree) pStream->zfree = def_free_func;
+
+ pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
+ if (!pComp)
+ return MZ_MEM_ERROR;
+
+ pStream->state = (struct mz_internal_state *)pComp;
+
+ if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
+ {
+ mz_deflateEnd(pStream);
+ return MZ_PARAM_ERROR;
+ }
+
+ return MZ_OK;
+}
+
+int mz_deflateReset(mz_streamp pStream)
+{
+ if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
+ pStream->total_in = pStream->total_out = 0;
+ tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
+ return MZ_OK;
+}
+
+int mz_deflate(mz_streamp pStream, int flush)
+{
+ size_t in_bytes, out_bytes;
+ mz_ulong orig_total_in, orig_total_out;
+ int mz_status = MZ_OK;
+
+ if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
+ if (!pStream->avail_out) return MZ_BUF_ERROR;
+
+ if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
+
+ if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
+ return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
+
+ orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
+ for ( ; ; )
+ {
+ tdefl_status defl_status;
+ in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
+
+ defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
+ pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
+ pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
+
+ pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
+ pStream->total_out += (mz_uint)out_bytes;
+
+ if (defl_status < 0)
+ {
+ mz_status = MZ_STREAM_ERROR;
+ break;
+ }
+ else if (defl_status == TDEFL_STATUS_DONE)
+ {
+ mz_status = MZ_STREAM_END;
+ break;
+ }
+ else if (!pStream->avail_out)
+ break;
+ else if ((!pStream->avail_in) && (flush != MZ_FINISH))
+ {
+ if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
+ break;
+ return MZ_BUF_ERROR; // Can't make forward progress without some input.
+ }
+ }
+ return mz_status;
+}
+
+int mz_deflateEnd(mz_streamp pStream)
+{
+ if (!pStream) return MZ_STREAM_ERROR;
+ if (pStream->state)
+ {
+ pStream->zfree(pStream->opaque, pStream->state);
+ pStream->state = NULL;
+ }
+ return MZ_OK;
+}
+
+mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
+{
+ (void)pStream;
+ // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
+ return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
+}
+
+int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
+{
+ int status;
+ mz_stream stream;
+ memset(&stream, 0, sizeof(stream));
+
+ // In case mz_ulong is 64-bits (argh I hate longs).
+ if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
+
+ stream.next_in = pSource;
+ stream.avail_in = (mz_uint32)source_len;
+ stream.next_out = pDest;
+ stream.avail_out = (mz_uint32)*pDest_len;
+
+ status = mz_deflateInit(&stream, level);
+ if (status != MZ_OK) return status;
+
+ status = mz_deflate(&stream, MZ_FINISH);
+ if (status != MZ_STREAM_END)
+ {
+ mz_deflateEnd(&stream);
+ return (status == MZ_OK) ? MZ_BUF_ERROR : status;
+ }
+
+ *pDest_len = stream.total_out;
+ return mz_deflateEnd(&stream);
+}
+
+int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
+{
+ return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
+}
+
+mz_ulong mz_compressBound(mz_ulong source_len)
+{
+ return mz_deflateBound(NULL, source_len);
+}
+
+typedef struct
+{
+ tinfl_decompressor m_decomp;
+ mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
+ mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
+ tinfl_status m_last_status;
+} inflate_state;
+
+int mz_inflateInit2(mz_streamp pStream, int window_bits)
+{
+ inflate_state *pDecomp;
+ if (!pStream) return MZ_STREAM_ERROR;
+ if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
+
+ pStream->data_type = 0;
+ pStream->adler = 0;
+ pStream->msg = NULL;
+ pStream->total_in = 0;
+ pStream->total_out = 0;
+ pStream->reserved = 0;
+ if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
+ if (!pStream->zfree) pStream->zfree = def_free_func;
+
+ pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
+ if (!pDecomp) return MZ_MEM_ERROR;
+
+ pStream->state = (struct mz_internal_state *)pDecomp;
+
+ tinfl_init(&pDecomp->m_decomp);
+ pDecomp->m_dict_ofs = 0;
+ pDecomp->m_dict_avail = 0;
+ pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
+ pDecomp->m_first_call = 1;
+ pDecomp->m_has_flushed = 0;
+ pDecomp->m_window_bits = window_bits;
+
+ return MZ_OK;
+}
+
+int mz_inflateInit(mz_streamp pStream)
+{
+ return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
+}
+
+int mz_inflate(mz_streamp pStream, int flush)
+{
+ inflate_state* pState;
+ mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
+ size_t in_bytes, out_bytes, orig_avail_in;
+ tinfl_status status;
+
+ if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
+ if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
+ if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
+
+ pState = (inflate_state*)pStream->state;
+ if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
+ orig_avail_in = pStream->avail_in;
+
+ first_call = pState->m_first_call; pState->m_first_call = 0;
+ if (pState->m_last_status < 0) return MZ_DATA_ERROR;
+
+ if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
+ pState->m_has_flushed |= (flush == MZ_FINISH);
+
+ if ((flush == MZ_FINISH) && (first_call))
+ {
+ // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
+ decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+ in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
+ status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
+ pState->m_last_status = status;
+ pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
+ pStream->adler = tinfl_get_adler32(&pState->m_decomp);
+ pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
+
+ if (status < 0)
+ return MZ_DATA_ERROR;
+ else if (status != TINFL_STATUS_DONE)
+ {
+ pState->m_last_status = TINFL_STATUS_FAILED;
+ return MZ_BUF_ERROR;
+ }
+ return MZ_STREAM_END;
+ }
+ // flush != MZ_FINISH then we must assume there's more input.
+ if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
+
+ if (pState->m_dict_avail)
+ {
+ n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
+ memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
+ pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
+ pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
+ return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
+ }
+
+ for ( ; ; )
+ {
+ in_bytes = pStream->avail_in;
+ out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
+
+ status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
+ pState->m_last_status = status;
+
+ pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
+ pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
+
+ pState->m_dict_avail = (mz_uint)out_bytes;
+
+ n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
+ memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
+ pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
+ pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
+
+ if (status < 0)
+ return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
+ else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
+ return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
+ else if (flush == MZ_FINISH)
+ {
+ // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
+ if (status == TINFL_STATUS_DONE)
+ return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
+ // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
+ else if (!pStream->avail_out)
+ return MZ_BUF_ERROR;
+ }
+ else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
+ break;
+ }
+
+ return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
+}
+
+int mz_inflateEnd(mz_streamp pStream)
+{
+ if (!pStream)
+ return MZ_STREAM_ERROR;
+ if (pStream->state)
+ {
+ pStream->zfree(pStream->opaque, pStream->state);
+ pStream->state = NULL;
+ }
+ return MZ_OK;
+}
+
+int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
+{
+ mz_stream stream;
+ int status;
+ memset(&stream, 0, sizeof(stream));
+
+ // In case mz_ulong is 64-bits (argh I hate longs).
+ if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
+
+ stream.next_in = pSource;
+ stream.avail_in = (mz_uint32)source_len;
+ stream.next_out = pDest;
+ stream.avail_out = (mz_uint32)*pDest_len;
+
+ status = mz_inflateInit(&stream);
+ if (status != MZ_OK)
+ return status;
+
+ status = mz_inflate(&stream, MZ_FINISH);
+ if (status != MZ_STREAM_END)
+ {
+ mz_inflateEnd(&stream);
+ return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
+ }
+ *pDest_len = stream.total_out;
+
+ return mz_inflateEnd(&stream);
+}
+
+const char *mz_error(int err)
+{
+ static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
+ {
+ { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
+ { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
+ };
+ mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
+ return NULL;
+}
+
+#endif //MINIZ_NO_ZLIB_APIS
+
+// ------------------- Low-level Decompression (completely independent from all compression API's)
+
+#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
+#define TINFL_MEMSET(p, c, l) memset(p, c, l)
+
+#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
+#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
+#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
+#define TINFL_CR_FINISH }
+
+// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
+// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
+#define TINFL_GET_BYTE(state_index, c) do { \
+ if (pIn_buf_cur >= pIn_buf_end) { \
+ for ( ; ; ) { \
+ if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
+ TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
+ if (pIn_buf_cur < pIn_buf_end) { \
+ c = *pIn_buf_cur++; \
+ break; \
+ } \
+ } else { \
+ c = 0; \
+ break; \
+ } \
+ } \
+ } else c = *pIn_buf_cur++; } MZ_MACRO_END
+
+#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
+#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
+#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
+
+// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
+// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
+// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
+// bit buffer contains >=15 bits (deflate's max. Huffman code size).
+#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
+ do { \
+ temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
+ if (temp >= 0) { \
+ code_len = temp >> 9; \
+ if ((code_len) && (num_bits >= code_len)) \
+ break; \
+ } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
+ code_len = TINFL_FAST_LOOKUP_BITS; \
+ do { \
+ temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
+ } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
+ } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
+ } while (num_bits < 15);
+
+// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
+// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
+// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
+// The slow path is only executed at the very end of the input buffer.
+#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
+ int temp; mz_uint code_len, c; \
+ if (num_bits < 15) { \
+ if ((pIn_buf_end - pIn_buf_cur) < 2) { \
+ TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
+ } else { \
+ bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
+ } \
+ } \
+ if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
+ code_len = temp >> 9, temp &= 511; \
+ else { \
+ code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
+ } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
+
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
+{
+ static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
+ static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
+ static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
+ static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+ static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+ static const int s_min_table_sizes[3] = { 257, 1, 4 };
+
+ tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
+ const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
+ mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
+ size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
+
+ // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
+ if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
+
+ num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
+ TINFL_CR_BEGIN
+
+ bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
+ if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
+ {
+ TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
+ counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
+ if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
+ if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
+ }
+
+ do
+ {
+ TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
+ if (r->m_type == 0)
+ {
+ TINFL_SKIP_BITS(5, num_bits & 7);
+ for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
+ if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
+ while ((counter) && (num_bits))
+ {
+ TINFL_GET_BITS(51, dist, 8);
+ while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
+ *pOut_buf_cur++ = (mz_uint8)dist;
+ counter--;
+ }
+ while (counter)
+ {
+ size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
+ while (pIn_buf_cur >= pIn_buf_end)
+ {
+ if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
+ {
+ TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
+ }
+ else
+ {
+ TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
+ }
+ }
+ n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
+ TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
+ }
+ }
+ else if (r->m_type == 3)
+ {
+ TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
+ }
+ else
+ {
+ if (r->m_type == 1)
+ {
+ mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
+ r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
+ for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
+ }
+ else
+ {
+ for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
+ MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
+ r->m_table_sizes[2] = 19;
+ }
+ for ( ; (int)r->m_type >= 0; r->m_type--)
+ {
+ int tree_next, tree_cur; tinfl_huff_table *pTable;
+ mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
+ for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
+ used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
+ for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
+ if ((65536 != total) && (used_syms > 1))
+ {
+ TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
+ }
+ for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
+ {
+ mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
+ cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
+ if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
+ if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
+ rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
+ for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
+ {
+ tree_cur -= ((rev_code >>= 1) & 1);
+ if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
+ }
+ tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
+ }
+ if (r->m_type == 2)
+ {
+ for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
+ {
+ mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
+ if ((dist == 16) && (!counter))
+ {
+ TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
+ }
+ num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
+ TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
+ }
+ if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
+ {
+ TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
+ }
+ TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
+ }
+ }
+ for ( ; ; )
+ {
+ mz_uint8 *pSrc;
+ for ( ; ; )
+ {
+ if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
+ {
+ TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
+ if (counter >= 256)
+ break;
+ while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
+ *pOut_buf_cur++ = (mz_uint8)counter;
+ }
+ else
+ {
+ int sym2; mz_uint code_len;
+#if TINFL_USE_64BIT_BITBUF
+ if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
+#else
+ if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
+#endif
+ if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
+ code_len = sym2 >> 9;
+ else
+ {
+ code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
+ }
+ counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
+ if (counter & 256)
+ break;
+
+#if !TINFL_USE_64BIT_BITBUF
+ if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
+#endif
+ if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
+ code_len = sym2 >> 9;
+ else
+ {
+ code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
+ }
+ bit_buf >>= code_len; num_bits -= code_len;
+
+ pOut_buf_cur[0] = (mz_uint8)counter;
+ if (sym2 & 256)
+ {
+ pOut_buf_cur++;
+ counter = sym2;
+ break;
+ }
+ pOut_buf_cur[1] = (mz_uint8)sym2;
+ pOut_buf_cur += 2;
+ }
+ }
+ if ((counter &= 511) == 256) break;
+
+ num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
+ if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
+
+ TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
+ num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
+ if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
+
+ dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
+ if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
+ {
+ TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
+ }
+
+ pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
+
+ if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
+ {
+ while (counter--)
+ {
+ while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
+ *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
+ }
+ continue;
+ }
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+ else if ((counter >= 9) && (counter <= dist))
+ {
+ const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
+ do
+ {
+ ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
+ ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
+ pOut_buf_cur += 8;
+ } while ((pSrc += 8) < pSrc_end);
+ if ((counter &= 7) < 3)
+ {
+ if (counter)
+ {
+ pOut_buf_cur[0] = pSrc[0];
+ if (counter > 1)
+ pOut_buf_cur[1] = pSrc[1];
+ pOut_buf_cur += counter;
+ }
+ continue;
+ }
+ }
+#endif
+ do
+ {
+ pOut_buf_cur[0] = pSrc[0];
+ pOut_buf_cur[1] = pSrc[1];
+ pOut_buf_cur[2] = pSrc[2];
+ pOut_buf_cur += 3; pSrc += 3;
+ } while ((int)(counter -= 3) > 2);
+ if ((int)counter > 0)
+ {
+ pOut_buf_cur[0] = pSrc[0];
+ if ((int)counter > 1)
+ pOut_buf_cur[1] = pSrc[1];
+ pOut_buf_cur += counter;
+ }
+ }
+ }
+ } while (!(r->m_final & 1));
+ if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
+ {
+ TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
+ }
+ TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
+ TINFL_CR_FINISH
+
+common_exit:
+ r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
+ *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
+ if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
+ {
+ const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
+ mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
+ while (buf_len)
+ {
+ for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
+ {
+ s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
+ s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
+ }
+ for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
+ s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
+ }
+ r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
+ }
+ return status;
+}
+
+// Higher level helper functions.
+void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
+{
+ tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
+ *pOut_len = 0;
+ tinfl_init(&decomp);
+ for ( ; ; )
+ {
+ size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
+ tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
+ (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+ if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
+ {
+ MZ_FREE(pBuf); *pOut_len = 0; return NULL;
+ }
+ src_buf_ofs += src_buf_size;
+ *pOut_len += dst_buf_size;
+ if (status == TINFL_STATUS_DONE) break;
+ new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
+ pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
+ if (!pNew_buf)
+ {
+ MZ_FREE(pBuf); *pOut_len = 0; return NULL;
+ }
+ pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
+ }
+ return pBuf;
+}
+
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
+{
+ tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
+ status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+ return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
+}
+
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+ int result = 0;
+ tinfl_decompressor decomp;
+ mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
+ if (!pDict)
+ return TINFL_STATUS_FAILED;
+ tinfl_init(&decomp);
+ for ( ; ; )
+ {
+ size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
+ tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
+ (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
+ in_buf_ofs += in_buf_size;
+ if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
+ break;
+ if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
+ {
+ result = (status == TINFL_STATUS_DONE);
+ break;
+ }
+ dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
+ }
+ MZ_FREE(pDict);
+ *pIn_buf_size = in_buf_ofs;
+ return result;
+}
+
+// ------------------- Low-level Compression (independent from all decompression API's)
+
+// Purposely making these tables static for faster init and thread safety.
+static const mz_uint16 s_tdefl_len_sym[256] = {
+ 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
+ 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
+ 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
+ 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
+ 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
+ 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
+ 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
+ 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };
+
+static const mz_uint8 s_tdefl_len_extra[256] = {
+ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 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,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,0 };
+
+static const mz_uint8 s_tdefl_small_dist_sym[512] = {
+ 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
+ 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+ 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
+ 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+ 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+ 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+ 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+ 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+ 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };
+
+static const mz_uint8 s_tdefl_small_dist_extra[512] = {
+ 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,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,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7 };
+
+static const mz_uint8 s_tdefl_large_dist_sym[128] = {
+ 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
+ 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
+ 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };
+
+static const mz_uint8 s_tdefl_large_dist_extra[128] = {
+ 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };
+
+// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
+typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
+static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
+{
+ mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
+ for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
+ while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
+ for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
+ {
+ const mz_uint32* pHist = &hist[pass << 8];
+ mz_uint offsets[256], cur_ofs = 0;
+ for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
+ for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
+ { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
+ }
+ return pCur_syms;
+}
+
+// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
+static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
+{
+ int root, leaf, next, avbl, used, dpth;
+ if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
+ A[0].m_key += A[1].m_key; root = 0; leaf = 2;
+ for (next=1; next < n-1; next++)
+ {
+ if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
+ if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
+ }
+ A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
+ avbl = 1; used = dpth = 0; root = n-2; next = n-1;
+ while (avbl>0)
+ {
+ while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
+ while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
+ avbl = 2*used; dpth++; used = 0;
+ }
+}
+
+// Limits canonical Huffman code table's max code size.
+enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
+static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
+{
+ int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
+ for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
+ for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
+ while (total != (1UL << max_code_size))
+ {
+ pNum_codes[max_code_size]--;
+ for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
+ total--;
+ }
+}
+
+static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
+{
+ int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
+ if (static_table)
+ {
+ for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
+ }
+ else
+ {
+ tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
+ int num_used_syms = 0;
+ const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
+ for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
+
+ pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
+
+ for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
+
+ tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
+
+ MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
+ for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
+ for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
+ }
+
+ next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
+
+ for (i = 0; i < table_len; i++)
+ {
+ mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
+ code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
+ d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
+ }
+}
+
+#define TDEFL_PUT_BITS(b, l) do { \
+ mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
+ d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
+ while (d->m_bits_in >= 8) { \
+ if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
+ *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
+ d->m_bit_buffer >>= 8; \
+ d->m_bits_in -= 8; \
+ } \
+} MZ_MACRO_END
+
+#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
+ if (rle_repeat_count < 3) { \
+ d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
+ while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
+ } else { \
+ d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
+} rle_repeat_count = 0; } }
+
+#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
+ if (rle_z_count < 3) { \
+ d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
+ } else if (rle_z_count <= 10) { \
+ d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
+ } else { \
+ d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
+} rle_z_count = 0; } }
+
+static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+static void tdefl_start_dynamic_block(tdefl_compressor *d)
+{
+ int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
+ mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
+
+ d->m_huff_count[0][256] = 1;
+
+ tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
+ tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
+
+ for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
+ for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
+
+ memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
+ memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
+ total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
+
+ memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
+ for (i = 0; i < total_code_sizes_to_pack; i++)
+ {
+ mz_uint8 code_size = code_sizes_to_pack[i];
+ if (!code_size)
+ {
+ TDEFL_RLE_PREV_CODE_SIZE();
+ if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
+ }
+ else
+ {
+ TDEFL_RLE_ZERO_CODE_SIZE();
+ if (code_size != prev_code_size)
+ {
+ TDEFL_RLE_PREV_CODE_SIZE();
+ d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
+ }
+ else if (++rle_repeat_count == 6)
+ {
+ TDEFL_RLE_PREV_CODE_SIZE();
+ }
+ }
+ prev_code_size = code_size;
+ }
+ if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
+
+ tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
+
+ TDEFL_PUT_BITS(2, 2);
+
+ TDEFL_PUT_BITS(num_lit_codes - 257, 5);
+ TDEFL_PUT_BITS(num_dist_codes - 1, 5);
+
+ for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
+ num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
+ for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
+
+ for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
+ {
+ mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
+ TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
+ if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
+ }
+}
+
+static void tdefl_start_static_block(tdefl_compressor *d)
+{
+ mz_uint i;
+ mz_uint8 *p = &d->m_huff_code_sizes[0][0];
+
+ for (i = 0; i <= 143; ++i) *p++ = 8;
+ for ( ; i <= 255; ++i) *p++ = 9;
+ for ( ; i <= 279; ++i) *p++ = 7;
+ for ( ; i <= 287; ++i) *p++ = 8;
+
+ memset(d->m_huff_code_sizes[1], 5, 32);
+
+ tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
+ tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
+
+ TDEFL_PUT_BITS(1, 2);
+}
+
+static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
+static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
+{
+ mz_uint flags;
+ mz_uint8 *pLZ_codes;
+ mz_uint8 *pOutput_buf = d->m_pOutput_buf;
+ mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
+ mz_uint64 bit_buffer = d->m_bit_buffer;
+ mz_uint bits_in = d->m_bits_in;
+
+#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
+
+ flags = 1;
+ for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
+ {
+ if (flags == 1)
+ flags = *pLZ_codes++ | 0x100;
+
+ if (flags & 1)
+ {
+ mz_uint s0, s1, n0, n1, sym, num_extra_bits;
+ mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
+
+ MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+ TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+ TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
+
+ // This sequence coaxes MSVC into using cmov's vs. jmp's.
+ s0 = s_tdefl_small_dist_sym[match_dist & 511];
+ n0 = s_tdefl_small_dist_extra[match_dist & 511];
+ s1 = s_tdefl_large_dist_sym[match_dist >> 8];
+ n1 = s_tdefl_large_dist_extra[match_dist >> 8];
+ sym = (match_dist < 512) ? s0 : s1;
+ num_extra_bits = (match_dist < 512) ? n0 : n1;
+
+ MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
+ TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
+ TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
+ }
+ else
+ {
+ mz_uint lit = *pLZ_codes++;
+ MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+ TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+
+ if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
+ {
+ flags >>= 1;
+ lit = *pLZ_codes++;
+ MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+ TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+
+ if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
+ {
+ flags >>= 1;
+ lit = *pLZ_codes++;
+ MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+ TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+ }
+ }
+ }
+
+ if (pOutput_buf >= d->m_pOutput_buf_end)
+ return MZ_FALSE;
+
+ *(mz_uint64*)pOutput_buf = bit_buffer;
+ pOutput_buf += (bits_in >> 3);
+ bit_buffer >>= (bits_in & ~7);
+ bits_in &= 7;
+ }
+
+#undef TDEFL_PUT_BITS_FAST
+
+ d->m_pOutput_buf = pOutput_buf;
+ d->m_bits_in = 0;
+ d->m_bit_buffer = 0;
+
+ while (bits_in)
+ {
+ mz_uint32 n = MZ_MIN(bits_in, 16);
+ TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
+ bit_buffer >>= n;
+ bits_in -= n;
+ }
+
+ TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
+
+ return (d->m_pOutput_buf < d->m_pOutput_buf_end);
+}
+#else
+static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
+{
+ mz_uint flags;
+ mz_uint8 *pLZ_codes;
+
+ flags = 1;
+ for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
+ {
+ if (flags == 1)
+ flags = *pLZ_codes++ | 0x100;
+ if (flags & 1)
+ {
+ mz_uint sym, num_extra_bits;
+ mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
+
+ MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+ TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+ TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
+
+ if (match_dist < 512)
+ {
+ sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
+ }
+ else
+ {
+ sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
+ }
+ MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
+ TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
+ TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
+ }
+ else
+ {
+ mz_uint lit = *pLZ_codes++;
+ MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+ TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+ }
+ }
+
+ TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
+
+ return (d->m_pOutput_buf < d->m_pOutput_buf_end);
+}
+#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
+
+static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
+{
+ if (static_block)
+ tdefl_start_static_block(d);
+ else
+ tdefl_start_dynamic_block(d);
+ return tdefl_compress_lz_codes(d);
+}
+
+static int tdefl_flush_block(tdefl_compressor *d, int flush)
+{
+ mz_uint saved_bit_buf, saved_bits_in;
+ mz_uint8 *pSaved_output_buf;
+ mz_bool comp_block_succeeded = MZ_FALSE;
+ int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
+ mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
+
+ d->m_pOutput_buf = pOutput_buf_start;
+ d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
+
+ MZ_ASSERT(!d->m_output_flush_remaining);
+ d->m_output_flush_ofs = 0;
+ d->m_output_flush_remaining = 0;
+
+ *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
+ d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
+
+ if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
+ {
+ TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
+ }
+
+ TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
+
+ pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
+
+ if (!use_raw_block)
+ comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
+
+ // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
+ if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
+ ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
+ {
+ mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
+ TDEFL_PUT_BITS(0, 2);
+ if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
+ for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
+ {
+ TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
+ }
+ for (i = 0; i < d->m_total_lz_bytes; ++i)
+ {
+ TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
+ }
+ }
+ // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
+ else if (!comp_block_succeeded)
+ {
+ d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
+ tdefl_compress_block(d, MZ_TRUE);
+ }
+
+ if (flush)
+ {
+ if (flush == TDEFL_FINISH)
+ {
+ if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
+ if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
+ }
+ else
+ {
+ mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
+ }
+ }
+
+ MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
+
+ memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
+ memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
+
+ d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
+
+ if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
+ {
+ if (d->m_pPut_buf_func)
+ {
+ *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
+ if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
+ return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
+ }
+ else if (pOutput_buf_start == d->m_output_buf)
+ {
+ int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
+ memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
+ d->m_out_buf_ofs += bytes_to_copy;
+ if ((n -= bytes_to_copy) != 0)
+ {
+ d->m_output_flush_ofs = bytes_to_copy;
+ d->m_output_flush_remaining = n;
+ }
+ }
+ else
+ {
+ d->m_out_buf_ofs += n;
+ }
+ }
+
+ return d->m_output_flush_remaining;
+}
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
+static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
+{
+ mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
+ mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
+ const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
+ mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
+ MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
+ for ( ; ; )
+ {
+ for ( ; ; )
+ {
+ if (--num_probes_left == 0) return;
+ #define TDEFL_PROBE \
+ next_probe_pos = d->m_next[probe_pos]; \
+ if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
+ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
+ if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
+ TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
+ }
+ if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
+ do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
+ (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
+ if (!probe_len)
+ {
+ *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
+ }
+ else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
+ {
+ *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
+ c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
+ }
+ }
+}
+#else
+static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
+{
+ mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
+ mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
+ const mz_uint8 *s = d->m_dict + pos, *p, *q;
+ mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
+ MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
+ for ( ; ; )
+ {
+ for ( ; ; )
+ {
+ if (--num_probes_left == 0) return;
+ #define TDEFL_PROBE \
+ next_probe_pos = d->m_next[probe_pos]; \
+ if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
+ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
+ if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
+ TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
+ }
+ if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
+ if (probe_len > match_len)
+ {
+ *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
+ c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
+ }
+ }
+}
+#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+static mz_bool tdefl_compress_fast(tdefl_compressor *d)
+{
+ // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
+ mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
+ mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
+ mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
+
+ while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
+ {
+ const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
+ mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
+ mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
+ d->m_src_buf_left -= num_bytes_to_process;
+ lookahead_size += num_bytes_to_process;
+
+ while (num_bytes_to_process)
+ {
+ mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
+ memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
+ if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
+ memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
+ d->m_pSrc += n;
+ dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
+ num_bytes_to_process -= n;
+ }
+
+ dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
+ if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
+
+ while (lookahead_size >= 4)
+ {
+ mz_uint cur_match_dist, cur_match_len = 1;
+ mz_uint8 *pCur_dict = d->m_dict + cur_pos;
+ mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
+ mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
+ mz_uint probe_pos = d->m_hash[hash];
+ d->m_hash[hash] = (mz_uint16)lookahead_pos;
+
+ if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
+ {
+ const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
+ const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
+ mz_uint32 probe_len = 32;
+ do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
+ (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
+ cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
+ if (!probe_len)
+ cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
+
+ if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
+ {
+ cur_match_len = 1;
+ *pLZ_code_buf++ = (mz_uint8)first_trigram;
+ *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
+ d->m_huff_count[0][(mz_uint8)first_trigram]++;
+ }
+ else
+ {
+ mz_uint32 s0, s1;
+ cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
+
+ MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
+
+ cur_match_dist--;
+
+ pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
+ *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
+ pLZ_code_buf += 3;
+ *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
+
+ s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
+ s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
+ d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
+
+ d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
+ }
+ }
+ else
+ {
+ *pLZ_code_buf++ = (mz_uint8)first_trigram;
+ *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
+ d->m_huff_count[0][(mz_uint8)first_trigram]++;
+ }
+
+ if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
+
+ total_lz_bytes += cur_match_len;
+ lookahead_pos += cur_match_len;
+ dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
+ cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
+ MZ_ASSERT(lookahead_size >= cur_match_len);
+ lookahead_size -= cur_match_len;
+
+ if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
+ {
+ int n;
+ d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
+ d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
+ if ((n = tdefl_flush_block(d, 0)) != 0)
+ return (n < 0) ? MZ_FALSE : MZ_TRUE;
+ total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
+ }
+ }
+
+ while (lookahead_size)
+ {
+ mz_uint8 lit = d->m_dict[cur_pos];
+
+ total_lz_bytes++;
+ *pLZ_code_buf++ = lit;
+ *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
+ if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
+
+ d->m_huff_count[0][lit]++;
+
+ lookahead_pos++;
+ dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
+ cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
+ lookahead_size--;
+
+ if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
+ {
+ int n;
+ d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
+ d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
+ if ((n = tdefl_flush_block(d, 0)) != 0)
+ return (n < 0) ? MZ_FALSE : MZ_TRUE;
+ total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
+ }
+ }
+ }
+
+ d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
+ d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
+ return MZ_TRUE;
+}
+#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+
+static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
+{
+ d->m_total_lz_bytes++;
+ *d->m_pLZ_code_buf++ = lit;
+ *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
+ d->m_huff_count[0][lit]++;
+}
+
+static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
+{
+ mz_uint32 s0, s1;
+
+ MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
+
+ d->m_total_lz_bytes += match_len;
+
+ d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
+
+ match_dist -= 1;
+ d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
+ d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
+
+ *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
+
+ s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
+ d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
+
+ if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
+}
+
+static mz_bool tdefl_compress_normal(tdefl_compressor *d)
+{
+ const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
+ tdefl_flush flush = d->m_flush;
+
+ while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
+ {
+ mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
+ // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
+ if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
+ {
+ mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
+ mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
+ mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
+ const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
+ src_buf_left -= num_bytes_to_process;
+ d->m_lookahead_size += num_bytes_to_process;
+ while (pSrc != pSrc_end)
+ {
+ mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
+ hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
+ d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
+ dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
+ }
+ }
+ else
+ {
+ while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
+ {
+ mz_uint8 c = *pSrc++;
+ mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
+ src_buf_left--;
+ d->m_dict[dst_pos] = c;
+ if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
+ d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
+ if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
+ {
+ mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
+ mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
+ d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
+ }
+ }
+ }
+ d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
+ if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
+ break;
+
+ // Simple lazy/greedy parsing state machine.
+ len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
+ if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
+ {
+ if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
+ {
+ mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
+ cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
+ if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
+ }
+ }
+ else
+ {
+ tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
+ }
+ if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
+ {
+ cur_match_dist = cur_match_len = 0;
+ }
+ if (d->m_saved_match_len)
+ {
+ if (cur_match_len > d->m_saved_match_len)
+ {
+ tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
+ if (cur_match_len >= 128)
+ {
+ tdefl_record_match(d, cur_match_len, cur_match_dist);
+ d->m_saved_match_len = 0; len_to_move = cur_match_len;
+ }
+ else
+ {
+ d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
+ }
+ }
+ else
+ {
+ tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
+ len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
+ }
+ }
+ else if (!cur_match_dist)
+ tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
+ else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
+ {
+ tdefl_record_match(d, cur_match_len, cur_match_dist);
+ len_to_move = cur_match_len;
+ }
+ else
+ {
+ d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
+ }
+ // Move the lookahead forward by len_to_move bytes.
+ d->m_lookahead_pos += len_to_move;
+ MZ_ASSERT(d->m_lookahead_size >= len_to_move);
+ d->m_lookahead_size -= len_to_move;
+ d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
+ // Check if it's time to flush the current LZ codes to the internal output buffer.
+ if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
+ ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
+ {
+ int n;
+ d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
+ if ((n = tdefl_flush_block(d, 0)) != 0)
+ return (n < 0) ? MZ_FALSE : MZ_TRUE;
+ }
+ }
+
+ d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
+ return MZ_TRUE;
+}
+
+static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
+{
+ if (d->m_pIn_buf_size)
+ {
+ *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
+ }
+
+ if (d->m_pOut_buf_size)
+ {
+ size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
+ memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
+ d->m_output_flush_ofs += (mz_uint)n;
+ d->m_output_flush_remaining -= (mz_uint)n;
+ d->m_out_buf_ofs += n;
+
+ *d->m_pOut_buf_size = d->m_out_buf_ofs;
+ }
+
+ return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
+}
+
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
+{
+ if (!d)
+ {
+ if (pIn_buf_size) *pIn_buf_size = 0;
+ if (pOut_buf_size) *pOut_buf_size = 0;
+ return TDEFL_STATUS_BAD_PARAM;
+ }
+
+ d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
+ d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
+ d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
+ d->m_out_buf_ofs = 0;
+ d->m_flush = flush;
+
+ if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
+ (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
+ {
+ if (pIn_buf_size) *pIn_buf_size = 0;
+ if (pOut_buf_size) *pOut_buf_size = 0;
+ return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
+ }
+ d->m_wants_to_finish |= (flush == TDEFL_FINISH);
+
+ if ((d->m_output_flush_remaining) || (d->m_finished))
+ return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+ if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
+ ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
+ ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
+ {
+ if (!tdefl_compress_fast(d))
+ return d->m_prev_return_status;
+ }
+ else
+#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+ {
+ if (!tdefl_compress_normal(d))
+ return d->m_prev_return_status;
+ }
+
+ if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
+ d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
+
+ if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
+ {
+ if (tdefl_flush_block(d, flush) < 0)
+ return d->m_prev_return_status;
+ d->m_finished = (flush == TDEFL_FINISH);
+ if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
+ }
+
+ return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
+}
+
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
+{
+ MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
+}
+
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+ d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
+ d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
+ d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
+ if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
+ d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
+ d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
+ d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
+ d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
+ d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
+ d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
+ d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
+ d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
+ memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
+ memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
+ return TDEFL_STATUS_OKAY;
+}
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
+{
+ return d->m_prev_return_status;
+}
+
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
+{
+ return d->m_adler32;
+}
+
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+ tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
+ pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
+ succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
+ succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
+ MZ_FREE(pComp); return succeeded;
+}
+
+typedef struct
+{
+ size_t m_size, m_capacity;
+ mz_uint8 *m_pBuf;
+ mz_bool m_expandable;
+} tdefl_output_buffer;
+
+static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
+{
+ tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
+ size_t new_size = p->m_size + len;
+ if (new_size > p->m_capacity)
+ {
+ size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
+ do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
+ pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
+ p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
+ }
+ memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
+ return MZ_TRUE;
+}
+
+void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
+{
+ tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
+ if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
+ out_buf.m_expandable = MZ_TRUE;
+ if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
+ *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
+}
+
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
+{
+ tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
+ if (!pOut_buf) return 0;
+ out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
+ if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
+ return out_buf.m_size;
+}
+
+#ifndef MINIZ_NO_ZLIB_APIS
+static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
+
+// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
+{
+ mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
+ if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
+
+ if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
+ else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
+ else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
+ else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
+ else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
+
+ return comp_flags;
+}
+#endif //MINIZ_NO_ZLIB_APIS
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
+#endif
+
+// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
+// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
+// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
+void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
+{
+ // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
+ static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
+ tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
+ if (!pComp) return NULL;
+ MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
+ // write dummy header
+ for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
+ // compress image data
+ tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
+ for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
+ if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
+ // write real header
+ *pLen_out = out_buf.m_size-41;
+ {
+ static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
+ mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
+ 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0,
+ (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
+ c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
+ memcpy(out_buf.m_pBuf, pnghdr, 41);
+ }
+ // write footer (IDAT CRC-32, followed by IEND chunk)
+ if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
+ c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
+ // compute final size of file, grab compressed data buffer and return
+ *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
+}
+void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
+{
+ // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
+ return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
+}
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+// ------------------- .ZIP archive reading
+
+#ifndef MINIZ_NO_ARCHIVE_APIS
+
+#ifdef MINIZ_NO_STDIO
+ #define MZ_FILE void *
+#else
+ #include <stdio.h>
+ #include <sys/stat.h>
+
+ #if defined(_MSC_VER) || defined(__MINGW64__)
+ static FILE *mz_fopen(const char *pFilename, const char *pMode)
+ {
+ FILE* pFile = NULL;
+ fopen_s(&pFile, pFilename, pMode);
+ return pFile;
+ }
+ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
+ {
+ FILE* pFile = NULL;
+ if (freopen_s(&pFile, pPath, pMode, pStream))
+ return NULL;
+ return pFile;
+ }
+ #ifndef MINIZ_NO_TIME
+ #include <sys/utime.h>
+ #endif
+ #define MZ_FILE FILE
+ #define MZ_FOPEN mz_fopen
+ #define MZ_FCLOSE fclose
+ #define MZ_FREAD fread
+ #define MZ_FWRITE fwrite
+ #define MZ_FTELL64 _ftelli64
+ #define MZ_FSEEK64 _fseeki64
+ #define MZ_FILE_STAT_STRUCT _stat
+ #define MZ_FILE_STAT _stat
+ #define MZ_FFLUSH fflush
+ #define MZ_FREOPEN mz_freopen
+ #define MZ_DELETE_FILE remove
+ #elif defined(__MINGW32__)
+ #ifndef MINIZ_NO_TIME
+ #include <sys/utime.h>
+ #endif
+ #define MZ_FILE FILE
+ #define MZ_FOPEN(f, m) fopen(f, m)
+ #define MZ_FCLOSE fclose
+ #define MZ_FREAD fread
+ #define MZ_FWRITE fwrite
+ #define MZ_FTELL64 ftello64
+ #define MZ_FSEEK64 fseeko64
+ #define MZ_FILE_STAT_STRUCT _stat
+ #define MZ_FILE_STAT _stat
+ #define MZ_FFLUSH fflush
+ #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+ #define MZ_DELETE_FILE remove
+ #elif defined(__TINYC__)
+ #ifndef MINIZ_NO_TIME
+ #include <sys/utime.h>
+ #endif
+ #define MZ_FILE FILE
+ #define MZ_FOPEN(f, m) fopen(f, m)
+ #define MZ_FCLOSE fclose
+ #define MZ_FREAD fread
+ #define MZ_FWRITE fwrite
+ #define MZ_FTELL64 ftell
+ #define MZ_FSEEK64 fseek
+ #define MZ_FILE_STAT_STRUCT stat
+ #define MZ_FILE_STAT stat
+ #define MZ_FFLUSH fflush
+ #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+ #define MZ_DELETE_FILE remove
+ #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
+ #ifndef MINIZ_NO_TIME
+ #include <utime.h>
+ #endif
+ #define MZ_FILE FILE
+ #define MZ_FOPEN(f, m) fopen64(f, m)
+ #define MZ_FCLOSE fclose
+ #define MZ_FREAD fread
+ #define MZ_FWRITE fwrite
+ #define MZ_FTELL64 ftello64
+ #define MZ_FSEEK64 fseeko64
+ #define MZ_FILE_STAT_STRUCT stat64
+ #define MZ_FILE_STAT stat64
+ #define MZ_FFLUSH fflush
+ #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
+ #define MZ_DELETE_FILE remove
+ #else
+ #ifndef MINIZ_NO_TIME
+ #include <utime.h>
+ #endif
+ #define MZ_FILE FILE
+ #define MZ_FOPEN(f, m) fopen(f, m)
+ #define MZ_FCLOSE fclose
+ #define MZ_FREAD fread
+ #define MZ_FWRITE fwrite
+ #define MZ_FTELL64 ftello
+ #define MZ_FSEEK64 fseeko
+ #define MZ_FILE_STAT_STRUCT stat
+ #define MZ_FILE_STAT stat
+ #define MZ_FFLUSH fflush
+ #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+ #define MZ_DELETE_FILE remove
+ #endif // #ifdef _MSC_VER
+#endif // #ifdef MINIZ_NO_STDIO
+
+#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
+
+// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
+enum
+{
+ // ZIP archive identifiers and record sizes
+ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
+ MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
+ // Central directory header record offsets
+ MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
+ MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
+ MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
+ MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
+ // Local directory header offsets
+ MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
+ MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
+ MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
+ // End of central directory offsets
+ MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
+ MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
+};
+
+typedef struct
+{
+ void *m_p;
+ size_t m_size, m_capacity;
+ mz_uint m_element_size;
+} mz_zip_array;
+
+struct mz_zip_internal_state_tag
+{
+ mz_zip_array m_central_dir;
+ mz_zip_array m_central_dir_offsets;
+ mz_zip_array m_sorted_central_dir_offsets;
+ MZ_FILE *m_pFile;
+ void *m_pMem;
+ size_t m_mem_size;
+ size_t m_mem_capacity;
+};
+
+#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
+#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
+
+static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
+{
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
+ memset(pArray, 0, sizeof(mz_zip_array));
+}
+
+static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
+{
+ void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
+ if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
+ if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
+ pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
+ return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
+{
+ if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
+ return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
+{
+ if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
+ pArray->m_size = new_size;
+ return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
+{
+ return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
+{
+ if (n==0) return MZ_TRUE;
+ assert(NULL!=pElements);
+ size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
+ memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
+ return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_TIME
+static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
+{
+ struct tm tm;
+ memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
+ tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
+ tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
+ return mktime(&tm);
+}
+
+static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
+{
+#ifdef _MSC_VER
+ struct tm tm_struct;
+ struct tm *tm = &tm_struct;
+ errno_t err = localtime_s(tm, &time);
+ if (err)
+ {
+ *pDOS_date = 0; *pDOS_time = 0;
+ return;
+ }
+#else
+ struct tm *tm = localtime(&time);
+#endif
+ *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
+ *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
+}
+#endif
+
+#ifndef MINIZ_NO_STDIO
+static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
+{
+#ifdef MINIZ_NO_TIME
+ (void)pFilename; *pDOS_date = *pDOS_time = 0;
+#else
+ struct MZ_FILE_STAT_STRUCT file_stat;
+ // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
+ if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
+ return MZ_FALSE;
+ mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
+#endif // #ifdef MINIZ_NO_TIME
+ return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_TIME
+static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
+{
+ struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
+ return !utime(pFilename, &t);
+}
+#endif // #ifndef MINIZ_NO_TIME
+#endif // #ifndef MINIZ_NO_STDIO
+
+static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
+{
+ (void)flags;
+ if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
+ return MZ_FALSE;
+
+ if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
+ if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
+ if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
+
+ pZip->m_zip_mode = MZ_ZIP_MODE_READING;
+ pZip->m_archive_size = 0;
+ pZip->m_central_directory_file_ofs = 0;
+ pZip->m_total_files = 0;
+
+ if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
+ return MZ_FALSE;
+ memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
+ MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
+ MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
+ MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
+ return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
+{
+ const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
+ const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
+ mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+ mz_uint8 l = 0, r = 0;
+ pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
+ pE = pL + MZ_MIN(l_len, r_len);
+ while (pL < pE)
+ {
+ if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
+ break;
+ pL++; pR++;
+ }
+ return (pL == pE) ? (l_len < r_len) : (l < r);
+}
+
+#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END
+
+// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
+static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
+{
+ mz_zip_internal_state *pState = pZip->m_pState;
+ const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
+ const mz_zip_array *pCentral_dir = &pState->m_central_dir;
+ mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
+ const int size = pZip->m_total_files;
+ int start = (size - 2) >> 1, end;
+ while (start >= 0)
+ {
+ int child, root = start;
+ for ( ; ; )
+ {
+ if ((child = (root << 1) + 1) >= size)
+ break;
+ child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
+ if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
+ break;
+ MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
+ }
+ start--;
+ }
+
+ end = size - 1;
+ while (end > 0)
+ {
+ int child, root = 0;
+ MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
+ for ( ; ; )
+ {
+ if ((child = (root << 1) + 1) >= end)
+ break;
+ child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
+ if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
+ break;
+ MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
+ }
+ end--;
+ }
+}
+
+static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
+{
+ mz_uint cdir_size, num_this_disk, cdir_disk_index;
+ mz_uint64 cdir_ofs;
+ mz_int64 cur_file_ofs;
+ const mz_uint8 *p;
+ mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
+ mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
+ // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
+ if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+ // Find the end of central directory record by scanning the file from the end towards the beginning.
+ cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
+ for ( ; ; )
+ {
+ int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
+ return MZ_FALSE;
+ for (i = n - 4; i >= 0; --i)
+ if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
+ break;
+ if (i >= 0)
+ {
+ cur_file_ofs += i;
+ break;
+ }
+ if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
+ return MZ_FALSE;
+ cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
+ }
+ // Read and verify the end of central directory record.
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+ if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
+ ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
+ return MZ_FALSE;
+
+ num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
+ cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
+ if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
+ return MZ_FALSE;
+
+ if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+
+ cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
+ if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
+ return MZ_FALSE;
+
+ pZip->m_central_directory_file_ofs = cdir_ofs;
+
+ if (pZip->m_total_files)
+ {
+ mz_uint i, n;
+
+ // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
+ if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
+ (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
+ return MZ_FALSE;
+
+ if (sort_central_dir)
+ {
+ if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
+ return MZ_FALSE;
+ }
+
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
+ return MZ_FALSE;
+
+ // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
+ p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
+ for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
+ {
+ mz_uint total_header_size, comp_size, decomp_size, disk_index;
+ if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
+ return MZ_FALSE;
+ MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
+ if (sort_central_dir)
+ MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
+ comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+ decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
+ if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
+ return MZ_FALSE;
+ disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
+ if ((disk_index != num_this_disk) && (disk_index != 1))
+ return MZ_FALSE;
+ if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
+ return MZ_FALSE;
+ if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
+ return MZ_FALSE;
+ n -= total_header_size; p += total_header_size;
+ }
+ }
+
+ if (sort_central_dir)
+ mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
+
+ return MZ_TRUE;
+}
+
+mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
+{
+ if ((!pZip) || (!pZip->m_pRead))
+ return MZ_FALSE;
+ if (!mz_zip_reader_init_internal(pZip, flags))
+ return MZ_FALSE;
+ pZip->m_archive_size = size;
+ if (!mz_zip_reader_read_central_dir(pZip, flags))
+ {
+ mz_zip_reader_end(pZip);
+ return MZ_FALSE;
+ }
+ return MZ_TRUE;
+}
+
+static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
+{
+ mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+ size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
+ memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
+ return s;
+}
+
+mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
+{
+ if (!mz_zip_reader_init_internal(pZip, flags))
+ return MZ_FALSE;
+ pZip->m_archive_size = size;
+ pZip->m_pRead = mz_zip_mem_read_func;
+ pZip->m_pIO_opaque = pZip;
+#ifdef __cplusplus
+ pZip->m_pState->m_pMem = const_cast<void *>(pMem);
+#else
+ pZip->m_pState->m_pMem = (void *)pMem;
+#endif
+ pZip->m_pState->m_mem_size = size;
+ if (!mz_zip_reader_read_central_dir(pZip, flags))
+ {
+ mz_zip_reader_end(pZip);
+ return MZ_FALSE;
+ }
+ return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
+{
+ mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+ mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
+ if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
+ return 0;
+ return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
+}
+
+mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
+{
+ mz_uint64 file_size;
+ MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
+ if (!pFile)
+ return MZ_FALSE;
+ if (MZ_FSEEK64(pFile, 0, SEEK_END))
+ {
+ MZ_FCLOSE(pFile);
+ return MZ_FALSE;
+ }
+ file_size = MZ_FTELL64(pFile);
+ if (!mz_zip_reader_init_internal(pZip, flags))
+ {
+ MZ_FCLOSE(pFile);
+ return MZ_FALSE;
+ }
+ pZip->m_pRead = mz_zip_file_read_func;
+ pZip->m_pIO_opaque = pZip;
+ pZip->m_pState->m_pFile = pFile;
+ pZip->m_archive_size = file_size;
+ if (!mz_zip_reader_read_central_dir(pZip, flags))
+ {
+ mz_zip_reader_end(pZip);
+ return MZ_FALSE;
+ }
+ return MZ_TRUE;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
+{
+ return pZip ? pZip->m_total_files : 0;
+}
+
+static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
+{
+ if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+ return NULL;
+ return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
+}
+
+mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
+{
+ mz_uint m_bit_flag;
+ const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+ if (!p)
+ return MZ_FALSE;
+ m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
+ return (m_bit_flag & 1);
+}
+
+mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
+{
+ mz_uint filename_len, external_attr;
+ const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+ if (!p)
+ return MZ_FALSE;
+
+ // First see if the filename ends with a '/' character.
+ filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+ if (filename_len)
+ {
+ if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
+ return MZ_TRUE;
+ }
+
+ // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct.
+ // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field.
+ // FIXME: Remove this check? Is it necessary - we already check the filename.
+ external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
+ if ((external_attr & 0x10) != 0)
+ return MZ_TRUE;
+
+ return MZ_FALSE;
+}
+
+mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
+{
+ mz_uint n;
+ const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+ if ((!p) || (!pStat))
+ return MZ_FALSE;
+
+ // Unpack the central directory record.
+ pStat->m_file_index = file_index;
+ pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
+ pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
+ pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
+ pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
+ pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
+#ifndef MINIZ_NO_TIME
+ pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
+#endif
+ pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
+ pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+ pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
+ pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
+ pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
+ pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
+
+ // Copy as much of the filename and comment as possible.
+ n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
+ memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';
+
+ n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
+ pStat->m_comment_size = n;
+ memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0';
+
+ return MZ_TRUE;
+}
+
+mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
+{
+ mz_uint n;
+ const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+ if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
+ n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+ if (filename_buf_size)
+ {
+ n = MZ_MIN(n, filename_buf_size - 1);
+ memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
+ pFilename[n] = '\0';
+ }
+ return n + 1;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
+{
+ mz_uint i;
+ if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
+ return 0 == memcmp(pA, pB, len);
+ for (i = 0; i < len; ++i)
+ if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
+ return MZ_FALSE;
+ return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
+{
+ const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
+ mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+ mz_uint8 l = 0, r = 0;
+ pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
+ pE = pL + MZ_MIN(l_len, r_len);
+ while (pL < pE)
+ {
+ if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
+ break;
+ pL++; pR++;
+ }
+ return (pL == pE) ? (int)(l_len - r_len) : (l - r);
+}
+
+static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
+{
+ mz_zip_internal_state *pState = pZip->m_pState;
+ const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
+ const mz_zip_array *pCentral_dir = &pState->m_central_dir;
+ mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
+ const int size = pZip->m_total_files;
+ const mz_uint filename_len = (mz_uint)strlen(pFilename);
+ int l = 0, h = size - 1;
+ while (l <= h)
+ {
+ int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
+ if (!comp)
+ return file_index;
+ else if (comp < 0)
+ l = m + 1;
+ else
+ h = m - 1;
+ }
+ return -1;
+}
+
+int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
+{
+ mz_uint file_index; size_t name_len, comment_len;
+ if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+ return -1;
+ if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
+ return mz_zip_reader_locate_file_binary_search(pZip, pName);
+ name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
+ comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
+ for (file_index = 0; file_index < pZip->m_total_files; file_index++)
+ {
+ const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
+ mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+ const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
+ if (filename_len < name_len)
+ continue;
+ if (comment_len)
+ {
+ mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
+ const char *pFile_comment = pFilename + filename_len + file_extra_len;
+ if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
+ continue;
+ }
+ if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
+ {
+ int ofs = filename_len - 1;
+ do
+ {
+ if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
+ break;
+ } while (--ofs >= 0);
+ ofs++;
+ pFilename += ofs; filename_len -= ofs;
+ }
+ if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
+ return file_index;
+ }
+ return -1;
+}
+
+mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
+{
+ int status = TINFL_STATUS_DONE;
+ mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
+ mz_zip_archive_file_stat file_stat;
+ void *pRead_buf;
+ mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
+ tinfl_decompressor inflator;
+
+ if ((buf_size) && (!pBuf))
+ return MZ_FALSE;
+
+ if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
+ return MZ_FALSE;
+
+ // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
+ if (!file_stat.m_comp_size)
+ return MZ_TRUE;
+
+ // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
+ // I'm torn how to handle this case - should it fail instead?
+ if (mz_zip_reader_is_file_a_directory(pZip, file_index))
+ return MZ_TRUE;
+
+ // Encryption and patch files are not supported.
+ if (file_stat.m_bit_flag & (1 | 32))
+ return MZ_FALSE;
+
+ // This function only supports stored and deflate.
+ if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
+ return MZ_FALSE;
+
+ // Ensure supplied output buffer is large enough.
+ needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
+ if (buf_size < needed_size)
+ return MZ_FALSE;
+
+ // Read and parse the local directory entry.
+ cur_file_ofs = file_stat.m_local_header_ofs;
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+ if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
+ return MZ_FALSE;
+
+ cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
+ if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
+ return MZ_FALSE;
+
+ if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
+ {
+ // The file is stored or the caller has requested the compressed data.
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
+ return MZ_FALSE;
+ return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
+ }
+
+ // Decompress the file either directly from memory or from a file input buffer.
+ tinfl_init(&inflator);
+
+ if (pZip->m_pState->m_pMem)
+ {
+ // Read directly from the archive in memory.
+ pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
+ read_buf_size = read_buf_avail = file_stat.m_comp_size;
+ comp_remaining = 0;
+ }
+ else if (pUser_read_buf)
+ {
+ // Use a user provided read buffer.
+ if (!user_read_buf_size)
+ return MZ_FALSE;
+ pRead_buf = (mz_uint8 *)pUser_read_buf;
+ read_buf_size = user_read_buf_size;
+ read_buf_avail = 0;
+ comp_remaining = file_stat.m_comp_size;
+ }
+ else
+ {
+ // Temporarily allocate a read buffer.
+ read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
+#ifdef _MSC_VER
+ if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
+#else
+ if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
+#endif
+ return MZ_FALSE;
+ if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
+ return MZ_FALSE;
+ read_buf_avail = 0;
+ comp_remaining = file_stat.m_comp_size;
+ }
+
+ do
+ {
+ size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
+ if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
+ {
+ read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+ {
+ status = TINFL_STATUS_FAILED;
+ break;
+ }
+ cur_file_ofs += read_buf_avail;
+ comp_remaining -= read_buf_avail;
+ read_buf_ofs = 0;
+ }
+ in_buf_size = (size_t)read_buf_avail;
+ status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
+ read_buf_avail -= in_buf_size;
+ read_buf_ofs += in_buf_size;
+ out_buf_ofs += out_buf_size;
+ } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
+
+ if (status == TINFL_STATUS_DONE)
+ {
+ // Make sure the entire file was decompressed, and check its CRC.
+ if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
+ status = TINFL_STATUS_FAILED;
+ }
+
+ if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+
+ return status == TINFL_STATUS_DONE;
+}
+
+mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
+{
+ int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
+ if (file_index < 0)
+ return MZ_FALSE;
+ return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
+}
+
+mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
+{
+ return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
+}
+
+mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
+{
+ return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
+}
+
+void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
+{
+ mz_uint64 comp_size, uncomp_size, alloc_size;
+ const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+ void *pBuf;
+
+ if (pSize)
+ *pSize = 0;
+ if (!p)
+ return NULL;
+
+ comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+ uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
+
+ alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
+#ifdef _MSC_VER
+ if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
+#else
+ if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
+#endif
+ return NULL;
+ if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
+ return NULL;
+
+ if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+ return NULL;
+ }
+
+ if (pSize) *pSize = (size_t)alloc_size;
+ return pBuf;
+}
+
+void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
+{
+ int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
+ if (file_index < 0)
+ {
+ if (pSize) *pSize = 0;
+ return MZ_FALSE;
+ }
+ return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
+}
+
+mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
+{
+ int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
+ mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
+ mz_zip_archive_file_stat file_stat;
+ void *pRead_buf = NULL; void *pWrite_buf = NULL;
+ mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
+
+ if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
+ return MZ_FALSE;
+
+ // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
+ if (!file_stat.m_comp_size)
+ return MZ_TRUE;
+
+ // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
+ // I'm torn how to handle this case - should it fail instead?
+ if (mz_zip_reader_is_file_a_directory(pZip, file_index))
+ return MZ_TRUE;
+
+ // Encryption and patch files are not supported.
+ if (file_stat.m_bit_flag & (1 | 32))
+ return MZ_FALSE;
+
+ // This function only supports stored and deflate.
+ if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
+ return MZ_FALSE;
+
+ // Read and parse the local directory entry.
+ cur_file_ofs = file_stat.m_local_header_ofs;
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+ if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
+ return MZ_FALSE;
+
+ cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
+ if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
+ return MZ_FALSE;
+
+ // Decompress the file either directly from memory or from a file input buffer.
+ if (pZip->m_pState->m_pMem)
+ {
+ pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
+ read_buf_size = read_buf_avail = file_stat.m_comp_size;
+ comp_remaining = 0;
+ }
+ else
+ {
+ read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
+ if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
+ return MZ_FALSE;
+ read_buf_avail = 0;
+ comp_remaining = file_stat.m_comp_size;
+ }
+
+ if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
+ {
+ // The file is stored or the caller has requested the compressed data.
+ if (pZip->m_pState->m_pMem)
+ {
+#ifdef _MSC_VER
+ if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
+#else
+ if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
+#endif
+ return MZ_FALSE;
+ if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
+ status = TINFL_STATUS_FAILED;
+ else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
+ file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
+ out_buf_ofs += file_stat.m_comp_size;
+ }
+ else
+ {
+ while (comp_remaining)
+ {
+ read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+ {
+ status = TINFL_STATUS_FAILED;
+ break;
+ }
+
+ if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
+ file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
+
+ if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+ {
+ status = TINFL_STATUS_FAILED;
+ break;
+ }
+ cur_file_ofs += read_buf_avail;
+ out_buf_ofs += read_buf_avail;
+ comp_remaining -= read_buf_avail;
+ }
+ }
+ }
+ else
+ {
+ tinfl_decompressor inflator;
+ tinfl_init(&inflator);
+
+ if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
+ status = TINFL_STATUS_FAILED;
+ else
+ {
+ do
+ {
+ mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
+ size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
+ if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
+ {
+ read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
+ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+ {
+ status = TINFL_STATUS_FAILED;
+ break;
+ }
+ cur_file_ofs += read_buf_avail;
+ comp_remaining -= read_buf_avail;
+ read_buf_ofs = 0;
+ }
+
+ in_buf_size = (size_t)read_buf_avail;
+ status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
+ read_buf_avail -= in_buf_size;
+ read_buf_ofs += in_buf_size;
+
+ if (out_buf_size)
+ {
+ if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
+ {
+ status = TINFL_STATUS_FAILED;
+ break;
+ }
+ file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
+ if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
+ {
+ status = TINFL_STATUS_FAILED;
+ break;
+ }
+ }
+ } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
+ }
+ }
+
+ if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
+ {
+ // Make sure the entire file was decompressed, and check its CRC.
+ if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
+ status = TINFL_STATUS_FAILED;
+ }
+
+ if (!pZip->m_pState->m_pMem)
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ if (pWrite_buf)
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
+
+ return status == TINFL_STATUS_DONE;
+}
+
+mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
+{
+ int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
+ if (file_index < 0)
+ return MZ_FALSE;
+ return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
+}
+
+#ifndef MINIZ_NO_STDIO
+static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
+{
+ (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
+}
+
+mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
+{
+ mz_bool status;
+ mz_zip_archive_file_stat file_stat;
+ MZ_FILE *pFile;
+ if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
+ return MZ_FALSE;
+ pFile = MZ_FOPEN(pDst_filename, "wb");
+ if (!pFile)
+ return MZ_FALSE;
+ status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
+ if (MZ_FCLOSE(pFile) == EOF)
+ return MZ_FALSE;
+#ifndef MINIZ_NO_TIME
+ if (status)
+ mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
+#endif
+ return status;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
+{
+ if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+ return MZ_FALSE;
+
+ if (pZip->m_pState)
+ {
+ mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
+ mz_zip_array_clear(pZip, &pState->m_central_dir);
+ mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
+ mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
+
+#ifndef MINIZ_NO_STDIO
+ if (pState->m_pFile)
+ {
+ MZ_FCLOSE(pState->m_pFile);
+ pState->m_pFile = NULL;
+ }
+#endif // #ifndef MINIZ_NO_STDIO
+
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
+ }
+ pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
+
+ return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
+{
+ int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
+ if (file_index < 0)
+ return MZ_FALSE;
+ return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
+}
+#endif
+
+// ------------------- .ZIP archive writing
+
+#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
+static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
+#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
+#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
+
+mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
+{
+ if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
+ return MZ_FALSE;
+
+ if (pZip->m_file_offset_alignment)
+ {
+ // Ensure user specified file offset alignment is a power of 2.
+ if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
+ return MZ_FALSE;
+ }
+
+ if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
+ if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
+ if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
+
+ pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
+ pZip->m_archive_size = existing_size;
+ pZip->m_central_directory_file_ofs = 0;
+ pZip->m_total_files = 0;
+
+ if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
+ return MZ_FALSE;
+ memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
+ MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
+ MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
+ MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
+ return MZ_TRUE;
+}
+
+static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
+{
+ mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+ mz_zip_internal_state *pState = pZip->m_pState;
+ mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
+#ifdef _MSC_VER
+ if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
+#else
+ if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
+#endif
+ return 0;
+ if (new_size > pState->m_mem_capacity)
+ {
+ void *pNew_block;
+ size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
+ if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
+ return 0;
+ pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
+ }
+ memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
+ pState->m_mem_size = (size_t)new_size;
+ return n;
+}
+
+mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
+{
+ pZip->m_pWrite = mz_zip_heap_write_func;
+ pZip->m_pIO_opaque = pZip;
+ if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
+ return MZ_FALSE;
+ if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
+ {
+ if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
+ {
+ mz_zip_writer_end(pZip);
+ return MZ_FALSE;
+ }
+ pZip->m_pState->m_mem_capacity = initial_allocation_size;
+ }
+ return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
+{
+ mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+ mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
+ if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
+ return 0;
+ return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
+}
+
+mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
+{
+ MZ_FILE *pFile;
+ pZip->m_pWrite = mz_zip_file_write_func;
+ pZip->m_pIO_opaque = pZip;
+ if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
+ return MZ_FALSE;
+ if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
+ {
+ mz_zip_writer_end(pZip);
+ return MZ_FALSE;
+ }
+ pZip->m_pState->m_pFile = pFile;
+ if (size_to_reserve_at_beginning)
+ {
+ mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
+ do
+ {
+ size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
+ {
+ mz_zip_writer_end(pZip);
+ return MZ_FALSE;
+ }
+ cur_ofs += n; size_to_reserve_at_beginning -= n;
+ } while (size_to_reserve_at_beginning);
+ }
+ return MZ_TRUE;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
+{
+ mz_zip_internal_state *pState;
+ if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+ return MZ_FALSE;
+ // No sense in trying to write to an archive that's already at the support max size
+ if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ pState = pZip->m_pState;
+
+ if (pState->m_pFile)
+ {
+#ifdef MINIZ_NO_STDIO
+ pFilename; return MZ_FALSE;
+#else
+ // Archive is being read from stdio - try to reopen as writable.
+ if (pZip->m_pIO_opaque != pZip)
+ return MZ_FALSE;
+ if (!pFilename)
+ return MZ_FALSE;
+ pZip->m_pWrite = mz_zip_file_write_func;
+ if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
+ {
+ // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
+ mz_zip_reader_end(pZip);
+ return MZ_FALSE;
+ }
+#endif // #ifdef MINIZ_NO_STDIO
+ }
+ else if (pState->m_pMem)
+ {
+ // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
+ if (pZip->m_pIO_opaque != pZip)
+ return MZ_FALSE;
+ pState->m_mem_capacity = pState->m_mem_size;
+ pZip->m_pWrite = mz_zip_heap_write_func;
+ }
+ // Archive is being read via a user provided read function - make sure the user has specified a write function too.
+ else if (!pZip->m_pWrite)
+ return MZ_FALSE;
+
+ // Start writing new files at the archive's current central directory location.
+ pZip->m_archive_size = pZip->m_central_directory_file_ofs;
+ pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
+ pZip->m_central_directory_file_ofs = 0;
+
+ return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
+{
+ return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
+}
+
+typedef struct
+{
+ mz_zip_archive *m_pZip;
+ mz_uint64 m_cur_archive_file_ofs;
+ mz_uint64 m_comp_size;
+} mz_zip_writer_add_state;
+
+static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
+{
+ mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
+ if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
+ return MZ_FALSE;
+ pState->m_cur_archive_file_ofs += len;
+ pState->m_comp_size += len;
+ return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
+{
+ (void)pZip;
+ memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
+ return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
+{
+ (void)pZip;
+ memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
+ return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
+{
+ mz_zip_internal_state *pState = pZip->m_pState;
+ mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
+ size_t orig_central_dir_size = pState->m_central_dir.m_size;
+ mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
+
+ // No zip64 support yet
+ if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
+ return MZ_FALSE;
+
+ if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
+ (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
+ (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
+ (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
+ (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
+ {
+ // Try to push the central directory array back into its original state.
+ mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
+ return MZ_FALSE;
+ }
+
+ return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
+{
+ // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
+ if (*pArchive_name == '/')
+ return MZ_FALSE;
+ while (*pArchive_name)
+ {
+ if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
+ return MZ_FALSE;
+ pArchive_name++;
+ }
+ return MZ_TRUE;
+}
+
+static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
+{
+ mz_uint32 n;
+ if (!pZip->m_file_offset_alignment)
+ return 0;
+ n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
+ return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
+}
+
+static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
+{
+ char buf[4096];
+ memset(buf, 0, MZ_MIN(sizeof(buf), n));
+ while (n)
+ {
+ mz_uint32 s = MZ_MIN(sizeof(buf), n);
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
+ return MZ_FALSE;
+ cur_file_ofs += s; n -= s;
+ }
+ return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
+{
+ mz_uint16 method = 0, dos_time = 0, dos_date = 0;
+ mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
+ mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0;
+ size_t archive_name_size;
+ mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
+ tdefl_compressor *pComp = NULL;
+ mz_bool store_data_uncompressed;
+ mz_zip_internal_state *pState;
+
+ if ((int)level_and_flags < 0)
+ level_and_flags = MZ_DEFAULT_LEVEL;
+ level = level_and_flags & 0xF;
+ store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
+
+ if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
+ return MZ_FALSE;
+
+ local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
+ pState = pZip->m_pState;
+
+ if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
+ return MZ_FALSE;
+ // No zip64 support yet
+ if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
+ return MZ_FALSE;
+ if (!mz_zip_writer_validate_archive_name(pArchive_name))
+ return MZ_FALSE;
+
+#ifndef MINIZ_NO_TIME
+ {
+ time_t cur_time; time(&cur_time);
+ mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
+ }
+#endif // #ifndef MINIZ_NO_TIME
+
+ archive_name_size = strlen(pArchive_name);
+ if (archive_name_size > 0xFFFF)
+ return MZ_FALSE;
+
+ num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
+
+ // no zip64 support yet
+ if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
+ {
+ // Set DOS Subdirectory attribute bit.
+ ext_attributes |= 0x10;
+ // Subdirectories cannot contain data.
+ if ((buf_size) || (uncomp_size))
+ return MZ_FALSE;
+ }
+
+ // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
+ if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
+ return MZ_FALSE;
+
+ if ((!store_data_uncompressed) && (buf_size))
+ {
+ if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
+ return MZ_FALSE;
+ }
+
+ if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+ return MZ_FALSE;
+ }
+ local_dir_header_ofs += num_alignment_padding_bytes;
+ if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
+ cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
+
+ MZ_CLEAR_OBJ(local_dir_header);
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+ return MZ_FALSE;
+ }
+ cur_archive_file_ofs += archive_name_size;
+
+ if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
+ {
+ uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
+ uncomp_size = buf_size;
+ if (uncomp_size <= 3)
+ {
+ level = 0;
+ store_data_uncompressed = MZ_TRUE;
+ }
+ }
+
+ if (store_data_uncompressed)
+ {
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+ return MZ_FALSE;
+ }
+
+ cur_archive_file_ofs += buf_size;
+ comp_size = buf_size;
+
+ if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
+ method = MZ_DEFLATED;
+ }
+ else if (buf_size)
+ {
+ mz_zip_writer_add_state state;
+
+ state.m_pZip = pZip;
+ state.m_cur_archive_file_ofs = cur_archive_file_ofs;
+ state.m_comp_size = 0;
+
+ if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
+ (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+ return MZ_FALSE;
+ }
+
+ comp_size = state.m_comp_size;
+ cur_archive_file_ofs = state.m_cur_archive_file_ofs;
+
+ method = MZ_DEFLATED;
+ }
+
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+ pComp = NULL;
+
+ // no zip64 support yet
+ if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
+ return MZ_FALSE;
+
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
+ return MZ_FALSE;
+
+ if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
+ return MZ_FALSE;
+
+ pZip->m_total_files++;
+ pZip->m_archive_size = cur_archive_file_ofs;
+
+ return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
+{
+ mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
+ mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
+ mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0, comp_size = 0;
+ size_t archive_name_size;
+ mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
+ MZ_FILE *pSrc_file = NULL;
+
+ if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
+ return MZ_FALSE;
+
+ local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
+
+ if ((int)level_and_flags < 0)
+ level_and_flags = MZ_DEFAULT_LEVEL;
+ level = level_and_flags & 0xF;
+
+ if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
+ return MZ_FALSE;
+ if (!mz_zip_writer_validate_archive_name(pArchive_name))
+ return MZ_FALSE;
+
+ archive_name_size = strlen(pArchive_name);
+ if (archive_name_size > 0xFFFF)
+ return MZ_FALSE;
+
+ num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
+
+ // no zip64 support yet
+ if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
+ return MZ_FALSE;
+
+ pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
+ if (!pSrc_file)
+ return MZ_FALSE;
+ MZ_FSEEK64(pSrc_file, 0, SEEK_END);
+ uncomp_size = MZ_FTELL64(pSrc_file);
+ MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
+
+ if (uncomp_size > 0xFFFFFFFF)
+ {
+ // No zip64 support yet
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+ if (uncomp_size <= 3)
+ level = 0;
+
+ if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
+ {
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+ local_dir_header_ofs += num_alignment_padding_bytes;
+ if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
+ cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
+
+ MZ_CLEAR_OBJ(local_dir_header);
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
+ {
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+ cur_archive_file_ofs += archive_name_size;
+
+ if (uncomp_size)
+ {
+ mz_uint64 uncomp_remaining = uncomp_size;
+ void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
+ if (!pRead_buf)
+ {
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+
+ if (!level)
+ {
+ while (uncomp_remaining)
+ {
+ mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
+ if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+ uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
+ uncomp_remaining -= n;
+ cur_archive_file_ofs += n;
+ }
+ comp_size = uncomp_size;
+ }
+ else
+ {
+ mz_bool result = MZ_FALSE;
+ mz_zip_writer_add_state state;
+ tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
+ if (!pComp)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+
+ state.m_pZip = pZip;
+ state.m_cur_archive_file_ofs = cur_archive_file_ofs;
+ state.m_comp_size = 0;
+
+ if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+
+ for ( ; ; )
+ {
+ size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
+ tdefl_status status;
+
+ if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
+ break;
+
+ uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
+ uncomp_remaining -= in_buf_size;
+
+ status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
+ if (status == TDEFL_STATUS_DONE)
+ {
+ result = MZ_TRUE;
+ break;
+ }
+ else if (status != TDEFL_STATUS_OKAY)
+ break;
+ }
+
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+
+ if (!result)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ MZ_FCLOSE(pSrc_file);
+ return MZ_FALSE;
+ }
+
+ comp_size = state.m_comp_size;
+ cur_archive_file_ofs = state.m_cur_archive_file_ofs;
+
+ method = MZ_DEFLATED;
+ }
+
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ }
+
+ MZ_FCLOSE(pSrc_file); pSrc_file = NULL;
+
+ // no zip64 support yet
+ if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
+ return MZ_FALSE;
+
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
+ return MZ_FALSE;
+
+ if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
+ return MZ_FALSE;
+
+ pZip->m_total_files++;
+ pZip->m_archive_size = cur_archive_file_ofs;
+
+ return MZ_TRUE;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
+{
+ mz_uint n, bit_flags, num_alignment_padding_bytes;
+ mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
+ mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
+ mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
+ mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
+ size_t orig_central_dir_size;
+ mz_zip_internal_state *pState;
+ void *pBuf; const mz_uint8 *pSrc_central_header;
+
+ if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
+ return MZ_FALSE;
+ if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
+ return MZ_FALSE;
+ pState = pZip->m_pState;
+
+ num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
+
+ // no zip64 support yet
+ if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
+ cur_dst_file_ofs = pZip->m_archive_size;
+
+ if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+ if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
+ return MZ_FALSE;
+ cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
+
+ if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
+ return MZ_FALSE;
+ cur_dst_file_ofs += num_alignment_padding_bytes;
+ local_dir_header_ofs = cur_dst_file_ofs;
+ if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
+
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+ return MZ_FALSE;
+ cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
+
+ n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
+ comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+
+ if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
+ return MZ_FALSE;
+
+ while (comp_bytes_remaining)
+ {
+ n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
+ if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+ return MZ_FALSE;
+ }
+ cur_src_file_ofs += n;
+
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+ return MZ_FALSE;
+ }
+ cur_dst_file_ofs += n;
+
+ comp_bytes_remaining -= n;
+ }
+
+ bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
+ if (bit_flags & 8)
+ {
+ // Copy data descriptor
+ if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+ return MZ_FALSE;
+ }
+
+ n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+ return MZ_FALSE;
+ }
+
+ cur_dst_file_ofs += n;
+ }
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+
+ // no zip64 support yet
+ if (cur_dst_file_ofs > 0xFFFFFFFF)
+ return MZ_FALSE;
+
+ orig_central_dir_size = pState->m_central_dir.m_size;
+
+ memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
+ MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
+ if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
+ return MZ_FALSE;
+
+ n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
+ if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
+ {
+ mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
+ return MZ_FALSE;
+ }
+
+ if (pState->m_central_dir.m_size > 0xFFFFFFFF)
+ return MZ_FALSE;
+ n = (mz_uint32)orig_central_dir_size;
+ if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
+ {
+ mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
+ return MZ_FALSE;
+ }
+
+ pZip->m_total_files++;
+ pZip->m_archive_size = cur_dst_file_ofs;
+
+ return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
+{
+ mz_zip_internal_state *pState;
+ mz_uint64 central_dir_ofs, central_dir_size;
+ mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
+
+ if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
+ return MZ_FALSE;
+
+ pState = pZip->m_pState;
+
+ // no zip64 support yet
+ if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
+ return MZ_FALSE;
+
+ central_dir_ofs = 0;
+ central_dir_size = 0;
+ if (pZip->m_total_files)
+ {
+ // Write central directory
+ central_dir_ofs = pZip->m_archive_size;
+ central_dir_size = pState->m_central_dir.m_size;
+ pZip->m_central_directory_file_ofs = central_dir_ofs;
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
+ return MZ_FALSE;
+ pZip->m_archive_size += central_dir_size;
+ }
+
+ // Write end of central directory record
+ MZ_CLEAR_OBJ(hdr);
+ MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
+ MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
+ MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
+ MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
+ MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
+
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
+ return MZ_FALSE;
+#ifndef MINIZ_NO_STDIO
+ if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
+ return MZ_FALSE;
+#endif // #ifndef MINIZ_NO_STDIO
+
+ pZip->m_archive_size += sizeof(hdr);
+
+ pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
+ return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
+{
+ if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
+ return MZ_FALSE;
+ if (pZip->m_pWrite != mz_zip_heap_write_func)
+ return MZ_FALSE;
+ if (!mz_zip_writer_finalize_archive(pZip))
+ return MZ_FALSE;
+
+ *pBuf = pZip->m_pState->m_pMem;
+ *pSize = pZip->m_pState->m_mem_size;
+ pZip->m_pState->m_pMem = NULL;
+ pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
+ return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
+{
+ mz_zip_internal_state *pState;
+ mz_bool status = MZ_TRUE;
+ if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
+ return MZ_FALSE;
+
+ pState = pZip->m_pState;
+ pZip->m_pState = NULL;
+ mz_zip_array_clear(pZip, &pState->m_central_dir);
+ mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
+ mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
+
+#ifndef MINIZ_NO_STDIO
+ if (pState->m_pFile)
+ {
+ MZ_FCLOSE(pState->m_pFile);
+ pState->m_pFile = NULL;
+ }
+#endif // #ifndef MINIZ_NO_STDIO
+
+ if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
+ pState->m_pMem = NULL;
+ }
+
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
+ pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
+ return status;
+}
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
+{
+ mz_bool status, created_new_archive = MZ_FALSE;
+ mz_zip_archive zip_archive;
+ struct MZ_FILE_STAT_STRUCT file_stat;
+ MZ_CLEAR_OBJ(zip_archive);
+ if ((int)level_and_flags < 0)
+ level_and_flags = MZ_DEFAULT_LEVEL;
+ if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
+ return MZ_FALSE;
+ if (!mz_zip_writer_validate_archive_name(pArchive_name))
+ return MZ_FALSE;
+ if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
+ {
+ // Create a new archive.
+ if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
+ return MZ_FALSE;
+ created_new_archive = MZ_TRUE;
+ }
+ else
+ {
+ // Append to an existing archive.
+ if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
+ return MZ_FALSE;
+ if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
+ {
+ mz_zip_reader_end(&zip_archive);
+ return MZ_FALSE;
+ }
+ }
+ status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
+ // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
+ if (!mz_zip_writer_finalize_archive(&zip_archive))
+ status = MZ_FALSE;
+ if (!mz_zip_writer_end(&zip_archive))
+ status = MZ_FALSE;
+ if ((!status) && (created_new_archive))
+ {
+ // It's a new archive and something went wrong, so just delete it.
+ int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
+ (void)ignoredStatus;
+ }
+ return status;
+}
+
+void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
+{
+ int file_index;
+ mz_zip_archive zip_archive;
+ void *p = NULL;
+
+ if (pSize)
+ *pSize = 0;
+
+ if ((!pZip_filename) || (!pArchive_name))
+ return NULL;
+
+ MZ_CLEAR_OBJ(zip_archive);
+ if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
+ return NULL;
+
+ if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0)
+ p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
+
+ mz_zip_reader_end(&zip_archive);
+ return p;
+}
+
+#endif // #ifndef MINIZ_NO_STDIO
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_FILE_ONLY
+
+/*
+ This is free and unencumbered software released into the public domain.
+
+ Anyone is free to copy, modify, publish, use, compile, sell, or
+ distribute this software, either in source code form or as a compiled
+ binary, for any purpose, commercial or non-commercial, and by any
+ means.
+
+ In jurisdictions that recognize copyright laws, the author or authors
+ of this software dedicate any and all copyright interest in the
+ software to the public domain. We make this dedication for the benefit
+ of the public at large and to the detriment of our heirs and
+ successors. We intend this dedication to be an overt act of
+ relinquishment in perpetuity of all present and future rights to this
+ software under copyright law.
+
+ 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 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.
+
+ For more information, please refer to <http://unlicense.org/>
+*/
diff --git a/src/3rdparty/assimp/contrib/zip/src/zip.c b/src/3rdparty/assimp/contrib/zip/src/zip.c
new file mode 100644
index 000000000..80573096b
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/zip/src/zip.c
@@ -0,0 +1,640 @@
+/*
+ * 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 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 "zip.h"
+#include "miniz.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#if defined _WIN32 || defined __WIN32__
+/* Win32, DOS */
+#include <direct.h>
+
+#define MKDIR(DIRNAME) _mkdir(DIRNAME)
+#define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL)
+#define HAS_DEVICE(P) \
+ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \
+ (P)[1] == ':')
+#define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0)
+#define ISSLASH(C) ((C) == '/' || (C) == '\\')
+
+#else
+#define MKDIR(DIRNAME) mkdir(DIRNAME, 0755)
+#define STRCLONE(STR) ((STR) ? strdup(STR) : NULL)
+#endif
+
+#ifndef FILESYSTEM_PREFIX_LEN
+#define FILESYSTEM_PREFIX_LEN(P) 0
+#endif
+
+#ifndef ISSLASH
+#define ISSLASH(C) ((C) == '/')
+#endif
+
+#define CLEANUP(ptr) \
+ do { \
+ if (ptr) { \
+ free((void *)ptr); \
+ ptr = NULL; \
+ } \
+ } while (0)
+
+static char *basename(const char *name) {
+ char const *p;
+ char const *base = name += FILESYSTEM_PREFIX_LEN(name);
+ int all_slashes = 1;
+
+ for (p = name; *p; p++) {
+ if (ISSLASH(*p))
+ base = p + 1;
+ else
+ all_slashes = 0;
+ }
+
+ /* If NAME is all slashes, arrange to return `/'. */
+ if (*base == '\0' && ISSLASH(*name) && all_slashes) --base;
+
+ return (char *)base;
+}
+
+static int mkpath(const char *path) {
+ char const *p;
+ char npath[MAX_PATH + 1] = {0};
+ int len = 0;
+
+ for (p = path; *p && len < MAX_PATH; p++) {
+ if (ISSLASH(*p) && len > 0) {
+ if (MKDIR(npath) == -1)
+ if (errno != EEXIST) return -1;
+ }
+ npath[len++] = *p;
+ }
+
+ return 0;
+}
+
+static char *strrpl(const char *str, char oldchar, char newchar) {
+ char *rpl = (char *)malloc(sizeof(char) * (1 + strlen(str)));
+ char *begin = rpl;
+ char c;
+ while((c = *str++)) {
+ if (c == oldchar) {
+ c = newchar;
+ }
+ *rpl++ = c;
+ }
+ *rpl = '\0';
+
+ return begin;
+}
+
+struct zip_entry_t {
+ int index;
+ const char *name;
+ mz_uint64 uncomp_size;
+ mz_uint64 comp_size;
+ mz_uint32 uncomp_crc32;
+ mz_uint64 offset;
+ mz_uint8 header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
+ mz_uint64 header_offset;
+ mz_uint16 method;
+ mz_zip_writer_add_state state;
+ tdefl_compressor comp;
+};
+
+struct zip_t {
+ mz_zip_archive archive;
+ mz_uint level;
+ struct zip_entry_t entry;
+ char mode;
+};
+
+struct zip_t *zip_open(const char *zipname, int level, char mode) {
+ struct zip_t *zip = NULL;
+
+ if (!zipname || strlen(zipname) < 1) {
+ // zip_t archive name is empty or NULL
+ goto cleanup;
+ }
+
+ if (level < 0) level = MZ_DEFAULT_LEVEL;
+ if ((level & 0xF) > MZ_UBER_COMPRESSION) {
+ // Wrong compression level
+ goto cleanup;
+ }
+
+ zip = (struct zip_t *)calloc((size_t)1, sizeof(struct zip_t));
+ if (!zip) goto cleanup;
+
+ zip->level = level;
+ zip->mode = mode;
+ switch (mode) {
+ case 'w':
+ // Create a new archive.
+ if (!mz_zip_writer_init_file(&(zip->archive), zipname, 0)) {
+ // Cannot initialize zip_archive writer
+ goto cleanup;
+ }
+ break;
+
+ case 'r':
+ case 'a':
+ if (!mz_zip_reader_init_file(
+ &(zip->archive), zipname,
+ level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) {
+ // An archive file does not exist or cannot initialize
+ // zip_archive reader
+ goto cleanup;
+ }
+
+ if (mode == 'a' &&
+ !mz_zip_writer_init_from_reader(&(zip->archive), zipname)) {
+ mz_zip_reader_end(&(zip->archive));
+ goto cleanup;
+ }
+
+ break;
+
+ default:
+ goto cleanup;
+ }
+
+ return zip;
+
+cleanup:
+ CLEANUP(zip);
+ return NULL;
+}
+
+void zip_close(struct zip_t *zip) {
+ if (zip) {
+ // Always finalize, even if adding failed for some reason, so we have a
+ // valid central directory.
+ mz_zip_writer_finalize_archive(&(zip->archive));
+
+ mz_zip_writer_end(&(zip->archive));
+ mz_zip_reader_end(&(zip->archive));
+
+ CLEANUP(zip);
+ }
+}
+
+int zip_entry_open(struct zip_t *zip, const char *entryname) {
+ char *locname = NULL;
+ size_t entrylen = 0;
+ mz_zip_archive *pzip = NULL;
+ mz_uint num_alignment_padding_bytes, level;
+
+ if (!zip || !entryname) {
+ return -1;
+ }
+
+ entrylen = strlen(entryname);
+ if (entrylen < 1) {
+ return -1;
+ }
+
+ pzip = &(zip->archive);
+ /*
+ .ZIP File Format Specification Version: 6.3.3
+
+ 4.4.17.1 The name of the file, with optional relative path.
+ The path stored MUST not contain a drive or
+ device letter, or a leading slash. All slashes
+ MUST be forward slashes '/' as opposed to
+ backwards slashes '\' for compatibility with Amiga
+ and UNIX file systems etc. If input came from standard
+ input, there is no file name field.
+ */
+ locname = strrpl(entryname, '\\', '/');
+
+ if (zip->mode == 'r') {
+ zip->entry.index = mz_zip_reader_locate_file(pzip, locname, NULL, 0);
+ CLEANUP(locname);
+ return (zip->entry.index < 0) ? -1 : 0;
+ }
+
+ zip->entry.index = zip->archive.m_total_files;
+ zip->entry.name = locname;
+ if (!zip->entry.name) {
+ // Cannot parse zip entry name
+ return -1;
+ }
+
+ zip->entry.comp_size = 0;
+ zip->entry.uncomp_size = 0;
+ zip->entry.uncomp_crc32 = MZ_CRC32_INIT;
+ zip->entry.offset = zip->archive.m_archive_size;
+ zip->entry.header_offset = zip->archive.m_archive_size;
+ memset(zip->entry.header, 0,
+ MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8));
+ zip->entry.method = 0;
+
+ num_alignment_padding_bytes =
+ mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
+
+ if (!pzip->m_pState || (pzip->m_zip_mode != MZ_ZIP_MODE_WRITING)) {
+ // Wrong zip mode
+ return -1;
+ }
+ if (zip->level & MZ_ZIP_FLAG_COMPRESSED_DATA) {
+ // Wrong zip compression level
+ return -1;
+ }
+ // no zip64 support yet
+ if ((pzip->m_total_files == 0xFFFF) ||
+ ((pzip->m_archive_size + num_alignment_padding_bytes +
+ MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
+ entrylen) > 0xFFFFFFFF)) {
+ // No zip64 support yet
+ return -1;
+ }
+ if (!mz_zip_writer_write_zeros(
+ pzip, zip->entry.offset,
+ num_alignment_padding_bytes + sizeof(zip->entry.header))) {
+ // Cannot memset zip entry header
+ return -1;
+ }
+
+ zip->entry.header_offset += num_alignment_padding_bytes;
+ if (pzip->m_file_offset_alignment) {
+ MZ_ASSERT((zip->entry.header_offset &
+ (pzip->m_file_offset_alignment - 1)) == 0);
+ }
+ zip->entry.offset +=
+ num_alignment_padding_bytes + sizeof(zip->entry.header);
+
+ if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, zip->entry.name,
+ entrylen) != entrylen) {
+ // Cannot write data to zip entry
+ return -1;
+ }
+
+ zip->entry.offset += entrylen;
+ level = zip->level & 0xF;
+ if (level) {
+ zip->entry.state.m_pZip = pzip;
+ zip->entry.state.m_cur_archive_file_ofs = zip->entry.offset;
+ zip->entry.state.m_comp_size = 0;
+
+ if (tdefl_init(&(zip->entry.comp), mz_zip_writer_add_put_buf_callback,
+ &(zip->entry.state),
+ tdefl_create_comp_flags_from_zip_params(
+ level, -15, MZ_DEFAULT_STRATEGY)) !=
+ TDEFL_STATUS_OKAY) {
+ // Cannot initialize the zip compressor
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int zip_entry_close(struct zip_t *zip) {
+ mz_zip_archive *pzip = NULL;
+ mz_uint level;
+ tdefl_status done;
+ mz_uint16 entrylen;
+ time_t t;
+ struct tm *tm;
+ mz_uint16 dos_time, dos_date;
+ int status = -1;
+
+ if (!zip) {
+ // zip_t handler is not initialized
+ return -1;
+ }
+
+ if (zip->mode == 'r') {
+ return 0;
+ }
+
+ pzip = &(zip->archive);
+ level = zip->level & 0xF;
+ if (level) {
+ done = tdefl_compress_buffer(&(zip->entry.comp), "", 0, TDEFL_FINISH);
+ if (done != TDEFL_STATUS_DONE && done != TDEFL_STATUS_OKAY) {
+ // Cannot flush compressed buffer
+ goto cleanup;
+ }
+ zip->entry.comp_size = zip->entry.state.m_comp_size;
+ zip->entry.offset = zip->entry.state.m_cur_archive_file_ofs;
+ zip->entry.method = MZ_DEFLATED;
+ }
+
+ entrylen = (mz_uint16)strlen(zip->entry.name);
+ t = time(NULL);
+ tm = localtime(&t);
+ dos_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
+ ((tm->tm_sec) >> 1));
+ dos_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
+ ((tm->tm_mon + 1) << 5) + tm->tm_mday);
+
+ // no zip64 support yet
+ if ((zip->entry.comp_size > 0xFFFFFFFF) ||
+ (zip->entry.offset > 0xFFFFFFFF)) {
+ // No zip64 support, yet
+ goto cleanup;
+ }
+
+ if (!mz_zip_writer_create_local_dir_header(
+ pzip, zip->entry.header, entrylen, 0, zip->entry.uncomp_size,
+ zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0,
+ dos_time, dos_date)) {
+ // Cannot create zip entry header
+ goto cleanup;
+ }
+
+ if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.header_offset,
+ zip->entry.header, sizeof(zip->entry.header)) !=
+ sizeof(zip->entry.header)) {
+ // Cannot write zip entry header
+ goto cleanup;
+ }
+
+ if (!mz_zip_writer_add_to_central_dir(
+ pzip, zip->entry.name, entrylen, NULL, 0, "", 0,
+ zip->entry.uncomp_size, zip->entry.comp_size,
+ zip->entry.uncomp_crc32, zip->entry.method, 0, dos_time, dos_date,
+ zip->entry.header_offset, 0)) {
+ // Cannot write to zip central dir
+ goto cleanup;
+ }
+
+ pzip->m_total_files++;
+ pzip->m_archive_size = zip->entry.offset;
+ status = 0;
+
+cleanup:
+ CLEANUP(zip->entry.name);
+ return status;
+}
+
+int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) {
+ mz_uint level;
+ mz_zip_archive *pzip = NULL;
+ tdefl_status status;
+
+ if (!zip) {
+ // zip_t handler is not initialized
+ return -1;
+ }
+
+ pzip = &(zip->archive);
+ if (buf && bufsize > 0) {
+ zip->entry.uncomp_size += bufsize;
+ zip->entry.uncomp_crc32 = (mz_uint32)mz_crc32(
+ zip->entry.uncomp_crc32, (const mz_uint8 *)buf, bufsize);
+
+ level = zip->level & 0xF;
+ if (!level) {
+ if ((pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, buf,
+ bufsize) != bufsize)) {
+ // Cannot write buffer
+ return -1;
+ }
+ zip->entry.offset += bufsize;
+ zip->entry.comp_size += bufsize;
+ } else {
+ status = tdefl_compress_buffer(&(zip->entry.comp), buf, bufsize,
+ TDEFL_NO_FLUSH);
+ if (status != TDEFL_STATUS_DONE && status != TDEFL_STATUS_OKAY) {
+ // Cannot compress buffer
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int zip_entry_fwrite(struct zip_t *zip, const char *filename) {
+ int status = 0;
+ size_t n = 0;
+ FILE *stream = NULL;
+ mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE] = {0};
+
+ if (!zip) {
+ // zip_t handler is not initialized
+ return -1;
+ }
+
+ stream = fopen(filename, "rb");
+ if (!stream) {
+ // Cannot open filename
+ return -1;
+ }
+
+ while ((n = fread(buf, sizeof(mz_uint8), MZ_ZIP_MAX_IO_BUF_SIZE, stream)) >
+ 0) {
+ if (zip_entry_write(zip, buf, n) < 0) {
+ status = -1;
+ break;
+ }
+ }
+ fclose(stream);
+
+ return status;
+}
+
+int zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize) {
+ mz_zip_archive *pzip = NULL;
+ mz_uint idx;
+
+ if (!zip) {
+ // zip_t handler is not initialized
+ return -1;
+ }
+
+ if (zip->mode != 'r' || zip->entry.index < 0) {
+ // the entry is not found or we do not have read access
+ return -1;
+ }
+
+ pzip = &(zip->archive);
+ idx = (mz_uint)zip->entry.index;
+ if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
+ // the entry is a directory
+ return -1;
+ }
+
+ *buf = mz_zip_reader_extract_to_heap(pzip, idx, bufsize, 0);
+ return (*buf) ? 0 : -1;
+}
+
+int zip_entry_fread(struct zip_t *zip, const char *filename) {
+ mz_zip_archive *pzip = NULL;
+ mz_uint idx;
+
+ if (!zip) {
+ // zip_t handler is not initialized
+ return -1;
+ }
+
+ if (zip->mode != 'r' || zip->entry.index < 0) {
+ // the entry is not found or we do not have read access
+ return -1;
+ }
+
+ pzip = &(zip->archive);
+ idx = (mz_uint)zip->entry.index;
+ if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
+ // the entry is a directory
+ return -1;
+ }
+
+ return (mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) ? 0 : -1;
+}
+
+int zip_entry_extract(struct zip_t *zip,
+ size_t (*on_extract)(void *arg, unsigned long long offset,
+ const void *buf, size_t bufsize),
+ void *arg) {
+ mz_zip_archive *pzip = NULL;
+ mz_uint idx;
+
+ if (!zip) {
+ // zip_t handler is not initialized
+ return -1;
+ }
+
+ if (zip->mode != 'r' || zip->entry.index < 0) {
+ // the entry is not found or we do not have read access
+ return -1;
+ }
+
+ pzip = &(zip->archive);
+ idx = (mz_uint)zip->entry.index;
+
+ return (mz_zip_reader_extract_to_callback(pzip, idx, on_extract, arg, 0))
+ ? 0
+ : -1;
+}
+
+int zip_create(const char *zipname, const char *filenames[], size_t len) {
+ int status = 0;
+ size_t i;
+ mz_zip_archive zip_archive;
+
+ if (!zipname || strlen(zipname) < 1) {
+ // zip_t archive name is empty or NULL
+ return -1;
+ }
+
+ // Create a new archive.
+ if (!memset(&(zip_archive), 0, sizeof(zip_archive))) {
+ // Cannot memset zip archive
+ return -1;
+ }
+
+ if (!mz_zip_writer_init_file(&zip_archive, zipname, 0)) {
+ // Cannot initialize zip_archive writer
+ return -1;
+ }
+
+ for (i = 0; i < len; ++i) {
+ const char *name = filenames[i];
+ if (!name) {
+ status = -1;
+ break;
+ }
+
+ if (!mz_zip_writer_add_file(&zip_archive, basename(name), name, "", 0,
+ ZIP_DEFAULT_COMPRESSION_LEVEL)) {
+ // Cannot add file to zip_archive
+ status = -1;
+ break;
+ }
+ }
+
+ mz_zip_writer_finalize_archive(&zip_archive);
+ mz_zip_writer_end(&zip_archive);
+ return status;
+}
+
+int zip_extract(const char *zipname, const char *dir,
+ int (*on_extract)(const char *filename, void *arg), void *arg) {
+ int status = -1;
+ mz_uint i, n;
+ char path[MAX_PATH + 1] = {0};
+ mz_zip_archive zip_archive;
+ mz_zip_archive_file_stat info;
+ size_t dirlen = 0;
+
+ if (!memset(&(zip_archive), 0, sizeof(zip_archive))) {
+ // Cannot memset zip archive
+ return -1;
+ }
+
+ if (!zipname || !dir) {
+ // Cannot parse zip archive name
+ return -1;
+ }
+
+ dirlen = strlen(dir);
+ if (dirlen + 1 > MAX_PATH) {
+ return -1;
+ }
+
+ // Now try to open the archive.
+ if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) {
+ // Cannot initialize zip_archive reader
+ return -1;
+ }
+
+ strcpy(path, dir);
+ if (!ISSLASH(path[dirlen - 1])) {
+#if defined _WIN32 || defined __WIN32__
+ path[dirlen] = '\\';
+#else
+ path[dirlen] = '/';
+#endif
+ ++dirlen;
+ }
+
+ // Get and print information about each file in the archive.
+ n = mz_zip_reader_get_num_files(&zip_archive);
+ for (i = 0; i < n; ++i) {
+ if (!mz_zip_reader_file_stat(&zip_archive, i, &info)) {
+ // Cannot get information about zip archive;
+ goto out;
+ }
+ strncpy(&path[dirlen], info.m_filename, MAX_PATH - dirlen);
+ if (mkpath(path) < 0) {
+ // Cannot make a path
+ goto out;
+ }
+
+ if (!mz_zip_reader_is_file_a_directory(&zip_archive, i)) {
+ if (!mz_zip_reader_extract_to_file(&zip_archive, i, path, 0)) {
+ // Cannot extract zip archive to file
+ goto out;
+ }
+ }
+
+ if (on_extract) {
+ if (on_extract(path, arg) < 0) {
+ goto out;
+ }
+ }
+ }
+ status = 0;
+
+out:
+ // Close the archive, freeing any resources it was using
+ if (!mz_zip_reader_end(&zip_archive)) {
+ // Cannot end zip reader
+ status = -1;
+ }
+
+ return status;
+}
diff --git a/src/3rdparty/assimp/contrib/zip/src/zip.h b/src/3rdparty/assimp/contrib/zip/src/zip.h
new file mode 100644
index 000000000..1611b5417
--- /dev/null
+++ b/src/3rdparty/assimp/contrib/zip/src/zip.h
@@ -0,0 +1,193 @@
+/*
+ * 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 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
+#ifndef ZIP_H
+#define ZIP_H
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH 32767 /* # chars in a path name including NULL */
+#endif
+
+#define ZIP_DEFAULT_COMPRESSION_LEVEL 6
+
+/*
+ This data structure is used throughout the library to represent zip archive
+ - forward declaration.
+*/
+struct zip_t;
+
+/*
+ Opens zip archive with compression level using the given mode.
+
+ Args:
+ zipname: zip archive file name.
+ level: compression level (0-9 are the standard zlib-style levels).
+ mode: file access mode.
+ 'r': opens a file for reading/extracting (the file must exists).
+ 'w': creates an empty file for writing.
+ 'a': appends to an existing archive.
+
+ Returns:
+ The zip archive handler or NULL on error
+*/
+extern struct zip_t *zip_open(const char *zipname, int level, char mode);
+
+/*
+ Closes zip archive, releases resources - always finalize.
+
+ Args:
+ zip: zip archive handler.
+*/
+extern void zip_close(struct zip_t *zip);
+
+/*
+ Opens a new entry for writing in a zip archive.
+
+ Args:
+ zip: zip archive handler.
+ entryname: an entry name in local dictionary.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_entry_open(struct zip_t *zip, const char *entryname);
+
+/*
+ Closes a zip entry, flushes buffer and releases resources.
+
+ Args:
+ zip: zip archive handler.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_entry_close(struct zip_t *zip);
+
+/*
+ Compresses an input buffer for the current zip entry.
+
+ Args:
+ zip: zip archive handler.
+ buf: input buffer.
+ bufsize: input buffer size (in bytes).
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize);
+
+/*
+ Compresses a file for the current zip entry.
+
+ Args:
+ zip: zip archive handler.
+ filename: input file.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_entry_fwrite(struct zip_t *zip, const char *filename);
+
+/*
+ Extracts the current zip entry into output buffer.
+ The function allocates sufficient memory for a output buffer.
+
+ Args:
+ zip: zip archive handler.
+ buf: output buffer.
+ bufsize: output buffer size (in bytes).
+
+ Note:
+ - remember to release memory allocated for a output buffer.
+ - for large entries, please take a look at zip_entry_extract function.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize);
+
+/*
+ Extracts the current zip entry into output file.
+
+ Args:
+ zip: zip archive handler.
+ filename: output file.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_entry_fread(struct zip_t *zip, const char *filename);
+
+/*
+ Extract the current zip entry using a callback function (on_extract).
+
+ Args:
+ zip: zip archive handler.
+ on_extract: callback function.
+ arg: opaque pointer (optional argument,
+ which you can pass to the on_extract callback)
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+ */
+extern int zip_entry_extract(struct zip_t *zip,
+ size_t (*on_extract)(void *arg,
+ unsigned long long offset,
+ const void *data,
+ size_t size),
+ void *arg);
+
+/*
+ Creates a new archive and puts files into a single zip archive.
+
+ Args:
+ zipname: zip archive file.
+ filenames: input files.
+ len: number of input files.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_create(const char *zipname, const char *filenames[], size_t len);
+
+/*
+ Extracts a zip archive file into directory.
+
+ If on_extract_entry is not NULL, the callback will be called after
+ successfully extracted each zip entry.
+ Returning a negative value from the callback will cause abort and return an
+ error. The last argument (void *arg) is optional, which you can use to pass
+ data to the on_extract_entry callback.
+
+ Args:
+ zipname: zip archive file.
+ dir: output directory.
+ on_extract_entry: on extract callback.
+ arg: opaque pointer.
+
+ Returns:
+ The return code - 0 on success, negative number (< 0) on error.
+*/
+extern int zip_extract(const char *zipname, const char *dir,
+ int (*on_extract_entry)(const char *filename, void *arg),
+ void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h b/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h
index 73973c50d..94ee1e474 100644
--- a/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h
+++ b/src/3rdparty/assimp/include/assimp/Compiler/pushpack1.h
@@ -36,11 +36,8 @@
#endif
#if defined(_MSC_VER)
-
// C4103: Packing was changed after the inclusion of the header, probably missing #pragma pop
# pragma warning (disable : 4103)
#endif
#define AI_PUSHPACK_IS_DEFINED
-
-
diff --git a/src/3rdparty/assimp/code/DefaultIOStream.h b/src/3rdparty/assimp/include/assimp/DefaultIOStream.h
index 510fc1d05..3668b27ec 100644
--- a/src/3rdparty/assimp/code/DefaultIOStream.h
+++ b/src/3rdparty/assimp/include/assimp/DefaultIOStream.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
#include <assimp/IOStream.hpp>
#include <assimp/importerdesc.h>
-#include "Defines.h"
+#include <assimp/Defines.h>
namespace Assimp {
@@ -55,15 +56,15 @@ namespace Assimp {
//! @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
+class ASSIMP_API DefaultIOStream : public IOStream
{
friend class DefaultIOSystem;
#if __ANDROID__
-#if __ANDROID_API__ > 9
-#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+# 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 // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+# endif // __ANDROID_API__ > 9
#endif // __ANDROID__
protected:
@@ -105,32 +106,30 @@ public:
void Flush();
private:
- // File datastructure, using clib
+ // File data-structure, using clib
FILE* mFile;
// Filename
std::string mFilename;
// Cached file size
- mutable size_t cachedSize;
+ mutable size_t mCachedSize;
};
-
// ----------------------------------------------------------------------------------
inline DefaultIOStream::DefaultIOStream () :
mFile (NULL),
mFilename (""),
- cachedSize (SIZE_MAX)
+ mCachedSize(SIZE_MAX)
{
// empty
}
-
// ----------------------------------------------------------------------------------
inline DefaultIOStream::DefaultIOStream (FILE* pFile,
const std::string &strFilename) :
mFile(pFile),
mFilename(strFilename),
- cachedSize (SIZE_MAX)
+ mCachedSize(SIZE_MAX)
{
// empty
}
diff --git a/src/3rdparty/assimp/code/DefaultIOSystem.h b/src/3rdparty/assimp/include/assimp/DefaultIOSystem.h
index 49960a847..d7cf031cf 100644
--- a/src/3rdparty/assimp/code/DefaultIOSystem.h
+++ b/src/3rdparty/assimp/include/assimp/DefaultIOSystem.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,7 +49,7 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** Default implementation of IOSystem using the standard C file functions */
-class DefaultIOSystem : public IOSystem
+class ASSIMP_API DefaultIOSystem : public IOSystem
{
public:
/** Constructor. */
diff --git a/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp b/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp
index 52574d5ea..4f1a7e1f4 100644
--- a/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp
+++ b/src/3rdparty/assimp/include/assimp/DefaultLogger.hpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
diff --git a/src/3rdparty/assimp/code/Defines.h b/src/3rdparty/assimp/include/assimp/Defines.h
index 15e1d83c2..15e1d83c2 100644
--- a/src/3rdparty/assimp/code/Defines.h
+++ b/src/3rdparty/assimp/include/assimp/Defines.h
diff --git a/src/3rdparty/assimp/include/assimp/Exporter.hpp b/src/3rdparty/assimp/include/assimp/Exporter.hpp
index 079060f4b..c6a6f684a 100644
--- a/src/3rdparty/assimp/include/assimp/Exporter.hpp
+++ b/src/3rdparty/assimp/include/assimp/Exporter.hpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2011, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Exporter.hpp
* @brief Defines the CPP-API for the Assimp export interface
*/
+#pragma once
#ifndef AI_EXPORT_HPP_INC
#define AI_EXPORT_HPP_INC
@@ -50,17 +52,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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
* 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
+ * The interface is modeled 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
@@ -73,17 +75,10 @@ namespace Assimp {
* #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
-//#ifdef __cplusplus
-// : public boost::noncopyable
-//#endif // __cplusplus
-{
+class ASSIMP_API Exporter {
public:
-
/** Function pointer type of a Export worker function */
typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*);
@@ -96,7 +91,7 @@ public:
// Worker function to do the actual exporting
fpExportFunc mExportFunction;
- // Postprocessing steps to be executed PRIOR to invoking mExportFunction
+ // Post-processing steps to be executed PRIOR to invoking mExportFunction
unsigned int mEnforcePP;
// Constructor to fill all entries
@@ -121,14 +116,10 @@ public:
public:
-
-
Exporter();
~Exporter();
public:
-
-
// -------------------------------------------------------------------
/** Supplies a custom IO handler to the exporter to use to open and
* access files.
@@ -162,8 +153,6 @@ public:
* @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.
@@ -182,9 +171,8 @@ public:
* 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);
-
+ const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* = NULL);
+ 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
@@ -212,16 +200,15 @@ public:
* 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
+ * the library (i.e. not copied using aiCopyScene and potentially modified afterwards),
+ * any post-processing steps already applied to the scene will not be applied again, unless
+ * they show non-idempotent behavior (#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);
-
+ 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
@@ -235,30 +222,26 @@ public:
* 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
+ * it manually would be to reclaim 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
@@ -269,13 +252,12 @@ public:
**/
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
+ * The returned pointer is of static storage duration if 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.
@@ -286,7 +268,6 @@ public:
* 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
@@ -300,11 +281,10 @@ public:
* 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
+ * built-in exporters because those are implicitly registered
* using #RegisterExporter).
* @param id Format id to be unregistered, this refers to the
* 'id' field of #aiExportFormatDesc.
@@ -312,16 +292,12 @@ public:
* 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;
};
-
-class ASSIMP_API ExportProperties
-{
+class ASSIMP_API ExportProperties {
public:
// Data type to store the key hash
typedef unsigned int KeyType;
@@ -329,16 +305,14 @@ public:
// 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, ai_real> FloatPropertyMap;
typedef std::map<KeyType, std::string> StringPropertyMap;
typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
public:
-
/** Standard constructor
* @see ExportProperties()
*/
-
ExportProperties();
// -------------------------------------------------------------------
@@ -379,7 +353,7 @@ public:
/** Set a floating-point configuration property.
* @see SetPropertyInteger()
*/
- bool SetPropertyFloat(const char* szName, float fValue);
+ bool SetPropertyFloat(const char* szName, ai_real fValue);
// -------------------------------------------------------------------
/** Set a string configuration property.
@@ -424,8 +398,8 @@ public:
/** Get a floating-point configuration property
* @see GetPropertyInteger()
*/
- float GetPropertyFloat(const char* szName,
- float fErrorReturn = 10e10f) const;
+ ai_real GetPropertyFloat(const char* szName,
+ ai_real fErrorReturn = 10e10f) const;
// -------------------------------------------------------------------
/** Get a string configuration property
@@ -486,19 +460,24 @@ protected:
MatrixPropertyMap mMatrixProperties;
};
-
// ----------------------------------------------------------------------------------
-inline const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const std::string& pFormatId,unsigned int pPreprocessing, const ExportProperties* pProperties)
+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, pProperties);
}
// ----------------------------------------------------------------------------------
-inline aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
+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, 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 6cc231b3d..ce5907a47 100644
--- a/src/3rdparty/assimp/include/assimp/IOStream.hpp
+++ b/src/3rdparty/assimp/include/assimp/IOStream.hpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief File I/O wrappers for C++.
*/
+#pragma once
#ifndef AI_IOSTREAM_H_INC
#define AI_IOSTREAM_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/IOSystem.hpp b/src/3rdparty/assimp/include/assimp/IOSystem.hpp
index abd7e5837..f4fbb6023 100644
--- a/src/3rdparty/assimp/include/assimp/IOSystem.hpp
+++ b/src/3rdparty/assimp/include/assimp/IOSystem.hpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* custom file handling logic to the Import library.
*/
+#pragma once
#ifndef AI_IOSYSTEM_H_INC
#define AI_IOSYSTEM_H_INC
@@ -54,10 +56,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "types.h"
+#ifdef _WIN32
+# include <direct.h>
+# include <stdlib.h>
+# include <stdio.h>
+#else
+# include <sys/stat.h>
+# include <sys/types.h>
+# include <unistd.h>
+#endif // _WIN32
+
#include <vector>
namespace Assimp {
-class IOStream;
+
+ class IOStream;
// ---------------------------------------------------------------------------
/** @brief CPP-API: Interface to the file system.
@@ -66,7 +79,8 @@ class IOStream;
* to the importer library. If you implement this interface, you also want to
* supply a custom implementation for IOStream.
*
- * @see Importer::SetIOHandler() */
+ * @see Importer::SetIOHandler()
+ */
class ASSIMP_API IOSystem
#ifndef SWIG
: public Intern::AllocateFromAssimpHeap
@@ -195,20 +209,37 @@ public:
*/
virtual bool PopDirectory();
+ // -------------------------------------------------------------------
+ /** @brief CReates an new directory at the given path.
+ * @param path [in] The path to create.
+ * @return True, when a directory was created. False if the directory
+ * cannot be created.
+ */
+ virtual bool CreateDirectory( const std::string &path );
+
+ // -------------------------------------------------------------------
+ /** @brief Will change the current directory to the given path.
+ * @param path [in] The path to change to.
+ * @return True, when the directory has changed successfully.
+ */
+ virtual bool ChangeDirectory( const std::string &path );
+
+ virtual bool DeleteFile( const std::string &file );
+
private:
std::vector<std::string> m_pathStack;
};
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE IOSystem::IOSystem() :
- m_pathStack()
-{
+AI_FORCE_INLINE
+IOSystem::IOSystem()
+: m_pathStack() {
// empty
}
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE IOSystem::~IOSystem()
-{
+AI_FORCE_INLINE
+IOSystem::~IOSystem() {
// empty
}
@@ -219,9 +250,8 @@ AI_FORCE_INLINE IOSystem::~IOSystem()
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE IOStream* IOSystem::Open(const std::string& pFile,
- const std::string& pMode)
-{
+AI_FORCE_INLINE
+IOStream* IOSystem::Open(const std::string& pFile, const std::string& pMode) {
// NOTE:
// For compatibility, interface was changed to const char* to
// avoid crashes between binary incompatible STL versions
@@ -229,8 +259,8 @@ AI_FORCE_INLINE IOStream* IOSystem::Open(const std::string& pFile,
}
// ----------------------------------------------------------------------------
-AI_FORCE_INLINE bool IOSystem::Exists( const std::string& pFile) const
-{
+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
@@ -238,9 +268,8 @@ AI_FORCE_INLINE bool IOSystem::Exists( const std::string& pFile) const
}
// ----------------------------------------------------------------------------
-inline bool IOSystem::ComparePaths (const std::string& one,
- const std::string& second) const
-{
+AI_FORCE_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
@@ -248,7 +277,8 @@ inline bool IOSystem::ComparePaths (const std::string& one,
}
// ----------------------------------------------------------------------------
-inline bool IOSystem::PushDirectory( const std::string &path ) {
+AI_FORCE_INLINE
+bool IOSystem::PushDirectory( const std::string &path ) {
if ( path.empty() ) {
return false;
}
@@ -259,7 +289,8 @@ inline bool IOSystem::PushDirectory( const std::string &path ) {
}
// ----------------------------------------------------------------------------
-inline const std::string &IOSystem::CurrentDirectory() const {
+AI_FORCE_INLINE
+const std::string &IOSystem::CurrentDirectory() const {
if ( m_pathStack.empty() ) {
static const std::string Dummy("");
return Dummy;
@@ -268,12 +299,14 @@ inline const std::string &IOSystem::CurrentDirectory() const {
}
// ----------------------------------------------------------------------------
-inline size_t IOSystem::StackSize() const {
+AI_FORCE_INLINE
+size_t IOSystem::StackSize() const {
return m_pathStack.size();
}
// ----------------------------------------------------------------------------
-inline bool IOSystem::PopDirectory() {
+AI_FORCE_INLINE
+bool IOSystem::PopDirectory() {
if ( m_pathStack.empty() ) {
return false;
}
@@ -284,7 +317,43 @@ inline bool IOSystem::PopDirectory() {
}
// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::CreateDirectory( const std::string &path ) {
+ if ( path.empty() ) {
+ return false;
+ }
+
+#ifdef _WIN32
+ return 0 != ::_mkdir( path.c_str() );
+#else
+ return 0 != ::mkdir( path.c_str(), 0777 );
+#endif // _WIN32
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::ChangeDirectory( const std::string &path ) {
+ if ( path.empty() ) {
+ return false;
+ }
+
+#ifdef _WIN32
+ return 0 != ::_chdir( path.c_str() );
+#else
+ return 0 != ::chdir( path.c_str() );
+#endif // _WIN32
+}
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::DeleteFile( const std::string &file ) {
+ if ( file.empty() ) {
+ return false;
+ }
+ const int retCode( ::remove( file.c_str() ) );
+ return ( 0 == retCode );
+}
} //!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 4c01367ed..f42a2deaf 100644
--- a/src/3rdparty/assimp/include/assimp/Importer.hpp
+++ b/src/3rdparty/assimp/include/assimp/Importer.hpp
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,22 +43,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Importer.hpp
* @brief Defines the C++-API to the Open Asset Import Library.
*/
-#ifndef INCLUDED_AI_ASSIMP_HPP
-#define INCLUDED_AI_ASSIMP_HPP
+#pragma once
+#ifndef AI_ASSIMP_HPP_INC
+#define AI_ASSIMP_HPP_INC
#ifndef __cplusplus
# error This header requires C++ to be used. Use assimp.h for plain C.
-#endif
+#endif // __cplusplus
// Public ASSIMP data structures
-#include "types.h"
-#include "config.h"
+#include <assimp/types.h>
namespace Assimp {
// =======================================================================
// Public interface to Assimp
class Importer;
- class Exporter; // export.hpp
class IOStream;
class IOSystem;
class ProgressHandler;
@@ -76,7 +76,6 @@ namespace Assimp {
// =======================================================================
// 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
@@ -118,7 +117,7 @@ public:
/**
* @brief The upper limit for hints.
*/
- static const unsigned int MaxLenHint = 200;
+ static const unsigned int MaxLenHint = 200;
public:
@@ -192,7 +191,6 @@ public:
*/
aiReturn UnregisterPPStep(BaseProcess* pImp);
-
// -------------------------------------------------------------------
/** Set an integer configuration property.
* @param szName Name of the property. All supported properties
@@ -223,7 +221,7 @@ public:
/** Set a floating-point configuration property.
* @see SetPropertyInteger()
*/
- bool SetPropertyFloat(const char* szName, float fValue);
+ bool SetPropertyFloat(const char* szName, ai_real fValue);
// -------------------------------------------------------------------
/** Set a string configuration property.
@@ -268,8 +266,8 @@ public:
/** Get a floating-point configuration property
* @see GetPropertyInteger()
*/
- float GetPropertyFloat(const char* szName,
- float fErrorReturn = 10e10f) const;
+ ai_real GetPropertyFloat(const char* szName,
+ ai_real fErrorReturn = 10e10) const;
// -------------------------------------------------------------------
/** Get a string configuration property
@@ -291,10 +289,10 @@ public:
// -------------------------------------------------------------------
/** 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 files. If you need the importer to use custom 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.
+ * your custom 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.
@@ -356,7 +354,7 @@ public:
bool IsDefaultProgressHandler() const;
// -------------------------------------------------------------------
- /** @brief Check whether a given set of postprocessing flags
+ /** @brief Check whether a given set of post-processing flags
* is supported.
*
* Some flags are mutually exclusive, others are probably
@@ -516,9 +514,6 @@ public:
* It will work as well for static linkage with Assimp.*/
aiScene* GetOrphanedScene();
-
-
-
// -------------------------------------------------------------------
/** Returns whether a given file extension is supported by ASSIMP.
*
@@ -557,7 +552,7 @@ public:
inline void GetExtensionList(std::string& szOut) const;
// -------------------------------------------------------------------
- /** Get the number of importrs currently registered with Assimp. */
+ /** Get the number of importers currently registered with Assimp. */
size_t GetImporterCount() const;
// -------------------------------------------------------------------
@@ -600,9 +595,6 @@ public:
* @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.
@@ -623,7 +615,6 @@ public:
* intended for use in production environments. */
void SetExtraVerbose(bool bDo);
-
// -------------------------------------------------------------------
/** Private, do not use. */
ImporterPimpl* Pimpl() { return pimpl; }
@@ -658,4 +649,5 @@ AI_FORCE_INLINE bool Importer::IsExtensionSupported(const std::string& szExtensi
}
} // !namespace Assimp
-#endif // INCLUDED_AI_ASSIMP_HPP
+
+#endif // AI_ASSIMP_HPP_INC
diff --git a/src/3rdparty/assimp/include/assimp/LogStream.hpp b/src/3rdparty/assimp/include/assimp/LogStream.hpp
index 477fe5321..1052f1fda 100644
--- a/src/3rdparty/assimp/include/assimp/LogStream.hpp
+++ b/src/3rdparty/assimp/include/assimp/LogStream.hpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -43,8 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INCLUDED_AI_LOGSTREAM_H
#define INCLUDED_AI_LOGSTREAM_H
+
#include "types.h"
+
namespace Assimp {
+
class IOSystem;
// ------------------------------------------------------------------------------------
@@ -60,12 +64,11 @@ class ASSIMP_API LogStream
{
protected:
/** @brief Default constructor */
- LogStream() {
- }
+ LogStream();
+
public:
/** @brief Virtual destructor */
- virtual ~LogStream() {
- }
+ virtual ~LogStream();
// -------------------------------------------------------------------
/** @brief Overwrite this for your own output methods
@@ -90,6 +93,17 @@ public:
IOSystem* io = NULL);
}; // !class LogStream
+
+inline
+LogStream::LogStream() {
+ // empty
+}
+
+inline
+LogStream::~LogStream() {
+ // empty
+}
+
// ------------------------------------------------------------------------------------
} // Namespace Assimp
diff --git a/src/3rdparty/assimp/include/assimp/Logger.hpp b/src/3rdparty/assimp/include/assimp/Logger.hpp
index 7f355b5bf..0875b6d7d 100644
--- a/src/3rdparty/assimp/include/assimp/Logger.hpp
+++ b/src/3rdparty/assimp/include/assimp/Logger.hpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -45,7 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_LOGGER_H
#include "types.h"
-namespace Assimp {
+
+namespace Assimp {
+
class LogStream;
// Maximum length of a log message. Longer messages are rejected.
diff --git a/src/3rdparty/assimp/include/assimp/NullLogger.hpp b/src/3rdparty/assimp/include/assimp/NullLogger.hpp
index 64b59a4a0..191db1aaa 100644
--- a/src/3rdparty/assimp/include/assimp/NullLogger.hpp
+++ b/src/3rdparty/assimp/include/assimp/NullLogger.hpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,7 +47,9 @@ 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.
*
diff --git a/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp b/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp
index 8b069c82e..2c5b2f4c5 100644
--- a/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp
+++ b/src/3rdparty/assimp/include/assimp/ProgressHandler.hpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,9 +42,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file ProgressHandler.hpp
* @brief Abstract base class 'ProgressHandler'.
*/
-#ifndef INCLUDED_AI_PROGRESSHANDLER_H
-#define INCLUDED_AI_PROGRESSHANDLER_H
+#pragma once
+#ifndef AI_PROGRESSHANDLER_H_INC
+#define AI_PROGRESSHANDLER_H_INC
+
#include "types.h"
+
namespace Assimp {
// ------------------------------------------------------------------------------------
@@ -119,4 +123,4 @@ public:
// ------------------------------------------------------------------------------------
} // Namespace Assimp
-#endif
+#endif // AI_PROGRESSHANDLER_H_INC
diff --git a/src/3rdparty/assimp/code/SceneCombiner.h b/src/3rdparty/assimp/include/assimp/SceneCombiner.h
index 81e58aaf3..aa57406b9 100644
--- a/src/3rdparty/assimp/code/SceneCombiner.h
+++ b/src/3rdparty/assimp/include/assimp/SceneCombiner.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -46,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h>
#include <assimp/types.h>
-#include "Defines.h"
+#include <assimp/Defines.h>
#include <stddef.h>
#include <set>
#include <list>
@@ -142,7 +143,6 @@ struct NodeAttachmentInfo
*/
#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
-
typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
// ---------------------------------------------------------------------------
@@ -152,7 +152,6 @@ struct BoneWithHash : public std::pair<uint32_t,aiString*> {
std::vector<BoneSrcIndex> pSrcBones;
};
-
// ---------------------------------------------------------------------------
/** @brief Utility for SceneCombiner
*/
@@ -198,13 +197,17 @@ struct SceneHelper
* The class is currently being used by various postprocessing steps
* and loaders (ie. LWS).
*/
-class SceneCombiner
-{
+class ASSIMP_API SceneCombiner {
// class cannot be instanced
- SceneCombiner() {}
+ SceneCombiner() {
+ // empty
+ }
-public:
+ ~SceneCombiner() {
+ // empty
+ }
+public:
// -------------------------------------------------------------------
/** Merges two or more scenes.
*
@@ -218,10 +221,9 @@ public:
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.
+ /** Merges two or more scenes and attaches all scenes to a specific
+ * position in the node graph of the master scene.
*
* @param dest Receives a pointer to the destination scene. If the
* pointer doesn't point to NULL when the function is called, the
@@ -237,7 +239,6 @@ public:
std::vector<AttachmentInfo>& src,
unsigned int flags = 0);
-
// -------------------------------------------------------------------
/** Merges two or more meshes
*
@@ -256,7 +257,6 @@ public:
std::vector<aiMesh*>::const_iterator begin,
std::vector<aiMesh*>::const_iterator end);
-
// -------------------------------------------------------------------
/** Merges two or more bones
*
diff --git a/src/3rdparty/assimp/include/assimp/ai_assert.h b/src/3rdparty/assimp/include/assimp/ai_assert.h
index 0caeff673..d8dbac8d2 100644
--- a/src/3rdparty/assimp/include/assimp/ai_assert.h
+++ b/src/3rdparty/assimp/include/assimp/ai_assert.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -38,15 +39,15 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#ifndef AI_DEBUG_H_INC
-#define AI_DEBUG_H_INC
+#pragma once
+#ifndef AI_ASSERT_H_INC
+#define AI_ASSERT_H_INC
#ifdef ASSIMP_BUILD_DEBUG
# include <assert.h>
# define ai_assert(expression) assert(expression)
#else
# define ai_assert(expression)
-#endif
-
+#endif //
-#endif
+#endif // AI_ASSERT_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/anim.h b/src/3rdparty/assimp/include/assimp/anim.h
index 393224e40..f8774b8fd 100644
--- a/src/3rdparty/assimp/include/assimp/anim.h
+++ b/src/3rdparty/assimp/include/assimp/anim.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -39,15 +40,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file anim.h
- * @brief Defines the data structures in which the imported animations
- * are returned.
- */
+/**
+ * @file anim.h
+ * @brief Defines the data structures in which the imported animations
+ * are returned.
+ */
+#pragma once
#ifndef AI_ANIM_H_INC
#define AI_ANIM_H_INC
-#include "types.h"
-#include "quaternion.h"
+#include <assimp/types.h>
+#include <assimp/quaternion.h>
#ifdef __cplusplus
extern "C" {
@@ -65,16 +68,20 @@ struct aiVectorKey
#ifdef __cplusplus
- //! Default constructor
- aiVectorKey(){}
+ /// @brief The default constructor.
+ aiVectorKey()
+ : mTime( 0.0 )
+ , mValue() {
+ // empty
+ }
+
+ /// @brief Construction from a given time and key value.
- //! Construction from a given time and key value
aiVectorKey(double time, const aiVector3D& value)
: mTime (time)
, mValue (value)
{}
-
typedef aiVector3D elem_type;
// Comparison operators. For use with std::find();
@@ -92,7 +99,7 @@ struct aiVectorKey
bool operator > (const aiVectorKey& o) const {
return mTime > o.mTime;
}
-#endif
+#endif // __cplusplus
};
// ---------------------------------------------------------------------------
@@ -107,7 +114,10 @@ struct aiQuatKey
C_STRUCT aiQuaternion mValue;
#ifdef __cplusplus
- aiQuatKey(){
+ aiQuatKey()
+ : mTime( 0.0 )
+ , mValue() {
+ // empty
}
/** Construction from a given time and key value */
@@ -144,7 +154,7 @@ struct aiMeshKey
double mTime;
/** Index into the aiMesh::mAnimMeshes array of the
- * mesh coresponding to the #aiMeshAnim hosting this
+ * mesh corresponding 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;
@@ -181,7 +191,6 @@ struct aiMeshKey
#endif
};
-
// ---------------------------------------------------------------------------
/** Binds a morph anim mesh to a specific point in time. */
struct aiMeshMorphKey
@@ -197,10 +206,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)
{
}
@@ -237,8 +246,6 @@ enum aiAnimBehaviour
* 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 */
#ifndef SWIG
@@ -261,8 +268,7 @@ enum aiAnimBehaviour
* Duplicate keys don't pass the validation step. Most likely there
* will be no negative time values, but they are not forbidden also ( so
* implementations need to cope with them! ) */
-struct aiNodeAnim
-{
+struct aiNodeAnim {
/** The name of the node affected by this animation. The node
* must exist and it must be unique.*/
C_STRUCT aiString mNodeName;
@@ -288,7 +294,6 @@ struct aiNodeAnim
* scaling and one position key. */
C_STRUCT aiQuatKey* mRotationKeys;
-
/** The number of scaling keys */
unsigned int mNumScalingKeys;
@@ -299,7 +304,6 @@ struct aiNodeAnim
* position and one rotation key.*/
C_STRUCT aiVectorKey* mScalingKeys;
-
/** Defines how the animation behaves before the first
* key is encountered.
*
@@ -315,17 +319,19 @@ struct aiNodeAnim
C_ENUM aiAnimBehaviour mPostState;
#ifdef __cplusplus
- aiNodeAnim()
- {
- mNumPositionKeys = 0; mPositionKeys = NULL;
- mNumRotationKeys = 0; mRotationKeys = NULL;
- mNumScalingKeys = 0; mScalingKeys = NULL;
-
- mPreState = mPostState = aiAnimBehaviour_DEFAULT;
+ aiNodeAnim()
+ : mNumPositionKeys( 0 )
+ , mPositionKeys( NULL )
+ , mNumRotationKeys( 0 )
+ , mRotationKeys( NULL )
+ , mNumScalingKeys( 0 )
+ , mScalingKeys( NULL )
+ , mPreState( aiAnimBehaviour_DEFAULT )
+ , mPostState( aiAnimBehaviour_DEFAULT ) {
+ // empty
}
- ~aiNodeAnim()
- {
+ ~aiNodeAnim() {
delete [] mPositionKeys;
delete [] mRotationKeys;
delete [] mScalingKeys;
@@ -343,7 +349,7 @@ 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
+ * the name can basically serve as wild-card to select a group
* of meshes with similar animation setup)*/
C_STRUCT aiString mName;
@@ -400,10 +406,9 @@ struct aiMeshMorphAnim
};
// ---------------------------------------------------------------------------
-/** An animation consists of keyframe data for a number of nodes. For
+/** An animation consists of key-frame data for a number of nodes. For
* each node affected by the animation a separate series of data is given.*/
-struct aiAnimation
-{
+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). */
@@ -432,7 +437,6 @@ struct aiAnimation
* The array is mNumMeshChannels in size. */
C_STRUCT aiMeshAnim** mMeshChannels;
-
/** The number of mesh animation channels. Each channel affects
* a single mesh and defines morphing animation. */
unsigned int mNumMorphMeshChannels;
@@ -442,56 +446,59 @@ struct aiAnimation
C_STRUCT aiMeshMorphAnim **mMorphMeshChannels;
#ifdef __cplusplus
- aiAnimation()
- : mDuration(-1.)
- , mTicksPerSecond()
- , mNumChannels()
- , mChannels()
- , mNumMeshChannels()
- , mMeshChannels()
- , mNumMorphMeshChannels()
- , mMorphMeshChannels()
- {
- }
+ aiAnimation()
+ : mDuration(-1.)
+ , mTicksPerSecond(0.)
+ , mNumChannels(0)
+ , mChannels(NULL)
+ , mNumMeshChannels(0)
+ , mMeshChannels(NULL)
+ , mNumMorphMeshChannels(0)
+ , mMorphMeshChannels(NULL) {
+ // empty
+ }
- ~aiAnimation()
- {
- // DO NOT REMOVE THIS ADDITIONAL CHECK
- if (mNumChannels && mChannels) {
- for( unsigned int a = 0; a < mNumChannels; a++) {
- delete mChannels[a];
- }
-
- delete [] mChannels;
- }
- if (mNumMeshChannels && mMeshChannels) {
- for( unsigned int a = 0; a < mNumMeshChannels; a++) {
- delete mMeshChannels[a];
- }
-
- delete [] mMeshChannels;
- }
- if (mNumMorphMeshChannels && mMorphMeshChannels) {
- for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) {
- delete mMorphMeshChannels[a];
- }
- }
- }
+ ~aiAnimation() {
+ // DO NOT REMOVE THIS ADDITIONAL CHECK
+ if ( mNumChannels && mChannels ) {
+ for( unsigned int a = 0; a < mNumChannels; a++) {
+ delete mChannels[ a ];
+ }
+
+ delete [] mChannels;
+ }
+ if (mNumMeshChannels && mMeshChannels) {
+ for( unsigned int a = 0; a < mNumMeshChannels; a++) {
+ delete mMeshChannels[a];
+ }
+
+ delete [] mMeshChannels;
+ }
+ if (mNumMorphMeshChannels && mMorphMeshChannels) {
+ for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) {
+ delete mMorphMeshChannels[a];
+ }
+
+ delete [] mMorphMeshChannels;
+ }
+ }
#endif // __cplusplus
};
#ifdef __cplusplus
-}
+}
-// some C++ utilities for inter- and extrapolation
+/// @brief Some C++ utilities for inter- and extrapolation
namespace Assimp {
// ---------------------------------------------------------------------------
-/** @brief CPP-API: Utility class to simplify interpolations of various data types.
- *
- * The type of interpolation is chosen automatically depending on the
- * types of the arguments. */
+/**
+ * @brief CPP-API: Utility class to simplify interpolations of various data types.
+ *
+ * The type of interpolation is chosen automatically depending on the
+ * types of the arguments.
+ */
template <typename T>
struct Interpolator
{
@@ -501,7 +508,7 @@ struct Interpolator
* 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 {
+ void operator () (T& out,const T& a, const T& b, ai_real d) const {
out = a + (b-a)*d;
}
}; // ! Interpolator <T>
@@ -511,7 +518,7 @@ struct Interpolator
template <>
struct Interpolator <aiQuaternion> {
void operator () (aiQuaternion& out,const aiQuaternion& a,
- const aiQuaternion& b, float d) const
+ const aiQuaternion& b, ai_real d) const
{
aiQuaternion::Interpolate(out,a,b,d);
}
@@ -520,16 +527,16 @@ struct Interpolator <aiQuaternion> {
template <>
struct Interpolator <unsigned int> {
void operator () (unsigned int& out,unsigned int a,
- unsigned int b, float d) const
+ unsigned int b, ai_real d) const
{
out = d>0.5f ? b : a;
}
}; // ! Interpolator <aiQuaternion>
template <>
-struct Interpolator <aiVectorKey> {
+struct Interpolator<aiVectorKey> {
void operator () (aiVector3D& out,const aiVectorKey& a,
- const aiVectorKey& b, float d) const
+ const aiVectorKey& b, ai_real d) const
{
Interpolator<aiVector3D> ipl;
ipl(out,a.mValue,b.mValue,d);
@@ -537,9 +544,9 @@ struct Interpolator <aiVectorKey> {
}; // ! Interpolator <aiVectorKey>
template <>
-struct Interpolator <aiQuatKey> {
+struct Interpolator<aiQuatKey> {
void operator () (aiQuaternion& out, const aiQuatKey& a,
- const aiQuatKey& b, float d) const
+ const aiQuatKey& b, ai_real d) const
{
Interpolator<aiQuaternion> ipl;
ipl(out,a.mValue,b.mValue,d);
@@ -547,9 +554,9 @@ struct Interpolator <aiQuatKey> {
}; // ! Interpolator <aiQuatKey>
template <>
-struct Interpolator <aiMeshKey> {
+struct Interpolator<aiMeshKey> {
void operator () (unsigned int& out, const aiMeshKey& a,
- const aiMeshKey& b, float d) const
+ const aiMeshKey& b, ai_real d) const
{
Interpolator<unsigned int> ipl;
ipl(out,a.mValue,b.mValue,d);
@@ -557,9 +564,9 @@ struct Interpolator <aiMeshKey> {
}; // ! Interpolator <aiQuatKey>
//! @endcond
-} // ! end namespace Assimp
-
+} // ! end namespace Assimp
#endif // __cplusplus
+
#endif // AI_ANIM_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/camera.h b/src/3rdparty/assimp/include/assimp/camera.h
index 37f1bdaa0..7b7bd0922 100644
--- a/src/3rdparty/assimp/include/assimp/camera.h
+++ b/src/3rdparty/assimp/include/assimp/camera.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -43,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Defines the aiCamera data structure
*/
+#pragma once
#ifndef AI_CAMERA_H_INC
#define AI_CAMERA_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/cexport.h b/src/3rdparty/assimp/include/assimp/cexport.h
index 71cb1f8ec..44b06fb3c 100644
--- a/src/3rdparty/assimp/include/assimp/cexport.h
+++ b/src/3rdparty/assimp/include/assimp/cexport.h
@@ -42,12 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file cexport.h
* @brief Defines the C-API for the Assimp export interface
*/
+#pragma once
#ifndef AI_EXPORT_H_INC
#define AI_EXPORT_H_INC
#ifndef ASSIMP_BUILD_NO_EXPORT
-#include "types.h"
+// Public ASSIMP data structures
+#include <assimp/types.h>
#ifdef __cplusplus
extern "C" {
@@ -86,7 +88,7 @@ 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. The description must be released by
+ * 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()
@@ -95,7 +97,7 @@ ASSIMP_API size_t aiGetExportFormatCount(void);
ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex);
// --------------------------------------------------------------------------------
-/** Release a description of the nth export file format. Must be returned by
+/** Release a description of the nth export file format. Must be returned by
* aiGetExportFormatDescription
* @param desc Pointer to the description
*/
@@ -259,4 +261,3 @@ ASSIMP_API void aiReleaseExportBlob( const C_STRUCT aiExportDataBlob* pData );
#endif // ASSIMP_BUILD_NO_EXPORT
#endif // AI_EXPORT_H_INC
-
diff --git a/src/3rdparty/assimp/include/assimp/cfileio.h b/src/3rdparty/assimp/include/assimp/cfileio.h
index d91974b78..63eeb59b0 100644
--- a/src/3rdparty/assimp/include/assimp/cfileio.h
+++ b/src/3rdparty/assimp/include/assimp/cfileio.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,10 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file cfileio.h
* @brief Defines generic C routines to access memory-mapped files
*/
+#pragma once
#ifndef AI_FILEIO_H_INC
#define AI_FILEIO_H_INC
-#include "types.h"
+#include <assimp/types.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -53,15 +55,15 @@ struct aiFileIO;
struct aiFile;
// aiFile callbacks
-typedef size_t (*aiFileWriteProc) (C_STRUCT aiFile*, const char*, size_t, size_t);
-typedef size_t (*aiFileReadProc) (C_STRUCT aiFile*, char*, size_t,size_t);
-typedef size_t (*aiFileTellProc) (C_STRUCT aiFile*);
-typedef void (*aiFileFlushProc) (C_STRUCT aiFile*);
-typedef aiReturn (*aiFileSeek)(C_STRUCT aiFile*, size_t, aiOrigin);
+typedef size_t (*aiFileWriteProc) (C_STRUCT aiFile*, const char*, size_t, size_t);
+typedef size_t (*aiFileReadProc) (C_STRUCT aiFile*, char*, size_t,size_t);
+typedef size_t (*aiFileTellProc) (C_STRUCT aiFile*);
+typedef void (*aiFileFlushProc) (C_STRUCT aiFile*);
+typedef C_ENUM aiReturn (*aiFileSeek) (C_STRUCT aiFile*, size_t, C_ENUM aiOrigin);
// aiFileIO callbacks
-typedef aiFile* (*aiFileOpenProc) (C_STRUCT aiFileIO*, const char*, const char*);
-typedef void (*aiFileCloseProc) (C_STRUCT aiFileIO*, C_STRUCT aiFile*);
+typedef C_STRUCT aiFile* (*aiFileOpenProc) (C_STRUCT aiFileIO*, const char*, const char*);
+typedef void (*aiFileCloseProc) (C_STRUCT aiFileIO*, C_STRUCT aiFile*);
// Represents user-defined data
typedef char* aiUserData;
diff --git a/src/3rdparty/assimp/include/assimp/cimport.h b/src/3rdparty/assimp/include/assimp/cimport.h
index de0cbae30..8aa125c67 100644
--- a/src/3rdparty/assimp/include/assimp/cimport.h
+++ b/src/3rdparty/assimp/include/assimp/cimport.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,9 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file cimport.h
* @brief Defines the C-API to the Open Asset Import Library.
*/
+#pragma once
#ifndef AI_ASSIMP_H_INC
#define AI_ASSIMP_H_INC
-#include "types.h"
+
+#include <assimp/types.h>
#include "importerdesc.h"
#ifdef __cplusplus
@@ -334,7 +337,7 @@ ASSIMP_API void aiReleaseImport(
* import process. NULL if there was no error. There can't be an error if you
* got a non-NULL #aiScene from #aiImportFile/#aiImportFileEx/#aiApplyPostProcessing.
*/
-ASSIMP_API const char* aiGetErrorString();
+ASSIMP_API const char* aiGetErrorString(void);
// --------------------------------------------------------------------------------
/** Returns whether a given file extension is supported by ASSIMP
@@ -414,7 +417,7 @@ ASSIMP_API void aiSetImportPropertyInteger(
ASSIMP_API void aiSetImportPropertyFloat(
C_STRUCT aiPropertyStore* store,
const char* szName,
- float value);
+ ai_real value);
// --------------------------------------------------------------------------------
/** Set a string property.
diff --git a/src/3rdparty/assimp/include/assimp/color4.h b/src/3rdparty/assimp/include/assimp/color4.h
index 6bcab45df..48e7aad30 100644
--- a/src/3rdparty/assimp/include/assimp/color4.h
+++ b/src/3rdparty/assimp/include/assimp/color4.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -41,10 +42,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file color4.h
* @brief RGBA color structure, including operators when compiling in C++
*/
+#pragma once
#ifndef AI_COLOR4D_H_INC
#define AI_COLOR4D_H_INC
-#include "./Compiler/pushpack1.h"
+#include "defs.h"
#ifdef __cplusplus
@@ -87,18 +89,16 @@ public:
// Red, green, blue and alpha color values
TReal r, g, b, a;
-} PACK_STRUCT; // !struct aiColor4D
+}; // !struct aiColor4D
-typedef aiColor4t<float> aiColor4D;
+typedef aiColor4t<ai_real> aiColor4D;
#else
struct aiColor4D {
- float r, g, b, a;
-} PACK_STRUCT;
+ ai_real r, g, b, a;
+};
#endif // __cplusplus
-#include "./Compiler/poppack1.h"
-
#endif // AI_COLOR4D_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/color4.inl b/src/3rdparty/assimp/include/assimp/color4.inl
index d69814714..b242c4e77 100644
--- a/src/3rdparty/assimp/include/assimp/color4.inl
+++ b/src/3rdparty/assimp/include/assimp/color4.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file color4.inl
* @brief Inline implementation of aiColor4t<TReal> operators
*/
+#pragma once
#ifndef AI_COLOR4D_INL_INC
#define AI_COLOR4D_INL_INC
@@ -75,12 +77,32 @@ AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f)
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
- return *(&r + i);
+ switch ( i ) {
+ case 0:
+ return r;
+ case 1:
+ return g;
+ case 2:
+ return b;
+ default:
+ break;
+ }
+ return r;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
- return *(&r + i);
+ switch ( i ) {
+ case 0:
+ return r;
+ case 1:
+ return g;
+ case 2:
+ return b;
+ default:
+ break;
+ }
+ return r;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
diff --git a/src/3rdparty/assimp/include/assimp/config.h b/src/3rdparty/assimp/include/assimp/config.h
index 3db8a5697..f881c56b4 100644
--- a/src/3rdparty/assimp/include/assimp/config.h
+++ b/src/3rdparty/assimp/include/assimp/config.h
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
All rights reserved.
@@ -55,8 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* #aiSetImportPropertyFloat,
* #aiSetImportPropertyString
*/
-#ifndef INCLUDED_AI_CONFIG_H
-#define INCLUDED_AI_CONFIG_H
+#ifndef AI_CONFIG_H_INC
+#define AI_CONFIG_H_INC
// ###########################################################################
@@ -266,6 +266,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"PP_FD_REMOVE"
// ---------------------------------------------------------------------------
+/**
+ * @brief Configures the #aiProcess_FindDegenerates to check the area of a
+ * trinagle to be greates than e-6. If this is not the case the triangle will
+ * be removed if #AI_CONFIG_PP_FD_REMOVE is set to true.
+ */
+#define AI_CONFIG_PP_FD_CHECKAREA \
+ "PP_FD_CHECKAREA"
+
+// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
* matching a name in a given list.
*
@@ -322,7 +331,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @brief Set the maximum number of bones affecting a single vertex
*
* This is used by the #aiProcess_LimitBoneWeights PostProcess-Step.
- * @note The default value is AI_LBW_MAX_WEIGHTS
+ * @note The default value is AI_LMW_MAX_WEIGHTS
* Property type: integer.*/
#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
"PP_LBW_MAX_WEIGHTS"
@@ -634,6 +643,15 @@ enum aiComponent
// ---------------------------------------------------------------------------
+/** @brief Set whether the fbx importer will search for embedded loaded textures, where no embedded texture data is provided.
+*
+* The default value is false (0)
+* Property type: bool
+*/
+#define AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES \
+ "IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES"
+
+// ---------------------------------------------------------------------------
/** @brief Set the vertex animation keyframe to be imported
*
* ASSIMP does not support vertex keyframes (only bone animation is supported).
@@ -843,14 +861,6 @@ enum aiComponent
#define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \
"IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
-/** @brief Specifies whether the IFC loader skips over IfcSpace elements.
- *
- * IfcSpace elements (and their geometric representations) are used to
- * represent, well, free space in a building storey.<br>
- * Property type: Bool. Default value: true.
- */
-#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
@@ -859,17 +869,14 @@ enum aiComponent
*/
#define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT"
-
// ---------------------------------------------------------------------------
-/** @brief Specifies whether the IFC loader skips over
- * shape representations of type 'Curve2D'.
+/** @brief Specifies whether the IFC loader skips over IfcSpace elements.
*
- * A lot of files contain both a faceted mesh representation and a outline
- * with a presentation type of 'Curve2D'. Currently Assimp doesn't convert those,
- * so turning this option off just clutters the log with errors.<br>
+ * IfcSpace elements (and their geometric representations) are used to
+ * represent, well, free space in a building storey.<br>
* Property type: Bool. Default value: true.
*/
-#define AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS "IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS"
+#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS"
// ---------------------------------------------------------------------------
/** @brief Specifies whether the IFC loader will use its own, custom triangulation
@@ -887,6 +894,38 @@ enum aiComponent
#define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
// ---------------------------------------------------------------------------
+/** @brief Set the tessellation conic angle for IFC smoothing curves.
+ *
+ * This is used by the IFC importer to determine the tessellation parameter
+ * for smoothing curves.
+ * @note The default value is AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE and the
+ * accepted values are in range [5.0, 120.0].
+ * Property type: Float.
+ */
+#define AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE "IMPORT_IFC_SMOOTHING_ANGLE"
+
+// default value for AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE
+#if (!defined AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE)
+# define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f
+#endif
+
+// ---------------------------------------------------------------------------
+/** @brief Set the tessellation for IFC cylindrical shapes.
+ *
+ * This is used by the IFC importer to determine the tessellation parameter
+ * for cylindrical shapes, i.e. the number of segments used to approximate a circle.
+ * @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the
+ * accepted values are in range [3, 180].
+ * Property type: Integer.
+ */
+#define AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION "IMPORT_IFC_CYLINDRICAL_TESSELLATION"
+
+// default value for AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION
+#if (!defined AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION)
+# define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32
+#endif
+
+// ---------------------------------------------------------------------------
/** @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
@@ -904,4 +943,22 @@ enum aiComponent
#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
+/**
+ * @brief Specifies a gobal key factor for scale, float value
+ */
+#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR"
+
+#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
+# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
+#endif // !! AI_DEBONE_THRESHOLD
+
+// ---------- All the Build/Compile-time defines ------------
+
+/** @brief Specifies if double precision is supported inside assimp
+ *
+ * Property type: Bool. Default value: undefined.
+ */
+
+//#cmakedefine ASSIMP_DOUBLE_PRECISION 1
+
#endif // !! AI_CONFIG_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/defs.h b/src/3rdparty/assimp/include/assimp/defs.h
index 2c9749357..20b234f90 100644
--- a/src/3rdparty/assimp/include/assimp/defs.h
+++ b/src/3rdparty/assimp/include/assimp/defs.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -44,8 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* blocks to find out how to customize _your_ Assimp build.
*/
-#ifndef INCLUDED_AI_DEFINES_H
-#define INCLUDED_AI_DEFINES_H
+#pragma once
+#ifndef AI_DEFINES_H_INC
+#define AI_DEFINES_H_INC
+
+#include <assimp/config.h>
//////////////////////////////////////////////////////////////////////////
/* Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific
@@ -209,7 +213,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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
@@ -228,6 +232,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
//////////////////////////////////////////////////////////////////////////
+ /* Define ASSIMP_DOUBLE_PRECISION to compile assimp
+ * with double precision support (64-bit). */
+ //////////////////////////////////////////////////////////////////////////
+
+#ifdef ASSIMP_DOUBLE_PRECISION
+ typedef double ai_real;
+ typedef signed long long int ai_int;
+ typedef unsigned long long int ai_uint;
+#else // ASSIMP_DOUBLE_PRECISION
+ typedef float ai_real;
+ typedef signed int ai_int;
+ typedef unsigned int ai_uint;
+#endif // ASSIMP_DOUBLE_PRECISION
+
+ //////////////////////////////////////////////////////////////////////////
/* Useful constants */
//////////////////////////////////////////////////////////////////////////
@@ -242,8 +261,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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)*(ai_real)0.0174532925)
+#define AI_RAD_TO_DEG(x) ((x)*(ai_real)57.2957795)
/* Support for big-endian builds */
#if defined(__BYTE_ORDER__)
@@ -268,5 +287,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type))
-
-#endif // !! INCLUDED_AI_DEFINES_H
+#endif // !! AI_DEFINES_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/importerdesc.h b/src/3rdparty/assimp/include/assimp/importerdesc.h
index b2b123aca..6b83b8aa2 100644
--- a/src/3rdparty/assimp/include/assimp/importerdesc.h
+++ b/src/3rdparty/assimp/include/assimp/importerdesc.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file importerdesc.h
* @brief #aiImporterFlags, aiImporterDesc implementation.
*/
-#ifndef INCLUDED_AI_IMPORTER_DESC_H
-#define INCLUDED_AI_IMPORTER_DESC_H
+#pragma once
+#ifndef AI_IMPORTER_DESC_H_INC
+#define AI_IMPORTER_DESC_H_INC
/** Mixed set of flags for #aiImporterDesc, indicating some features
@@ -140,4 +142,4 @@ Will return a NULL-pointer if no assigned importer desc. was found for the given
*/
ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImporterDesc( const char *extension );
-#endif
+#endif // AI_IMPORTER_DESC_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/light.h b/src/3rdparty/assimp/include/assimp/light.h
index 939d5b6cd..324339a97 100644
--- a/src/3rdparty/assimp/include/assimp/light.h
+++ b/src/3rdparty/assimp/include/assimp/light.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -43,8 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Defines the aiLight data structure
*/
-#ifndef __AI_LIGHT_H_INC__
-#define __AI_LIGHT_H_INC__
+#pragma once
+#ifndef AI_LIGHT_H_INC
+#define AI_LIGHT_H_INC
#include "types.h"
@@ -250,7 +252,7 @@ struct aiLight
#ifdef __cplusplus
}
-#endif
+#endif
-#endif // !! __AI_LIGHT_H_INC__
+#endif // !! AI_LIGHT_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/material.h b/src/3rdparty/assimp/include/assimp/material.h
index 87d27c569..a12e7d076 100644
--- a/src/3rdparty/assimp/include/assimp/material.h
+++ b/src/3rdparty/assimp/include/assimp/material.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file material.h
* @brief Defines the material system of the library
*/
-
+#pragma once
#ifndef AI_MATERIAL_H_INC
#define AI_MATERIAL_H_INC
@@ -413,7 +414,7 @@ enum aiTextureFlags
* 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
+ * position and SourceColor is the material color before the transparency
* calculation.<br>
* This corresponds to the #AI_MATKEY_BLEND_FUNC property.
*/
@@ -477,13 +478,14 @@ struct aiUVTransform
* rotation center is 0.5f|0.5f. The default value
* 0.f.
*/
- float mRotation;
+ ai_real mRotation;
#ifdef __cplusplus
aiUVTransform()
- : mScaling (1.f,1.f)
- , mRotation (0.f)
+ : mTranslation (0.0,0.0)
+ , mScaling (1.0,1.0)
+ , mRotation (0.0)
{
// nothing to be done here ...
}
@@ -508,6 +510,14 @@ enum aiPropertyTypeInfo
*/
aiPTI_Float = 0x1,
+ /** Array of double-precision (64 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.
+ */
+ aiPTI_Double = 0x2,
+
/** The material property is an aiString.
*
* Arrays of strings aren't possible, aiGetMaterialString() (or the
@@ -660,7 +670,7 @@ public:
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;
+ unsigned int idx, ai_real* pOut, unsigned int* pMax) const;
// -------------------------------------------------------------------
/** @brief Retrieve a Type value with a specific key
@@ -681,7 +691,7 @@ public:
unsigned int idx, int& pOut) const;
aiReturn Get(const char* pKey,unsigned int type,
- unsigned int idx, float& pOut) const;
+ unsigned int idx, ai_real& pOut) const;
aiReturn Get(const char* pKey,unsigned int type,
unsigned int idx, aiString& pOut) const;
@@ -705,37 +715,40 @@ public:
// -------------------------------------------------------------------
/** 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)).
- */
+ *
+ * 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.
+ * If the texture is embedded, receives a '*' followed by the id of
+ * the texture (for the textures stored in the corresponding scene) which
+ * can be converted to an int using a function like atoi.
+ * 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,
+ ai_real* blend = NULL,
aiTextureOp* op = NULL,
aiTextureMapMode* mapmode = NULL) const;
@@ -817,6 +830,12 @@ public:
unsigned int type = 0,
unsigned int index = 0);
+ aiReturn AddProperty (const double* 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,
@@ -1311,9 +1330,9 @@ 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);
@@ -1348,7 +1367,7 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray(
const char* pKey,
unsigned int type,
unsigned int index,
- float* pOut,
+ ai_real* pOut,
unsigned int* pMax);
@@ -1377,7 +1396,7 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat,
const char* pKey,
unsigned int type,
unsigned int index,
- float* pOut)
+ ai_real* pOut)
{
return aiGetMaterialFloatArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
}
@@ -1414,7 +1433,7 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial*
inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
const char* pKey,
unsigned int type,
- unsigned int index,
+ unsigned int index,
int* pOut)
{
return aiGetMaterialIntegerArray(pMat,pKey,type,index,pOut,(unsigned int*)0x0);
@@ -1491,7 +1510,10 @@ ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMa
* #aiGetMaterialTextureCount() can be used to determine the number of
* textures in a particular texture stack.
* @param[out] path Receives the output path
- * This parameter must be non-null.
+ * If the texture is embedded, receives a '*' followed by the id of
+ * the texture (for the textures stored in the corresponding scene) which
+ * can be converted to an int using a function like atoi.
+ * This parameter must be non-null.
* @param mapping The texture mapping mode to be used.
* Pass NULL if you're not interested in this information.
* @param[out] uvindex For UV-mapped textures: receives the index of the UV
@@ -1516,7 +1538,7 @@ ASSIMP_API aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
aiString* path,
aiTextureMapping* mapping = NULL,
unsigned int* uvindex = NULL,
- float* blend = NULL,
+ ai_real* blend = NULL,
aiTextureOp* op = NULL,
aiTextureMapMode* mapmode = NULL,
unsigned int* flags = NULL);
@@ -1527,7 +1549,7 @@ C_ENUM aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
C_STRUCT aiString* path,
C_ENUM aiTextureMapping* mapping /*= NULL*/,
unsigned int* uvindex /*= NULL*/,
- float* blend /*= NULL*/,
+ ai_real* blend /*= NULL*/,
C_ENUM aiTextureOp* op /*= NULL*/,
C_ENUM aiTextureMapMode* mapmode /*= NULL*/,
unsigned int* flags /*= NULL*/);
diff --git a/src/3rdparty/assimp/include/assimp/material.inl b/src/3rdparty/assimp/include/assimp/material.inl
index 994e608b4..2c31fd571 100644
--- a/src/3rdparty/assimp/include/assimp/material.inl
+++ b/src/3rdparty/assimp/include/assimp/material.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -43,9 +44,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Defines the C++ getters for the material system
*/
+#pragma once
#ifndef AI_MATERIAL_INL_INC
#define AI_MATERIAL_INL_INC
+// ---------------------------------------------------------------------------
+inline aiPropertyTypeInfo ai_real_to_property_type_info(float)
+{
+ return aiPTI_Float;
+}
+
+inline aiPropertyTypeInfo ai_real_to_property_type_info(double)
+{
+ return aiPTI_Double;
+}
+// ---------------------------------------------------------------------------
+
//! @cond never
// ---------------------------------------------------------------------------
@@ -54,7 +68,7 @@ inline aiReturn aiMaterial::GetTexture( aiTextureType type,
C_STRUCT aiString* path,
aiTextureMapping* mapping /*= NULL*/,
unsigned int* uvindex /*= NULL*/,
- float* blend /*= NULL*/,
+ ai_real* blend /*= NULL*/,
aiTextureOp* op /*= NULL*/,
aiTextureMapMode* mapmode /*= NULL*/) const
{
@@ -122,7 +136,7 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,float* pOut,
+ unsigned int idx,ai_real* pOut,
unsigned int* pMax) const
{
return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
@@ -136,7 +150,7 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
}
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
- unsigned int idx,float& pOut) const
+ unsigned int idx,ai_real& pOut) const
{
return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
}
@@ -201,6 +215,18 @@ inline aiReturn aiMaterial::AddProperty(const float* pInput,
}
// ---------------------------------------------------------------------------
+inline aiReturn aiMaterial::AddProperty(const double* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(double),
+ pKey,type,index,aiPTI_Double);
+}
+
+// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
const unsigned int pNumValues,
const char* pKey,
@@ -209,7 +235,7 @@ inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
{
return AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiUVTransform),
- pKey,type,index,aiPTI_Float);
+ pKey,type,index,ai_real_to_property_type_info(pInput->mRotation));
}
// ---------------------------------------------------------------------------
@@ -221,7 +247,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
{
return AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiColor4D),
- pKey,type,index,aiPTI_Float);
+ pKey,type,index,ai_real_to_property_type_info(pInput->a));
}
// ---------------------------------------------------------------------------
@@ -233,7 +259,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
{
return AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiColor3D),
- pKey,type,index,aiPTI_Float);
+ pKey,type,index,ai_real_to_property_type_info(pInput->b));
}
// ---------------------------------------------------------------------------
@@ -245,7 +271,7 @@ inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
{
return AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiVector3D),
- pKey,type,index,aiPTI_Float);
+ pKey,type,index,ai_real_to_property_type_info(pInput->x));
}
// ---------------------------------------------------------------------------
@@ -282,6 +308,19 @@ inline aiReturn aiMaterial::AddProperty<float>(const float* pInput,
// ---------------------------------------------------------------------------
template<>
+inline aiReturn aiMaterial::AddProperty<double>(const double* pInput,
+ const unsigned int pNumValues,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index)
+{
+ return AddBinaryProperty((const void*)pInput,
+ pNumValues * sizeof(double),
+ pKey,type,index,aiPTI_Double);
+}
+
+// ---------------------------------------------------------------------------
+template<>
inline aiReturn aiMaterial::AddProperty<aiUVTransform>(const aiUVTransform* pInput,
const unsigned int pNumValues,
const char* pKey,
diff --git a/src/3rdparty/assimp/include/assimp/matrix3x3.h b/src/3rdparty/assimp/include/assimp/matrix3x3.h
index 725b1c34c..3cf575e38 100644
--- a/src/3rdparty/assimp/include/assimp/matrix3x3.h
+++ b/src/3rdparty/assimp/include/assimp/matrix3x3.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,10 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file matrix3x3.h
* @brief Definition of a 3x3 matrix, including operators when compiling in C++
*/
-#ifndef AI_MATRIX3x3_H_INC
-#define AI_MATRIX3x3_H_INC
+#pragma once
+#ifndef AI_MATRIX3X3_H_INC
+#define AI_MATRIX3X3_H_INC
-#include "./Compiler/pushpack1.h"
+#include "defs.h"
#ifdef __cplusplus
@@ -151,8 +153,8 @@ public:
/** @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
+ * Output: mtx[3][3] -- a 3x3 matrix in column-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
*/
@@ -163,20 +165,18 @@ public:
TReal a1, a2, a3;
TReal b1, b2, b3;
TReal c1, c2, c3;
-} PACK_STRUCT;
+};
-typedef aiMatrix3x3t<float> aiMatrix3x3;
+typedef aiMatrix3x3t<ai_real> aiMatrix3x3;
#else
struct aiMatrix3x3 {
- float a1, a2, a3;
- float b1, b2, b3;
- float c1, c2, c3;
-} PACK_STRUCT;
+ ai_real a1, a2, a3;
+ ai_real b1, b2, b3;
+ ai_real c1, c2, c3;
+};
#endif // __cplusplus
-#include "./Compiler/poppack1.h"
-
-#endif // AI_MATRIX3x3_H_INC
+#endif // AI_MATRIX3X3_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/matrix3x3.inl b/src/3rdparty/assimp/include/assimp/matrix3x3.inl
index 9ace3f97b..14f2cd2fc 100644
--- a/src/3rdparty/assimp/include/assimp/matrix3x3.inl
+++ b/src/3rdparty/assimp/include/assimp/matrix3x3.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file matrix3x3.inl
* @brief Inline implementation of the 3x3 matrix operators
*/
-#ifndef AI_MATRIX3x3_INL_INC
-#define AI_MATRIX3x3_INL_INC
+#pragma once
+#ifndef AI_MATRIX3X3_INL_INC
+#define AI_MATRIX3X3_INL_INC
#ifdef __cplusplus
#include "matrix3x3.h"
@@ -100,16 +102,34 @@ inline aiMatrix3x3t<TReal> aiMatrix3x3t<TReal>::operator* (const aiMatrix3x3t<TR
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-inline TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex)
-{
- return &this->a1 + p_iIndex * 3;
+inline TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) {
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ default:
+ break;
+ }
+ return &a1;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
-inline const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const
-{
- return &this->a1 + p_iIndex * 3;
+inline const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const {
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ default:
+ break;
+ }
+ return &a1;
}
// ------------------------------------------------------------------------------------------------
@@ -241,7 +261,7 @@ 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
*/
@@ -333,4 +353,4 @@ inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::FromToMatrix(const aiVector3t<T
#endif // __cplusplus
-#endif // AI_MATRIX3x3_INL_INC
+#endif // AI_MATRIX3X3_INL_INC
diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.h b/src/3rdparty/assimp/include/assimp/matrix4x4.h
index fc77b6964..4311fa118 100644
--- a/src/3rdparty/assimp/include/assimp/matrix4x4.h
+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -41,11 +42,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file matrix4x4.h
* @brief 4x4 matrix structure, including operators when compiling in C++
*/
+#pragma once
#ifndef AI_MATRIX4X4_H_INC
#define AI_MATRIX4X4_H_INC
#include "vector3.h"
-#include "./Compiler/pushpack1.h"
+#include "defs.h"
#ifdef __cplusplus
@@ -91,7 +93,15 @@ public:
public:
// array access operators
+ /** @fn TReal* operator[] (unsigned int p_iIndex)
+ * @param [in] p_iIndex - index of the row.
+ * @return pointer to pointed row.
+ */
TReal* operator[] (unsigned int p_iIndex);
+
+ /** @fn const TReal* operator[] (unsigned int p_iIndex) const
+ * @overload TReal* operator[] (unsigned int p_iIndex)
+ */
const TReal* operator[] (unsigned int p_iIndex) const;
// comparison operators
@@ -103,6 +113,8 @@ public:
// matrix multiplication.
aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);
aiMatrix4x4t operator * (const aiMatrix4x4t& m) const;
+ aiMatrix4x4t operator * (const TReal& aFloat) const;
+ aiMatrix4x4t operator + (const aiMatrix4x4t& aMatrix) const;
template <typename TOther>
operator aiMatrix4x4t<TOther> () const;
@@ -138,6 +150,27 @@ public:
void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
aiVector3t<TReal>& position) const;
+ // -------------------------------------------------------------------
+ /** @fn void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const
+ * @brief Decompose a trafo matrix into its original components.
+ * Thx to good FAQ at http://www.gamedev.ru/code/articles/faq_matrix_quat
+ * @param [out] pScaling - Receives the output scaling for the x,y,z axes.
+ * @param [out] pRotation - Receives the output rotation as a Euler angles.
+ * @param [out] pPosition - Receives the output position for the x,y,z axes.
+ */
+ void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const;
+
+ // -------------------------------------------------------------------
+ /** @fn void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle, aiVector3t<TReal>& pPosition) const
+ * @brief Decompose a trafo matrix into its original components
+ * Thx to good FAQ at http://www.gamedev.ru/code/articles/faq_matrix_quat
+ * @param [out] pScaling - Receives the output scaling for the x,y,z axes.
+ * @param [out] pRotationAxis - Receives the output rotation axis.
+ * @param [out] pRotationAngle - Receives the output rotation angle for @ref pRotationAxis.
+ * @param [out] pPosition - Receives the output position for the x,y,z axes.
+ */
+ void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle, aiVector3t<TReal>& pPosition) const;
+
// -------------------------------------------------------------------
/** @brief Decompose a trafo matrix with no scaling into its
* original components
@@ -191,7 +224,7 @@ public:
* @return Reference to the output matrix
*/
static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
- aiMatrix4x4t& out);
+ aiMatrix4x4t& out);
// -------------------------------------------------------------------
/** @brief Returns a translation matrix
@@ -199,7 +232,8 @@ public:
* @param out Receives the output matrix
* @return Reference to the output matrix
*/
- static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
+ static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v,
+ aiMatrix4x4t& out);
// -------------------------------------------------------------------
/** @brief Returns a scaling matrix
@@ -219,29 +253,27 @@ public:
* Journal of Graphics Tools, 4(4):1-4, 1999
*/
static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
- const aiVector3t<TReal>& to, aiMatrix4x4t& out);
+ 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;
+};
-typedef aiMatrix4x4t<float> aiMatrix4x4;
+typedef aiMatrix4x4t<ai_real> aiMatrix4x4;
#else
struct aiMatrix4x4 {
- float a1, a2, a3, a4;
- float b1, b2, b3, b4;
- float c1, c2, c3, c4;
- float d1, d2, d3, d4;
-} PACK_STRUCT;
+ ai_real a1, a2, a3, a4;
+ ai_real b1, b2, b3, b4;
+ ai_real c1, c2, c3, c4;
+ ai_real d1, d2, d3, d4;
+};
#endif // __cplusplus
-#include "./Compiler/poppack1.h"
-
#endif // AI_MATRIX4X4_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.inl b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
index 9ce794f0a..b15d50a09 100644
--- a/src/3rdparty/assimp/include/assimp/matrix4x4.inl
+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file matrix4x4.inl
* @brief Inline implementation of the 4x4 matrix operators
*/
-#ifndef AI_MATRIX4x4_INL_INC
-#define AI_MATRIX4x4_INL_INC
+#pragma once
+#ifndef AI_MATRIX4X4_INL_INC
+#define AI_MATRIX4X4_INL_INC
#ifdef __cplusplus
@@ -156,6 +158,54 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::operator *= (const aiMatrix4x4t
// ----------------------------------------------------------------------------------------
template <typename TReal>
+inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const TReal& aFloat) const
+{
+ aiMatrix4x4t<TReal> temp(
+ a1 * aFloat,
+ a2 * aFloat,
+ a3 * aFloat,
+ a4 * aFloat,
+ b1 * aFloat,
+ b2 * aFloat,
+ b3 * aFloat,
+ b4 * aFloat,
+ c1 * aFloat,
+ c2 * aFloat,
+ c3 * aFloat,
+ c4 * aFloat,
+ d1 * aFloat,
+ d2 * aFloat,
+ d3 * aFloat,
+ d4 * aFloat);
+ return temp;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator+ (const aiMatrix4x4t<TReal>& m) const
+{
+ aiMatrix4x4t<TReal> temp(
+ m.a1 + a1,
+ m.a2 + a2,
+ m.a3 + a3,
+ m.a4 + a4,
+ m.b1 + b1,
+ m.b2 + b2,
+ m.b3 + b3,
+ m.b4 + b4,
+ m.c1 + c1,
+ m.c2 + c2,
+ m.c3 + c3,
+ m.c4 + c4,
+ m.d1 + d1,
+ m.d2 + d2,
+ m.d3 + d3,
+ m.d4 + d4);
+ return temp;
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const aiMatrix4x4t<TReal>& m) const
{
aiMatrix4x4t<TReal> temp( *this);
@@ -242,9 +292,19 @@ 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;
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ case 3:
+ return &d1;
+ default:
+ break;
+ }
+ return &a1;
}
// ----------------------------------------------------------------------------------------
@@ -254,8 +314,19 @@ inline const TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) const
return NULL;
}
- // XXX same
- return &this->a1 + p_iIndex * 4;
+ switch ( p_iIndex ) {
+ case 0:
+ return &a1;
+ case 1:
+ return &b1;
+ case 2:
+ return &c1;
+ case 3:
+ return &d1;
+ default:
+ break;
+ }
+ return &a1;
}
// ----------------------------------------------------------------------------------------
@@ -298,57 +369,126 @@ inline bool aiMatrix4x4t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsil
}
// ----------------------------------------------------------------------------------------
-template <typename TReal>
-inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
- 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];
+#define ASSIMP_MATRIX4_4_DECOMPOSE_PART \
+ const aiMatrix4x4t<TReal>& _this = *this;/* Create alias for conveniance. */ \
+ \
+ /* extract translation */ \
+ pPosition.x = _this[0][3]; \
+ pPosition.y = _this[1][3]; \
+ pPosition.z = _this[2][3]; \
+ \
+ /* extract the columns of the matrix. */ \
+ aiVector3t<TReal> vCols[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 */ \
+ pScaling.x = vCols[0].Length(); \
+ pScaling.y = vCols[1].Length(); \
+ pScaling.z = vCols[2].Length(); \
+ \
+ /* and the sign of the scaling */ \
+ if (Determinant() < 0) pScaling = -pScaling; \
+ \
+ /* and remove all scaling from the matrix */ \
+ if(pScaling.x) vCols[0] /= pScaling.x; \
+ if(pScaling.y) vCols[1] /= pScaling.y; \
+ if(pScaling.z) vCols[2] /= pScaling.z; \
+ \
+ do {} while(false)
+
- // 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;
- }
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& pScaling, aiQuaterniont<TReal>& pRotation,
+ aiVector3t<TReal>& pPosition) const
+{
+ ASSIMP_MATRIX4_4_DECOMPOSE_PART;
// 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);
+ aiMatrix3x3t<TReal> m(vCols[0].x,vCols[1].x,vCols[2].x,
+ vCols[0].y,vCols[1].y,vCols[2].y,
+ vCols[0].z,vCols[1].z,vCols[2].z);
// and generate the rotation quaternion from it
- rotation = aiQuaterniont<TReal>(m);
+ pRotation = aiQuaterniont<TReal>(m);
+}
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const
+{
+ ASSIMP_MATRIX4_4_DECOMPOSE_PART;
+
+ /*
+ | CE -CF D 0 |
+ M = | BDE+AF -BDF+AE -BC 0 |
+ | -ADE+BF -ADF+BE AC 0 |
+ | 0 0 0 1 |
+
+ A = cos(angle_x), B = sin(angle_x);
+ C = cos(angle_y), D = sin(angle_y);
+ E = cos(angle_z), F = sin(angle_z);
+ */
+
+ // Use a small epsilon to solve floating-point inaccuracies
+ const TReal epsilon = 10e-3f;
+
+ pRotation.y = std::asin(vCols[2].x);// D. Angle around oY.
+
+ TReal C = std::cos(pRotation.y);
+
+ if(std::fabs(C) > epsilon)
+ {
+ // Finding angle around oX.
+ TReal tan_x = vCols[2].z / C;// A
+ TReal tan_y = -vCols[2].y / C;// B
+
+ pRotation.x = std::atan2(tan_y, tan_x);
+ // Finding angle around oZ.
+ tan_x = vCols[0].x / C;// E
+ tan_y = -vCols[1].x / C;// F
+ pRotation.z = std::atan2(tan_y, tan_x);
+ }
+ else
+ {// oY is fixed.
+ pRotation.x = 0;// Set angle around oX to 0. => A == 1, B == 0, C == 0, D == 1.
+
+ // And finding angle around oZ.
+ TReal tan_x = vCols[1].y;// -BDF+AE => E
+ TReal tan_y = vCols[0].y;// BDE+AF => F
+
+ pRotation.z = std::atan2(tan_y, tan_x);
+ }
+}
+
+#undef ASSIMP_MATRIX4_4_DECOMPOSE_PART
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle,
+ aiVector3t<TReal>& pPosition) const
+{
+aiQuaterniont<TReal> pRotation;
+
+ Decompose(pScaling, pRotation, pPosition);
+ pRotation.Normalize();
+
+ TReal angle_cos = pRotation.w;
+ TReal angle_sin = std::sqrt(1.0f - angle_cos * angle_cos);
+
+ pRotationAngle = std::acos(angle_cos) * 2;
+
+ // Use a small epsilon to solve floating-point inaccuracies
+ const TReal epsilon = 10e-3f;
+
+ if(std::fabs(angle_sin) < epsilon) angle_sin = 1;
+
+ pRotationAxis.x = pRotation.x / angle_sin;
+ pRotationAxis.y = pRotation.y / angle_sin;
+ pRotationAxis.z = pRotation.z / angle_sin;
}
// ----------------------------------------------------------------------------------------
@@ -522,7 +662,7 @@ 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
*/
@@ -538,4 +678,4 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromToMatrix(const aiVector3t<T
}
#endif // __cplusplus
-#endif // AI_MATRIX4x4_INL_INC
+#endif // AI_MATRIX4X4_INL_INC
diff --git a/src/3rdparty/assimp/include/assimp/mesh.h b/src/3rdparty/assimp/include/assimp/mesh.h
index 5fd30bb02..c8648c778 100644
--- a/src/3rdparty/assimp/include/assimp/mesh.h
+++ b/src/3rdparty/assimp/include/assimp/mesh.h
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
All rights reserved.
@@ -43,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @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
-#define INCLUDED_AI_MESH_H
+#pragma once
+#ifndef AI_MESH_H_INC
+#define AI_MESH_H_INC
#include "types.h"
@@ -54,7 +55,7 @@ extern "C" {
// ---------------------------------------------------------------------------
// Limits. These values are required to match the settings Assimp was
-// compiled against. Therfore, do not redefine them unless you build the
+// compiled against. Therefore, do not redefine them unless you build the
// library from source using the same definitions.
// ---------------------------------------------------------------------------
@@ -376,8 +377,10 @@ struct aiAnimMesh
* from language bindings.
*/
unsigned int mNumVertices;
-
- /** Weight of the AnimMesh. */
+
+ /**
+ * Weight of the AnimMesh.
+ */
float mWeight;
#ifdef __cplusplus
@@ -388,6 +391,7 @@ struct aiAnimMesh
, mTangents( NULL )
, mBitangents( NULL )
, mNumVertices( 0 )
+ , mWeight( 0.0f )
{
// fixme consider moving this to the ctor initializer list as well
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
@@ -623,17 +627,20 @@ struct aiMesh
C_STRUCT aiString mName;
- /** NOT CURRENTLY IN USE. The number of attachment meshes */
+ /** The number of attachment meshes. Note! Currently only works with Collada loader. */
unsigned int mNumAnimMeshes;
- /** NOT CURRENTLY IN USE. Attachment meshes for this mesh, for vertex-based animation.
+ /** 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). */
+ * mesh'es vertex components (usually positions, normals).
+ * Note! Currently only works with Collada loader.*/
C_STRUCT aiAnimMesh** mAnimMeshes;
- /** Method of morphing when animeshes are specified. */
+ /**
+ * Method of morphing when animeshes are specified.
+ */
unsigned int mMethod;
-
+
#ifdef __cplusplus
//! Default constructor. Initializes all members to 0
@@ -651,6 +658,7 @@ struct aiMesh
, mMaterialIndex( 0 )
, mNumAnimMeshes( 0 )
, mAnimMeshes( NULL )
+ , mMethod( 0 )
{
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{
@@ -761,5 +769,5 @@ struct aiMesh
#ifdef __cplusplus
}
#endif //! extern "C"
-#endif // __AI_MESH_H_INC
+#endif // AI_MESH_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/metadata.h b/src/3rdparty/assimp/include/assimp/metadata.h
index 579ccd446..92db9b59a 100644
--- a/src/3rdparty/assimp/include/assimp/metadata.h
+++ b/src/3rdparty/assimp/include/assimp/metadata.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,41 +43,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file metadata.h
* @brief Defines the data structures for holding node meta information.
*/
-#ifndef __AI_METADATA_H_INC__
-#define __AI_METADATA_H_INC__
-
-#include <assert.h>
+#pragma once
+#ifndef AI_METADATA_H_INC
+#define AI_METADATA_H_INC
#if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "Compiler/pstdint.h"
+# include "Compiler/pstdint.h"
#else
-#include <limits.h>
-#include <stdint.h>
+# include <stdint.h>
#endif
-
-
// -------------------------------------------------------------------------------
/**
* Enum used to distinguish data types
*/
// -------------------------------------------------------------------------------
-typedef enum aiMetadataType
-{
- AI_BOOL = 0,
- AI_INT = 1,
- AI_UINT64 = 2,
- AI_FLOAT = 3,
- AI_AISTRING = 4,
- AI_AIVECTOR3D = 5,
+typedef enum aiMetadataType {
+ AI_BOOL = 0,
+ AI_INT32 = 1,
+ AI_UINT64 = 2,
+ AI_FLOAT = 3,
+ AI_DOUBLE = 4,
+ AI_AISTRING = 5,
+ AI_AIVECTOR3D = 6,
#ifndef SWIG
FORCE_32BIT = INT_MAX
#endif
} aiMetadataType;
-
-
// -------------------------------------------------------------------------------
/**
* Metadata entry
@@ -84,37 +79,30 @@ typedef enum aiMetadataType
* The type field uniquely identifies the underlying type of the data field
*/
// -------------------------------------------------------------------------------
-struct aiMetadataEntry
-{
+struct aiMetadataEntry {
aiMetadataType mType;
void* mData;
};
-
-
#ifdef __cplusplus
#include <string>
-
-
// -------------------------------------------------------------------------------
/**
* Helper functions to get the aiType enum entry for a type
*/
// -------------------------------------------------------------------------------
-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( const aiString & ) { return AI_AISTRING; }
-inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
-
-
-
-#endif
+inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
+inline aiMetadataType GetAiType( int32_t ) { return AI_INT32; }
+inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
+inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
+inline aiMetadataType GetAiType( double ) { return AI_DOUBLE; }
+inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; }
+inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
+#endif // __cplusplus
// -------------------------------------------------------------------------------
/**
@@ -123,8 +111,7 @@ inline aiMetadataType GetAiType( const 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;
@@ -137,33 +124,32 @@ struct aiMetadata
#ifdef __cplusplus
- /** Constructor */
+ /**
+ * @brief The default constructor, set all members to zero by default.
+ */
aiMetadata()
- // set all members to zero by default
- : mNumProperties(0)
- , mKeys(NULL)
- , mValues(NULL)
- {}
-
+ : mNumProperties(0)
+ , mKeys(NULL)
+ , mValues(NULL) {
+ // empty
+ }
- /** Destructor */
- ~aiMetadata()
- {
- delete[] mKeys;
+ /**
+ * @brief The destructor.
+ */
+ ~aiMetadata() {
+ delete [] mKeys;
mKeys = NULL;
- if (mValues)
- {
+ if (mValues) {
// Delete each metadata entry
- for (unsigned i=0; i<mNumProperties; ++i)
- {
+ for (unsigned i=0; i<mNumProperties; ++i) {
void* data = mValues[i].mData;
- switch (mValues[i].mType)
- {
+ switch (mValues[i].mType) {
case AI_BOOL:
delete static_cast<bool*>(data);
break;
- case AI_INT:
- delete static_cast<int*>(data);
+ case AI_INT32:
+ delete static_cast<int32_t*>(data);
break;
case AI_UINT64:
delete static_cast<uint64_t*>(data);
@@ -171,6 +157,9 @@ struct aiMetadata
case AI_FLOAT:
delete static_cast<float*>(data);
break;
+ case AI_DOUBLE:
+ delete static_cast<double*>(data);
+ break;
case AI_AISTRING:
delete static_cast<aiString*>(data);
break;
@@ -181,7 +170,6 @@ struct aiMetadata
case FORCE_32BIT:
#endif
default:
- assert(false);
break;
}
}
@@ -192,13 +180,67 @@ struct aiMetadata
}
}
+ /**
+ * @brief Allocates property fields + keys.
+ * @param numProperties Number of requested properties.
+ */
+ static inline
+ aiMetadata *Alloc( unsigned int numProperties ) {
+ if ( 0 == numProperties ) {
+ return nullptr;
+ }
+
+ aiMetadata *data = new aiMetadata;
+ data->mNumProperties = numProperties;
+ data->mKeys = new aiString[ data->mNumProperties ]();
+ data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
+
+ return data;
+ }
+
+ /**
+ * @brief Deallocates property fields + keys.
+ */
+ static inline
+ void Dealloc( aiMetadata *metadata ) {
+ delete metadata;
+ }
+
+ template<typename T>
+ inline void Add(const std::string& key, const T& value)
+ {
+ aiString* new_keys = new aiString[mNumProperties + 1];
+ aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
+
+ for(unsigned int i = 0; i < mNumProperties; ++i)
+ {
+ new_keys[i] = mKeys[i];
+ new_values[i] = mValues[i];
+ }
+
+ delete mKeys;
+ delete mValues;
+ mKeys = new_keys;
+ mValues = new_values;
+
+ mNumProperties++;
+
+ Set(mNumProperties - 1, key, value);
+ }
template<typename T>
- inline void Set( unsigned index, const std::string& key, const T& value )
- {
+ inline
+ bool Set( unsigned index, const std::string& key, const T& value ) {
// In range assertion
- assert(index < mNumProperties);
+ if ( index >= mNumProperties ) {
+ return false;
+ }
+
+ // Ensure that we have a valid key.
+ if ( key.empty() ) {
+ return false;
+ }
// Set metadata key
mKeys[index] = key;
@@ -207,13 +249,17 @@ struct aiMetadata
mValues[index].mType = GetAiType(value);
// Copy the given value to the dynamic storage
mValues[index].mData = new T(value);
+
+ return true;
}
template<typename T>
- inline bool Get( unsigned index, T& value )
- {
+ inline
+ bool Get( unsigned index, T& value ) {
// In range assertion
- assert(index < mNumProperties);
+ if ( index >= mNumProperties ) {
+ return false;
+ }
// Return false if the output data type does
// not match the found value's data type
@@ -224,16 +270,19 @@ struct aiMetadata
// 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 )
- {
+ 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);
+ for ( unsigned int i = 0; i < mNumProperties; ++i ) {
+ if ( mKeys[ i ] == key ) {
+ return Get( i, value );
+ }
+ }
return false;
}
@@ -242,10 +291,24 @@ struct aiMetadata
return Get(aiString(key), value);
}
-#endif // __cplusplus
+ /// Return metadata entry for analyzing it by user.
+ /// \param [in] pIndex - index of the entry.
+ /// \param [out] pKey - pointer to the key value.
+ /// \param [out] pEntry - pointer to the entry: type and value.
+ /// \return false - if pIndex is out of range, else - true.
+ inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) {
+ if ( index >= mNumProperties ) {
+ return false;
+ }
-};
+ key = &mKeys[index];
+ entry = &mValues[index];
-#endif // __AI_METADATA_H_INC__
+ return true;
+ }
+#endif // __cplusplus
+
+};
+#endif // AI_METADATA_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
index 6f806f922..41d800487 100644
--- a/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
+++ b/src/3rdparty/assimp/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h
@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC
#define AI_ANDROIDJNIIOSYSTEM_H_INC
-#include "../code/DefaultIOSystem.h"
+#include <assimp/DefaultIOSystem.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/native_activity.h>
diff --git a/src/3rdparty/assimp/include/assimp/postprocess.h b/src/3rdparty/assimp/include/assimp/postprocess.h
index 04de7a275..970df8e8a 100644
--- a/src/3rdparty/assimp/include/assimp/postprocess.h
+++ b/src/3rdparty/assimp/include/assimp/postprocess.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file postprocess.h
* @brief Definitions for import post processing steps
*/
+#pragma once
#ifndef AI_POSTPROCESS_H_INC
#define AI_POSTPROCESS_H_INC
@@ -523,7 +525,17 @@ enum aiPostProcessSteps
* 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_Debone = 0x4000000,
+
+ // -------------------------------------------------------------------------
+ /** <hr>This step will perform a global scale of the model.
+ *
+ * Some importers are providing a mechanism to define a scaling unit for the
+ * model. This post processing step can be used to do so.
+ *
+ * Use <tt>#AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY</tt> to control this.
+ */
+ aiProcess_GlobalScale = 0x8000000
// aiProcess_GenEntityMeshes = 0x100000,
// aiProcess_OptimizeAnimations = 0x200000
diff --git a/src/3rdparty/assimp/include/assimp/quaternion.h b/src/3rdparty/assimp/include/assimp/quaternion.h
index fe213f71e..a5cb67a9a 100644
--- a/src/3rdparty/assimp/include/assimp/quaternion.h
+++ b/src/3rdparty/assimp/include/assimp/quaternion.h
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -41,11 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file quaternion.h
* @brief Quaternion structure, including operators when compiling in C++
*/
+#pragma once
#ifndef AI_QUATERNION_H_INC
#define AI_QUATERNION_H_INC
#ifdef __cplusplus
+#include "defs.h"
+
template <typename TReal> class aiVector3t;
template <typename TReal> class aiMatrix3x3t;
@@ -112,15 +116,14 @@ public:
TReal w, x, y, z;
} ;
-typedef aiQuaterniont<float> aiQuaternion;
+typedef aiQuaterniont<ai_real> aiQuaternion;
#else
struct aiQuaternion {
- float w, x, y, z;
+ ai_real w, x, y, z;
};
#endif
-
#endif // AI_QUATERNION_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/quaternion.inl b/src/3rdparty/assimp/include/assimp/quaternion.inl
index db27c25ff..d0bf5831c 100644
--- a/src/3rdparty/assimp/include/assimp/quaternion.inl
+++ b/src/3rdparty/assimp/include/assimp/quaternion.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file quaternion.inl
* @brief Inline implementation of aiQuaterniont<TReal> operators
*/
+#pragma once
#ifndef AI_QUATERNION_INL_INC
#define AI_QUATERNION_INL_INC
@@ -280,4 +282,4 @@ inline aiVector3t<TReal> aiQuaterniont<TReal>::Rotate (const aiVector3t<TReal>&
}
#endif
-#endif
+#endif // AI_QUATERNION_INL_INC
diff --git a/src/3rdparty/assimp/include/assimp/scene.h b/src/3rdparty/assimp/include/assimp/scene.h
index 8987ac6a3..342c316d6 100644
--- a/src/3rdparty/assimp/include/assimp/scene.h
+++ b/src/3rdparty/assimp/include/assimp/scene.h
@@ -1,9 +1,10 @@
-/*
+/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,8 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file scene.h
* @brief Defines the data structures in which the imported scene is returned.
*/
-#ifndef __AI_SCENE_H_INC__
-#define __AI_SCENE_H_INC__
+#pragma once
+#ifndef AI_SCENE_H_INC
+#define AI_SCENE_H_INC
#include "types.h"
#include "texture.h"
@@ -58,9 +60,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" {
#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wattributes"
+#endif
// -------------------------------------------------------------------------------
-/** A node in the imported hierarchy.
+/**
+ * A node in the imported hierarchy.
*
* Each node has name, a parent node (except for the root node),
* a transformation relative to its parent and possibly several child nodes.
@@ -68,7 +75,7 @@ extern "C" {
* the imported scene does consist of only a single root node without children.
*/
// -------------------------------------------------------------------------------
-struct aiNode
+struct ASSIMP_API aiNode
{
/** The name of the node.
*
@@ -109,7 +116,7 @@ struct aiNode
/** The number of meshes of this node. */
unsigned int mNumMeshes;
- /** The meshes of this node. Each entry is an index into the
+ /** The meshes of this node. Each entry is an index into the
* mesh list of the #aiScene.
*/
unsigned int* mMeshes;
@@ -123,47 +130,13 @@ struct aiNode
#ifdef __cplusplus
/** Constructor */
- aiNode()
- // set all members to zero by default
- : mName("")
- , mParent(NULL)
- , mNumChildren(0)
- , mChildren(NULL)
- , mNumMeshes(0)
- , mMeshes(NULL)
- , mMetaData(NULL)
- {
- }
-
+ aiNode();
/** 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)
- {
- }
+ explicit aiNode(const std::string& name);
/** 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;
- }
-
+ ~aiNode();
/** Searches for a node with a specific name, beginning at this
* nodes. Normally you will call this method on the root node
@@ -172,49 +145,32 @@ struct aiNode
* @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
- {
+ inline
+ const aiNode* FindNode(const aiString& name) const {
return FindNode(name.data);
}
-
- inline aiNode* FindNode(const aiString& name)
- {
+ inline
+ aiNode* FindNode(const aiString& name) {
return FindNode(name.data);
}
+ const aiNode* FindNode(const char* name) const;
- 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;
- }
+ aiNode* FindNode(const char* name);
+ /**
+ * @brief Will add new children.
+ * @param numChildren Number of children to add.
+ * @param children The array with pointers showing to the children.
+ */
+ void addChildren(unsigned int numChildren, aiNode **children);
#endif // __cplusplus
};
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
// -------------------------------------------------------------------------------
/**
@@ -264,6 +220,13 @@ struct aiNode
*/
#define AI_SCENE_FLAGS_TERRAIN 0x10
+ /**
+ * Specifies that the scene data can be shared between structures. For example:
+ * one vertex in few faces. \ref AI_SCENE_FLAGS_NON_VERBOSE_FORMAT can not be
+ * used for this because \ref AI_SCENE_FLAGS_NON_VERBOSE_FORMAT has internal
+ * meaning about postprocessing steps.
+ */
+#define AI_SCENE_FLAGS_ALLOW_SHARED 0x20
// -------------------------------------------------------------------------------
/** The root structure of the imported data.
@@ -276,7 +239,6 @@ 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
@@ -284,7 +246,6 @@ struct aiScene
*/
unsigned int mFlags;
-
/** The root node of the hierarchy.
*
* There will always be at least the root node if the import
@@ -294,8 +255,6 @@ struct aiScene
*/
C_STRUCT aiNode* mRootNode;
-
-
/** The number of meshes in the scene. */
unsigned int mNumMeshes;
@@ -308,8 +267,6 @@ struct aiScene
*/
C_STRUCT aiMesh** mMeshes;
-
-
/** The number of materials in the scene. */
unsigned int mNumMaterials;
@@ -322,8 +279,6 @@ struct aiScene
*/
C_STRUCT aiMaterial** mMaterials;
-
-
/** The number of animations in the scene. */
unsigned int mNumAnimations;
@@ -334,8 +289,6 @@ struct aiScene
*/
C_STRUCT aiAnimation** mAnimations;
-
-
/** The number of textures embedded into the file */
unsigned int mNumTextures;
@@ -347,7 +300,6 @@ struct aiScene
*/
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
*/
@@ -360,7 +312,6 @@ struct aiScene
*/
C_STRUCT aiLight** mLights;
-
/** The number of cameras in the scene. Cameras
* are fully optional, in most cases this attribute will be 0
*/
@@ -385,33 +336,38 @@ struct 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; }
+ 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; }
+ inline bool HasMaterials() const {
+ return mMaterials != NULL && mNumMaterials > 0;
+ }
//! Check whether the scene contains lights
- inline bool HasLights() const
- { return mLights != NULL && mNumLights > 0; }
+ inline bool HasLights() const {
+ return mLights != NULL && mNumLights > 0;
+ }
//! Check whether the scene contains textures
- inline bool HasTextures() const
- { return mTextures != NULL && mNumTextures > 0; }
+ inline bool HasTextures() const {
+ return mTextures != NULL && mNumTextures > 0;
+ }
//! Check whether the scene contains cameras
- inline bool HasCameras() const
- { return mCameras != NULL && mNumCameras > 0; }
+ inline bool HasCameras() const {
+ return mCameras != NULL && mNumCameras > 0;
+ }
//! Check whether the scene contains animations
- inline bool HasAnimations() const
- { return mAnimations != NULL && mNumAnimations > 0; }
+ inline bool HasAnimations() const {
+ return mAnimations != NULL && mNumAnimations > 0;
+ }
#endif // __cplusplus
-
/** Internal data, do not touch */
#ifdef __cplusplus
void* mPrivate;
@@ -425,4 +381,4 @@ struct aiScene
} //! namespace Assimp
#endif
-#endif // __AI_SCENE_H_INC__
+#endif // AI_SCENE_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/texture.h b/src/3rdparty/assimp/include/assimp/texture.h
index ee3ee3149..c09ef2cbe 100644
--- a/src/3rdparty/assimp/include/assimp/texture.h
+++ b/src/3rdparty/assimp/include/assimp/texture.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -47,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* pixels, and "compressed" textures, which are stored in a file format
* such as PNG or TGA.
*/
-
+#pragma once
#ifndef AI_TEXTURE_H_INC
#define AI_TEXTURE_H_INC
@@ -59,6 +60,14 @@ extern "C" {
// --------------------------------------------------------------------------------
+
+/** \def AI_EMBEDDED_TEXNAME_PREFIX
+ * \ref AI_MAKE_EMBEDDED_TEXNAME
+ */
+#ifndef AI_EMBEDDED_TEXNAME_PREFIX
+# define AI_EMBEDDED_TEXNAME_PREFIX "*"
+#endif
+
/** @def AI_MAKE_EMBEDDED_TEXNAME
* Used to build the reserved path name used by the material system to
* reference textures that are embedded into their corresponding
@@ -66,7 +75,7 @@ extern "C" {
* (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_) AI_EMBEDDED_TEXNAME_PREFIX # _n_
#endif
@@ -139,10 +148,17 @@ struct aiTexture
unsigned int mHeight;
/** A hint from the loader to make it easier for applications
- * to determine the type of embedded compressed textures.
+ * to determine the type of embedded textures.
*
- * If mHeight != 0 this member is undefined. Otherwise it
- * is set set to '\\0\\0\\0\\0' if the loader has no additional
+ * If mHeight != 0 this member is show how data is packed. Hint will consist of
+ * two parts: channel order and channel bitness (count of the bits for every
+ * color channel). For simple parsing by the viewer it's better to not omit
+ * absent color channel and just use 0 for bitness. For example:
+ * 1. Image contain RGBA and 8 bit per channel, achFormatHint == "rgba8888";
+ * 2. Image contain ARGB and 8 bit per channel, achFormatHint == "argb8888";
+ * 3. Image contain RGB and 5 bit for R and B channels and 6 bit for G channel, achFormatHint == "rgba5650";
+ * 4. One color image with B channel and 1 bit for it, achFormatHint == "rgba0010";
+ * If mHeight == 0 then achFormatHint 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
@@ -150,7 +166,7 @@ struct aiTexture
* E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case.
* The fourth character will always be '\\0'.
*/
- char achFormatHint[4];
+ char achFormatHint[9];// 8 for string + 1 for terminator.
/** Data of the texture.
*
@@ -172,7 +188,7 @@ struct aiTexture
//! @return true if the given string matches the format hint
bool CheckFormat(const char* s) const
{
- return (0 == ::strncmp(achFormatHint,s,3));
+ return (0 == ::strncmp(achFormatHint, s, sizeof(achFormatHint)));
}
// Construction
diff --git a/src/3rdparty/assimp/include/assimp/types.h b/src/3rdparty/assimp/include/assimp/types.h
index 592d5c64d..0012a0bba 100644
--- a/src/3rdparty/assimp/include/assimp/types.h
+++ b/src/3rdparty/assimp/include/assimp/types.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,12 +43,12 @@ 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.
*/
+#pragma once
#ifndef AI_TYPES_H_INC
#define AI_TYPES_H_INC
// Some runtime headers
#include <sys/types.h>
-#include <math.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
@@ -109,13 +110,12 @@ extern "C" {
/** Maximum dimension for strings, ASSIMP strings are zero terminated. */
#ifdef __cplusplus
+static
const size_t MAXLEN = 1024;
#else
# define MAXLEN 1024
#endif
-#include "./Compiler/pushpack1.h"
-
// ----------------------------------------------------------------------------------
/** Represents a plane in a three-dimensional, euclidean space
*/
@@ -123,7 +123,7 @@ 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)
+ aiPlane (ai_real _a, ai_real _b, ai_real _c, ai_real _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) {}
@@ -131,8 +131,8 @@ struct aiPlane
#endif // !__cplusplus
//! Plane equation
- float a,b,c,d;
-} PACK_STRUCT; // !struct aiPlane
+ ai_real a,b,c,d;
+}; // !struct aiPlane
// ----------------------------------------------------------------------------------
/** Represents a ray
@@ -150,7 +150,7 @@ struct aiRay
//! Position and direction of the ray
C_STRUCT aiVector3D pos, dir;
-} PACK_STRUCT; // !struct aiRay
+}; // !struct aiRay
// ----------------------------------------------------------------------------------
/** Represents a color in Red-Green-Blue space.
@@ -159,8 +159,8 @@ 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) {}
- explicit aiColor3D (float _r) : r(_r), g(_r), b(_r) {}
+ aiColor3D (ai_real _r, ai_real _g, ai_real _b) : r(_r), g(_g), b(_b) {}
+ explicit aiColor3D (ai_real _r) : r(_r), g(_r), b(_r) {}
aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {}
/** Component-wise comparison */
@@ -176,11 +176,7 @@ struct aiColor3D
/** 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)
- )
- );
+ return r < other.r || ( r == other.r && (g < other.g || (g == other.g && b < other.b ) ) );
}
/** Component-wise addition */
@@ -199,32 +195,38 @@ struct aiColor3D
}
/** Multiply with a scalar */
- aiColor3D operator*(float f) const {
+ aiColor3D operator*(ai_real f) const {
return aiColor3D(r*f,g*f,b*f);
}
/** Access a specific color component */
- float operator[](unsigned int i) const {
+ ai_real operator[](unsigned int i) const {
return *(&r + i);
}
/** Access a specific color component */
- float& operator[](unsigned int i) {
- return *(&r + i);
+ ai_real& operator[](unsigned int i) {
+ if ( 0 == i ) {
+ return r;
+ } else if ( 1 == i ) {
+ return g;
+ } else if ( 2 == i ) {
+ return b;
+ }
+ return r;
}
/** Check whether a color is black */
bool IsBlack() const {
- static const float epsilon = 10e-3f;
+ static const ai_real epsilon = ai_real(10e-3);
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;
-} PACK_STRUCT; // !struct aiColor3D
-#include "./Compiler/poppack1.h"
+ ai_real r, g, b;
+}; // !struct aiColor3D
// ----------------------------------------------------------------------------------
/** Represents an UTF-8 string, zero byte terminated.
@@ -512,4 +514,5 @@ struct aiMemoryInfo
#include "quaternion.inl"
#include "matrix3x3.inl"
#include "matrix4x4.inl"
-#endif
+
+#endif // AI_TYPES_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/vector2.h b/src/3rdparty/assimp/include/assimp/vector2.h
index 199743e26..564d1f8b5 100644
--- a/src/3rdparty/assimp/include/assimp/vector2.h
+++ b/src/3rdparty/assimp/include/assimp/vector2.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -41,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file vector2.h
* @brief 2D vector structure, including operators when compiling in C++
*/
+#pragma once
#ifndef AI_VECTOR2D_H_INC
#define AI_VECTOR2D_H_INC
@@ -51,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#include "./Compiler/pushpack1.h"
+#include "defs.h"
// ----------------------------------------------------------------------------------
/** Represents a two-dimensional vector.
@@ -98,12 +101,12 @@ public:
TReal x, y;
} PACK_STRUCT;
-typedef aiVector2t<float> aiVector2D;
+typedef aiVector2t<ai_real> aiVector2D;
#else
struct aiVector2D {
- float x, y;
+ ai_real x, y;
};
#endif // __cplusplus
diff --git a/src/3rdparty/assimp/include/assimp/vector2.inl b/src/3rdparty/assimp/include/assimp/vector2.inl
index ae823fc1a..5ce13eece 100644
--- a/src/3rdparty/assimp/include/assimp/vector2.inl
+++ b/src/3rdparty/assimp/include/assimp/vector2.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file vector2.inl
* @brief Inline implementation of aiVector2t<TReal> operators
*/
+#pragma once
#ifndef AI_VECTOR2D_INL_INC
#define AI_VECTOR2D_INL_INC
@@ -221,4 +223,5 @@ inline aiVector2t<TReal> operator - ( const aiVector2t<TReal>& v)
}
#endif
-#endif
+
+#endif // AI_VECTOR2D_INL_INC
diff --git a/src/3rdparty/assimp/include/assimp/vector3.h b/src/3rdparty/assimp/include/assimp/vector3.h
index 84f785f8f..641dab795 100644
--- a/src/3rdparty/assimp/include/assimp/vector3.h
+++ b/src/3rdparty/assimp/include/assimp/vector3.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -41,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file vector3.h
* @brief 3D vector structure, including operators when compiling in C++
*/
+#pragma once
#ifndef AI_VECTOR3D_H_INC
#define AI_VECTOR3D_H_INC
@@ -50,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# include <math.h>
#endif
-#include "./Compiler/pushpack1.h"
+#include "defs.h"
#ifdef __cplusplus
@@ -63,11 +65,10 @@ template <typename TReal>
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:
@@ -96,7 +97,6 @@ public:
operator aiVector3t<TOther> () const;
public:
-
/** @brief Set the components of a vector
* @param pX X component
* @param pY Y component
@@ -107,7 +107,6 @@ public:
* @return Square length */
TReal SquareLength() const;
-
/** @brief Get the length of the vector
* @return length */
TReal Length() const;
@@ -126,25 +125,21 @@ public:
const aiVector3t SymMul(const aiVector3t& o);
TReal x, y, z;
-} PACK_STRUCT;
+};
-typedef aiVector3t<float> aiVector3D;
+typedef aiVector3t<ai_real> aiVector3D;
#else
struct aiVector3D {
- float x, y, z;
-} PACK_STRUCT;
+ ai_real x, y, z;
+};
#endif // __cplusplus
-#include "./Compiler/poppack1.h"
-
#ifdef __cplusplus
-
-
#endif // __cplusplus
#endif // AI_VECTOR3D_H_INC
diff --git a/src/3rdparty/assimp/include/assimp/vector3.inl b/src/3rdparty/assimp/include/assimp/vector3.inl
index 0d0d62968..a074bb23a 100644
--- a/src/3rdparty/assimp/include/assimp/vector3.inl
+++ b/src/3rdparty/assimp/include/assimp/vector3.inl
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file vector3.inl
* @brief Inline implementation of aiVector3t<TReal> operators
*/
+#pragma once
#ifndef AI_VECTOR3D_INL_INC
#define AI_VECTOR3D_INL_INC
@@ -140,12 +142,34 @@ AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatri
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal aiVector3t<TReal>::operator[](unsigned int i) const {
- return *(&x + i);
+// return *(&x + i);
+ switch (i) {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ break;
+ }
+ return x;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE TReal& aiVector3t<TReal>::operator[](unsigned int i) {
- return *(&x + i);
+// return *(&x + i);
+ switch (i) {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ break;
+ }
+ return x;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
diff --git a/src/3rdparty/assimp/include/assimp/version.h b/src/3rdparty/assimp/include/assimp/version.h
index 403798c1b..d1821fa2b 100644
--- a/src/3rdparty/assimp/include/assimp/version.h
+++ b/src/3rdparty/assimp/include/assimp/version.h
@@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
@@ -43,8 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Functions to query the version of the Assimp runtime, check
* compile flags, ...
*/
-#ifndef INCLUDED_AI_VERSION_H
-#define INCLUDED_AI_VERSION_H
+#pragma once
+#ifndef AI_VERSION_H_INC
+#define AI_VERSION_H_INC
#include "defs.h"
@@ -102,4 +104,5 @@ ASSIMP_API unsigned int aiGetCompileFlags (void);
} // end extern "C"
#endif
-#endif // !! #ifndef INCLUDED_AI_VERSION_H
+#endif // !! #ifndef AI_VERSION_H_INC
+
diff --git a/src/3rdparty/assimp/revision.h b/src/3rdparty/assimp/revision.h
index 05fde9ff4..af5dc3ab0 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 0xa8673d4
+#define GitVersion 0x80799bd
#define GitBranch "master"
#endif // ASSIMP_REVISION_H_INC