diff options
Diffstat (limited to 'thirdparty/assimp/code')
| -rw-r--r-- | thirdparty/assimp/code/CApi/AssimpCExport.cpp | 156 | ||||
| -rw-r--r-- | thirdparty/assimp/code/CApi/CInterfaceIOWrapper.cpp (renamed from thirdparty/assimp/code/CInterfaceIOWrapper.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/CApi/CInterfaceIOWrapper.h (renamed from thirdparty/assimp/code/CInterfaceIOWrapper.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Assimp.cpp | 695 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/BaseImporter.cpp (renamed from thirdparty/assimp/code/BaseImporter.cpp) | 48 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/BaseProcess.cpp (renamed from thirdparty/assimp/code/BaseProcess.cpp) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/BaseProcess.h (renamed from thirdparty/assimp/code/BaseProcess.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Bitmap.cpp (renamed from thirdparty/assimp/code/Bitmap.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/CreateAnimMesh.cpp (renamed from thirdparty/assimp/code/CreateAnimMesh.cpp) | 4 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/DefaultIOStream.cpp (renamed from thirdparty/assimp/code/DefaultIOStream.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/DefaultIOSystem.cpp (renamed from thirdparty/assimp/code/DefaultIOSystem.cpp) | 161 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/DefaultLogger.cpp (renamed from thirdparty/assimp/code/DefaultLogger.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/DefaultProgressHandler.h (renamed from thirdparty/assimp/code/DefaultProgressHandler.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Exporter.cpp (renamed from thirdparty/assimp/code/Exporter.cpp) | 74 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/FileLogStream.h (renamed from thirdparty/assimp/code/FileLogStream.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/FileSystemFilter.h (renamed from thirdparty/assimp/code/FileSystemFilter.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/IFF.h | 102 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Importer.cpp (renamed from thirdparty/assimp/code/Importer.cpp) | 19 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Importer.h (renamed from thirdparty/assimp/code/Importer.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/ImporterRegistry.cpp (renamed from thirdparty/assimp/code/ImporterRegistry.cpp) | 102 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/PolyTools.h (renamed from thirdparty/assimp/code/PolyTools.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/PostStepRegistry.cpp (renamed from thirdparty/assimp/code/PostStepRegistry.cpp) | 70 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/RemoveComments.cpp (renamed from thirdparty/assimp/code/RemoveComments.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/SGSpatialSort.cpp (renamed from thirdparty/assimp/code/SGSpatialSort.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/SceneCombiner.cpp (renamed from thirdparty/assimp/code/SceneCombiner.cpp) | 50 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/ScenePreprocessor.cpp (renamed from thirdparty/assimp/code/ScenePreprocessor.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/ScenePreprocessor.h (renamed from thirdparty/assimp/code/ScenePreprocessor.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/ScenePrivate.h (renamed from thirdparty/assimp/code/ScenePrivate.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/SkeletonMeshBuilder.cpp (renamed from thirdparty/assimp/code/SkeletonMeshBuilder.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/SpatialSort.cpp (renamed from thirdparty/assimp/code/SpatialSort.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/SplitByBoneCountProcess.cpp (renamed from thirdparty/assimp/code/SplitByBoneCountProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/SplitByBoneCountProcess.h (renamed from thirdparty/assimp/code/SplitByBoneCountProcess.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/StandardShapes.cpp (renamed from thirdparty/assimp/code/StandardShapes.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/StdOStreamLogStream.h (renamed from thirdparty/assimp/code/StdOStreamLogStream.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Subdivision.cpp (renamed from thirdparty/assimp/code/Subdivision.cpp) | 7 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/TargetAnimation.cpp (renamed from thirdparty/assimp/code/TargetAnimation.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/TargetAnimation.h (renamed from thirdparty/assimp/code/TargetAnimation.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Version.cpp (renamed from thirdparty/assimp/code/Version.cpp) | 14 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/VertexTriangleAdjacency.cpp (renamed from thirdparty/assimp/code/VertexTriangleAdjacency.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/VertexTriangleAdjacency.h (renamed from thirdparty/assimp/code/VertexTriangleAdjacency.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/Win32DebugLogStream.h (renamed from thirdparty/assimp/code/Win32DebugLogStream.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/assbin_chunks.h | 196 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/scene.cpp (renamed from thirdparty/assimp/code/scene.cpp) | 18 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/simd.cpp (renamed from thirdparty/assimp/code/simd.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Common/simd.h (renamed from thirdparty/assimp/code/simd.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXAnimation.cpp (renamed from thirdparty/assimp/code/FBXAnimation.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp (renamed from thirdparty/assimp/code/FBXBinaryTokenizer.cpp) | 12 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXCommon.h (renamed from thirdparty/assimp/code/FBXCommon.h) | 4 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXCompileConfig.h (renamed from thirdparty/assimp/code/FBXCompileConfig.h) | 8 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXConverter.cpp (renamed from thirdparty/assimp/code/FBXConverter.cpp) | 598 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXConverter.h (renamed from thirdparty/assimp/code/FBXConverter.h) | 106 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXDeformer.cpp (renamed from thirdparty/assimp/code/FBXDeformer.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXDocument.cpp (renamed from thirdparty/assimp/code/FBXDocument.cpp) | 8 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXDocument.h (renamed from thirdparty/assimp/code/FBXDocument.h) | 43 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp (renamed from thirdparty/assimp/code/FBXDocumentUtil.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXDocumentUtil.h (renamed from thirdparty/assimp/code/FBXDocumentUtil.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXExportNode.cpp (renamed from thirdparty/assimp/code/FBXExportNode.cpp) | 11 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXExportNode.h (renamed from thirdparty/assimp/code/FBXExportNode.h) | 12 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXExportProperty.cpp (renamed from thirdparty/assimp/code/FBXExportProperty.cpp) | 255 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXExportProperty.h (renamed from thirdparty/assimp/code/FBXExportProperty.h) | 48 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXExporter.cpp (renamed from thirdparty/assimp/code/FBXExporter.cpp) | 270 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXExporter.h (renamed from thirdparty/assimp/code/FBXExporter.h) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXImportSettings.h (renamed from thirdparty/assimp/code/FBXImportSettings.h) | 39 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXImporter.cpp | 198 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXImporter.h (renamed from thirdparty/assimp/code/FBXImporter.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXMaterial.cpp (renamed from thirdparty/assimp/code/FBXMaterial.cpp) | 58 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp (renamed from thirdparty/assimp/code/FBXMeshGeometry.cpp) | 36 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXMeshGeometry.h (renamed from thirdparty/assimp/code/FBXMeshGeometry.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXModel.cpp (renamed from thirdparty/assimp/code/FBXModel.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp (renamed from thirdparty/assimp/code/FBXNodeAttribute.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXParser.cpp (renamed from thirdparty/assimp/code/FBXParser.cpp) | 12 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXParser.h (renamed from thirdparty/assimp/code/FBXParser.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXProperties.cpp (renamed from thirdparty/assimp/code/FBXProperties.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXProperties.h (renamed from thirdparty/assimp/code/FBXProperties.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXTokenizer.cpp (renamed from thirdparty/assimp/code/FBXTokenizer.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXTokenizer.h (renamed from thirdparty/assimp/code/FBXTokenizer.h) | 12 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXUtil.cpp | 243 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBX/FBXUtil.h (renamed from thirdparty/assimp/code/FBXUtil.h) | 34 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBXImporter.cpp | 197 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FBXUtil.cpp | 120 | ||||
| -rw-r--r-- | thirdparty/assimp/code/FIReader.cpp | 1834 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDCpp14.h | 83 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDImporter.cpp | 370 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDImporter.h | 96 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDPmdParser.h | 597 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDPmxParser.cpp | 604 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDPmxParser.h | 782 | ||||
| -rw-r--r-- | thirdparty/assimp/code/MMDVmdParser.h | 376 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Material/MaterialSystem.cpp (renamed from thirdparty/assimp/code/MaterialSystem.cpp) | 31 | ||||
| -rw-r--r-- | thirdparty/assimp/code/Material/MaterialSystem.h (renamed from thirdparty/assimp/code/MaterialSystem.h) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ArmaturePopulate.cpp | 268 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ArmaturePopulate.h | 112 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.cpp (renamed from thirdparty/assimp/code/CalcTangentsProcess.cpp) | 6 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.h (renamed from thirdparty/assimp/code/CalcTangentsProcess.h) | 4 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.cpp (renamed from thirdparty/assimp/code/ComputeUVMappingProcess.cpp) | 6 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.h (renamed from thirdparty/assimp/code/ComputeUVMappingProcess.h) | 3 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.cpp (renamed from thirdparty/assimp/code/ConvertToLHProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.h (renamed from thirdparty/assimp/code/ConvertToLHProcess.h) | 3 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/DeboneProcess.cpp (renamed from thirdparty/assimp/code/DeboneProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/DeboneProcess.h (renamed from thirdparty/assimp/code/DeboneProcess.h) | 17 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/DropFaceNormalsProcess.cpp (renamed from thirdparty/assimp/code/DropFaceNormalsProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/DropFaceNormalsProcess.h (renamed from thirdparty/assimp/code/DropFaceNormalsProcess.h) | 11 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/EmbedTexturesProcess.cpp (renamed from thirdparty/assimp/code/EmbedTexturesProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/EmbedTexturesProcess.h (renamed from thirdparty/assimp/code/EmbedTexturesProcess.h) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FindDegenerates.cpp (renamed from thirdparty/assimp/code/FindDegenerates.cpp) | 1 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FindDegenerates.h (renamed from thirdparty/assimp/code/FindDegenerates.h) | 3 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FindInstancesProcess.cpp (renamed from thirdparty/assimp/code/FindInstancesProcess.cpp) | 12 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FindInstancesProcess.h (renamed from thirdparty/assimp/code/FindInstancesProcess.h) | 4 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FindInvalidDataProcess.cpp (renamed from thirdparty/assimp/code/FindInvalidDataProcess.cpp) | 1 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FindInvalidDataProcess.h (renamed from thirdparty/assimp/code/FindInvalidDataProcess.h) | 3 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FixNormalsStep.cpp (renamed from thirdparty/assimp/code/FixNormalsStep.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/FixNormalsStep.h (renamed from thirdparty/assimp/code/FixNormalsStep.h) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.cpp | 115 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.h | 76 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/GenFaceNormalsProcess.cpp (renamed from thirdparty/assimp/code/GenFaceNormalsProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/GenFaceNormalsProcess.h (renamed from thirdparty/assimp/code/GenFaceNormalsProcess.h) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/GenVertexNormalsProcess.cpp (renamed from thirdparty/assimp/code/GenVertexNormalsProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/GenVertexNormalsProcess.h (renamed from thirdparty/assimp/code/GenVertexNormalsProcess.h) | 18 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ImproveCacheLocality.cpp (renamed from thirdparty/assimp/code/ImproveCacheLocality.cpp) | 65 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ImproveCacheLocality.h (renamed from thirdparty/assimp/code/ImproveCacheLocality.h) | 7 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/JoinVerticesProcess.cpp (renamed from thirdparty/assimp/code/JoinVerticesProcess.cpp) | 25 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/JoinVerticesProcess.h (renamed from thirdparty/assimp/code/JoinVerticesProcess.h) | 10 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/LimitBoneWeightsProcess.cpp (renamed from thirdparty/assimp/code/LimitBoneWeightsProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/LimitBoneWeightsProcess.h (renamed from thirdparty/assimp/code/LimitBoneWeightsProcess.h) | 34 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/MakeVerboseFormat.cpp (renamed from thirdparty/assimp/code/MakeVerboseFormat.cpp) | 29 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/MakeVerboseFormat.h (renamed from thirdparty/assimp/code/MakeVerboseFormat.h) | 10 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/OptimizeGraph.cpp (renamed from thirdparty/assimp/code/OptimizeGraph.cpp) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/OptimizeGraph.h (renamed from thirdparty/assimp/code/OptimizeGraph.h) | 27 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/OptimizeMeshes.cpp (renamed from thirdparty/assimp/code/OptimizeMeshes.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/OptimizeMeshes.h (renamed from thirdparty/assimp/code/OptimizeMeshes.h) | 10 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/PretransformVertices.cpp (renamed from thirdparty/assimp/code/PretransformVertices.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/PretransformVertices.h (renamed from thirdparty/assimp/code/PretransformVertices.h) | 15 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ProcessHelper.cpp (renamed from thirdparty/assimp/code/ProcessHelper.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ProcessHelper.h (renamed from thirdparty/assimp/code/ProcessHelper.h) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/RemoveRedundantMaterials.cpp (renamed from thirdparty/assimp/code/RemoveRedundantMaterials.cpp) | 10 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/RemoveRedundantMaterials.h (renamed from thirdparty/assimp/code/RemoveRedundantMaterials.h) | 18 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/RemoveVCProcess.cpp (renamed from thirdparty/assimp/code/RemoveVCProcess.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/RemoveVCProcess.h (renamed from thirdparty/assimp/code/RemoveVCProcess.h) | 3 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ScaleProcess.cpp | 208 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ScaleProcess.h (renamed from thirdparty/assimp/code/ScaleProcess.h) | 15 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/SortByPTypeProcess.cpp (renamed from thirdparty/assimp/code/SortByPTypeProcess.cpp) | 18 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/SortByPTypeProcess.h (renamed from thirdparty/assimp/code/SortByPTypeProcess.h) | 11 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/SplitLargeMeshes.cpp (renamed from thirdparty/assimp/code/SplitLargeMeshes.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/SplitLargeMeshes.h (renamed from thirdparty/assimp/code/SplitLargeMeshes.h) | 9 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/TextureTransform.cpp (renamed from thirdparty/assimp/code/TextureTransform.cpp) | 0 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/TextureTransform.h (renamed from thirdparty/assimp/code/TextureTransform.h) | 2 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/TriangulateProcess.cpp (renamed from thirdparty/assimp/code/TriangulateProcess.cpp) | 10 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/TriangulateProcess.h (renamed from thirdparty/assimp/code/TriangulateProcess.h) | 8 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ValidateDataStructure.cpp (renamed from thirdparty/assimp/code/ValidateDataStructure.cpp) | 96 | ||||
| -rw-r--r-- | thirdparty/assimp/code/PostProcessing/ValidateDataStructure.h (renamed from thirdparty/assimp/code/ValidateDataStructure.h) | 11 | ||||
| -rw-r--r-- | thirdparty/assimp/code/RawLoader.cpp | 331 | ||||
| -rw-r--r-- | thirdparty/assimp/code/ScaleProcess.cpp | 103 | ||||
| -rw-r--r-- | thirdparty/assimp/code/res/resource.h | 14 | ||||
| -rw-r--r-- | thirdparty/assimp/code/revision.h | 23 |
154 files changed, 4021 insertions, 6591 deletions
diff --git a/thirdparty/assimp/code/CApi/AssimpCExport.cpp b/thirdparty/assimp/code/CApi/AssimpCExport.cpp new file mode 100644 index 0000000000..7557edcfc6 --- /dev/null +++ b/thirdparty/assimp/code/CApi/AssimpCExport.cpp @@ -0,0 +1,156 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file AssimpCExport.cpp +Assimp C export interface. See Exporter.cpp for some notes. +*/ + +#ifndef ASSIMP_BUILD_NO_EXPORT + +#include "CInterfaceIOWrapper.h" +#include <assimp/SceneCombiner.h> +#include "Common/ScenePrivate.h" +#include <assimp/Exporter.hpp> + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API size_t aiGetExportFormatCount(void) +{ + return Exporter().GetExportFormatCount(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) +{ + // Note: this is valid as the index always pertains to a built-in exporter, + // for which the returned structure is guaranteed to be of static storage duration. + Exporter exporter; + const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) ); + if (NULL == orig) { + return NULL; + } + + aiExportFormatDesc *desc = new aiExportFormatDesc; + desc->description = new char[ strlen( orig->description ) + 1 ](); + ::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) ); + desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ](); + ::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) ); + desc->id = new char[ strlen( orig->id ) + 1 ](); + ::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) ); + + return desc; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) { + if (NULL == desc) { + return; + } + + delete [] desc->description; + delete [] desc->fileExtension; + delete [] desc->id; + delete desc; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut) +{ + if (!pOut || !pIn) { + return; + } + + SceneCombiner::CopyScene(pOut,pIn,true); + ScenePriv(*pOut)->mIsCopy = true; +} + + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn) +{ + // note: aiReleaseImport() is also able to delete scene copies, but in addition + // it also handles scenes with import metadata. + delete pIn; +} + + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing ) +{ + return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing); +} + + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing ) +{ + Exporter exp; + + if (pIO) { + exp.SetIOHandler(new CIOSystemWrapper(pIO)); + } + return exp.Export(pScene,pFormatId,pFileName,pPreprocessing); +} + + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) +{ + Exporter exp; + if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) { + return NULL; + } + const aiExportDataBlob* blob = exp.GetOrphanedBlob(); + ai_assert(blob); + + return blob; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData ) +{ + delete pData; +} + +#endif // !ASSIMP_BUILD_NO_EXPORT diff --git a/thirdparty/assimp/code/CInterfaceIOWrapper.cpp b/thirdparty/assimp/code/CApi/CInterfaceIOWrapper.cpp index 5a3a49565a..5a3a49565a 100644 --- a/thirdparty/assimp/code/CInterfaceIOWrapper.cpp +++ b/thirdparty/assimp/code/CApi/CInterfaceIOWrapper.cpp diff --git a/thirdparty/assimp/code/CInterfaceIOWrapper.h b/thirdparty/assimp/code/CApi/CInterfaceIOWrapper.h index 2162320302..2162320302 100644 --- a/thirdparty/assimp/code/CInterfaceIOWrapper.h +++ b/thirdparty/assimp/code/CApi/CInterfaceIOWrapper.h diff --git a/thirdparty/assimp/code/Common/Assimp.cpp b/thirdparty/assimp/code/Common/Assimp.cpp new file mode 100644 index 0000000000..178b2c01d0 --- /dev/null +++ b/thirdparty/assimp/code/Common/Assimp.cpp @@ -0,0 +1,695 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +/** @file Assimp.cpp + * @brief Implementation of the Plain-C API + */ + +#include <assimp/cimport.h> +#include <assimp/LogStream.hpp> +#include <assimp/DefaultLogger.hpp> +#include <assimp/Importer.hpp> +#include <assimp/importerdesc.h> +#include <assimp/scene.h> +#include <assimp/GenericProperty.h> +#include <assimp/Exceptional.h> +#include <assimp/BaseImporter.h> + +#include "CApi/CInterfaceIOWrapper.h" +#include "Importer.h" +#include "ScenePrivate.h" + +#include <list> + +// ------------------------------------------------------------------------------------------------ +#ifndef ASSIMP_BUILD_SINGLETHREADED +# include <thread> +# include <mutex> +#endif +// ------------------------------------------------------------------------------------------------ +using namespace Assimp; + +namespace Assimp { + // underlying structure for aiPropertyStore + typedef BatchLoader::PropertyMap PropertyMap; + + /** Stores the LogStream objects for all active C log streams */ + struct mpred { + bool operator () (const aiLogStream& s0, const aiLogStream& s1) const { + return s0.callback<s1.callback&&s0.user<s1.user; + } + }; + typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap; + + /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */ + typedef std::list<Assimp::LogStream*> PredefLogStreamMap; + + /** Local storage of all active log streams */ + static LogStreamMap gActiveLogStreams; + + /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */ + static PredefLogStreamMap gPredefinedStreams; + + /** Error message of the last failed import process */ + static std::string gLastErrorString; + + /** Verbose logging active or not? */ + static aiBool gVerboseLogging = false; + + /** will return all registered importers. */ + void GetImporterInstanceList(std::vector< BaseImporter* >& out); + + /** will delete all registered importers. */ + void DeleteImporterInstanceList(std::vector< BaseImporter* >& out); +} // namespace assimp + + +#ifndef ASSIMP_BUILD_SINGLETHREADED +/** Global mutex to manage the access to the log-stream map */ +static std::mutex gLogStreamMutex; +#endif + +// ------------------------------------------------------------------------------------------------ +// Custom LogStream implementation for the C-API +class LogToCallbackRedirector : public LogStream { +public: + explicit LogToCallbackRedirector(const aiLogStream& s) + : stream (s) { + ai_assert(NULL != s.callback); + } + + ~LogToCallbackRedirector() { +#ifndef ASSIMP_BUILD_SINGLETHREADED + std::lock_guard<std::mutex> lock(gLogStreamMutex); +#endif + // (HACK) Check whether the 'stream.user' pointer points to a + // custom LogStream allocated by #aiGetPredefinedLogStream. + // In this case, we need to delete it, too. Of course, this + // might cause strange problems, but the chance is quite low. + + PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(), + gPredefinedStreams.end(), (Assimp::LogStream*)stream.user); + + if (it != gPredefinedStreams.end()) { + delete *it; + gPredefinedStreams.erase(it); + } + } + + /** @copydoc LogStream::write */ + void write(const char* message) { + stream.callback(message,stream.user); + } + +private: + aiLogStream stream; +}; + +// ------------------------------------------------------------------------------------------------ +void ReportSceneNotFoundError() { + ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. " + "The C-API does not accept scenes produced by the C++ API and vice versa"); + + ai_assert(false); +} + +// ------------------------------------------------------------------------------------------------ +// Reads the given file and returns its content. +const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) { + return aiImportFileEx(pFile,pFlags,NULL); +} + +// ------------------------------------------------------------------------------------------------ +const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) { + return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL); +} + +// ------------------------------------------------------------------------------------------------ +const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, + aiFileIO* pFS, const aiPropertyStore* props) { + ai_assert(NULL != pFile); + + const aiScene* scene = NULL; + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // create an Importer for this file + Assimp::Importer* imp = new Assimp::Importer(); + + // copy properties + if(props) { + const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props); + ImporterPimpl* pimpl = imp->Pimpl(); + pimpl->mIntProperties = pp->ints; + pimpl->mFloatProperties = pp->floats; + pimpl->mStringProperties = pp->strings; + pimpl->mMatrixProperties = pp->matrices; + } + // setup a custom IO system if necessary + if (pFS) { + imp->SetIOHandler( new CIOSystemWrapper (pFS) ); + } + + // and have it read the file + scene = imp->ReadFile( pFile, pFlags); + + // if succeeded, store the importer in the scene and keep it alive + if( scene) { + ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) ); + priv->mOrigImporter = imp; + } else { + // if failed, extract error code and destroy the import + gLastErrorString = imp->GetErrorString(); + delete imp; + } + + // return imported data. If the import failed the pointer is NULL anyways + ASSIMP_END_EXCEPTION_REGION(const aiScene*); + + return scene; +} + +// ------------------------------------------------------------------------------------------------ +const aiScene* aiImportFileFromMemory( + const char* pBuffer, + unsigned int pLength, + unsigned int pFlags, + const char* pHint) +{ + return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL); +} + +// ------------------------------------------------------------------------------------------------ +const aiScene* aiImportFileFromMemoryWithProperties( + const char* pBuffer, + unsigned int pLength, + unsigned int pFlags, + const char* pHint, + const aiPropertyStore* props) +{ + ai_assert( NULL != pBuffer ); + ai_assert( 0 != pLength ); + + const aiScene* scene = NULL; + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // create an Importer for this file + Assimp::Importer* imp = new Assimp::Importer(); + + // copy properties + if(props) { + const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props); + ImporterPimpl* pimpl = imp->Pimpl(); + pimpl->mIntProperties = pp->ints; + pimpl->mFloatProperties = pp->floats; + pimpl->mStringProperties = pp->strings; + pimpl->mMatrixProperties = pp->matrices; + } + + // and have it read the file from the memory buffer + scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint); + + // if succeeded, store the importer in the scene and keep it alive + if( scene) { + ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) ); + priv->mOrigImporter = imp; + } + else { + // if failed, extract error code and destroy the import + gLastErrorString = imp->GetErrorString(); + delete imp; + } + // return imported data. If the import failed the pointer is NULL anyways + ASSIMP_END_EXCEPTION_REGION(const aiScene*); + return scene; +} + +// ------------------------------------------------------------------------------------------------ +// Releases all resources associated with the given import process. +void aiReleaseImport( const aiScene* pScene) +{ + if (!pScene) { + return; + } + + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // find the importer associated with this data + const ScenePrivateData* priv = ScenePriv(pScene); + if( !priv || !priv->mOrigImporter) { + delete pScene; + } + else { + // deleting the Importer also deletes the scene + // Note: the reason that this is not written as 'delete priv->mOrigImporter' + // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339) + Importer* importer = priv->mOrigImporter; + delete importer; + } + + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene, + unsigned int pFlags) +{ + const aiScene* sc = NULL; + + + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // find the importer associated with this data + const ScenePrivateData* priv = ScenePriv(pScene); + if( !priv || !priv->mOrigImporter) { + ReportSceneNotFoundError(); + return NULL; + } + + sc = priv->mOrigImporter->ApplyPostProcessing(pFlags); + + if (!sc) { + aiReleaseImport(pScene); + return NULL; + } + + ASSIMP_END_EXCEPTION_REGION(const aiScene*); + return sc; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing( const aiScene *scene, + BaseProcess* process, + bool requestValidation ) { + const aiScene* sc( NULL ); + + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // find the importer associated with this data + const ScenePrivateData* priv = ScenePriv( scene ); + if ( NULL == priv || NULL == priv->mOrigImporter ) { + ReportSceneNotFoundError(); + return NULL; + } + + sc = priv->mOrigImporter->ApplyCustomizedPostProcessing( process, requestValidation ); + + if ( !sc ) { + aiReleaseImport( scene ); + return NULL; + } + + ASSIMP_END_EXCEPTION_REGION( const aiScene* ); + + return sc; +} + +// ------------------------------------------------------------------------------------------------ +void CallbackToLogRedirector (const char* msg, char* dt) +{ + ai_assert( NULL != msg ); + ai_assert( NULL != dt ); + LogStream* s = (LogStream*)dt; + + s->write(msg); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file) +{ + aiLogStream sout; + + ASSIMP_BEGIN_EXCEPTION_REGION(); + LogStream* stream = LogStream::createDefaultStream(pStream,file); + if (!stream) { + sout.callback = NULL; + sout.user = NULL; + } + else { + sout.callback = &CallbackToLogRedirector; + sout.user = (char*)stream; + } + gPredefinedStreams.push_back(stream); + ASSIMP_END_EXCEPTION_REGION(aiLogStream); + return sout; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiAttachLogStream( const aiLogStream* stream ) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); + +#ifndef ASSIMP_BUILD_SINGLETHREADED + std::lock_guard<std::mutex> lock(gLogStreamMutex); +#endif + + LogStream* lg = new LogToCallbackRedirector(*stream); + gActiveLogStreams[*stream] = lg; + + if (DefaultLogger::isNullLogger()) { + DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); + } + DefaultLogger::get()->attachStream(lg); + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); + +#ifndef ASSIMP_BUILD_SINGLETHREADED + std::lock_guard<std::mutex> lock(gLogStreamMutex); +#endif + // find the log-stream associated with this data + LogStreamMap::iterator it = gActiveLogStreams.find( *stream); + // it should be there... else the user is playing fools with us + if( it == gActiveLogStreams.end()) { + return AI_FAILURE; + } + DefaultLogger::get()->detatchStream( it->second ); + delete it->second; + + gActiveLogStreams.erase( it); + + if (gActiveLogStreams.empty()) { + DefaultLogger::kill(); + } + ASSIMP_END_EXCEPTION_REGION(aiReturn); + return AI_SUCCESS; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiDetachAllLogStreams(void) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); +#ifndef ASSIMP_BUILD_SINGLETHREADED + std::lock_guard<std::mutex> lock(gLogStreamMutex); +#endif + Logger *logger( DefaultLogger::get() ); + if ( NULL == logger ) { + return; + } + + for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { + logger->detatchStream( it->second ); + delete it->second; + } + gActiveLogStreams.clear(); + DefaultLogger::kill(); + + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiEnableVerboseLogging(aiBool d) +{ + if (!DefaultLogger::isNullLogger()) { + DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); + } + gVerboseLogging = d; +} + +// ------------------------------------------------------------------------------------------------ +// Returns the error text of the last failed import process. +const char* aiGetErrorString() +{ + return gLastErrorString.c_str(); +} + +// ----------------------------------------------------------------------------------------------- +// Return the description of a importer given its index +const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex) +{ + return Importer().GetImporterInfo(pIndex); +} + +// ----------------------------------------------------------------------------------------------- +// Return the number of importers +size_t aiGetImportFormatCount(void) +{ + return Importer().GetImporterCount(); +} + +// ------------------------------------------------------------------------------------------------ +// Returns the error text of the last failed import process. +aiBool aiIsExtensionSupported(const char* szExtension) +{ + ai_assert(NULL != szExtension); + aiBool candoit=AI_FALSE; + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // FIXME: no need to create a temporary Importer instance just for that .. + Assimp::Importer tmp; + candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE; + + ASSIMP_END_EXCEPTION_REGION(aiBool); + return candoit; +} + +// ------------------------------------------------------------------------------------------------ +// Get a list of all file extensions supported by ASSIMP +void aiGetExtensionList(aiString* szOut) +{ + ai_assert(NULL != szOut); + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // FIXME: no need to create a temporary Importer instance just for that .. + Assimp::Importer tmp; + tmp.GetExtensionList(*szOut); + + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +// Get the memory requirements for a particular import. +void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn, + C_STRUCT aiMemoryInfo* in) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); + + // find the importer associated with this data + const ScenePrivateData* priv = ScenePriv(pIn); + if( !priv || !priv->mOrigImporter) { + ReportSceneNotFoundError(); + return; + } + + return priv->mOrigImporter->GetMemoryRequirements(*in); + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void) +{ + return reinterpret_cast<aiPropertyStore*>( new PropertyMap() ); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p) +{ + delete reinterpret_cast<PropertyMap*>(p); +} + +// ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyInteger +ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); + PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); + SetGenericProperty<int>(pp->ints,szName,value); + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyFloat +ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); + PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); + SetGenericProperty<ai_real>(pp->floats,szName,value); + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyString +ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName, + const C_STRUCT aiString* st) +{ + if (!st) { + return; + } + ASSIMP_BEGIN_EXCEPTION_REGION(); + PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); + SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str())); + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyMatrix +ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName, + const C_STRUCT aiMatrix4x4* mat) +{ + if (!mat) { + return; + } + ASSIMP_BEGIN_EXCEPTION_REGION(); + PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); + SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat); + ASSIMP_END_EXCEPTION_REGION(void); +} + +// ------------------------------------------------------------------------------------------------ +// Rotation matrix to quaternion +ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat) +{ + ai_assert( NULL != quat ); + ai_assert( NULL != mat ); + *quat = aiQuaternion(*mat); +} + +// ------------------------------------------------------------------------------------------------ +// Matrix decomposition +ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling, + aiQuaternion* rotation, + aiVector3D* position) +{ + ai_assert( NULL != rotation ); + ai_assert( NULL != position ); + ai_assert( NULL != scaling ); + ai_assert( NULL != mat ); + mat->Decompose(*scaling,*rotation,*position); +} + +// ------------------------------------------------------------------------------------------------ +// Matrix transpose +ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat) +{ + ai_assert(NULL != mat); + mat->Transpose(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat) +{ + ai_assert(NULL != mat); + mat->Transpose(); +} + +// ------------------------------------------------------------------------------------------------ +// Vector transformation +ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec, + const aiMatrix3x3* mat) +{ + ai_assert( NULL != mat ); + ai_assert( NULL != vec); + *vec *= (*mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec, + const aiMatrix4x4* mat) +{ + ai_assert( NULL != mat ); + ai_assert( NULL != vec ); + + *vec *= (*mat); +} + +// ------------------------------------------------------------------------------------------------ +// Matrix multiplication +ASSIMP_API void aiMultiplyMatrix4( + aiMatrix4x4* dst, + const aiMatrix4x4* src) +{ + ai_assert( NULL != dst ); + ai_assert( NULL != src ); + *dst = (*dst) * (*src); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMultiplyMatrix3( + aiMatrix3x3* dst, + const aiMatrix3x3* src) +{ + ai_assert( NULL != dst ); + ai_assert( NULL != src ); + *dst = (*dst) * (*src); +} + +// ------------------------------------------------------------------------------------------------ +// Matrix identity +ASSIMP_API void aiIdentityMatrix3( + aiMatrix3x3* mat) +{ + ai_assert(NULL != mat); + *mat = aiMatrix3x3(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiIdentityMatrix4( + aiMatrix4x4* mat) +{ + ai_assert(NULL != mat); + *mat = aiMatrix4x4(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) { + if( NULL == extension ) { + return NULL; + } + const aiImporterDesc *desc( NULL ); + std::vector< BaseImporter* > out; + GetImporterInstanceList( out ); + for( size_t i = 0; i < out.size(); ++i ) { + if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) { + desc = out[ i ]->GetInfo(); + break; + } + } + + DeleteImporterInstanceList(out); + + return desc; +} + +// ------------------------------------------------------------------------------------------------ diff --git a/thirdparty/assimp/code/BaseImporter.cpp b/thirdparty/assimp/code/Common/BaseImporter.cpp index 4803c6d6f2..5c1e605549 100644 --- a/thirdparty/assimp/code/BaseImporter.cpp +++ b/thirdparty/assimp/code/Common/BaseImporter.cpp @@ -67,7 +67,20 @@ using namespace Assimp; // Constructor to be privately used by Importer BaseImporter::BaseImporter() AI_NO_EXCEPT : m_progress() { - // nothing to do here + /** + * Assimp Importer + * unit conversions available + * if you need another measurment unit add it below. + * it's currently defined in assimp that we prefer meters. + * + * NOTE: Initialised here rather than in the header file + * to workaround a VS2013 bug with brace initialisers + * */ + importerUnits[ImporterUnits::M] = 1.0; + importerUnits[ImporterUnits::CM] = 0.01; + importerUnits[ImporterUnits::MM] = 0.001; + importerUnits[ImporterUnits::INCHES] = 0.0254; + importerUnits[ImporterUnits::FEET] = 0.3048; } // ------------------------------------------------------------------------------------------------ @@ -76,9 +89,25 @@ BaseImporter::~BaseImporter() { // nothing to do here } +void BaseImporter::UpdateImporterScale( Importer* pImp ) +{ + ai_assert(pImp != nullptr); + ai_assert(importerScale != 0.0); + ai_assert(fileScale != 0.0); + + double activeScale = importerScale * fileScale; + + // Set active scaling + pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, static_cast<float>( activeScale) ); + + ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale ); +} + // ------------------------------------------------------------------------------------------------ // Imports the given file and returns the imported data. -aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) { +aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) { + + m_progress = pImp->GetProgressHandler(); if (nullptr == m_progress) { return nullptr; @@ -100,6 +129,11 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, { InternReadFile( pFile, sc.get(), &filter); + // Calculate import scale hook - required because pImp not available anywhere else + // passes scale into ScaleProcess + UpdateImporterScale(pImp); + + } catch( const std::exception& err ) { // extract error description m_ErrorText = err.what(); @@ -112,7 +146,7 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, } // ------------------------------------------------------------------------------------------------ -void BaseImporter::SetupProperties(const Importer* /*pImp*/) +void BaseImporter::SetupProperties(const Importer* pImp) { // the default implementation does nothing } @@ -320,7 +354,11 @@ std::string BaseImporter::GetExtension( const std::string& file ) { return false; } -#include "../contrib/utf8cpp/source/utf8.h" +#ifdef ASSIMP_USE_HUNTER +# include <utf8/utf8.h> +#else +# include "../contrib/utf8cpp/source/utf8.h" +#endif // ------------------------------------------------------------------------------------------------ // Convert to UTF8 data @@ -584,6 +622,8 @@ aiScene* BatchLoader::GetImport( unsigned int which ) return nullptr; } + + // ------------------------------------------------------------------------------------------------ void BatchLoader::LoadAll() { diff --git a/thirdparty/assimp/code/BaseProcess.cpp b/thirdparty/assimp/code/Common/BaseProcess.cpp index 18872c3693..e247be418d 100644 --- a/thirdparty/assimp/code/BaseProcess.cpp +++ b/thirdparty/assimp/code/Common/BaseProcess.cpp @@ -89,7 +89,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp) // and kill the partially imported data delete pImp->Pimpl()->mScene; - pImp->Pimpl()->mScene = NULL; + pImp->Pimpl()->mScene = nullptr; } } diff --git a/thirdparty/assimp/code/BaseProcess.h b/thirdparty/assimp/code/Common/BaseProcess.h index 4d5c7a76be..4d5c7a76be 100644 --- a/thirdparty/assimp/code/BaseProcess.h +++ b/thirdparty/assimp/code/Common/BaseProcess.h diff --git a/thirdparty/assimp/code/Bitmap.cpp b/thirdparty/assimp/code/Common/Bitmap.cpp index b22b71ea9e..b22b71ea9e 100644 --- a/thirdparty/assimp/code/Bitmap.cpp +++ b/thirdparty/assimp/code/Common/Bitmap.cpp diff --git a/thirdparty/assimp/code/CreateAnimMesh.cpp b/thirdparty/assimp/code/Common/CreateAnimMesh.cpp index 1a052849bb..98b60e5319 100644 --- a/thirdparty/assimp/code/CreateAnimMesh.cpp +++ b/thirdparty/assimp/code/Common/CreateAnimMesh.cpp @@ -47,10 +47,6 @@ namespace Assimp { aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) { aiAnimMesh *animesh = new aiAnimMesh; - animesh->mVertices = NULL; - animesh->mNormals = NULL; - animesh->mTangents = NULL; - animesh->mBitangents = NULL; animesh->mNumVertices = mesh->mNumVertices; if (mesh->mVertices) { animesh->mVertices = new aiVector3D[animesh->mNumVertices]; diff --git a/thirdparty/assimp/code/DefaultIOStream.cpp b/thirdparty/assimp/code/Common/DefaultIOStream.cpp index 1c100b6189..1c100b6189 100644 --- a/thirdparty/assimp/code/DefaultIOStream.cpp +++ b/thirdparty/assimp/code/Common/DefaultIOStream.cpp diff --git a/thirdparty/assimp/code/DefaultIOSystem.cpp b/thirdparty/assimp/code/Common/DefaultIOSystem.cpp index d40b67de32..6fdc24dd80 100644 --- a/thirdparty/assimp/code/DefaultIOSystem.cpp +++ b/thirdparty/assimp/code/Common/DefaultIOSystem.cpp @@ -61,83 +61,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -// maximum path length -// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html -#ifdef PATH_MAX -# define PATHLIMIT PATH_MAX -#else -# define PATHLIMIT 4096 +#ifdef _WIN32 +static std::wstring Utf8ToWide(const char* in) +{ + int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0); + // size includes terminating null; std::wstring adds null automatically + std::wstring out(static_cast<size_t>(size) - 1, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size); + return out; +} + +static std::string WideToUtf8(const wchar_t* in) +{ + int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr); + // size includes terminating null; std::string adds null automatically + std::string out(static_cast<size_t>(size) - 1, '\0'); + WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr); + return out; +} #endif // ------------------------------------------------------------------------------------------------ // Tests for the existence of a file at the given path. -bool DefaultIOSystem::Exists( const char* pFile) const +bool DefaultIOSystem::Exists(const char* pFile) const { #ifdef _WIN32 - wchar_t fileName16[PATHLIMIT]; - -#ifndef WindowsStore - bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0; - if (isUnicode) { - - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); - struct __stat64 filestat; - if (0 != _wstat64(fileName16, &filestat)) { - return false; - } - } else { -#endif - FILE* file = ::fopen(pFile, "rb"); - if (!file) - return false; - - ::fclose(file); -#ifndef WindowsStore + struct __stat64 filestat; + if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) { + return false; } -#endif #else - FILE* file = ::fopen( pFile, "rb"); - if( !file) + FILE* file = ::fopen(pFile, "rb"); + if (!file) return false; - ::fclose( file); + ::fclose(file); #endif return true; } // ------------------------------------------------------------------------------------------------ // Open a new file with a given path. -IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) +IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode) { - ai_assert(NULL != strFile); - ai_assert(NULL != strMode); + ai_assert(strFile != nullptr); + ai_assert(strMode != nullptr); FILE* file; #ifdef _WIN32 - wchar_t fileName16[PATHLIMIT]; -#ifndef WindowsStore - bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0; - if (isUnicode) { - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); - std::string mode8(strMode); - file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str()); - } else { -#endif - file = ::fopen(strFile, strMode); -#ifndef WindowsStore - } -#endif + file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str()); #else file = ::fopen(strFile, strMode); #endif - if (nullptr == file) + if (!file) return nullptr; - return new DefaultIOStream(file, (std::string) strFile); + return new DefaultIOStream(file, strFile); } // ------------------------------------------------------------------------------------------------ // Closes the given file and releases all resources associated with it. -void DefaultIOSystem::Close( IOStream* pFile) +void DefaultIOSystem::Close(IOStream* pFile) { delete pFile; } @@ -155,78 +138,56 @@ char DefaultIOSystem::getOsSeparator() const // ------------------------------------------------------------------------------------------------ // IOSystem default implementation (ComparePaths isn't a pure virtual function) -bool IOSystem::ComparePaths (const char* one, const char* second) const +bool IOSystem::ComparePaths(const char* one, const char* second) const { - return !ASSIMP_stricmp(one,second); + return !ASSIMP_stricmp(one, second); } // ------------------------------------------------------------------------------------------------ // Convert a relative path into an absolute path -inline static void MakeAbsolutePath (const char* in, char* _out) +inline static std::string MakeAbsolutePath(const char* in) { - ai_assert(in && _out); -#if defined( _MSC_VER ) || defined( __MINGW32__ ) -#ifndef WindowsStore - bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0; - if (isUnicode) { - wchar_t out16[PATHLIMIT]; - wchar_t in16[PATHLIMIT]; - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, -1, out16, PATHLIMIT); - wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT); - if (ret) { - WideCharToMultiByte(CP_UTF8, MB_PRECOMPOSED, out16, -1, _out, PATHLIMIT, nullptr, nullptr); - } - if (!ret) { - // preserve the input path, maybe someone else is able to fix - // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); - strcpy(_out, in); - } - - } else { -#endif - char* ret = :: _fullpath(_out, in, PATHLIMIT); - if (!ret) { - // preserve the input path, maybe someone else is able to fix - // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); - strcpy(_out, in); - } -#ifndef WindowsStore + ai_assert(in); + std::string out; +#ifdef _WIN32 + wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0); + if (ret) { + out = WideToUtf8(ret); + free(ret); } -#endif #else - // use realpath - char* ret = realpath(in, _out); - if(!ret) { + char* ret = realpath(in, nullptr); + if (ret) { + out = ret; + free(ret); + } +#endif + if (!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); - strcpy(_out,in); + out = in; } -#endif + return out; } // ------------------------------------------------------------------------------------------------ // DefaultIOSystem's more specialized implementation -bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const +bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const { // chances are quite good both paths are formatted identically, // so we can hopefully return here already - if( !ASSIMP_stricmp(one,second) ) + if (!ASSIMP_stricmp(one, second)) return true; - char temp1[PATHLIMIT]; - char temp2[PATHLIMIT]; - - MakeAbsolutePath (one, temp1); - MakeAbsolutePath (second, temp2); + std::string temp1 = MakeAbsolutePath(one); + std::string temp2 = MakeAbsolutePath(second); - return !ASSIMP_stricmp(temp1,temp2); + return !ASSIMP_stricmp(temp1, temp2); } // ------------------------------------------------------------------------------------------------ -std::string DefaultIOSystem::fileName( const std::string &path ) +std::string DefaultIOSystem::fileName(const std::string& path) { std::string ret = path; std::size_t last = ret.find_last_of("\\/"); @@ -235,16 +196,16 @@ std::string DefaultIOSystem::fileName( const std::string &path ) } // ------------------------------------------------------------------------------------------------ -std::string DefaultIOSystem::completeBaseName( const std::string &path ) +std::string DefaultIOSystem::completeBaseName(const std::string& path) { std::string ret = fileName(path); std::size_t pos = ret.find_last_of('.'); - if(pos != ret.npos) ret = ret.substr(0, pos); + if (pos != std::string::npos) ret = ret.substr(0, pos); return ret; } // ------------------------------------------------------------------------------------------------ -std::string DefaultIOSystem::absolutePath( const std::string &path ) +std::string DefaultIOSystem::absolutePath(const std::string& path) { std::string ret = path; std::size_t last = ret.find_last_of("\\/"); @@ -253,5 +214,3 @@ std::string DefaultIOSystem::absolutePath( const std::string &path ) } // ------------------------------------------------------------------------------------------------ - -#undef PATHLIMIT diff --git a/thirdparty/assimp/code/DefaultLogger.cpp b/thirdparty/assimp/code/Common/DefaultLogger.cpp index de3528d2b4..de3528d2b4 100644 --- a/thirdparty/assimp/code/DefaultLogger.cpp +++ b/thirdparty/assimp/code/Common/DefaultLogger.cpp diff --git a/thirdparty/assimp/code/DefaultProgressHandler.h b/thirdparty/assimp/code/Common/DefaultProgressHandler.h index bd2cce00be..bd2cce00be 100644 --- a/thirdparty/assimp/code/DefaultProgressHandler.h +++ b/thirdparty/assimp/code/Common/DefaultProgressHandler.h diff --git a/thirdparty/assimp/code/Exporter.cpp b/thirdparty/assimp/code/Common/Exporter.cpp index 8848e87f5b..4ce1a2bd80 100644 --- a/thirdparty/assimp/code/Exporter.cpp +++ b/thirdparty/assimp/code/Common/Exporter.cpp @@ -61,15 +61,16 @@ Here we implement only the C++ interface (Assimp::Exporter). #include <assimp/mesh.h> #include <assimp/postprocess.h> #include <assimp/scene.h> - -#include "DefaultProgressHandler.h" -#include "BaseProcess.h" -#include "JoinVerticesProcess.h" -#include "MakeVerboseFormat.h" -#include "ConvertToLHProcess.h" -#include "PretransformVertices.h" #include <assimp/Exceptional.h> -#include "ScenePrivate.h" + +#include "Common/DefaultProgressHandler.h" +#include "Common/BaseProcess.h" +#include "Common/ScenePrivate.h" +#include "PostProcessing/CalcTangentsProcess.h" +#include "PostProcessing/MakeVerboseFormat.h" +#include "PostProcessing/JoinVerticesProcess.h" +#include "PostProcessing/ConvertToLHProcess.h" +#include "PostProcessing/PretransformVertices.h" #include <memory> @@ -101,6 +102,9 @@ void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperti void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); +void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneA3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*); // ------------------------------------------------------------------------------------------------ // global array of all export formats which Assimp supports in its current build @@ -161,11 +165,11 @@ Exporter::ExportFormatEntry gExporters[] = #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER - Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0 ), + Exporter::ExportFormatEntry( "assbin", "Assimp Binary File", "assbin" , &ExportSceneAssbin, 0 ), #endif #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER - Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0 ), + Exporter::ExportFormatEntry( "assxml", "Assimp XML Document", "assxml" , &ExportSceneAssxml, 0 ), #endif #ifndef ASSIMP_BUILD_NO_X3D_EXPORTER @@ -177,8 +181,17 @@ Exporter::ExportFormatEntry gExporters[] = Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ), #endif +#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER + Exporter::ExportFormatEntry( "m3d", "Model 3D (binary)", "m3d", &ExportSceneM3D, 0 ), + Exporter::ExportFormatEntry( "a3d", "Model 3D (ascii)", "m3d", &ExportSceneA3D, 0 ), +#endif + #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER - Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ) + Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ), +#endif + +#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER + Exporter::ExportFormatEntry( "assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0) #endif }; @@ -288,7 +301,7 @@ void Exporter::SetProgressHandler(ProgressHandler* pHandler) { // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId, - unsigned int, const ExportProperties* /*pProperties*/ ) { + unsigned int pPreprocessing, const ExportProperties* pProperties) { if (pimpl->blob) { delete pimpl->blob; pimpl->blob = nullptr; @@ -298,7 +311,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha BlobIOSystem* blobio = new BlobIOSystem(); pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio ); - if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) { + if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) { pimpl->mIOSystem = old; return nullptr; } @@ -310,34 +323,6 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha } // ------------------------------------------------------------------------------------------------ -bool IsVerboseFormat(const aiMesh* mesh) { - // avoid slow vector<bool> specialization - std::vector<unsigned int> seen(mesh->mNumVertices,0); - for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { - const aiFace& f = mesh->mFaces[i]; - for(unsigned int j = 0; j < f.mNumIndices; ++j) { - if(++seen[f.mIndices[j]] == 2) { - // found a duplicate index - return false; - } - } - } - - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool IsVerboseFormat(const aiScene* pScene) { - for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - if(!IsVerboseFormat(pScene->mMeshes[i])) { - return false; - } - } - - return true; -} - -// ------------------------------------------------------------------------------------------------ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -346,7 +331,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c // format. They will likely not be aware that there is a flag in the scene to indicate // this, however. To avoid surprises and bug reports, we check for duplicates in // meshes upfront. - const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene); + const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || MakeVerboseFormatProcess::IsVerboseFormat(pScene); pimpl->mProgressHandler->UpdateFileWrite(0, 4); @@ -466,7 +451,10 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c } ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. - exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties); + ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; + pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again); + exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); + exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); pimpl->mProgressHandler->UpdateFileWrite(4, 4); } catch (DeadlyExportError& err) { diff --git a/thirdparty/assimp/code/FileLogStream.h b/thirdparty/assimp/code/Common/FileLogStream.h index 740c503192..740c503192 100644 --- a/thirdparty/assimp/code/FileLogStream.h +++ b/thirdparty/assimp/code/Common/FileLogStream.h diff --git a/thirdparty/assimp/code/FileSystemFilter.h b/thirdparty/assimp/code/Common/FileSystemFilter.h index 9923cdbdd3..9923cdbdd3 100644 --- a/thirdparty/assimp/code/FileSystemFilter.h +++ b/thirdparty/assimp/code/Common/FileSystemFilter.h diff --git a/thirdparty/assimp/code/Common/IFF.h b/thirdparty/assimp/code/Common/IFF.h new file mode 100644 index 0000000000..91d7d48289 --- /dev/null +++ b/thirdparty/assimp/code/Common/IFF.h @@ -0,0 +1,102 @@ +// Definitions for the Interchange File Format (IFF) +// Alexander Gessler, 2006 +// Adapted to Assimp August 2008 + +#ifndef AI_IFF_H_INCLUDED +#define AI_IFF_H_INCLUDED + +#include <assimp/ByteSwapper.h> + +namespace Assimp { +namespace IFF { + +///////////////////////////////////////////////////////////////////////////////// +//! Describes an IFF chunk header +///////////////////////////////////////////////////////////////////////////////// +struct ChunkHeader +{ + //! Type of the chunk header - FourCC + uint32_t type; + + //! Length of the chunk data, in bytes + uint32_t length; +}; + + +///////////////////////////////////////////////////////////////////////////////// +//! Describes an IFF sub chunk header +///////////////////////////////////////////////////////////////////////////////// +struct SubChunkHeader +{ + //! Type of the chunk header - FourCC + uint32_t type; + + //! Length of the chunk data, in bytes + uint16_t length; +}; + + +#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \ + ((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d))) + + +#define AI_IFF_FOURCC_FORM AI_IFF_FOURCC('F','O','R','M') + + +///////////////////////////////////////////////////////////////////////////////// +//! Load a chunk header +//! @param outFile Pointer to the file data - points to the chunk data afterwards +//! @return Copy of the chunk header +///////////////////////////////////////////////////////////////////////////////// +inline ChunkHeader LoadChunk(uint8_t*& outFile) +{ + ChunkHeader head; + ::memcpy(&head.type, outFile, 4); + outFile += 4; + ::memcpy(&head.length, outFile, 4); + outFile += 4; + AI_LSWAP4(head.length); + AI_LSWAP4(head.type); + return head; +} + +///////////////////////////////////////////////////////////////////////////////// +//! Load a sub chunk header +//! @param outFile Pointer to the file data - points to the chunk data afterwards +//! @return Copy of the sub chunk header +///////////////////////////////////////////////////////////////////////////////// +inline SubChunkHeader LoadSubChunk(uint8_t*& outFile) +{ + SubChunkHeader head; + ::memcpy(&head.type, outFile, 4); + outFile += 4; + ::memcpy(&head.length, outFile, 2); + outFile += 2; + AI_LSWAP2(head.length); + AI_LSWAP4(head.type); + return head; +} + +///////////////////////////////////////////////////////////////////////////////// +//! Read the file header and return the type of the file and its size +//! @param outFile Pointer to the file data. The buffer must at +//! least be 12 bytes large. +//! @param fileType Receives the type of the file +//! @return 0 if everything was OK, otherwise an error message +///////////////////////////////////////////////////////////////////////////////// +inline const char* ReadHeader(uint8_t* outFile, uint32_t& fileType) +{ + ChunkHeader head = LoadChunk(outFile); + if(AI_IFF_FOURCC_FORM != head.type) + { + return "The file is not an IFF file: FORM chunk is missing"; + } + ::memcpy(&fileType, outFile, 4); + AI_LSWAP4(fileType); + return 0; +} + + +}} + +#endif // !! AI_IFF_H_INCLUDED diff --git a/thirdparty/assimp/code/Importer.cpp b/thirdparty/assimp/code/Common/Importer.cpp index 65b16471cc..91b50859a0 100644 --- a/thirdparty/assimp/code/Importer.cpp +++ b/thirdparty/assimp/code/Common/Importer.cpp @@ -64,15 +64,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ------------------------------------------------------------------------------------------------ // Internal headers // ------------------------------------------------------------------------------------------------ -#include "Importer.h" -#include <assimp/BaseImporter.h> -#include "BaseProcess.h" +#include "Common/Importer.h" +#include "Common/BaseProcess.h" +#include "Common/DefaultProgressHandler.h" +#include "PostProcessing/ProcessHelper.h" +#include "Common/ScenePreprocessor.h" +#include "Common/ScenePrivate.h" -#include "DefaultProgressHandler.h" +#include <assimp/BaseImporter.h> #include <assimp/GenericProperty.h> -#include "ProcessHelper.h" -#include "ScenePreprocessor.h" -#include "ScenePrivate.h" #include <assimp/MemoryIOWrapper.h> #include <assimp/Profiler.h> #include <assimp/TinyFormatter.h> @@ -86,7 +86,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/DefaultIOSystem.h> #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS -# include "ValidateDataStructure.h" +# include "PostProcessing/ValidateDataStructure.h" #endif using namespace Assimp::Profiling; @@ -590,10 +590,12 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // Find an worker class which can handle the file BaseImporter* imp = NULL; + SetPropertyInteger("importerIndex", -1); for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) { imp = pimpl->mImporter[a]; + SetPropertyInteger("importerIndex", a); break; } } @@ -606,6 +608,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { imp = pimpl->mImporter[a]; + SetPropertyInteger("importerIndex", a); break; } } diff --git a/thirdparty/assimp/code/Importer.h b/thirdparty/assimp/code/Common/Importer.h index a439d99c2f..a439d99c2f 100644 --- a/thirdparty/assimp/code/Importer.h +++ b/thirdparty/assimp/code/Common/Importer.h diff --git a/thirdparty/assimp/code/ImporterRegistry.cpp b/thirdparty/assimp/code/Common/ImporterRegistry.cpp index 747815fa6f..b9f28f0356 100644 --- a/thirdparty/assimp/code/ImporterRegistry.cpp +++ b/thirdparty/assimp/code/Common/ImporterRegistry.cpp @@ -56,146 +56,149 @@ corresponding preprocessor flag to selectively disable formats. // (include_new_importers_here) // ------------------------------------------------------------------------------------------------ #ifndef ASSIMP_BUILD_NO_X_IMPORTER -# include "XFileImporter.h" +# include "X/XFileImporter.h" #endif #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER -# include "AMFImporter.hpp" +# include "AMF/AMFImporter.hpp" #endif #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER -# include "3DSLoader.h" +# include "3DS/3DSLoader.h" #endif #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER -# include "MD3Loader.h" +# include "MD3/MD3Loader.h" #endif #ifndef ASSIMP_BUILD_NO_MDL_IMPORTER -# include "MDLLoader.h" +# include "MDL/MDLLoader.h" #endif #ifndef ASSIMP_BUILD_NO_MD2_IMPORTER -# include "MD2Loader.h" +# include "MD2/MD2Loader.h" #endif #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER -# include "PlyLoader.h" +# include "Ply/PlyLoader.h" #endif #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER -# include "ASELoader.h" +# include "ASE/ASELoader.h" #endif #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER -# include "ObjFileImporter.h" +# include "Obj/ObjFileImporter.h" #endif #ifndef ASSIMP_BUILD_NO_HMP_IMPORTER -# include "HMPLoader.h" +# include "HMP/HMPLoader.h" #endif #ifndef ASSIMP_BUILD_NO_SMD_IMPORTER -# include "SMDLoader.h" +# include "SMD/SMDLoader.h" #endif #ifndef ASSIMP_BUILD_NO_MDC_IMPORTER -# include "MDCLoader.h" +# include "MDC/MDCLoader.h" #endif #ifndef ASSIMP_BUILD_NO_MD5_IMPORTER -# include "MD5Loader.h" +# include "MD5/MD5Loader.h" #endif #ifndef ASSIMP_BUILD_NO_STL_IMPORTER -# include "STLLoader.h" +# include "STL/STLLoader.h" #endif #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER -# include "LWOLoader.h" +# include "LWO/LWOLoader.h" #endif #ifndef ASSIMP_BUILD_NO_DXF_IMPORTER -# include "DXFLoader.h" +# include "DXF/DXFLoader.h" #endif #ifndef ASSIMP_BUILD_NO_NFF_IMPORTER -# include "NFFLoader.h" +# include "NFF/NFFLoader.h" #endif #ifndef ASSIMP_BUILD_NO_RAW_IMPORTER -# include "RawLoader.h" +# include "Raw/RawLoader.h" #endif #ifndef ASSIMP_BUILD_NO_SIB_IMPORTER -# include "SIBImporter.h" +# include "SIB/SIBImporter.h" #endif #ifndef ASSIMP_BUILD_NO_OFF_IMPORTER -# include "OFFLoader.h" +# include "OFF/OFFLoader.h" #endif #ifndef ASSIMP_BUILD_NO_AC_IMPORTER -# include "ACLoader.h" +# include "AC/ACLoader.h" #endif #ifndef ASSIMP_BUILD_NO_BVH_IMPORTER -# include "BVHLoader.h" +# include "BVH/BVHLoader.h" #endif #ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER -# include "IRRMeshLoader.h" +# include "Irr/IRRMeshLoader.h" #endif #ifndef ASSIMP_BUILD_NO_IRR_IMPORTER -# include "IRRLoader.h" +# include "Irr/IRRLoader.h" #endif #ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER -# include "Q3DLoader.h" +# include "Q3D/Q3DLoader.h" #endif #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER -# include "B3DImporter.h" +# include "B3D/B3DImporter.h" #endif #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER -# include "ColladaLoader.h" +# include "Collada/ColladaLoader.h" #endif #ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER -# include "TerragenLoader.h" +# include "Terragen/TerragenLoader.h" #endif #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER -# include "CSMLoader.h" +# include "CSM/CSMLoader.h" #endif #ifndef ASSIMP_BUILD_NO_3D_IMPORTER -# include "UnrealLoader.h" +# include "Unreal/UnrealLoader.h" #endif #ifndef ASSIMP_BUILD_NO_LWS_IMPORTER -# include "LWSLoader.h" +# include "LWS/LWSLoader.h" #endif #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER -# include "OgreImporter.h" +# include "Ogre/OgreImporter.h" #endif #ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER -# include "OpenGEXImporter.h" +# include "OpenGEX/OpenGEXImporter.h" #endif #ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER -# include "MS3DLoader.h" +# include "MS3D/MS3DLoader.h" #endif #ifndef ASSIMP_BUILD_NO_COB_IMPORTER -# include "COBLoader.h" +# include "COB/COBLoader.h" #endif #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER -# include "BlenderLoader.h" +# include "Blender/BlenderLoader.h" #endif #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER -# include "Q3BSPFileImporter.h" +# include "Q3BSP/Q3BSPFileImporter.h" #endif #ifndef ASSIMP_BUILD_NO_NDO_IMPORTER -# include "NDOLoader.h" +# include "NDO/NDOLoader.h" #endif #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER # include "Importer/IFC/IFCLoader.h" #endif #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER -# include "XGLLoader.h" +# include "XGL/XGLLoader.h" #endif #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER -# include "FBXImporter.h" +# include "FBX/FBXImporter.h" #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER -# include "AssbinLoader.h" +# include "Assbin/AssbinLoader.h" #endif #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER -# include "glTFImporter.h" -# include "glTF2Importer.h" +# include "glTF/glTFImporter.h" +# include "glTF2/glTF2Importer.h" #endif #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER -# include "C4DImporter.h" +# include "C4D/C4DImporter.h" #endif #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER -# include "D3MFImporter.h" +# include "3MF/D3MFImporter.h" #endif #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER -# include "X3DImporter.hpp" +# include "X3D/X3DImporter.hpp" #endif #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER -# include "MMDImporter.h" +# include "MMD/MMDImporter.h" +#endif +#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER +# include "M3D/M3DImporter.h" #endif #ifndef ASSIMP_BUILD_NO_STEP_IMPORTER # include "Importer/StepFile/StepFileImporter.h" @@ -223,6 +226,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER) out.push_back( new Discreet3DSImporter()); #endif +#if (!defined ASSIMP_BUILD_NO_M3D_IMPORTER) + out.push_back( new M3DImporter()); +#endif #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER) out.push_back( new MD3Importer()); #endif @@ -364,7 +370,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){ for(size_t i= 0; i<deleteList.size();++i){ delete deleteList[i]; - deleteList[i]=NULL; + deleteList[i]=nullptr; }//for } diff --git a/thirdparty/assimp/code/PolyTools.h b/thirdparty/assimp/code/Common/PolyTools.h index fbbda0e7d1..fbbda0e7d1 100644 --- a/thirdparty/assimp/code/PolyTools.h +++ b/thirdparty/assimp/code/Common/PolyTools.h diff --git a/thirdparty/assimp/code/PostStepRegistry.cpp b/thirdparty/assimp/code/Common/PostStepRegistry.cpp index 15b4a28843..8ff4af0400 100644 --- a/thirdparty/assimp/code/PostStepRegistry.cpp +++ b/thirdparty/assimp/code/Common/PostStepRegistry.cpp @@ -48,89 +48,97 @@ directly (unless you are adding new steps), instead use the corresponding preprocessor flag to selectively disable steps. */ -#include "ProcessHelper.h" +#include "PostProcessing/ProcessHelper.h" #ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS -# include "CalcTangentsProcess.h" +# include "PostProcessing/CalcTangentsProcess.h" #endif #ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS -# include "JoinVerticesProcess.h" +# include "PostProcessing/JoinVerticesProcess.h" #endif #if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) -# include "ConvertToLHProcess.h" +# include "PostProcessing/ConvertToLHProcess.h" #endif #ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS -# include "TriangulateProcess.h" +# include "PostProcessing/TriangulateProcess.h" #endif #ifndef ASSIMP_BUILD_NO_DROPFACENORMALS_PROCESS -# include "DropFaceNormalsProcess.h" +# include "PostProcessing/DropFaceNormalsProcess.h" #endif #ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS -# include "GenFaceNormalsProcess.h" +# include "PostProcessing/GenFaceNormalsProcess.h" #endif #ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS -# include "GenVertexNormalsProcess.h" +# include "PostProcessing/GenVertexNormalsProcess.h" #endif #ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS -# include "RemoveVCProcess.h" +# include "PostProcessing/RemoveVCProcess.h" #endif #ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS -# include "SplitLargeMeshes.h" +# include "PostProcessing/SplitLargeMeshes.h" #endif #ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS -# include "PretransformVertices.h" +# include "PostProcessing/PretransformVertices.h" #endif #ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS -# include "LimitBoneWeightsProcess.h" +# include "PostProcessing/LimitBoneWeightsProcess.h" #endif #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS -# include "ValidateDataStructure.h" +# include "PostProcessing/ValidateDataStructure.h" #endif #ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS -# include "ImproveCacheLocality.h" +# include "PostProcessing/ImproveCacheLocality.h" #endif #ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS -# include "FixNormalsStep.h" +# include "PostProcessing/FixNormalsStep.h" #endif #ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS -# include "RemoveRedundantMaterials.h" +# include "PostProcessing/RemoveRedundantMaterials.h" #endif #if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS) -# include "EmbedTexturesProcess.h" +# include "PostProcessing/EmbedTexturesProcess.h" #endif #ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS -# include "FindInvalidDataProcess.h" +# include "PostProcessing/FindInvalidDataProcess.h" #endif #ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS -# include "FindDegenerates.h" +# include "PostProcessing/FindDegenerates.h" #endif #ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS -# include "SortByPTypeProcess.h" +# include "PostProcessing/SortByPTypeProcess.h" #endif #ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS -# include "ComputeUVMappingProcess.h" +# include "PostProcessing/ComputeUVMappingProcess.h" #endif #ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS -# include "TextureTransform.h" +# include "PostProcessing/TextureTransform.h" #endif #ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS -# include "FindInstancesProcess.h" +# include "PostProcessing/FindInstancesProcess.h" #endif #ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS -# include "OptimizeMeshes.h" +# include "PostProcessing/OptimizeMeshes.h" #endif #ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS -# include "OptimizeGraph.h" +# include "PostProcessing/OptimizeGraph.h" #endif #ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS -# include "SplitByBoneCountProcess.h" +# include "Common/SplitByBoneCountProcess.h" #endif #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS -# include "DeboneProcess.h" +# include "PostProcessing/DeboneProcess.h" #endif #if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) -# include "ScaleProcess.h" +# include "PostProcessing/ScaleProcess.h" #endif +#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS) +# include "PostProcessing/ArmaturePopulate.h" +#endif +#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS) +# include "PostProcessing/GenBoundingBoxesProcess.h" +#endif + + namespace Assimp { @@ -176,6 +184,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) out.push_back( new ScaleProcess()); #endif +#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS) + out.push_back( new ArmaturePopulate()); +#endif #if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS) out.push_back( new PretransformVertices()); #endif @@ -246,6 +257,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS) out.push_back( new ImproveCacheLocalityProcess()); #endif +#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS) + out.push_back(new GenBoundingBoxesProcess); +#endif } } diff --git a/thirdparty/assimp/code/RemoveComments.cpp b/thirdparty/assimp/code/Common/RemoveComments.cpp index 91700a7699..91700a7699 100644 --- a/thirdparty/assimp/code/RemoveComments.cpp +++ b/thirdparty/assimp/code/Common/RemoveComments.cpp diff --git a/thirdparty/assimp/code/SGSpatialSort.cpp b/thirdparty/assimp/code/Common/SGSpatialSort.cpp index 120070b0aa..120070b0aa 100644 --- a/thirdparty/assimp/code/SGSpatialSort.cpp +++ b/thirdparty/assimp/code/Common/SGSpatialSort.cpp diff --git a/thirdparty/assimp/code/SceneCombiner.cpp b/thirdparty/assimp/code/Common/SceneCombiner.cpp index e445bd7434..f7b13cc951 100644 --- a/thirdparty/assimp/code/SceneCombiner.cpp +++ b/thirdparty/assimp/code/Common/SceneCombiner.cpp @@ -1091,6 +1091,35 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) { aiFace& f = dest->mFaces[i]; GetArrayCopy(f.mIndices,f.mNumIndices); } + + // make a deep copy of all blend shapes + CopyPtrArray(dest->mAnimMeshes, dest->mAnimMeshes, dest->mNumAnimMeshes); +} + +// ------------------------------------------------------------------------------------------------ +void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) { + if (nullptr == _dest || nullptr == src) { + return; + } + + aiAnimMesh* dest = *_dest = new aiAnimMesh(); + + // get a flat copy + ::memcpy(dest, src, sizeof(aiAnimMesh)); + + // and reallocate all arrays + GetArrayCopy(dest->mVertices, dest->mNumVertices); + GetArrayCopy(dest->mNormals, dest->mNumVertices); + GetArrayCopy(dest->mTangents, dest->mNumVertices); + GetArrayCopy(dest->mBitangents, dest->mNumVertices); + + unsigned int n = 0; + while (dest->HasTextureCoords(n)) + GetArrayCopy(dest->mTextureCoords[n++], dest->mNumVertices); + + n = 0; + while (dest->HasVertexColors(n)) + GetArrayCopy(dest->mColors[n++], dest->mNumVertices); } // ------------------------------------------------------------------------------------------------ @@ -1167,6 +1196,7 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) { // and reallocate all arrays CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels ); + CopyPtrArray( dest->mMorphMeshChannels, src->mMorphMeshChannels, dest->mNumMorphMeshChannels ); } // ------------------------------------------------------------------------------------------------ @@ -1186,6 +1216,26 @@ void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) { GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys ); } +void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } + + aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim(); + + // get a flat copy + ::memcpy(dest,src,sizeof(aiMeshMorphAnim)); + + // and reallocate all arrays + GetArrayCopy( dest->mKeys, dest->mNumKeys ); + for (ai_uint i = 0; i < dest->mNumKeys;++i) { + dest->mKeys[i].mValues = new unsigned int[dest->mKeys[i].mNumValuesAndWeights]; + dest->mKeys[i].mWeights = new double[dest->mKeys[i].mNumValuesAndWeights]; + ::memcpy(dest->mKeys[i].mValues, src->mKeys[i].mValues, dest->mKeys[i].mNumValuesAndWeights * sizeof(unsigned int)); + ::memcpy(dest->mKeys[i].mWeights, src->mKeys[i].mWeights, dest->mKeys[i].mNumValuesAndWeights * sizeof(double)); + } +} + // ------------------------------------------------------------------------------------------------ void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) { if ( nullptr == _dest || nullptr == src ) { diff --git a/thirdparty/assimp/code/ScenePreprocessor.cpp b/thirdparty/assimp/code/Common/ScenePreprocessor.cpp index 432a3d7666..432a3d7666 100644 --- a/thirdparty/assimp/code/ScenePreprocessor.cpp +++ b/thirdparty/assimp/code/Common/ScenePreprocessor.cpp diff --git a/thirdparty/assimp/code/ScenePreprocessor.h b/thirdparty/assimp/code/Common/ScenePreprocessor.h index 3f4c8d7c3f..3f4c8d7c3f 100644 --- a/thirdparty/assimp/code/ScenePreprocessor.h +++ b/thirdparty/assimp/code/Common/ScenePreprocessor.h diff --git a/thirdparty/assimp/code/ScenePrivate.h b/thirdparty/assimp/code/Common/ScenePrivate.h index f336aafc9a..f336aafc9a 100644 --- a/thirdparty/assimp/code/ScenePrivate.h +++ b/thirdparty/assimp/code/Common/ScenePrivate.h diff --git a/thirdparty/assimp/code/SkeletonMeshBuilder.cpp b/thirdparty/assimp/code/Common/SkeletonMeshBuilder.cpp index 06cfe034e9..06cfe034e9 100644 --- a/thirdparty/assimp/code/SkeletonMeshBuilder.cpp +++ b/thirdparty/assimp/code/Common/SkeletonMeshBuilder.cpp diff --git a/thirdparty/assimp/code/SpatialSort.cpp b/thirdparty/assimp/code/Common/SpatialSort.cpp index a4f3a4e4b8..a4f3a4e4b8 100644 --- a/thirdparty/assimp/code/SpatialSort.cpp +++ b/thirdparty/assimp/code/Common/SpatialSort.cpp diff --git a/thirdparty/assimp/code/SplitByBoneCountProcess.cpp b/thirdparty/assimp/code/Common/SplitByBoneCountProcess.cpp index 2ef66a9afc..2ef66a9afc 100644 --- a/thirdparty/assimp/code/SplitByBoneCountProcess.cpp +++ b/thirdparty/assimp/code/Common/SplitByBoneCountProcess.cpp diff --git a/thirdparty/assimp/code/SplitByBoneCountProcess.h b/thirdparty/assimp/code/Common/SplitByBoneCountProcess.h index 6c904a9df4..6c904a9df4 100644 --- a/thirdparty/assimp/code/SplitByBoneCountProcess.h +++ b/thirdparty/assimp/code/Common/SplitByBoneCountProcess.h diff --git a/thirdparty/assimp/code/StandardShapes.cpp b/thirdparty/assimp/code/Common/StandardShapes.cpp index 2e5100130f..2e5100130f 100644 --- a/thirdparty/assimp/code/StandardShapes.cpp +++ b/thirdparty/assimp/code/Common/StandardShapes.cpp diff --git a/thirdparty/assimp/code/StdOStreamLogStream.h b/thirdparty/assimp/code/Common/StdOStreamLogStream.h index 893e261a2b..893e261a2b 100644 --- a/thirdparty/assimp/code/StdOStreamLogStream.h +++ b/thirdparty/assimp/code/Common/StdOStreamLogStream.h diff --git a/thirdparty/assimp/code/Subdivision.cpp b/thirdparty/assimp/code/Common/Subdivision.cpp index 19db223a55..60c54939f5 100644 --- a/thirdparty/assimp/code/Subdivision.cpp +++ b/thirdparty/assimp/code/Common/Subdivision.cpp @@ -43,9 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/Subdivision.h> #include <assimp/SceneCombiner.h> #include <assimp/SpatialSort.h> -#include "ProcessHelper.h" #include <assimp/Vertex.h> #include <assimp/ai_assert.h> + +#include "PostProcessing/ProcessHelper.h" + #include <stdio.h> using namespace Assimp; @@ -56,8 +58,7 @@ void mydummy() {} * implementation is basing on recursive refinement. Directly evaluating the result is also * possible and much quicker, but it depends on lengthy matrix lookup tables. */ // ------------------------------------------------------------------------------------------------ -class CatmullClarkSubdivider : public Subdivider -{ +class CatmullClarkSubdivider : public Subdivider { public: void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input); void Subdivide (aiMesh** smesh, size_t nmesh, diff --git a/thirdparty/assimp/code/TargetAnimation.cpp b/thirdparty/assimp/code/Common/TargetAnimation.cpp index b8062499ff..b8062499ff 100644 --- a/thirdparty/assimp/code/TargetAnimation.cpp +++ b/thirdparty/assimp/code/Common/TargetAnimation.cpp diff --git a/thirdparty/assimp/code/TargetAnimation.h b/thirdparty/assimp/code/Common/TargetAnimation.h index 91634ab5aa..91634ab5aa 100644 --- a/thirdparty/assimp/code/TargetAnimation.h +++ b/thirdparty/assimp/code/Common/TargetAnimation.h diff --git a/thirdparty/assimp/code/Version.cpp b/thirdparty/assimp/code/Common/Version.cpp index cc94340ac8..cf1da7d5ba 100644 --- a/thirdparty/assimp/code/Version.cpp +++ b/thirdparty/assimp/code/Common/Version.cpp @@ -46,8 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/scene.h> #include "ScenePrivate.h" -static const unsigned int MajorVersion = 4; -static const unsigned int MinorVersion = 1; +#include "revision.h" // -------------------------------------------------------------------------------- // Legal information string - don't remove this. @@ -56,9 +55,9 @@ 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-2017, assimp team\n" +"(c) 2006-2019, assimp team\n" "License under the terms and conditions of the 3-clause BSD license\n" -"http://assimp.sourceforge.net\n" +"http://assimp.org\n" ; // ------------------------------------------------------------------------------------------------ @@ -70,13 +69,13 @@ ASSIMP_API const char* aiGetLegalString () { // ------------------------------------------------------------------------------------------------ // Get Assimp minor version ASSIMP_API unsigned int aiGetVersionMinor () { - return MinorVersion; + return VER_MINOR; } // ------------------------------------------------------------------------------------------------ // Get Assimp major version ASSIMP_API unsigned int aiGetVersionMajor () { - return MajorVersion; + return VER_MAJOR; } // ------------------------------------------------------------------------------------------------ @@ -104,9 +103,6 @@ ASSIMP_API unsigned int aiGetCompileFlags () { return flags; } -// include current build revision, which is even updated from time to time -- :-) -#include "revision.h" - // ------------------------------------------------------------------------------------------------ ASSIMP_API unsigned int aiGetVersionRevision() { return GitVersion; diff --git a/thirdparty/assimp/code/VertexTriangleAdjacency.cpp b/thirdparty/assimp/code/Common/VertexTriangleAdjacency.cpp index 7cfd1a3505..7cfd1a3505 100644 --- a/thirdparty/assimp/code/VertexTriangleAdjacency.cpp +++ b/thirdparty/assimp/code/Common/VertexTriangleAdjacency.cpp diff --git a/thirdparty/assimp/code/VertexTriangleAdjacency.h b/thirdparty/assimp/code/Common/VertexTriangleAdjacency.h index f3be47612d..f3be47612d 100644 --- a/thirdparty/assimp/code/VertexTriangleAdjacency.h +++ b/thirdparty/assimp/code/Common/VertexTriangleAdjacency.h diff --git a/thirdparty/assimp/code/Win32DebugLogStream.h b/thirdparty/assimp/code/Common/Win32DebugLogStream.h index a6063a261e..a6063a261e 100644 --- a/thirdparty/assimp/code/Win32DebugLogStream.h +++ b/thirdparty/assimp/code/Common/Win32DebugLogStream.h diff --git a/thirdparty/assimp/code/Common/assbin_chunks.h b/thirdparty/assimp/code/Common/assbin_chunks.h new file mode 100644 index 0000000000..15e4af5e7d --- /dev/null +++ b/thirdparty/assimp/code/Common/assbin_chunks.h @@ -0,0 +1,196 @@ +#ifndef INCLUDED_ASSBIN_CHUNKS_H +#define INCLUDED_ASSBIN_CHUNKS_H + +#define ASSBIN_VERSION_MAJOR 1 +#define ASSBIN_VERSION_MINOR 0 + +/** +@page assfile .ASS File formats + +@section over Overview +Assimp provides its own interchange format, which is intended to applications which need +to serialize 3D-models and to reload them quickly. Assimp's file formats are designed to +be read by Assimp itself. They encode additional information needed by Assimp to optimize +its postprocessing pipeline. If you once apply specific steps to a scene, then save it +and reread it from an ASS format using the same post processing settings, they won't +be executed again. + +The format comes in two flavours: XML and binary - both of them hold a complete dump of +the 'aiScene' data structure returned by the APIs. The focus for the binary format +(<tt>.assbin</tt>) is fast loading. Optional deflate compression helps reduce file size. The XML +flavour, <tt>.assxml</tt> or simply .xml, is just a plain-to-xml conversion of aiScene. + +ASSBIN is Assimp's binary interchange format. assimp_cmd (<tt><root>/tools/assimp_cmd</tt>) is able to +write it and the core library provides a loader for it. + +@section assxml XML File format + +The format is pretty much self-explanatory due to its similarity to the in-memory aiScene structure. +With few exceptions, C structures are wrapped in XML elements. + +The DTD for ASSXML can be found in <tt><root>/doc/AssXML_Scheme.xml</tt>. Or have look +at the output files generated by assimp_cmd. + +@section assbin Binary file format + +The ASSBIN file format is composed of chunks to represent the hierarchical aiScene data structure. +This makes the format extensible and allows backward-compatibility with future data structure +versions. The <tt><root>/code/assbin_chunks.h</tt> header contains some magic constants +for use by stand-alone ASSBIN loaders. Also, Assimp's own file writer can be found +in <tt><root>/tools/assimp_cmd/WriteDumb.cpp</tt> (yes, the 'b' is no typo ...). + +@verbatim + +------------------------------------------------------------------------------- +1. File structure: +------------------------------------------------------------------------------- + +---------------------- +| Header (512 bytes) | +---------------------- +| Variable chunks | +---------------------- + +------------------------------------------------------------------------------- +2. Definitions: +------------------------------------------------------------------------------- + +integer is four bytes wide, stored in little-endian byte order. +short is two bytes wide, stored in little-endian byte order. +byte is a single byte. +string is an integer n followed by n UTF-8 characters, not terminated by zero +float is an IEEE 754 single-precision floating-point value +double is an IEEE 754 double-precision floating-point value +t[n] is an array of n elements of type t + +------------------------------------------------------------------------------- +2. Header: +------------------------------------------------------------------------------- + +byte[44] Magic identification string for ASSBIN files. + 'ASSIMP.binary' + +integer Major version of the Assimp library which wrote the file +integer Minor version of the Assimp library which wrote the file + match these against ASSBIN_VERSION_MAJOR and ASSBIN_VERSION_MINOR + +integer SVN revision of the Assimp library (intended for our internal + debugging - if you write Ass files from your own APPs, set this value to 0. +integer Assimp compile flags + +short 0 for normal files, 1 for shortened dumps for regression tests + these should have the file extension assbin.regress + +short 1 if the data after the header is compressed with the DEFLATE algorithm, + 0 for uncompressed files. + For compressed files, the first integer after the header is + always the uncompressed data size + +byte[256] Zero-terminated source file name, UTF-8 +byte[128] Zero-terminated command line parameters passed to assimp_cmd, UTF-8 + +byte[64] Reserved for future use +---> Total length: 512 bytes + +------------------------------------------------------------------------------- +3. Chunks: +------------------------------------------------------------------------------- + +integer Magic chunk ID (ASSBIN_CHUNK_XXX) +integer Chunk data length, in bytes + (unknown chunks are possible, a good reader skips over them) + (chunk-data-length does not include the first two integers) + +byte[n] chunk-data-length bytes of data, depending on the chunk type + +Chunks can contain nested chunks. Nested chunks are ALWAYS at the end of the chunk, +their size is included in chunk-data-length. + +The chunk layout for all ASSIMP data structures is derived from their C declarations. +The general 'rule' to get from Assimp headers to the serialized layout is: + + 1. POD members (i.e. aiMesh::mPrimitiveTypes, aiMesh::mNumVertices), + in order of declaration. + + 2. Array-members (aiMesh::mFaces, aiMesh::mVertices, aiBone::mWeights), + in order of declaration. + + 2. Object array members (i.e aiMesh::mBones, aiScene::mMeshes) are stored in + subchunks directly following the data written in 1.) and 2.) + + + Of course, there are some exceptions to this general order: + +[[aiScene]] + + - The root node holding the scene structure is naturally stored in + a ASSBIN_CHUNK_AINODE subchunk following 1.) and 2.) (which is + empty for aiScene). + +[[aiMesh]] + + - mTextureCoords and mNumUVComponents are serialized as follows: + + [number of used uv channels times] + integer mNumUVComponents[n] + float mTextureCoords[n][3] + + -> more than AI_MAX_TEXCOORD_CHANNELS can be stored. This allows Assimp + builds with different settings for AI_MAX_TEXCOORD_CHANNELS to exchange + data. + -> the on-disk format always uses 3 floats to write UV coordinates. + If mNumUVComponents[0] is 1, the corresponding mTextureCoords array + consists of 3 floats. + + - The array member block of aiMesh is prefixed with an integer that specifies + the kinds of vertex components actually present in the mesh. This is a + bitwise combination of the ASSBIN_MESH_HAS_xxx constants. + +[[aiFace]] + + - mNumIndices is stored as short + - mIndices are written as short, if aiMesh::mNumVertices<65536 + +[[aiNode]] + + - mParent is omitted + +[[aiLight]] + + - mAttenuationXXX not written if aiLight::mType == aiLightSource_DIRECTIONAL + - mAngleXXX not written if aiLight::mType != aiLightSource_SPOT + +[[aiMaterial]] + + - mNumAllocated is omitted, for obvious reasons :-) + + + @endverbatim*/ + + +#define ASSBIN_HEADER_LENGTH 512 + +// these are the magic chunk identifiers for the binary ASS file format +#define ASSBIN_CHUNK_AICAMERA 0x1234 +#define ASSBIN_CHUNK_AILIGHT 0x1235 +#define ASSBIN_CHUNK_AITEXTURE 0x1236 +#define ASSBIN_CHUNK_AIMESH 0x1237 +#define ASSBIN_CHUNK_AINODEANIM 0x1238 +#define ASSBIN_CHUNK_AISCENE 0x1239 +#define ASSBIN_CHUNK_AIBONE 0x123a +#define ASSBIN_CHUNK_AIANIMATION 0x123b +#define ASSBIN_CHUNK_AINODE 0x123c +#define ASSBIN_CHUNK_AIMATERIAL 0x123d +#define ASSBIN_CHUNK_AIMATERIALPROPERTY 0x123e + +#define ASSBIN_MESH_HAS_POSITIONS 0x1 +#define ASSBIN_MESH_HAS_NORMALS 0x2 +#define ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS 0x4 +#define ASSBIN_MESH_HAS_TEXCOORD_BASE 0x100 +#define ASSBIN_MESH_HAS_COLOR_BASE 0x10000 + +#define ASSBIN_MESH_HAS_TEXCOORD(n) (ASSBIN_MESH_HAS_TEXCOORD_BASE << n) +#define ASSBIN_MESH_HAS_COLOR(n) (ASSBIN_MESH_HAS_COLOR_BASE << n) + + +#endif // INCLUDED_ASSBIN_CHUNKS_H diff --git a/thirdparty/assimp/code/scene.cpp b/thirdparty/assimp/code/Common/scene.cpp index 2acb348d81..d15619acff 100644 --- a/thirdparty/assimp/code/scene.cpp +++ b/thirdparty/assimp/code/Common/scene.cpp @@ -44,23 +44,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. aiNode::aiNode() : mName("") -, mParent(NULL) +, mParent(nullptr) , mNumChildren(0) -, mChildren(NULL) +, mChildren(nullptr) , mNumMeshes(0) -, mMeshes(NULL) -, mMetaData(NULL) { +, mMeshes(nullptr) +, mMetaData(nullptr) { // empty } aiNode::aiNode(const std::string& name) : mName(name) -, mParent(NULL) +, mParent(nullptr) , mNumChildren(0) -, mChildren(NULL) +, mChildren(nullptr) , mNumMeshes(0) -, mMeshes(NULL) -, mMetaData(NULL) { +, mMeshes(nullptr) +, mMetaData(nullptr) { // empty } @@ -68,7 +68,7 @@ aiNode::aiNode(const std::string& name) aiNode::~aiNode() { // delete all children recursively // to make sure we won't crash if the data is invalid ... - if (mChildren && mNumChildren) + if (mNumChildren && mChildren) { for (unsigned int a = 0; a < mNumChildren; a++) delete mChildren[a]; diff --git a/thirdparty/assimp/code/simd.cpp b/thirdparty/assimp/code/Common/simd.cpp index 04615f408e..04615f408e 100644 --- a/thirdparty/assimp/code/simd.cpp +++ b/thirdparty/assimp/code/Common/simd.cpp diff --git a/thirdparty/assimp/code/simd.h b/thirdparty/assimp/code/Common/simd.h index 3eecdd4581..3eecdd4581 100644 --- a/thirdparty/assimp/code/simd.h +++ b/thirdparty/assimp/code/Common/simd.h diff --git a/thirdparty/assimp/code/FBXAnimation.cpp b/thirdparty/assimp/code/FBX/FBXAnimation.cpp index 874914431b..874914431b 100644 --- a/thirdparty/assimp/code/FBXAnimation.cpp +++ b/thirdparty/assimp/code/FBX/FBXAnimation.cpp diff --git a/thirdparty/assimp/code/FBXBinaryTokenizer.cpp b/thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp index 7138df4315..a4a2bc8e79 100644 --- a/thirdparty/assimp/code/FBXBinaryTokenizer.cpp +++ b/thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp @@ -98,7 +98,7 @@ namespace FBX { // return (flags & to_check) != 0; //} // ------------------------------------------------------------------------------------------------ -Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset) +Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset) : #ifdef DEBUG contents(sbegin, static_cast<size_t>(send-sbegin)), @@ -122,18 +122,18 @@ namespace { // ------------------------------------------------------------------------------------------------ // signal tokenization error, this is always unrecoverable. Throws DeadlyImportError. -AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX; -AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) +AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) { throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset)); } // ------------------------------------------------------------------------------------------------ -uint32_t Offset(const char* begin, const char* cursor) { +size_t Offset(const char* begin, const char* cursor) { ai_assert(begin <= cursor); - return static_cast<unsigned int>(cursor - begin); + return cursor - begin; } // ------------------------------------------------------------------------------------------------ @@ -424,7 +424,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, // ------------------------------------------------------------------------------------------------ // 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) +void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) { ai_assert(input); diff --git a/thirdparty/assimp/code/FBXCommon.h b/thirdparty/assimp/code/FBX/FBXCommon.h index fcb20a5cad..e516449130 100644 --- a/thirdparty/assimp/code/FBXCommon.h +++ b/thirdparty/assimp/code/FBX/FBXCommon.h @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER - +namespace Assimp { namespace FBX { const std::string NULL_RECORD = { // 13 null bytes @@ -80,7 +80,7 @@ namespace FBX TransformInheritance_MAX // end-of-enum sentinel }; } - +} #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // AI_FBXCOMMON_H_INC diff --git a/thirdparty/assimp/code/FBXCompileConfig.h b/thirdparty/assimp/code/FBX/FBXCompileConfig.h index 3a3841fa5b..03536a1823 100644 --- a/thirdparty/assimp/code/FBXCompileConfig.h +++ b/thirdparty/assimp/code/FBX/FBXCompileConfig.h @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_COMPILECONFIG_H #include <map> +#include <set> // #if _MSC_VER > 1500 || (defined __GNUC___) @@ -54,16 +55,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # else # define fbx_unordered_map map # define fbx_unordered_multimap multimap +# define fbx_unordered_set set +# define fbx_unordered_multiset multiset #endif #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP # include <unordered_map> +# include <unordered_set> # if _MSC_VER > 1600 # define fbx_unordered_map unordered_map # define fbx_unordered_multimap unordered_multimap +# define fbx_unordered_set unordered_set +# define fbx_unordered_multiset unordered_multiset # else # define fbx_unordered_map tr1::unordered_map # define fbx_unordered_multimap tr1::unordered_multimap +# define fbx_unordered_set tr1::unordered_set +# define fbx_unordered_multiset tr1::unordered_multiset # endif #endif diff --git a/thirdparty/assimp/code/FBXConverter.cpp b/thirdparty/assimp/code/FBX/FBXConverter.cpp index 000c4ed53b..d8a22d9f74 100644 --- a/thirdparty/assimp/code/FBXConverter.cpp +++ b/thirdparty/assimp/code/FBX/FBXConverter.cpp @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImporter.h" #include <assimp/StringComparison.h> +#include <assimp/MathFunctions.h> #include <assimp/scene.h> @@ -66,6 +67,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <vector> #include <sstream> #include <iomanip> +#include <cstdint> +#include <iostream> +#include <stdlib.h> namespace Assimp { namespace FBX { @@ -74,16 +78,33 @@ namespace Assimp { #define MAGIC_NODE_TAG "_$AssimpFbx$" -#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L - - FBXConverter::FBXConverter(aiScene* out, const Document& doc) - : defaultMaterialIndex() - , out(out) - , doc(doc) { +#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL + + FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones ) + : defaultMaterialIndex() + , lights() + , cameras() + , textures() + , materials_converted() + , textures_converted() + , meshes_converted() + , node_anim_chain_bits() + , mNodeNames() + , anim_fps() + , out(out) + , doc(doc) { // animations need to be converted first since this will // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. ConvertAnimations(); + // Embedded textures in FBX could be connected to nothing but to itself, + // for instance Texture -> Video connection only but not to the main graph, + // The idea here is to traverse all objects to find these Textures and convert them, + // so later during material conversion it will find converted texture in the textures_converted array. + if (doc.Settings().readTextures) + { + ConvertOrphantEmbeddedTextures(); + } ConvertRootNode(); if (doc.Settings().readAllMaterials) { @@ -128,13 +149,50 @@ namespace Assimp { void FBXConverter::ConvertRootNode() { out->mRootNode = new aiNode(); - out->mRootNode->mName.Set("RootNode"); + std::string unique_name; + GetUniqueName("RootNode", unique_name); + out->mRootNode->mName.Set(unique_name); // root has ID 0 - ConvertNodes(0L, *out->mRootNode); + ConvertNodes(0L, out->mRootNode, out->mRootNode); + } + + static std::string getAncestorBaseName(const aiNode* node) + { + const char* nodeName = nullptr; + size_t length = 0; + while (node && (!nodeName || length == 0)) + { + nodeName = node->mName.C_Str(); + length = node->mName.length; + node = node->mParent; + } + + if (!nodeName || length == 0) + { + return {}; + } + // could be std::string_view if c++17 available + return std::string(nodeName, length); } - void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) { + // Make unique name + std::string FBXConverter::MakeUniqueNodeName(const Model* const model, const aiNode& parent) + { + std::string original_name = FixNodeName(model->Name()); + if (original_name.empty()) + { + original_name = getAncestorBaseName(&parent); + } + std::string unique_name; + GetUniqueName(original_name, unique_name); + return unique_name; + } + /// todo: pre-build node hierarchy + /// todo: get bone from stack + /// todo: make map of aiBone* to aiNode* + /// then update convert clusters to the new format + void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) { const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); std::vector<aiNode*> nodes; @@ -145,79 +203,69 @@ namespace Assimp { try { for (const Connection* con : conns) { - // ignore object-property links if (con->PropertyName().length()) { - continue; + // really important we document why this is ignored. + FBXImporter::LogInfo("ignoring property link - no docs on why this is ignored"); + continue; //? } + // convert connection source object into Object base class const Object* const object = con->SourceObject(); if (nullptr == object) { - FBXImporter::LogWarn("failed to convert source object for Model link"); + FBXImporter::LogError("failed to convert source object for Model link"); continue; } + // FBX Model::Cube, Model::Bone001, etc elements + // This detects if we can cast the object into this model structure. const Model* const model = dynamic_cast<const Model*>(object); if (nullptr != model) { nodes_chain.clear(); post_nodes_chain.clear(); - aiMatrix4x4 new_abs_transform = parent_transform; - + aiMatrix4x4 new_abs_transform = parent->mTransformation; + std::string node_name = FixNodeName(model->Name()); // even though there is only a single input node, the design of // assimp (or rather: the complicated transformation chain that // is employed by fbx) means that we may need multiple aiNode's // to represent a fbx node's transformation. - GenerateTransformationNodeChain(*model, nodes_chain, post_nodes_chain); - ai_assert(nodes_chain.size()); - std::string original_name = FixNodeName(model->Name()); + // generate node transforms - this includes pivot data + // if need_additional_node is true then you t + const bool need_additional_node = GenerateTransformationNodeChain(*model, node_name, nodes_chain, post_nodes_chain); - // check if any of the nodes in the chain has the name the fbx node - // is supposed to have. If there is none, add another node to - // preserve the name - people might have scripts etc. that rely - // on specific node names. - aiNode* name_carrier = NULL; - for (aiNode* prenode : nodes_chain) { - if (!strcmp(prenode->mName.C_Str(), original_name.c_str())) { - name_carrier = prenode; - break; - } - } + // assert that for the current node we must have at least a single transform + ai_assert(nodes_chain.size()); - if (!name_carrier) { - std::string old_original_name = original_name; - GetUniqueName(old_original_name, original_name); - nodes_chain.push_back(new aiNode(original_name)); - } - else { - original_name = nodes_chain.back()->mName.C_Str(); + if (need_additional_node) { + nodes_chain.push_back(new aiNode(node_name)); } //setup metadata on newest node SetupNodeMetadata(*model, *nodes_chain.back()); // link all nodes in a row - aiNode* last_parent = &parent; - for (aiNode* prenode : nodes_chain) { - ai_assert(prenode); + aiNode* last_parent = parent; + for (aiNode* child : nodes_chain) { + ai_assert(child); - if (last_parent != &parent) { + if (last_parent != parent) { last_parent->mNumChildren = 1; last_parent->mChildren = new aiNode*[1]; - last_parent->mChildren[0] = prenode; + last_parent->mChildren[0] = child; } - prenode->mParent = last_parent; - last_parent = prenode; + child->mParent = last_parent; + last_parent = child; - new_abs_transform *= prenode->mTransformation; + new_abs_transform *= child->mTransformation; } // attach geometry - ConvertModel(*model, *nodes_chain.back(), new_abs_transform); + ConvertModel(*model, nodes_chain.back(), root_node, new_abs_transform); // check if there will be any child nodes const std::vector<const Connection*>& child_conns @@ -229,7 +277,7 @@ namespace Assimp { for (aiNode* postnode : post_nodes_chain) { ai_assert(postnode); - if (last_parent != &parent) { + if (last_parent != parent) { last_parent->mNumChildren = 1; last_parent->mChildren = new aiNode*[1]; last_parent->mChildren[0] = postnode; @@ -251,15 +299,15 @@ namespace Assimp { ); } - // attach sub-nodes (if any) - ConvertNodes(model->ID(), *last_parent, new_abs_transform); + // recursion call - child nodes + ConvertNodes(model->ID(), last_parent, root_node); if (doc.Settings().readLights) { - ConvertLights(*model, original_name); + ConvertLights(*model, node_name); } if (doc.Settings().readCameras) { - ConvertCameras(*model, original_name); + ConvertCameras(*model, node_name); } nodes.push_back(nodes_chain.front()); @@ -268,11 +316,17 @@ namespace Assimp { } if (nodes.size()) { - parent.mChildren = new aiNode*[nodes.size()](); - parent.mNumChildren = static_cast<unsigned int>(nodes.size()); + parent->mChildren = new aiNode*[nodes.size()](); + parent->mNumChildren = static_cast<unsigned int>(nodes.size()); - std::swap_ranges(nodes.begin(), nodes.end(), parent.mChildren); + std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren); + } + else + { + parent->mNumChildren = 0; + parent->mChildren = nullptr; } + } catch (std::exception&) { Util::delete_fun<aiNode> deleter; @@ -377,6 +431,7 @@ namespace Assimp { break; default: ai_assert(false); + break; } } @@ -389,11 +444,6 @@ namespace Assimp { out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); - //cameras are defined along positive x direction - /*out_camera->mPosition = cam.Position(); - out_camera->mLookAt = (cam.InterestPosition() - out_camera->mPosition).Normalize(); - out_camera->mUp = cam.UpVector();*/ - 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); @@ -410,19 +460,19 @@ namespace Assimp { void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName) { - int i = 0; uniqueName = name; - while (mNodeNames.find(uniqueName) != mNodeNames.end()) + auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count + unsigned int& i = it_pair.first->second; + while (!it_pair.second) { - ++i; - std::stringstream ext; + i++; + std::ostringstream ext; ext << name << std::setfill('0') << std::setw(3) << i; uniqueName = ext.str(); + it_pair = mNodeNames.insert({ uniqueName, 0 }); } - mNodeNames.insert(uniqueName); } - const char* FBXConverter::NameTransformationComp(TransformationComp comp) { switch (comp) { case TransformationComp_Translation: @@ -529,7 +579,7 @@ namespace Assimp { return; } - const float angle_epsilon = 1e-6f; + const float angle_epsilon = Math::getEpsilon<float>(); out = aiMatrix4x4(); @@ -636,8 +686,7 @@ namespace Assimp { if ((v - all_ones).SquareLength() > zero_epsilon) { return true; } - } - else if (ok) { + } else if (ok) { if (v.SquareLength() > zero_epsilon) { return true; } @@ -652,7 +701,7 @@ namespace Assimp { return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp); } - void FBXConverter::GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, + bool FBXConverter::GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes) { const PropertyTable& props = model.Props(); const Model::RotOrder rot = model.RotationOrder(); @@ -660,30 +709,37 @@ namespace Assimp { bool ok; aiMatrix4x4 chain[TransformationComp_MAXIMUM]; + + ai_assert(TransformationComp_MAXIMUM < 32); + std::uint32_t chainBits = 0; + // A node won't need a node chain if it only has these. + const std::uint32_t chainMaskSimple = (1 << TransformationComp_Translation) + (1 << TransformationComp_Scaling) + (1 << TransformationComp_Rotation); + // A node will need a node chain if it has any of these. + const std::uint32_t chainMaskComplex = ((1 << (TransformationComp_MAXIMUM)) - 1) - chainMaskSimple; + std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4()); // generate transformation matrices for all the different transformation components - const float zero_epsilon = 1e-6f; + const float zero_epsilon = Math::getEpsilon<float>(); const aiVector3D all_ones(1.0f, 1.0f, 1.0f); - bool is_complex = false; const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok); if (ok && PreRotation.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_PreRotation); GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]); } const aiVector3D& PostRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok); if (ok && PostRotation.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_PostRotation); GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]); } const aiVector3D& RotationPivot = PropertyGet<aiVector3D>(props, "RotationPivot", ok); if (ok && RotationPivot.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_RotationPivot) | (1 << TransformationComp_RotationPivotInverse); aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]); aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]); @@ -691,21 +747,21 @@ namespace Assimp { const aiVector3D& RotationOffset = PropertyGet<aiVector3D>(props, "RotationOffset", ok); if (ok && RotationOffset.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_RotationOffset); aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]); } const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>(props, "ScalingOffset", ok); if (ok && ScalingOffset.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_ScalingOffset); aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]); } const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>(props, "ScalingPivot", ok); if (ok && ScalingPivot.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_ScalingPivot) | (1 << TransformationComp_ScalingPivotInverse); aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]); aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]); @@ -713,22 +769,28 @@ namespace Assimp { const aiVector3D& Translation = PropertyGet<aiVector3D>(props, "Lcl Translation", ok); if (ok && Translation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_Translation); + aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]); } const aiVector3D& Scaling = PropertyGet<aiVector3D>(props, "Lcl Scaling", ok); if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_Scaling); + aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]); } const aiVector3D& Rotation = PropertyGet<aiVector3D>(props, "Lcl Rotation", ok); if (ok && Rotation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_Rotation); + GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]); } const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok); if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_GeometricScaling); aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]); aiVector3D GeometricScalingInverse = GeometricScaling; bool canscale = true; @@ -743,13 +805,14 @@ namespace Assimp { } } if (canscale) { + chainBits = chainBits | (1 << TransformationComp_GeometricScalingInverse); aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]); } } const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>(props, "GeometricRotation", ok); if (ok && GeometricRotation.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_GeometricRotation) | (1 << TransformationComp_GeometricRotationInverse); GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]); GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]); chain[TransformationComp_GeometricRotationInverse].Inverse(); @@ -757,7 +820,7 @@ namespace Assimp { const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>(props, "GeometricTranslation", ok); if (ok && GeometricTranslation.SquareLength() > zero_epsilon) { - is_complex = true; + chainBits = chainBits | (1 << TransformationComp_GeometricTranslation) | (1 << TransformationComp_GeometricTranslationInverse); aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]); aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]); } @@ -765,14 +828,12 @@ namespace Assimp { // is_complex needs to be consistent with NeedsComplexTransformationChain() // or the interplay between this code and the animation converter would // not be guaranteed. - ai_assert(NeedsComplexTransformationChain(model) == is_complex); - - std::string name = FixNodeName(model.Name()); + //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0)); // now, if we have more than just Translation, Scaling and Rotation, // we need to generate a full node chain to accommodate for assimp's // lack to express pivots and offsets. - if (is_complex && doc.Settings().preservePivots) { + if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) { FBXImporter::LogInfo("generating full transformation chain for node: " + name); // query the anim_chain_bits dictionary to find out which chain elements @@ -785,7 +846,7 @@ namespace Assimp { for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) { const TransformationComp comp = static_cast<TransformationComp>(i); - if (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) { + if ((chainBits & bit) == 0 && (anim_chain_bitmask & bit) == 0) { continue; } @@ -810,20 +871,20 @@ namespace Assimp { } ai_assert(output_nodes.size()); - return; + return true; } // else, we can just multiply the matrices together aiNode* nd = new aiNode(); output_nodes.push_back(nd); - std::string uniqueName; - GetUniqueName(name, uniqueName); - nd->mName.Set(uniqueName); + // name passed to the method is already unique + nd->mName.Set(name); for (const auto &transform : chain) { nd->mTransformation = nd->mTransformation * transform; } + return false; } void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd) @@ -869,7 +930,8 @@ namespace Assimp { } } - void FBXConverter::ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform) + void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { const std::vector<const Geometry*>& geos = model.GetGeometry(); @@ -881,11 +943,12 @@ namespace Assimp { const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo); const LineGeometry* const line = dynamic_cast<const LineGeometry*>(geo); if (mesh) { - const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, node_global_transform, nd); + const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, parent, root_node, + absolute_transform); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); } else if (line) { - const std::vector<unsigned int>& indices = ConvertLine(*line, model, node_global_transform, nd); + const std::vector<unsigned int>& indices = ConvertLine(*line, model, parent, root_node); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); } else { @@ -894,15 +957,16 @@ namespace Assimp { } if (meshes.size()) { - nd.mMeshes = new unsigned int[meshes.size()](); - nd.mNumMeshes = static_cast<unsigned int>(meshes.size()); + parent->mMeshes = new unsigned int[meshes.size()](); + parent->mNumMeshes = static_cast<unsigned int>(meshes.size()); - std::swap_ranges(meshes.begin(), meshes.end(), nd.mMeshes); + std::swap_ranges(meshes.begin(), meshes.end(), parent->mMeshes); } } - std::vector<unsigned int> FBXConverter::ConvertMesh(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + std::vector<unsigned int> + FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { std::vector<unsigned int> temp; @@ -926,18 +990,18 @@ namespace Assimp { const MatIndexArray::value_type base = mindices[0]; for (MatIndexArray::value_type index : mindices) { if (index != base) { - return ConvertMeshMultiMaterial(mesh, model, node_global_transform, nd); + return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform); } } } // faster code-path, just copy the data - temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform, nd)); + temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node)); return temp; } std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry& line, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + aiNode *parent, aiNode *root_node) { std::vector<unsigned int> temp; @@ -948,7 +1012,7 @@ namespace Assimp { return temp; } - aiMesh* const out_mesh = SetupEmptyMesh(line, nd); + aiMesh* const out_mesh = SetupEmptyMesh(line, root_node); out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; // copy vertices @@ -962,7 +1026,9 @@ namespace Assimp { unsigned int epcount = 0; for (unsigned i = 0; i < indices.size(); i++) { - if (indices[i] < 0) epcount++; + if (indices[i] < 0) { + epcount++; + } } unsigned int pcount = static_cast<unsigned int>( indices.size() ); unsigned int scount = out_mesh->mNumFaces = pcount - epcount; @@ -981,7 +1047,7 @@ namespace Assimp { return temp; } - aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode& nd) + aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode *parent) { aiMesh* const out_mesh = new aiMesh(); meshes.push_back(out_mesh); @@ -998,17 +1064,18 @@ namespace Assimp { } else { - out_mesh->mName = nd.mName; + out_mesh->mName = parent->mName; } return out_mesh; } - unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, + const aiMatrix4x4 &absolute_transform, aiNode *parent, + aiNode *root_node) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent); const std::vector<aiVector3D>& vertices = mesh.GetVertices(); const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts(); @@ -1075,7 +1142,7 @@ namespace Assimp { binormals = &tempBinormals; } else { - binormals = NULL; + binormals = nullptr; } } @@ -1125,8 +1192,9 @@ namespace Assimp { ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]); } - if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { - ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION); + if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) { + ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION, + nullptr); } std::vector<aiAnimMesh*> animMeshes; @@ -1171,8 +1239,10 @@ namespace Assimp { return static_cast<unsigned int>(meshes.size() - 1); } - std::vector<unsigned int> FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + std::vector<unsigned int> + FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, + aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); ai_assert(mindices.size()); @@ -1183,7 +1253,7 @@ namespace Assimp { for (MatIndexArray::value_type index : mindices) { if (had.find(index) == had.end()) { - indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform, nd)); + indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform)); had.insert(index); } } @@ -1191,18 +1261,18 @@ namespace Assimp { return indices; } - unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform, - aiNode& nd) + unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, + MatIndexArray::value_type index, + aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { - aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent); const MatIndexArray& mindices = mesh.GetMaterialIndices(); const std::vector<aiVector3D>& vertices = mesh.GetVertices(); const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts(); - const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL; + const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != nullptr; unsigned int count_faces = 0; unsigned int count_vertices = 0; @@ -1222,10 +1292,10 @@ namespace Assimp { ai_assert(count_faces); ai_assert(count_vertices); - // mapping from output indices to DOM indexing, needed to resolve weights + // mapping from output indices to DOM indexing, needed to resolve weights or blendshapes std::vector<unsigned int> reverseMapping; - - if (process_weights) { + std::map<unsigned int, unsigned int> translateIndexMap; + if (process_weights || mesh.GetBlendShapes().size() > 0) { reverseMapping.resize(count_vertices); } @@ -1262,7 +1332,7 @@ namespace Assimp { binormals = &tempBinormals; } else { - binormals = NULL; + binormals = nullptr; } } @@ -1332,6 +1402,7 @@ namespace Assimp { if (reverseMapping.size()) { reverseMapping[cursor] = in_cursor; + translateIndexMap[in_cursor] = cursor; } out_mesh->mVertices[cursor] = vertices[in_cursor]; @@ -1360,16 +1431,60 @@ namespace Assimp { ConvertMaterialForMesh(out_mesh, model, mesh, index); if (process_weights) { - ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping); + ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, index, &reverseMapping); + } + + std::vector<aiAnimMesh*> animMeshes; + for (const BlendShape* blendShape : mesh.GetBlendShapes()) { + for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) { + const std::vector<const ShapeGeometry*>& shapeGeometries = blendShapeChannel->GetShapeGeometries(); + for (size_t i = 0; i < shapeGeometries.size(); i++) { + aiAnimMesh* animMesh = aiCreateAnimMesh(out_mesh); + const ShapeGeometry* shapeGeometry = shapeGeometries.at(i); + const std::vector<aiVector3D>& vertices = shapeGeometry->GetVertices(); + const std::vector<aiVector3D>& normals = shapeGeometry->GetNormals(); + const std::vector<unsigned int>& indices = shapeGeometry->GetIndices(); + animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); + for (size_t j = 0; j < indices.size(); j++) { + unsigned int index = indices.at(j); + aiVector3D vertex = vertices.at(j); + aiVector3D normal = normals.at(j); + unsigned int count = 0; + const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count); + for (unsigned int k = 0; k < count; k++) { + unsigned int outIndex = outIndices[k]; + if (translateIndexMap.find(outIndex) == translateIndexMap.end()) + continue; + unsigned int index = translateIndexMap[outIndex]; + animMesh->mVertices[index] += vertex; + if (animMesh->mNormals != nullptr) { + animMesh->mNormals[index] += normal; + animMesh->mNormals[index].NormalizeSafe(); + } + } + } + animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f; + animMeshes.push_back(animMesh); + } + } + } + + const size_t numAnimMeshes = animMeshes.size(); + if (numAnimMeshes > 0) { + out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes); + out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes]; + for (size_t i = 0; i < numAnimMeshes; i++) { + out_mesh->mAnimMeshes[i] = animMeshes.at(i); + } } return static_cast<unsigned int>(meshes.size() - 1); } - void FBXConverter::ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, - const aiMatrix4x4& node_global_transform, - unsigned int materialIndex, - std::vector<unsigned int>* outputVertStartIndices) + void FBXConverter::ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, + const aiMatrix4x4 &absolute_transform, + aiNode *parent, aiNode *root_node, unsigned int materialIndex, + std::vector<unsigned int> *outputVertStartIndices) { ai_assert(geo.DeformerSkin()); @@ -1380,41 +1495,35 @@ namespace Assimp { const Skin& sk = *geo.DeformerSkin(); std::vector<aiBone*> bones; - bones.reserve(sk.Clusters().size()); const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; ai_assert(no_mat_check || outputVertStartIndices); try { - + // iterate over the sub deformers for (const Cluster* cluster : sk.Clusters()) { ai_assert(cluster); const WeightIndexArray& indices = cluster->GetIndices(); - if (indices.empty()) { - continue; - } - const MatIndexArray& mats = geo.GetMaterialIndices(); - bool ok = false; - const size_t no_index_sentinel = std::numeric_limits<size_t>::max(); count_out_indices.clear(); index_out_indices.clear(); out_indices.clear(); + // now check if *any* of these weights is contained in the output mesh, // taking notes so we don't need to do it twice. for (WeightIndexArray::value_type index : indices) { unsigned int count = 0; const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); - // ToOutputVertexIndex only returns NULL if index is out of bounds + // ToOutputVertexIndex only returns nullptr if index is out of bounds // which should never happen - ai_assert(out_idx != NULL); + ai_assert(out_idx != nullptr); index_out_indices.push_back(no_index_sentinel); count_out_indices.push_back(0); @@ -1424,13 +1533,11 @@ namespace Assimp { if (index_out_indices.back() == no_index_sentinel) { index_out_indices.back() = out_indices.size(); - } if (no_mat_check) { out_indices.push_back(out_idx[i]); - } - else { + } else { // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) const std::vector<unsigned int>::iterator it = std::lower_bound( outputVertStartIndices->begin(), @@ -1441,8 +1548,7 @@ namespace Assimp { out_indices.push_back(std::distance(outputVertStartIndices->begin(), it)); } - ++count_out_indices.back(); - ok = true; + ++count_out_indices.back(); } } } @@ -1450,66 +1556,103 @@ namespace Assimp { // if we found at least one, generate the output bones // XXX this could be heavily simplified by collecting the bone // data in a single step. - if (ok) { - ConvertCluster(bones, model, *cluster, out_indices, index_out_indices, - count_out_indices, node_global_transform); - } + ConvertCluster(bones, cluster, out_indices, index_out_indices, + count_out_indices, absolute_transform, parent, root_node); } + + bone_map.clear(); } - catch (std::exception&) { + catch (std::exception&e) { std::for_each(bones.begin(), bones.end(), Util::delete_fun<aiBone>()); throw; } if (bones.empty()) { + out->mBones = nullptr; + out->mNumBones = 0; return; - } + } else { + out->mBones = new aiBone *[bones.size()](); + out->mNumBones = static_cast<unsigned int>(bones.size()); - out->mBones = new aiBone*[bones.size()](); - out->mNumBones = static_cast<unsigned int>(bones.size()); - - std::swap_ranges(bones.begin(), bones.end(), out->mBones); + std::swap_ranges(bones.begin(), bones.end(), out->mBones); + } } - void FBXConverter::ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl, - std::vector<size_t>& out_indices, - std::vector<size_t>& index_out_indices, - std::vector<size_t>& count_out_indices, - const aiMatrix4x4& node_global_transform) + const aiNode* FBXConverter::GetNodeByName( const aiString& name, aiNode *current_node ) { + aiNode * iter = current_node; + //printf("Child count: %d", iter->mNumChildren); + return iter; + } - aiBone* const bone = new aiBone(); - bones.push_back(bone); + void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl, + std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices, + std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, + aiNode *parent, aiNode *root_node) { + ai_assert(cl); // make sure cluster valid + std::string deformer_name = cl->TargetNode()->Name(); + aiString bone_name = aiString(FixNodeName(deformer_name)); - bone->mName = FixNodeName(cl.TargetNode()->Name()); + aiBone *bone = nullptr; - bone->mOffsetMatrix = cl.TransformLink(); - bone->mOffsetMatrix.Inverse(); + if (bone_map.count(deformer_name)) { + std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name + << std::endl; + bone = bone_map[deformer_name]; + } else { + std::cout << "created new bone " << bone_name.C_Str() << ". Deformer: " << deformer_name << std::endl; + bone = new aiBone(); + bone->mName = bone_name; - bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; + // store local transform link for post processing + bone->mOffsetMatrix = cl->TransformLink(); + bone->mOffsetMatrix.Inverse(); - bone->mNumWeights = static_cast<unsigned int>(out_indices.size()); - aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; + aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform; - const size_t no_index_sentinel = std::numeric_limits<size_t>::max(); - const WeightArray& weights = cl.GetWeights(); + bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset - const size_t c = index_out_indices.size(); - for (size_t i = 0; i < c; ++i) { - const size_t index_index = index_out_indices[i]; - if (index_index == no_index_sentinel) { - continue; - } + // + // Now calculate the aiVertexWeights + // + + aiVertexWeight *cursor = nullptr; + + bone->mNumWeights = static_cast<unsigned int>(out_indices.size()); + cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; + + const size_t no_index_sentinel = std::numeric_limits<size_t>::max(); + const WeightArray& weights = cl->GetWeights(); - const size_t cc = count_out_indices[i]; - for (size_t j = 0; j < cc; ++j) { - aiVertexWeight& out_weight = *cursor++; + const size_t c = index_out_indices.size(); + for (size_t i = 0; i < c; ++i) { + const size_t index_index = index_out_indices[i]; - out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]); - out_weight.mWeight = weights[i]; + if (index_index == no_index_sentinel) { + continue; + } + + const size_t cc = count_out_indices[i]; + for (size_t j = 0; j < cc; ++j) { + // cursor runs from first element relative to the start + // or relative to the start of the next indexes. + aiVertexWeight& out_weight = *cursor++; + + out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]); + out_weight.mWeight = weights[i]; + } } + + bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone)); } + + std::cout << "bone research: Indicies size: " << out_indices.size() << std::endl; + + // lookup must be populated in case something goes wrong + // this also allocates bones to mesh instance outside + local_mesh_bones.push_back(bone); } void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, @@ -1581,6 +1724,13 @@ namespace Assimp { out_mat->AddProperty(&str, AI_MATKEY_NAME); } + // Set the shading mode as best we can: The FBX specification only mentions Lambert and Phong, and only Phong is mentioned in Assimp's aiShadingMode enum. + if (material.GetShadingModel() == "phong") + { + aiShadingMode shadingMode = aiShadingMode_Phong; + out_mat->AddProperty<aiShadingMode>(&shadingMode, 1, AI_MATKEY_SHADING_MODEL); + } + // shading stuff and colors SetShadingPropertiesCommon(out_mat, props); SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh ); @@ -1606,7 +1756,7 @@ namespace Assimp { out_tex->pcData = reinterpret_cast<aiTexel*>(const_cast<Video&>(video).RelinquishContent()); // try to extract a hint from the file extension - const std::string& filename = video.FileName().empty() ? video.RelativeFilename() : video.FileName(); + const std::string& filename = video.RelativeFilename().empty() ? video.FileName() : video.RelativeFilename(); std::string ext = BaseImporter::GetExtension(filename); if (ext == "jpeg") { @@ -1617,7 +1767,7 @@ namespace Assimp { memcpy(out_tex->achFormatHint, ext.c_str(), ext.size()); } - out_tex->mFilename.Set(video.FileName().c_str()); + out_tex->mFilename.Set(filename.c_str()); return static_cast<unsigned int>(textures.size() - 1); } @@ -1632,7 +1782,7 @@ namespace Assimp { 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); + VideoMap::const_iterator it = textures_converted.find(*media); if (it != textures_converted.end()) { index = (*it).second; textureReady = true; @@ -1640,7 +1790,7 @@ namespace Assimp { else { if (media->ContentLength() > 0) { index = ConvertVideo(*media); - textures_converted[media] = index; + textures_converted[*media] = index; textureReady = true; } } @@ -1663,9 +1813,8 @@ namespace Assimp { } void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh) - { + const std::string& propName, + aiTextureType target, const MeshGeometry* const mesh) { TextureMap::const_iterator it = textures.find(propName); if (it == textures.end()) { return; @@ -1924,6 +2073,21 @@ namespace Assimp { TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh); TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh); TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh); + + // Maya PBR + TrySetTextureProperties(out_mat, textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + + // Maya stingray + TrySetTextureProperties(out_mat, textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh); } void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh) @@ -2041,6 +2205,12 @@ namespace Assimp { CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f); } + // try to get the transparency factor + const float TransparencyFactor = PropertyGet<float>(props, "TransparencyFactor", ok); + if (ok) { + out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR); + } + // use of TransparencyFactor is inconsistent. // Maya always stores it as 1.0, // so we can't use it to set AI_MATKEY_OPACITY. @@ -2144,13 +2314,13 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa if (media != nullptr && media->ContentLength() > 0) { unsigned int index; - VideoMap::const_iterator it = textures_converted.find(media); + VideoMap::const_iterator it = textures_converted.find(*media); if (it != textures_converted.end()) { index = (*it).second; } else { index = ConvertVideo(*media); - textures_converted[media] = index; + textures_converted[*media] = index; } // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) @@ -2578,7 +2748,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa // sanity check whether the input is ok static void validateAnimCurveNodes(const std::vector<const AnimationCurveNode*>& curves, bool strictMode) { - const Object* target(NULL); + const Object* target(nullptr); for (const AnimationCurveNode* node : curves) { if (!target) { target = node->Target(); @@ -2609,7 +2779,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa #ifdef ASSIMP_BUILD_DEBUG validateAnimCurveNodes(curves, doc.Settings().strictMode); #endif - const AnimationCurveNode* curve_node = NULL; + const AnimationCurveNode* curve_node = nullptr; for (const AnimationCurveNode* node : curves) { ai_assert(node); @@ -2869,7 +3039,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa TransformationCompDefaultValue(comp) ); - const float epsilon = 1e-6f; + const float epsilon = Math::getEpsilon<float>(); return (dyn_val - static_val).SquareLength() < epsilon; } @@ -3386,8 +3556,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa na->mNumScalingKeys = static_cast<unsigned int>(keys.size()); na->mScalingKeys = new aiVectorKey[keys.size()]; - if (keys.size() > 0) + if (keys.size() > 0) { InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime); + } } void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, @@ -3456,7 +3627,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa ai_assert(!out->mMeshes); ai_assert(!out->mNumMeshes); - // note: the trailing () ensures initialization with NULL - not + // note: the trailing () ensures initialization with nullptr - not // many C++ users seem to know this, so pointing it out to avoid // confusion why this code works. @@ -3503,10 +3674,51 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa } } + void FBXConverter::ConvertOrphantEmbeddedTextures() + { + // in C++14 it could be: + // for (auto&& [id, object] : objects) + for (auto&& id_and_object : doc.Objects()) + { + auto&& id = std::get<0>(id_and_object); + auto&& object = std::get<1>(id_and_object); + // If an object doesn't have parent + if (doc.ConnectionsBySource().count(id) == 0) + { + const Texture* realTexture = nullptr; + try + { + const auto& element = object->GetElement(); + const Token& key = element.KeyToken(); + const char* obtype = key.begin(); + const size_t length = static_cast<size_t>(key.end() - key.begin()); + if (strncmp(obtype, "Texture", length) == 0) + { + const Texture* texture = static_cast<const Texture*>(object->Get()); + if (texture->Media() && texture->Media()->ContentLength() > 0) + { + realTexture = texture; + } + } + } + catch (...) + { + // do nothing + } + if (realTexture) + { + const Video* media = realTexture->Media(); + unsigned int index = ConvertVideo(*media); + textures_converted[*media] = index; + } + } + } + } + // ------------------------------------------------------------------------------------------------ - void ConvertToAssimpScene(aiScene* out, const Document& doc) + void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones) { - FBXConverter converter(out, doc); + FBXConverter converter(out, doc, removeEmptyBones); } } // !FBX diff --git a/thirdparty/assimp/code/FBXConverter.h b/thirdparty/assimp/code/FBX/FBXConverter.h index 398baa445f..46693bdca6 100644 --- a/thirdparty/assimp/code/FBXConverter.h +++ b/thirdparty/assimp/code/FBX/FBXConverter.h @@ -52,12 +52,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXUtil.h" #include "FBXProperties.h" #include "FBXImporter.h" + #include <assimp/anim.h> #include <assimp/material.h> #include <assimp/light.h> #include <assimp/texture.h> #include <assimp/camera.h> #include <assimp/StringComparison.h> +#include <unordered_map> +#include <unordered_set> struct aiScene; struct aiNode; @@ -73,15 +76,13 @@ namespace Assimp { namespace FBX { class Document; - -using NodeNameCache = std::set<std::string>; - /** * Convert a FBX #Document to #aiScene * @param out Empty scene to be populated - * @param doc Parsed FBX document + * @param doc Parsed FBX document + * @param removeEmptyBones Will remove bones, which do not have any references to vertices. */ -void ConvertToAssimpScene(aiScene* out, const Document& doc); +void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones); /** Dummy class to encapsulate the conversion process */ class FBXConverter { @@ -112,7 +113,7 @@ public: }; public: - FBXConverter(aiScene* out, const Document& doc); + FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones); ~FBXConverter(); private: @@ -122,7 +123,7 @@ private: // ------------------------------------------------------------------------------------------------ // collect and assign child nodes - void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4()); + void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ void ConvertLights(const Model& model, const std::string &orig_name ); @@ -145,6 +146,11 @@ private: const char* NameTransformationComp(TransformationComp comp); // ------------------------------------------------------------------------------------------------ + // Returns an unique name for a node or traverses up a hierarchy until a non-empty name is found and + // then makes this name unique + std::string MakeUniqueNodeName(const Model* const model, const aiNode& parent); + + // ------------------------------------------------------------------------------------------------ // note: this returns the REAL fbx property names const char* NameTransformationCompProperty(TransformationComp comp); @@ -167,38 +173,41 @@ private: /** * note: memory for output_nodes will be managed by the caller */ - void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes); + bool GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes); // ------------------------------------------------------------------------------------------------ void SetupNodeMetadata(const Model& model, aiNode& nd); // ------------------------------------------------------------------------------------------------ - void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform); + void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed - std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + std::vector<unsigned int> + ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ - aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd); + aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent); // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, + const aiMatrix4x4 &absolute_transform, aiNode *parent, + aiNode *root_node); // ------------------------------------------------------------------------------------------------ - std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + std::vector<unsigned int> + ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform, aiNode& nd); + unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index, + aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */ @@ -211,17 +220,17 @@ private: * - outputVertStartIndices is only used when a material index is specified, it gives for * each output vertex the DOM index it maps to. */ - void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, - const aiMatrix4x4& node_global_transform = aiMatrix4x4(), - unsigned int materialIndex = NO_MATERIAL_SEPARATION, - std::vector<unsigned int>* outputVertStartIndices = NULL); - + void ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, + aiNode *parent = NULL, aiNode *root_node = NULL, + unsigned int materialIndex = NO_MATERIAL_SEPARATION, + std::vector<unsigned int> *outputVertStartIndices = NULL); + // lookup + static const aiNode* GetNodeByName( const aiString& name, aiNode *current_node ); // ------------------------------------------------------------------------------------------------ - void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl, - std::vector<size_t>& out_indices, - std::vector<size_t>& index_out_indices, - std::vector<size_t>& count_out_indices, - const aiMatrix4x4& node_global_transform); + void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl, + std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices, + std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, + aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, @@ -418,8 +427,11 @@ private: // copy generated meshes, animations, lights, cameras and textures to the output scene void TransferDataToScene(); -private: + // ------------------------------------------------------------------------------------------------ + // FBX file could have embedded textures not connected to anything + void ConvertOrphantEmbeddedTextures(); +private: // 0: not assigned yet, others: index is value - 1 unsigned int defaultMaterialIndex; @@ -429,26 +441,48 @@ private: std::vector<aiLight*> lights; std::vector<aiCamera*> cameras; std::vector<aiTexture*> textures; - - typedef std::map<const Material*, unsigned int> MaterialMap; + using MaterialMap = std::fbx_unordered_map<const Material*, unsigned int>; MaterialMap materials_converted; - typedef std::map<const Video*, unsigned int> VideoMap; + using VideoMap = std::fbx_unordered_map<const Video, unsigned int>; VideoMap textures_converted; - typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap; + using MeshMap = std::fbx_unordered_map<const Geometry*, std::vector<unsigned int> >; MeshMap meshes_converted; // fixed node name -> which trafo chain components have animations? - typedef std::map<std::string, unsigned int> NodeAnimBitMap; + using NodeAnimBitMap = std::fbx_unordered_map<std::string, unsigned int> ; NodeAnimBitMap node_anim_chain_bits; + // number of nodes with the same name + using NodeNameCache = std::fbx_unordered_map<std::string, unsigned int>; NodeNameCache mNodeNames; + + // Deformer name is not the same as a bone name - it does contain the bone name though :) + // Deformer names in FBX are always unique in an FBX file. + std::map<const std::string, aiBone *> bone_map; + double anim_fps; aiScene* const out; const FBX::Document& doc; + + static void BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene, + std::vector<aiBone*>& bones); + + void BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene, + const std::vector<aiBone *> &bones, + std::map<aiBone *, aiNode *> &bone_stack, + std::vector<aiNode*> &node_stack ); + + static void BuildNodeList(aiNode *current_node, std::vector<aiNode *> &nodes); + + static aiNode *GetNodeFromStack(const aiString &node_name, std::vector<aiNode *> &nodes); + + static aiNode *GetArmatureRoot(aiNode *bone_node, std::vector<aiBone*> &bone_list); + + static bool IsBoneNode(const aiString &bone_name, std::vector<aiBone *> &bones); }; } diff --git a/thirdparty/assimp/code/FBXDeformer.cpp b/thirdparty/assimp/code/FBX/FBXDeformer.cpp index 6927553450..6927553450 100644 --- a/thirdparty/assimp/code/FBXDeformer.cpp +++ b/thirdparty/assimp/code/FBX/FBXDeformer.cpp diff --git a/thirdparty/assimp/code/FBXDocument.cpp b/thirdparty/assimp/code/FBX/FBXDocument.cpp index 1af08fe6d8..506fd978dd 100644 --- a/thirdparty/assimp/code/FBXDocument.cpp +++ b/thirdparty/assimp/code/FBX/FBXDocument.cpp @@ -90,14 +90,6 @@ const Object* LazyObject::Get(bool dieOnError) return object.get(); } - // if this is the root object, we return a dummy since there - // is no root object int he fbx file - it is just referenced - // with id 0. - if(id == 0L) { - object.reset(new Object(id, element, "Model::RootNode")); - return object.get(); - } - const Token& key = element.KeyToken(); const TokenList& tokens = element.Tokens(); diff --git a/thirdparty/assimp/code/FBXDocument.h b/thirdparty/assimp/code/FBX/FBXDocument.h index c849defdcd..a60d7d9efa 100644 --- a/thirdparty/assimp/code/FBXDocument.h +++ b/thirdparty/assimp/code/FBX/FBXDocument.h @@ -627,7 +627,7 @@ public: return content; } - uint32_t ContentLength() const { + uint64_t ContentLength() const { return contentLength; } @@ -637,13 +637,27 @@ public: return ptr; } + bool operator==(const Video& other) const + { + return ( + type == other.type + && relativeFileName == other.relativeFileName + && fileName == other.fileName + ); + } + + bool operator<(const Video& other) const + { + return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName); + } + private: std::string type; std::string relativeFileName; std::string fileName; std::shared_ptr<const PropertyTable> props; - uint32_t contentLength; + uint64_t contentLength; uint8_t* content; }; @@ -1005,10 +1019,10 @@ public: // during their entire lifetime (Document). FBX files have // up to many thousands of objects (most of which we never use), // so the memory overhead for them should be kept at a minimum. -typedef std::map<uint64_t, LazyObject*> ObjectMap; +typedef std::fbx_unordered_map<uint64_t, LazyObject*> ObjectMap; typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap; -typedef std::multimap<uint64_t, const Connection*> ConnectionMap; +typedef std::fbx_unordered_multimap<uint64_t, const Connection*> ConnectionMap; /** DOM class for global document settings, a single instance per document can * be accessed via Document.Globals(). */ @@ -1177,4 +1191,25 @@ private: } // Namespace FBX } // Namespace Assimp +namespace std +{ + template <> + struct hash<const Assimp::FBX::Video> + { + std::size_t operator()(const Assimp::FBX::Video& video) const + { + using std::size_t; + using std::hash; + using std::string; + + size_t res = 17; + res = res * 31 + hash<string>()(video.Name()); + res = res * 31 + hash<string>()(video.RelativeFilename()); + res = res * 31 + hash<string>()(video.Type()); + + return res; + } + }; +} + #endif // INCLUDED_AI_FBX_DOCUMENT_H diff --git a/thirdparty/assimp/code/FBXDocumentUtil.cpp b/thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp index f84691479a..f84691479a 100644 --- a/thirdparty/assimp/code/FBXDocumentUtil.cpp +++ b/thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp diff --git a/thirdparty/assimp/code/FBXDocumentUtil.h b/thirdparty/assimp/code/FBX/FBXDocumentUtil.h index 2450109e59..2450109e59 100644 --- a/thirdparty/assimp/code/FBXDocumentUtil.h +++ b/thirdparty/assimp/code/FBX/FBXDocumentUtil.h diff --git a/thirdparty/assimp/code/FBXExportNode.cpp b/thirdparty/assimp/code/FBX/FBXExportNode.cpp index e5215466a1..06c89cee46 100644 --- a/thirdparty/assimp/code/FBXExportNode.cpp +++ b/thirdparty/assimp/code/FBX/FBXExportNode.cpp @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <sstream> // ostringstream #include <memory> // shared_ptr +namespace Assimp { // AddP70<type> helpers... there's no usable pattern here, // so all are defined as separate functions. // Even "animatable" properties are often completely different @@ -252,7 +253,8 @@ void FBX::Node::DumpChildren( } else { std::ostringstream ss; DumpChildrenAscii(ss, indent); - s.PutString(ss.str()); + if (ss.tellp() > 0) + s.PutString(ss.str()); } } @@ -266,7 +268,8 @@ void FBX::Node::End( } else { std::ostringstream ss; EndAscii(ss, indent, has_children); - s.PutString(ss.str()); + if (ss.tellp() > 0) + s.PutString(ss.str()); } } @@ -367,7 +370,7 @@ void FBX::Node::EndBinary( bool has_children ) { // if there were children, add a null record - if (has_children) { s.PutString(FBX::NULL_RECORD); } + if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); } // now go back and write initial pos this->end_pos = s.Tell(); @@ -563,6 +566,6 @@ void FBX::Node::WritePropertyNode( FBX::Node::WritePropertyNodeAscii(name, v, s, indent); } } - +} #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/thirdparty/assimp/code/FBXExportNode.h b/thirdparty/assimp/code/FBX/FBXExportNode.h index e1ebc36969..ef3bc781a4 100644 --- a/thirdparty/assimp/code/FBXExportNode.h +++ b/thirdparty/assimp/code/FBX/FBXExportNode.h @@ -54,16 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <string> #include <vector> +namespace Assimp { namespace FBX { class Node; } -class FBX::Node -{ -public: // public data members +class FBX::Node { +public: // TODO: accessors std::string name; // node name - std::vector<FBX::Property> properties; // node properties + std::vector<FBX::FBXExportProperty> properties; // node properties std::vector<FBX::Node> children; // child nodes // some nodes always pretend they have children... @@ -214,7 +214,7 @@ public: // static member functions Assimp::StreamWriterLE& s, bool binary, int indent ) { - FBX::Property p(value); + FBX::FBXExportProperty p(value); FBX::Node node(name, p); node.Dump(s, binary, indent); } @@ -264,7 +264,7 @@ private: // static helper functions ); }; - +} #endif // ASSIMP_BUILD_NO_FBX_EXPORTER diff --git a/thirdparty/assimp/code/FBXExportProperty.cpp b/thirdparty/assimp/code/FBX/FBXExportProperty.cpp index 9981d6b1c6..f2a63b72b9 100644 --- a/thirdparty/assimp/code/FBXExportProperty.cpp +++ b/thirdparty/assimp/code/FBX/FBXExportProperty.cpp @@ -52,187 +52,206 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <locale> #include <sstream> // ostringstream +namespace Assimp { +namespace FBX { // constructors for single element properties -FBX::Property::Property(bool v) - : type('C'), data(1) -{ - data = {uint8_t(v)}; -} +FBXExportProperty::FBXExportProperty(bool v) +: type('C') +, data(1, uint8_t(v)) {} -FBX::Property::Property(int16_t v) : type('Y'), data(2) -{ +FBXExportProperty::FBXExportProperty(int16_t v) +: type('Y') +, data(2) { uint8_t* d = data.data(); (reinterpret_cast<int16_t*>(d))[0] = v; } -FBX::Property::Property(int32_t v) : type('I'), data(4) -{ +FBXExportProperty::FBXExportProperty(int32_t v) +: type('I') +, data(4) { uint8_t* d = data.data(); (reinterpret_cast<int32_t*>(d))[0] = v; } -FBX::Property::Property(float v) : type('F'), data(4) -{ +FBXExportProperty::FBXExportProperty(float v) +: type('F') +, data(4) { uint8_t* d = data.data(); (reinterpret_cast<float*>(d))[0] = v; } -FBX::Property::Property(double v) : type('D'), data(8) -{ +FBXExportProperty::FBXExportProperty(double v) +: type('D') +, data(8) { uint8_t* d = data.data(); (reinterpret_cast<double*>(d))[0] = v; } -FBX::Property::Property(int64_t v) : type('L'), data(8) -{ +FBXExportProperty::FBXExportProperty(int64_t v) +: type('L') +, data(8) { uint8_t* d = data.data(); (reinterpret_cast<int64_t*>(d))[0] = v; } - // constructors for array-type properties -FBX::Property::Property(const char* c, bool raw) - : Property(std::string(c), raw) -{} +FBXExportProperty::FBXExportProperty(const char* c, bool raw) +: FBXExportProperty(std::string(c), raw) { + // empty +} // strings can either be saved as "raw" (R) data, or "string" (S) data -FBX::Property::Property(const std::string& s, bool raw) - : type(raw ? 'R' : 'S'), data(s.size()) -{ +FBXExportProperty::FBXExportProperty(const std::string& s, bool raw) +: type(raw ? 'R' : 'S') +, data(s.size()) { for (size_t i = 0; i < s.size(); ++i) { data[i] = uint8_t(s[i]); } } -FBX::Property::Property(const std::vector<uint8_t>& r) - : type('R'), data(r) -{} +FBXExportProperty::FBXExportProperty(const std::vector<uint8_t>& r) +: type('R') +, data(r) { + // empty +} -FBX::Property::Property(const std::vector<int32_t>& va) - : type('i'), data(4*va.size()) -{ +FBXExportProperty::FBXExportProperty(const std::vector<int32_t>& va) +: type('i') +, data(4 * va.size() ) { int32_t* d = reinterpret_cast<int32_t*>(data.data()); - for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } + for (size_t i = 0; i < va.size(); ++i) { + d[i] = va[i]; + } } -FBX::Property::Property(const std::vector<int64_t>& va) - : type('l'), data(8*va.size()) -{ +FBXExportProperty::FBXExportProperty(const std::vector<int64_t>& va) +: type('l') +, data(8 * va.size()) { int64_t* d = reinterpret_cast<int64_t*>(data.data()); - for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } + for (size_t i = 0; i < va.size(); ++i) { + d[i] = va[i]; + } } -FBX::Property::Property(const std::vector<float>& va) - : type('f'), data(4*va.size()) -{ +FBXExportProperty::FBXExportProperty(const std::vector<float>& va) +: type('f') +, data(4 * va.size()) { float* d = reinterpret_cast<float*>(data.data()); - for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } + for (size_t i = 0; i < va.size(); ++i) { + d[i] = va[i]; + } } -FBX::Property::Property(const std::vector<double>& va) - : type('d'), data(8*va.size()) -{ +FBXExportProperty::FBXExportProperty(const std::vector<double>& va) +: type('d') +, data(8 * va.size()) { double* d = reinterpret_cast<double*>(data.data()); - for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } + for (size_t i = 0; i < va.size(); ++i) { + d[i] = va[i]; + } } -FBX::Property::Property(const aiMatrix4x4& vm) - : type('d'), data(8*16) -{ +FBXExportProperty::FBXExportProperty(const aiMatrix4x4& vm) +: type('d') +, data(8 * 16) { double* d = reinterpret_cast<double*>(data.data()); for (unsigned int c = 0; c < 4; ++c) { for (unsigned int r = 0; r < 4; ++r) { - d[4*c+r] = vm[r][c]; + d[4 * c + r] = vm[r][c]; } } } // public member functions -size_t FBX::Property::size() -{ +size_t FBXExportProperty::size() { switch (type) { - case 'C': case 'Y': case 'I': case 'F': case 'D': case 'L': - return data.size() + 1; - case 'S': case 'R': - return data.size() + 5; - case 'i': case 'd': - return data.size() + 13; - default: - throw DeadlyExportError("Requested size on property of unknown type"); + case 'C': + case 'Y': + case 'I': + case 'F': + case 'D': + case 'L': + return data.size() + 1; + case 'S': + case 'R': + return data.size() + 5; + case 'i': + case 'd': + return data.size() + 13; + default: + throw DeadlyExportError("Requested size on property of unknown type"); } } -void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s) -{ +void FBXExportProperty::DumpBinary(Assimp::StreamWriterLE& s) { s.PutU1(type); uint8_t* d = data.data(); size_t N; switch (type) { - case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return; - case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return; - case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return; - case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return; - case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return; - case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return; - case 'S': - case 'R': - s.PutU4(uint32_t(data.size())); - for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); } - return; - case 'i': - N = data.size() / 4; - s.PutU4(uint32_t(N)); // number of elements - s.PutU4(0); // no encoding (1 would be zip-compressed) - // TODO: compress if large? - s.PutU4(uint32_t(data.size())); // data size - for (size_t i = 0; i < N; ++i) { - s.PutI4((reinterpret_cast<int32_t*>(d))[i]); - } - return; - case 'l': - N = data.size() / 8; - s.PutU4(uint32_t(N)); // number of elements - s.PutU4(0); // no encoding (1 would be zip-compressed) - // TODO: compress if large? - s.PutU4(uint32_t(data.size())); // data size - for (size_t i = 0; i < N; ++i) { - s.PutI8((reinterpret_cast<int64_t*>(d))[i]); - } - return; - case 'f': - N = data.size() / 4; - s.PutU4(uint32_t(N)); // number of elements - s.PutU4(0); // no encoding (1 would be zip-compressed) - // TODO: compress if large? - s.PutU4(uint32_t(data.size())); // data size - for (size_t i = 0; i < N; ++i) { - s.PutF4((reinterpret_cast<float*>(d))[i]); - } - return; - case 'd': - N = data.size() / 8; - s.PutU4(uint32_t(N)); // number of elements - s.PutU4(0); // no encoding (1 would be zip-compressed) - // TODO: compress if large? - s.PutU4(uint32_t(data.size())); // data size - for (size_t i = 0; i < N; ++i) { - s.PutF8((reinterpret_cast<double*>(d))[i]); - } - return; - default: - std::ostringstream err; - err << "Tried to dump property with invalid type '"; - err << type << "'!"; - throw DeadlyExportError(err.str()); + case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return; + case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return; + case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return; + case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return; + case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return; + case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return; + case 'S': + case 'R': + s.PutU4(uint32_t(data.size())); + for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); } + return; + case 'i': + N = data.size() / 4; + s.PutU4(uint32_t(N)); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(uint32_t(data.size())); // data size + for (size_t i = 0; i < N; ++i) { + s.PutI4((reinterpret_cast<int32_t*>(d))[i]); + } + return; + case 'l': + N = data.size() / 8; + s.PutU4(uint32_t(N)); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(uint32_t(data.size())); // data size + for (size_t i = 0; i < N; ++i) { + s.PutI8((reinterpret_cast<int64_t*>(d))[i]); + } + return; + case 'f': + N = data.size() / 4; + s.PutU4(uint32_t(N)); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(uint32_t(data.size())); // data size + for (size_t i = 0; i < N; ++i) { + s.PutF4((reinterpret_cast<float*>(d))[i]); + } + return; + case 'd': + N = data.size() / 8; + s.PutU4(uint32_t(N)); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(uint32_t(data.size())); // data size + for (size_t i = 0; i < N; ++i) { + s.PutF8((reinterpret_cast<double*>(d))[i]); + } + return; + default: + std::ostringstream err; + err << "Tried to dump property with invalid type '"; + err << type << "'!"; + throw DeadlyExportError(err.str()); } } -void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent) -{ +void FBXExportProperty::DumpAscii(Assimp::StreamWriterLE& outstream, int indent) { std::ostringstream ss; ss.imbue(std::locale::classic()); ss.precision(15); // this seems to match official FBX SDK exports @@ -240,8 +259,7 @@ void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent) outstream.PutString(ss.str()); } -void FBX::Property::DumpAscii(std::ostream& s, int indent) -{ +void FBXExportProperty::DumpAscii(std::ostream& s, int indent) { // no writing type... or anything. just shove it into the stream. uint8_t* d = data.data(); size_t N; @@ -360,5 +378,8 @@ void FBX::Property::DumpAscii(std::ostream& s, int indent) } } +} // Namespace FBX +} // Namespace Assimp + #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/thirdparty/assimp/code/FBXExportProperty.h b/thirdparty/assimp/code/FBX/FBXExportProperty.h index 9c9d37c362..d692fe6ee3 100644 --- a/thirdparty/assimp/code/FBXExportProperty.h +++ b/thirdparty/assimp/code/FBX/FBXExportProperty.h @@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER - #include <assimp/types.h> // aiMatrix4x4 #include <assimp/StreamWriter.h> // StreamWriterLE @@ -56,11 +55,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <ostream> #include <type_traits> // is_void +namespace Assimp { namespace FBX { - class Property; -} -/** FBX::Property +/** @brief FBX::Property * * Holds a value of any of FBX's recognized types, * each represented by a particular one-character code. @@ -78,35 +76,34 @@ namespace FBX { * S : string (array of 1-byte char) * R : raw data (array of bytes) */ -class FBX::Property -{ +class FBXExportProperty { public: // constructors for basic types. // all explicit to avoid accidental typecasting - explicit Property(bool v); + explicit FBXExportProperty(bool v); // TODO: determine if there is actually a byte type, // or if this always means <bool>. 'C' seems to imply <char>, // so possibly the above was intended to represent both. - explicit Property(int16_t v); - explicit Property(int32_t v); - explicit Property(float v); - explicit Property(double v); - explicit Property(int64_t v); + explicit FBXExportProperty(int16_t v); + explicit FBXExportProperty(int32_t v); + explicit FBXExportProperty(float v); + explicit FBXExportProperty(double v); + explicit FBXExportProperty(int64_t v); // strings can either be stored as 'R' (raw) or 'S' (string) type - explicit Property(const char* c, bool raw=false); - explicit Property(const std::string& s, bool raw=false); - explicit Property(const std::vector<uint8_t>& r); - explicit Property(const std::vector<int32_t>& va); - explicit Property(const std::vector<int64_t>& va); - explicit Property(const std::vector<double>& va); - explicit Property(const std::vector<float>& va); - explicit Property(const aiMatrix4x4& vm); + explicit FBXExportProperty(const char* c, bool raw = false); + explicit FBXExportProperty(const std::string& s, bool raw = false); + explicit FBXExportProperty(const std::vector<uint8_t>& r); + explicit FBXExportProperty(const std::vector<int32_t>& va); + explicit FBXExportProperty(const std::vector<int64_t>& va); + explicit FBXExportProperty(const std::vector<double>& va); + explicit FBXExportProperty(const std::vector<float>& va); + explicit FBXExportProperty(const aiMatrix4x4& vm); // this will catch any type not defined above, // so that we don't accidentally convert something we don't want. // for example (const char*) --> (bool)... seriously wtf C++ template <class T> - explicit Property(T v) : type('X') { + explicit FBXExportProperty(T v) : type('X') { static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION"); } // note: no line wrap so it appears verbatim on the compiler error @@ -114,9 +111,9 @@ public: size_t size(); // write this property node as binary data to the given stream - void DumpBinary(Assimp::StreamWriterLE &s); - void DumpAscii(Assimp::StreamWriterLE &s, int indent=0); - void DumpAscii(std::ostream &s, int indent=0); + void DumpBinary(Assimp::StreamWriterLE& s); + void DumpAscii(Assimp::StreamWriterLE& s, int indent = 0); + void DumpAscii(std::ostream& s, int indent = 0); // note: make sure the ostream is in classic "C" locale private: @@ -124,6 +121,9 @@ private: std::vector<uint8_t> data; }; +} // Namespace FBX +} // Namespace Assimp + #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // AI_FBXEXPORTPROPERTY_H_INC diff --git a/thirdparty/assimp/code/FBXExporter.cpp b/thirdparty/assimp/code/FBX/FBXExporter.cpp index acb1227144..9316dc4f02 100644 --- a/thirdparty/assimp/code/FBXExporter.cpp +++ b/thirdparty/assimp/code/FBX/FBXExporter.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXExportNode.h" #include "FBXExportProperty.h" #include "FBXCommon.h" +#include "FBXUtil.h" #include <assimp/version.h> // aiGetVersion #include <assimp/IOSystem.hpp> @@ -66,6 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <vector> #include <array> #include <unordered_set> +#include <numeric> // RESOURCES: // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ @@ -73,7 +75,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian +using namespace Assimp; +using namespace Assimp::FBX; + // some constants that we'll use for writing metadata +namespace Assimp { namespace FBX { const std::string EXPORT_VERSION_STR = "7.4.0"; const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015 @@ -92,11 +98,6 @@ namespace FBX { ";------------------------------------------------------------------"; } -using namespace Assimp; -using namespace FBX; - -namespace Assimp { - // --------------------------------------------------------------------- // Worker function for exporting a scene to binary FBX. // Prototyped and registered in Exporter.cpp @@ -121,6 +122,7 @@ namespace Assimp { IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties + ){ // initialize the exporter FBXExporter exporter(pScene, pProperties); @@ -1004,6 +1006,9 @@ void FBXExporter::WriteObjects () object_node.EndProperties(outstream, binary, indent); object_node.BeginChildren(outstream, binary, indent); + bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true); + std::vector<std::vector<int32_t>> vVertexIndice;//save vertex_indices as it is needed later + // geometry (aiMesh) mesh_uids.clear(); indent = 1; @@ -1030,21 +1035,35 @@ void FBXExporter::WriteObjects () std::vector<int32_t> vertex_indices; // map of vertex value to its index in the data vector std::map<aiVector3D,size_t> index_by_vertex_value; - int32_t index = 0; - for (size_t vi = 0; vi < m->mNumVertices; ++vi) { - aiVector3D vtx = m->mVertices[vi]; - auto elem = index_by_vertex_value.find(vtx); - if (elem == index_by_vertex_value.end()) { - vertex_indices.push_back(index); - index_by_vertex_value[vtx] = index; - flattened_vertices.push_back(vtx[0]); - flattened_vertices.push_back(vtx[1]); - flattened_vertices.push_back(vtx[2]); - ++index; - } else { - vertex_indices.push_back(int32_t(elem->second)); + if(bJoinIdenticalVertices){ + int32_t index = 0; + for (size_t vi = 0; vi < m->mNumVertices; ++vi) { + aiVector3D vtx = m->mVertices[vi]; + auto elem = index_by_vertex_value.find(vtx); + if (elem == index_by_vertex_value.end()) { + vertex_indices.push_back(index); + index_by_vertex_value[vtx] = index; + flattened_vertices.push_back(vtx[0]); + flattened_vertices.push_back(vtx[1]); + flattened_vertices.push_back(vtx[2]); + ++index; + } else { + vertex_indices.push_back(int32_t(elem->second)); + } } } + else { // do not join vertex, respect the export flag + vertex_indices.resize(m->mNumVertices); + std::iota(vertex_indices.begin(), vertex_indices.end(), 0); + for(unsigned int v = 0; v < m->mNumVertices; ++ v) { + aiVector3D vtx = m->mVertices[v]; + flattened_vertices.push_back(vtx.x); + flattened_vertices.push_back(vtx.y); + flattened_vertices.push_back(vtx.z); + } + } + vVertexIndice.push_back(vertex_indices); + FBX::Node::WritePropertyNode( "Vertices", flattened_vertices, outstream, binary, indent ); @@ -1115,6 +1134,51 @@ void FBXExporter::WriteObjects () normals.End(outstream, binary, indent, true); } + // colors, if any + // TODO only one color channel currently + const int32_t colorChannelIndex = 0; + if (m->HasVertexColors(colorChannelIndex)) { + FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex)); + vertexcolors.Begin(outstream, binary, indent); + vertexcolors.DumpProperties(outstream, binary, indent); + vertexcolors.EndProperties(outstream, binary, indent); + vertexcolors.BeginChildren(outstream, binary, indent); + indent = 3; + FBX::Node::WritePropertyNode( + "Version", int32_t(101), outstream, binary, indent + ); + char layerName[8]; + sprintf(layerName, "COLOR_%d", colorChannelIndex); + FBX::Node::WritePropertyNode( + "Name", (const char*)layerName, outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "MappingInformationType", "ByPolygonVertex", + outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "ReferenceInformationType", "Direct", + outstream, binary, indent + ); + std::vector<double> color_data; + color_data.reserve(4 * polygon_data.size()); + for (size_t fi = 0; fi < m->mNumFaces; ++fi) { + const aiFace &f = m->mFaces[fi]; + for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { + const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]]; + color_data.push_back(c.r); + color_data.push_back(c.g); + color_data.push_back(c.b); + color_data.push_back(c.a); + } + } + FBX::Node::WritePropertyNode( + "Colors", color_data, outstream, binary, indent + ); + indent = 2; + vertexcolors.End(outstream, binary, indent, true); + } + // uvs, if any for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) { if (m->mNumUVComponents[uvi] > 2) { @@ -1208,6 +1272,11 @@ void FBXExporter::WriteObjects () le.AddChild("Type", "LayerElementNormal"); le.AddChild("TypedIndex", int32_t(0)); layer.AddChild(le); + // TODO only 1 color channel currently + le = FBX::Node("LayerElement"); + le.AddChild("Type", "LayerElementColor"); + le.AddChild("TypedIndex", int32_t(0)); + layer.AddChild(le); le = FBX::Node("LayerElement"); le.AddChild("Type", "LayerElementMaterial"); le.AddChild("TypedIndex", int32_t(0)); @@ -1218,6 +1287,16 @@ void FBXExporter::WriteObjects () layer.AddChild(le); layer.Dump(outstream, binary, indent); + for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr) + { + FBX::Node layerExtra("Layer", int32_t(lr)); + layerExtra.AddChild("Version", int32_t(100)); + FBX::Node leExtra("LayerElement"); + leExtra.AddChild("Type", "LayerElementUV"); + leExtra.AddChild("TypedIndex", int32_t(lr)); + layerExtra.AddChild(leExtra); + layerExtra.Dump(outstream, binary, indent); + } // finish the node record indent = 1; n.End(outstream, binary, indent, true); @@ -1393,10 +1472,6 @@ void FBXExporter::WriteObjects () // FbxVideo - stores images used by textures. for (const auto &it : uid_by_image) { - if (it.first.compare(0, 1, "*") == 0) { - // TODO: embedded textures - continue; - } FBX::Node n("Video"); const int64_t& uid = it.second; const std::string name = ""; // TODO: ... name??? @@ -1406,7 +1481,33 @@ void FBXExporter::WriteObjects () // TODO: get full path... relative path... etc... ugh... // for now just use the same path for everything, // and hopefully one of them will work out. - const std::string& path = it.first; + std::string path = it.first; + // try get embedded texture + const aiTexture* embedded_texture = mScene->GetEmbeddedTexture(it.first.c_str()); + if (embedded_texture != nullptr) { + // change the path (use original filename, if available. If name is empty, concatenate texture index with file extension) + std::stringstream newPath; + if (embedded_texture->mFilename.length > 0) { + newPath << embedded_texture->mFilename.C_Str(); + } else if (embedded_texture->achFormatHint[0]) { + int texture_index = std::stoi(path.substr(1, path.size() - 1)); + newPath << texture_index << "." << embedded_texture->achFormatHint; + } + path = newPath.str(); + // embed the texture + size_t texture_size = static_cast<size_t>(embedded_texture->mWidth * std::max(embedded_texture->mHeight, 1u)); + if (binary) { + // embed texture as binary data + std::vector<uint8_t> tex_data; + tex_data.resize(texture_size); + memcpy(&tex_data[0], (char*)embedded_texture->pcData, texture_size); + n.AddChild("Content", tex_data); + } else { + // embed texture in base64 encoding + std::string encoded_texture = FBX::Util::EncodeBase64((char*)embedded_texture->pcData, texture_size); + n.AddChild("Content", encoded_texture); + } + } p.AddP70("Path", "KString", "XRefUrl", "", path); n.AddChild(p); n.AddChild("UseMipMap", int32_t(0)); @@ -1419,17 +1520,17 @@ void FBXExporter::WriteObjects () // referenced by material_index/texture_type pairs. std::map<std::pair<size_t,size_t>,int64_t> texture_uids; const std::map<aiTextureType,std::string> prop_name_by_tt = { - {aiTextureType_DIFFUSE, "DiffuseColor"}, - {aiTextureType_SPECULAR, "SpecularColor"}, - {aiTextureType_AMBIENT, "AmbientColor"}, - {aiTextureType_EMISSIVE, "EmissiveColor"}, - {aiTextureType_HEIGHT, "Bump"}, - {aiTextureType_NORMALS, "NormalMap"}, - {aiTextureType_SHININESS, "ShininessExponent"}, - {aiTextureType_OPACITY, "TransparentColor"}, + {aiTextureType_DIFFUSE, "DiffuseColor"}, + {aiTextureType_SPECULAR, "SpecularColor"}, + {aiTextureType_AMBIENT, "AmbientColor"}, + {aiTextureType_EMISSIVE, "EmissiveColor"}, + {aiTextureType_HEIGHT, "Bump"}, + {aiTextureType_NORMALS, "NormalMap"}, + {aiTextureType_SHININESS, "ShininessExponent"}, + {aiTextureType_OPACITY, "TransparentColor"}, {aiTextureType_DISPLACEMENT, "DisplacementColor"}, //{aiTextureType_LIGHTMAP, "???"}, - {aiTextureType_REFLECTION, "ReflectionColor"} + {aiTextureType_REFLECTION, "ReflectionColor"} //{aiTextureType_UNKNOWN, ""} }; for (size_t i = 0; i < mScene->mNumMaterials; ++i) { @@ -1575,19 +1676,41 @@ void FBXExporter::WriteObjects () // one sticky point is that the number of vertices may not match, // because assimp splits vertices by normal, uv, etc. + // functor for aiNode sorting + struct SortNodeByName + { + bool operator()(const aiNode *lhs, const aiNode *rhs) const + { + return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0; + } + }; + // first we should mark the skeleton for each mesh. // the skeleton must include not only the aiBones, // but also all their parent nodes. // anything that affects the position of any bone node must be included. - std::vector<std::set<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes); + // Use SorNodeByName to make sure the exported result will be the same across all systems + // Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent + std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes); // at the same time we can build a list of all the skeleton nodes, // which will be used later to mark them as type "limbNode". std::unordered_set<const aiNode*> limbnodes; + + //actual bone nodes in fbx, without parenting-up + std::unordered_set<std::string> setAllBoneNamesInScene; + for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) + { + aiMesh* pMesh = mScene->mMeshes[m]; + for(unsigned int b = 0; b < pMesh->mNumBones; ++ b) + setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data); + } + aiMatrix4x4 mxTransIdentity; + // and a map of nodes by bone name, as finding them is annoying. std::map<std::string,aiNode*> node_by_bone; for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { const aiMesh* m = mScene->mMeshes[mi]; - std::set<const aiNode*> skeleton; + std::set<const aiNode*, SortNodeByName> skeleton; for (size_t bi =0; bi < m->mNumBones; ++bi) { const aiBone* b = m->mBones[bi]; const std::string name(b->mName.C_Str()); @@ -1626,6 +1749,11 @@ void FBXExporter::WriteObjects () if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) { continue; } + //not a bone in scene && no effect in transform + if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end() + && parent->mTransformation == mxTransIdentity) { + continue; + } // otherwise check if this is the root of the skeleton bool end = false; // is the mesh part of this node? @@ -1646,8 +1774,7 @@ void FBXExporter::WriteObjects () } if (end) { break; } } - limbnodes.insert(parent); - skeleton.insert(parent); + // if it was the skeleton root we can finish here if (end) { break; } } @@ -1689,28 +1816,8 @@ void FBXExporter::WriteObjects () // connect it connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]); - // we will be indexing by vertex... - // but there might be a different number of "vertices" - // between assimp and our output FBX. - // this code is cut-and-pasted from the geometry section above... - // ideally this should not be so. - // --- - // index of original vertex in vertex data vector - std::vector<int32_t> vertex_indices; - // map of vertex value to its index in the data vector - std::map<aiVector3D,size_t> index_by_vertex_value; - int32_t index = 0; - for (size_t vi = 0; vi < m->mNumVertices; ++vi) { - aiVector3D vtx = m->mVertices[vi]; - auto elem = index_by_vertex_value.find(vtx); - if (elem == index_by_vertex_value.end()) { - vertex_indices.push_back(index); - index_by_vertex_value[vtx] = index; - ++index; - } else { - vertex_indices.push_back(int32_t(elem->second)); - } - } + //computed before + std::vector<int32_t>& vertex_indices = vVertexIndice[mi]; // TODO, FIXME: this won't work if anything is not in the bind pose. // for now if such a situation is detected, we throw an exception. @@ -1728,7 +1835,7 @@ void FBXExporter::WriteObjects () aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); // now make a subdeformer for each bone in the skeleton - const std::set<const aiNode*> &skeleton = skeleton_by_mesh[mi]; + const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi]; for (const aiNode* bone_node : skeleton) { // if there's a bone for this node, find it const aiBone* b = nullptr; @@ -1788,41 +1895,10 @@ void FBXExporter::WriteObjects () inverse_bone_xform.Inverse(); aiMatrix4x4 tr = inverse_bone_xform * mesh_xform; - // this should be the same as the bone's mOffsetMatrix. - // if it's not the same, the skeleton isn't in the bind pose. - const float epsilon = 1e-4f; // some error is to be expected - bool bone_xform_okay = true; - if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { - not_in_bind_pose.insert(b); - bone_xform_okay = false; - } + sdnode.AddChild("Transform", tr); - // if we have a bone we should use the mOffsetMatrix, - // otherwise try to just use the calculated transform. - if (b) { - sdnode.AddChild("Transform", b->mOffsetMatrix); - } else { - sdnode.AddChild("Transform", tr); - } - // note: it doesn't matter if we mix these, - // because if they disagree we'll throw an exception later. - // it could be that the skeleton is not in the bone pose - // but all bones are still defined, - // in which case this would use the mOffsetMatrix for everything - // and a correct skeleton would still be output. - - // transformlink should be the position of the bone in world space. - // if the bone is in the bind pose (or nonexistent), - // we can just use the matrix we already calculated - if (bone_xform_okay) { - sdnode.AddChild("TransformLink", bone_xform); - // otherwise we can only work it out using the mesh position. - } else { - aiMatrix4x4 trl = b->mOffsetMatrix; - trl.Inverse(); - trl *= mesh_xform; - sdnode.AddChild("TransformLink", trl); - } + + sdnode.AddChild("TransformLink", bone_xform); // note: this means we ALWAYS rely on the mesh node transform // being unchanged from the time the skeleton was bound. // there's not really any way around this at the moment. @@ -2237,8 +2313,8 @@ void FBXExporter::WriteModelNode( // not sure what these are for, // but they seem to be omnipresent - m.AddChild("Shading", Property(true)); - m.AddChild("Culling", Property("CullingOff")); + m.AddChild("Shading", FBXExportProperty(true)); + m.AddChild("Culling", FBXExportProperty("CullingOff")); m.Dump(outstream, binary, 1); } @@ -2351,7 +2427,7 @@ void FBXExporter::WriteModelNodes( na.AddProperties( node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode" ); - na.AddChild("TypeFlags", Property("Skeleton")); + na.AddChild("TypeFlags", FBXExportProperty("Skeleton")); na.Dump(outstream, binary, 1); // and connect them connections.emplace_back("C", "OO", node_attribute_uid, node_uid); @@ -2407,7 +2483,7 @@ void FBXExporter::WriteModelNodes( void FBXExporter::WriteAnimationCurveNode( StreamWriterLE& outstream, int64_t uid, - std::string name, // "T", "R", or "S" + const std::string& name, // "T", "R", or "S" aiVector3D default_value, std::string property_name, // "Lcl Translation" etc int64_t layer_uid, diff --git a/thirdparty/assimp/code/FBXExporter.h b/thirdparty/assimp/code/FBX/FBXExporter.h index 71fb55c57f..1ae727eda9 100644 --- a/thirdparty/assimp/code/FBXExporter.h +++ b/thirdparty/assimp/code/FBX/FBXExporter.h @@ -156,7 +156,7 @@ namespace Assimp void WriteAnimationCurveNode( StreamWriterLE& outstream, int64_t uid, - std::string name, // "T", "R", or "S" + const std::string& name, // "T", "R", or "S" aiVector3D default_value, std::string property_name, // "Lcl Translation" etc int64_t animation_layer_uid, diff --git a/thirdparty/assimp/code/FBXImportSettings.h b/thirdparty/assimp/code/FBX/FBXImportSettings.h index d5e1c20608..1a4c80f8b2 100644 --- a/thirdparty/assimp/code/FBXImportSettings.h +++ b/thirdparty/assimp/code/FBX/FBXImportSettings.h @@ -53,19 +53,22 @@ namespace FBX { struct ImportSettings { ImportSettings() - : strictMode(true) - , readAllLayers(true) - , readAllMaterials(false) - , readMaterials(true) - , readTextures(true) - , readCameras(true) - , readLights(true) - , readAnimations(true) - , readWeights(true) - , preservePivots(true) - , optimizeEmptyAnimationCurves(true) - , useLegacyEmbeddedTextureNaming(false) - {} + : strictMode(true) + , readAllLayers(true) + , readAllMaterials(false) + , readMaterials(true) + , readTextures(true) + , readCameras(true) + , readLights(true) + , readAnimations(true) + , readWeights(true) + , preservePivots(true) + , optimizeEmptyAnimationCurves(true) + , useLegacyEmbeddedTextureNaming(false) + , removeEmptyBones( true ) + , convertToMeters( false ) { + // empty + } /** enable strict mode: @@ -141,8 +144,16 @@ struct ImportSettings bool optimizeEmptyAnimationCurves; /** use legacy naming for embedded textures eg: (*0, *1, *2) - **/ + */ bool useLegacyEmbeddedTextureNaming; + + /** Empty bones shall be removed + */ + bool removeEmptyBones; + + /** Set to true to perform a conversion from cm to meter after the import + */ + bool convertToMeters; }; diff --git a/thirdparty/assimp/code/FBX/FBXImporter.cpp b/thirdparty/assimp/code/FBX/FBXImporter.cpp new file mode 100644 index 0000000000..afcc1ddc78 --- /dev/null +++ b/thirdparty/assimp/code/FBX/FBXImporter.cpp @@ -0,0 +1,198 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. +r +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXImporter.cpp + * @brief Implementation of the FBX importer. + */ + +#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER + +#include "FBXImporter.h" + +#include "FBXConverter.h" +#include "FBXDocument.h" +#include "FBXParser.h" +#include "FBXTokenizer.h" +#include "FBXUtil.h" + +#include <assimp/MemoryIOWrapper.h> +#include <assimp/StreamReader.h> +#include <assimp/importerdesc.h> +#include <assimp/Importer.hpp> + +namespace Assimp { + +template <> +const char *LogFunctions<FBXImporter>::Prefix() { + static auto prefix = "FBX: "; + return prefix; +} + +} // namespace Assimp + +using namespace Assimp; +using namespace Assimp::Formatter; +using namespace Assimp::FBX; + +namespace { + +static const aiImporterDesc desc = { + "Autodesk FBX Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "fbx" +}; +} + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by #Importer +FBXImporter::FBXImporter() { +} + +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +FBXImporter::~FBXImporter() { +} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool FBXImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { + const std::string &extension = GetExtension(pFile); + if (extension == std::string(desc.mFileExtensions)) { + return true; + } + + else if ((!extension.length() || checkSig) && pIOHandler) { + // at least ASCII-FBX files usually have a 'FBX' somewhere in their head + const char *tokens[] = { "fbx" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +// List all extensions handled by this loader +const aiImporterDesc *FBXImporter::GetInfo() const { + return &desc; +} + +// ------------------------------------------------------------------------------------------------ +// Setup configuration properties for the loader +void FBXImporter::SetupProperties(const Importer *pImp) { + settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true); + settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false); + settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true); + settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true); + settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true); + settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true); + settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true); + settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false); + settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); + settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); + settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); + settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); + settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); +} + +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb")); + if (!stream) { + ThrowException("Could not open file for reading"); + } + + // read entire file into memory - no streaming for this, fbx + // files can grow large, but the assimp output data structure + // then becomes very large, too. Assimp doesn't support + // streaming for its output data structures so the net win with + // streaming input data would be very low. + std::vector<char> contents; + contents.resize(stream->FileSize() + 1); + stream->Read(&*contents.begin(), 1, contents.size() - 1); + contents[contents.size() - 1] = 0; + const char *const begin = &*contents.begin(); + + // broadphase tokenizing pass in which we identify the core + // syntax elements of FBX (brackets, commas, key:value mappings) + TokenList tokens; + try { + + bool is_binary = false; + if (!strncmp(begin, "Kaydara FBX Binary", 18)) { + is_binary = true; + TokenizeBinary(tokens, begin, contents.size()); + } else { + Tokenize(tokens, begin); + } + + // use this information to construct a very rudimentary + // parse-tree representing the FBX scope structure + Parser parser(tokens, is_binary); + + // take the raw parse-tree and convert it to a FBX DOM + Document doc(parser, settings); + + // convert the FBX DOM to aiScene + ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones); + + // size relative to cm + float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor(); + + // Set FBX file scale is relative to CM must be converted to M for + // assimp universal format (M) + SetFileScale(size_relative_to_cm * 0.01f); + + std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>()); + } catch (std::exception &) { + std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>()); + throw; + } +} + +#endif // !ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/thirdparty/assimp/code/FBXImporter.h b/thirdparty/assimp/code/FBX/FBXImporter.h index c365b2cddf..c365b2cddf 100644 --- a/thirdparty/assimp/code/FBXImporter.h +++ b/thirdparty/assimp/code/FBX/FBXImporter.h diff --git a/thirdparty/assimp/code/FBXMaterial.cpp b/thirdparty/assimp/code/FBX/FBXMaterial.cpp index 08347740fa..f43a8b84b0 100644 --- a/thirdparty/assimp/code/FBXMaterial.cpp +++ b/thirdparty/assimp/code/FBX/FBXMaterial.cpp @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/ByteSwapper.h> #include <algorithm> // std::transform +#include "FBXUtil.h" namespace Assimp { namespace FBX { @@ -206,6 +207,20 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc); + // 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available. + bool ok; + const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok); + if (ok) { + uvScaling.x = scaling.x; + uvScaling.y = scaling.y; + } + + const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok); + if (ok) { + uvTrans.x = trans.x; + uvTrans.y = trans.y; + } + // resolve video links if(doc.Settings().readTextures) { const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); @@ -301,13 +316,52 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0)); } - if(Content) { + if(Content && !Content->Tokens().empty()) { //this field is omitted when the embedded texture is already loaded, let's ignore if it's not found try { const Token& token = GetRequiredToken(*Content, 0); const char* data = token.begin(); if (!token.IsBinary()) { - DOMWarning("video content is not binary data, ignoring", &element); + if (*data != '"') { + DOMError("embedded content is not surrounded by quotation marks", &element); + } + else { + size_t targetLength = 0; + auto numTokens = Content->Tokens().size(); + // First time compute size (it could be large like 64Gb and it is good to allocate it once) + for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) + { + const Token& dataToken = GetRequiredToken(*Content, tokenIdx); + size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes + const char* base64data = dataToken.begin() + 1; + const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength); + if (outLength == 0) + { + DOMError("Corrupted embedded content found", &element); + } + targetLength += outLength; + } + if (targetLength == 0) + { + DOMError("Corrupted embedded content found", &element); + } + content = new uint8_t[targetLength]; + contentLength = static_cast<uint64_t>(targetLength); + size_t dst_offset = 0; + for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) + { + const Token& dataToken = GetRequiredToken(*Content, tokenIdx); + size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes + const char* base64data = dataToken.begin() + 1; + dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset); + } + if (targetLength != dst_offset) + { + delete[] content; + contentLength = 0; + DOMError("Corrupted embedded content found", &element); + } + } } else if (static_cast<size_t>(token.end() - data) < 5) { DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element); diff --git a/thirdparty/assimp/code/FBXMeshGeometry.cpp b/thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp index d75476b826..1386e2383c 100644 --- a/thirdparty/assimp/code/FBXMeshGeometry.cpp +++ b/thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp @@ -115,7 +115,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin if(tempVerts.empty()) { FBXImporter::LogWarn("encountered mesh with no vertices"); - return; } std::vector<int> tempFaces; @@ -123,7 +122,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin if(tempFaces.empty()) { FBXImporter::LogWarn("encountered mesh with no faces"); - return; } m_vertices.reserve(tempFaces.size()); @@ -568,15 +566,15 @@ void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, cons } // ------------------------------------------------------------------------------------------------ -static const std::string TangentIndexToken = "TangentIndex"; -static const std::string TangentsIndexToken = "TangentsIndex"; +static const char *TangentIndexToken = "TangentIndex"; +static const char *TangentsIndexToken = "TangentsIndex"; void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source, const std::string& MappingInformationType, const std::string& ReferenceInformationType) { const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent"; - const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken.c_str() : TangentIndexToken.c_str(); + const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken; ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType, str, strIdx, @@ -612,8 +610,11 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons const std::string& ReferenceInformationType) { const size_t face_count = m_faces.size(); - ai_assert(face_count); - + if( 0 == face_count ) + { + return; + } + // materials are handled separately. First of all, they are assigned per-face // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect // has a slightly different meaning for materials. @@ -624,16 +625,15 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons if (materials_out.empty()) { FBXImporter::LogError(Formatter::format("expected material index, ignoring")); return; - } - else if (materials_out.size() > 1) { + } else if (materials_out.size() > 1) { FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one")); materials_out.clear(); } - m_materials.assign(m_vertices.size(),materials_out[0]); - } - else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") { - m_materials.resize(face_count); + materials_out.resize(m_vertices.size()); + std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0)); + } else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") { + materials_out.resize(face_count); if(materials_out.size() != face_count) { FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") @@ -641,18 +641,16 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons ); return; } - } - else { + } else { FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ") << MappingInformationType << "," << ReferenceInformationType); } } // ------------------------------------------------------------------------------------------------ ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) - : Geometry(id, element, name, doc) -{ - const Scope* sc = element.Compound(); - if (!sc) { +: Geometry(id, element, name, doc) { + const Scope *sc = element.Compound(); + if (nullptr == sc) { DOMError("failed to read Geometry object (class: Shape), no data scope found"); } const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element); diff --git a/thirdparty/assimp/code/FBXMeshGeometry.h b/thirdparty/assimp/code/FBX/FBXMeshGeometry.h index d6d4512177..d6d4512177 100644 --- a/thirdparty/assimp/code/FBXMeshGeometry.h +++ b/thirdparty/assimp/code/FBX/FBXMeshGeometry.h diff --git a/thirdparty/assimp/code/FBXModel.cpp b/thirdparty/assimp/code/FBX/FBXModel.cpp index 589af36ac7..589af36ac7 100644 --- a/thirdparty/assimp/code/FBXModel.cpp +++ b/thirdparty/assimp/code/FBX/FBXModel.cpp diff --git a/thirdparty/assimp/code/FBXNodeAttribute.cpp b/thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp index b72e5637ee..b72e5637ee 100644 --- a/thirdparty/assimp/code/FBXNodeAttribute.cpp +++ b/thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp diff --git a/thirdparty/assimp/code/FBXParser.cpp b/thirdparty/assimp/code/FBX/FBXParser.cpp index b255c47347..4a9346040d 100644 --- a/thirdparty/assimp/code/FBXParser.cpp +++ b/thirdparty/assimp/code/FBX/FBXParser.cpp @@ -117,7 +117,7 @@ namespace FBX { Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) { - TokenPtr n = NULL; + TokenPtr n = nullptr; do { n = parser.AdvanceToNextToken(); if(!n) { @@ -643,9 +643,9 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el) if (type == 'd') { const double* d = reinterpret_cast<const double*>(&buff[0]); for (unsigned int i = 0; i < count3; ++i, d += 3) { - out.push_back(aiVector3D(static_cast<float>(d[0]), - static_cast<float>(d[1]), - static_cast<float>(d[2]))); + out.push_back(aiVector3D(static_cast<ai_real>(d[0]), + static_cast<ai_real>(d[1]), + static_cast<ai_real>(d[2]))); } // for debugging /*for ( size_t i = 0; i < out.size(); i++ ) { @@ -963,7 +963,6 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el) } } - // ------------------------------------------------------------------------------------------------ // read an array of uints void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el) @@ -1280,7 +1279,6 @@ float ParseTokenAsFloat(const Token& t) return i; } - // ------------------------------------------------------------------------------------------------ // wrapper around ParseTokenAsInt() with ParseError handling int ParseTokenAsInt(const Token& t) @@ -1293,8 +1291,6 @@ int ParseTokenAsInt(const Token& t) return i; } - - // ------------------------------------------------------------------------------------------------ // wrapper around ParseTokenAsInt64() with ParseError handling int64_t ParseTokenAsInt64(const Token& t) diff --git a/thirdparty/assimp/code/FBXParser.h b/thirdparty/assimp/code/FBX/FBXParser.h index 7b0cf72039..7b0cf72039 100644 --- a/thirdparty/assimp/code/FBXParser.h +++ b/thirdparty/assimp/code/FBX/FBXParser.h diff --git a/thirdparty/assimp/code/FBXProperties.cpp b/thirdparty/assimp/code/FBX/FBXProperties.cpp index 8d7036b6a9..8d7036b6a9 100644 --- a/thirdparty/assimp/code/FBXProperties.cpp +++ b/thirdparty/assimp/code/FBX/FBXProperties.cpp diff --git a/thirdparty/assimp/code/FBXProperties.h b/thirdparty/assimp/code/FBX/FBXProperties.h index 58755542fc..58755542fc 100644 --- a/thirdparty/assimp/code/FBXProperties.h +++ b/thirdparty/assimp/code/FBX/FBXProperties.h diff --git a/thirdparty/assimp/code/FBXTokenizer.cpp b/thirdparty/assimp/code/FBX/FBXTokenizer.cpp index 252cce3557..252cce3557 100644 --- a/thirdparty/assimp/code/FBXTokenizer.cpp +++ b/thirdparty/assimp/code/FBX/FBXTokenizer.cpp diff --git a/thirdparty/assimp/code/FBXTokenizer.h b/thirdparty/assimp/code/FBX/FBXTokenizer.h index 2af29743f4..afa588a470 100644 --- a/thirdparty/assimp/code/FBXTokenizer.h +++ b/thirdparty/assimp/code/FBX/FBXTokenizer.h @@ -93,7 +93,7 @@ public: Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column); /** construct a binary token */ - Token(const char* sbegin, const char* send, TokenType type, unsigned int offset); + Token(const char* sbegin, const char* send, TokenType type, size_t offset); ~Token(); @@ -118,14 +118,14 @@ public: return type; } - unsigned int Offset() const { + size_t Offset() const { ai_assert(IsBinary()); return offset; } unsigned int Line() const { ai_assert(!IsBinary()); - return line; + return static_cast<unsigned int>(line); } unsigned int Column() const { @@ -147,8 +147,8 @@ private: const TokenType type; union { - const unsigned int line; - unsigned int offset; + size_t line; + size_t offset; }; const unsigned int column; }; @@ -178,7 +178,7 @@ void Tokenize(TokenList& output_tokens, const char* input); * @param input_buffer Binary input buffer to be processed. * @param length Length of input buffer, in bytes. There is no 0-terminal. * @throw DeadlyImportError if something goes wrong */ -void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length); +void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length); } // ! FBX diff --git a/thirdparty/assimp/code/FBX/FBXUtil.cpp b/thirdparty/assimp/code/FBX/FBXUtil.cpp new file mode 100644 index 0000000000..c10e057c8c --- /dev/null +++ b/thirdparty/assimp/code/FBX/FBXUtil.cpp @@ -0,0 +1,243 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXUtil.cpp + * @brief Implementation of internal FBX utility functions + */ + +#include "FBXUtil.h" +#include "FBXTokenizer.h" + +#include <assimp/TinyFormatter.h> +#include <string> +#include <cstring> + +#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER + +namespace Assimp { +namespace FBX { +namespace Util { + +// ------------------------------------------------------------------------------------------------ +const char* TokenTypeString(TokenType t) +{ + switch(t) { + case TokenType_OPEN_BRACKET: + return "TOK_OPEN_BRACKET"; + + case TokenType_CLOSE_BRACKET: + return "TOK_CLOSE_BRACKET"; + + case TokenType_DATA: + return "TOK_DATA"; + + case TokenType_COMMA: + return "TOK_COMMA"; + + case TokenType_KEY: + return "TOK_KEY"; + + case TokenType_BINARY_DATA: + return "TOK_BINARY_DATA"; + } + + ai_assert(false); + return ""; +} + + +// ------------------------------------------------------------------------------------------------ +std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset) +{ + return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) ); +} + +// ------------------------------------------------------------------------------------------------ +std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column) +{ + return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " << col " << column << ") " << text) ); +} + +// ------------------------------------------------------------------------------------------------ +std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok) +{ + if(tok->IsBinary()) { + return static_cast<std::string>( (Formatter::format() << prefix << + " (" << TokenTypeString(tok->Type()) << + ", offset 0x" << std::hex << tok->Offset() << ") " << + text) ); + } + + return static_cast<std::string>( (Formatter::format() << prefix << + " (" << TokenTypeString(tok->Type()) << + ", line " << tok->Line() << + ", col " << tok->Column() << ") " << + text) ); +} + +// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; +static const uint8_t base64DecodeTable[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, + 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, + 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255 +}; + +uint8_t DecodeBase64(char ch) +{ + const auto idx = static_cast<uint8_t>(ch); + if (idx > 127) + return 255; + return base64DecodeTable[idx]; +} + +size_t ComputeDecodedSizeBase64(const char* in, size_t inLength) +{ + if (inLength < 2) + { + return 0; + } + const size_t equals = size_t(in[inLength - 1] == '=') + size_t(in[inLength - 2] == '='); + const size_t full_length = (inLength * 3) >> 2; // div by 4 + if (full_length < equals) + { + return 0; + } + return full_length - equals; +} + +size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength) +{ + if (maxOutLength == 0 || inLength < 2) { + return 0; + } + const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '='); + size_t dst_offset = 0; + int val = 0, valb = -8; + for (size_t src_offset = 0; src_offset < realLength; ++src_offset) + { + const uint8_t table_value = Util::DecodeBase64(in[src_offset]); + if (table_value == 255) + { + return 0; + } + val = (val << 6) + table_value; + valb += 6; + if (valb >= 0) + { + out[dst_offset++] = static_cast<uint8_t>((val >> valb) & 0xFF); + valb -= 8; + val &= 0xFFF; + } + } + return dst_offset; +} + +static const char to_base64_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +char EncodeBase64(char byte) +{ + return to_base64_string[(size_t)byte]; +} + +/** Encodes a block of 4 bytes to base64 encoding +* +* @param bytes Bytes to encode. +* @param out_string String to write encoded values to. +* @param string_pos Position in out_string.*/ +void EncodeByteBlock(const char* bytes, std::string& out_string, size_t string_pos) +{ + char b0 = (bytes[0] & 0xFC) >> 2; + char b1 = (bytes[0] & 0x03) << 4 | ((bytes[1] & 0xF0) >> 4); + char b2 = (bytes[1] & 0x0F) << 2 | ((bytes[2] & 0xC0) >> 6); + char b3 = (bytes[2] & 0x3F); + + out_string[string_pos + 0] = EncodeBase64(b0); + out_string[string_pos + 1] = EncodeBase64(b1); + out_string[string_pos + 2] = EncodeBase64(b2); + out_string[string_pos + 3] = EncodeBase64(b3); +} + +std::string EncodeBase64(const char* data, size_t length) +{ + // calculate extra bytes needed to get a multiple of 3 + size_t extraBytes = 3 - length % 3; + + // number of base64 bytes + size_t encodedBytes = 4 * (length + extraBytes) / 3; + + std::string encoded_string(encodedBytes, '='); + + // read blocks of 3 bytes + for (size_t ib3 = 0; ib3 < length / 3; ib3++) + { + const size_t iByte = ib3 * 3; + const size_t iEncodedByte = ib3 * 4; + const char* currData = &data[iByte]; + + EncodeByteBlock(currData, encoded_string, iEncodedByte); + } + + // if size of data is not a multiple of 3, also encode the final bytes (and add zeros where needed) + if (extraBytes > 0) + { + char finalBytes[4] = { 0,0,0,0 }; + memcpy(&finalBytes[0], &data[length - length % 3], length % 3); + + const size_t iEncodedByte = encodedBytes - 4; + EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte); + + // add '=' at the end + for (size_t i = 0; i < 4 * extraBytes / 3; i++) + encoded_string[encodedBytes - i - 1] = '='; + } + return encoded_string; +} + +} // !Util +} // !FBX +} // !Assimp + +#endif diff --git a/thirdparty/assimp/code/FBXUtil.h b/thirdparty/assimp/code/FBX/FBXUtil.h index 1a37d346b4..b634418858 100644 --- a/thirdparty/assimp/code/FBXUtil.h +++ b/thirdparty/assimp/code/FBX/FBXUtil.h @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXCompileConfig.h" #include "FBXTokenizer.h" +#include <stdint.h> namespace Assimp { namespace FBX { @@ -77,7 +78,7 @@ const char* TokenTypeString(TokenType t); * @param line Line index, 1-based * @param column Column index, 1-based * @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/ -std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset); +std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset); /** Format log/error messages using a given line location in the source file. @@ -98,6 +99,37 @@ std::string AddLineAndColumn(const std::string& prefix, const std::string& text, * @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/ std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok); +/** Decode a single Base64-encoded character. +* +* @param ch Character to decode (from base64 to binary). +* @return decoded byte value*/ +uint8_t DecodeBase64(char ch); + +/** Compute decoded size of a Base64-encoded string +* +* @param in Characters to decode. +* @param inLength Number of characters to decode. +* @return size of the decoded data (number of bytes)*/ +size_t ComputeDecodedSizeBase64(const char* in, size_t inLength); + +/** Decode a Base64-encoded string +* +* @param in Characters to decode. +* @param inLength Number of characters to decode. +* @param out Pointer where we will store the decoded data. +* @param maxOutLength Size of output buffer. +* @return size of the decoded data (number of bytes)*/ +size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength); + +char EncodeBase64(char byte); + +/** Encode bytes in base64-encoding +* +* @param data Binary data to encode. +* @param inLength Number of bytes to encode. +* @return base64-encoded string*/ +std::string EncodeBase64(const char* data, size_t length); + } } } diff --git a/thirdparty/assimp/code/FBXImporter.cpp b/thirdparty/assimp/code/FBXImporter.cpp deleted file mode 100644 index 2cc8bffc29..0000000000 --- a/thirdparty/assimp/code/FBXImporter.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. -r -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** @file FBXImporter.cpp - * @brief Implementation of the FBX importer. - */ - -#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER - -#include "FBXImporter.h" - -#include "FBXTokenizer.h" -#include "FBXParser.h" -#include "FBXUtil.h" -#include "FBXDocument.h" -#include "FBXConverter.h" - -#include <assimp/StreamReader.h> -#include <assimp/MemoryIOWrapper.h> -#include <assimp/Importer.hpp> -#include <assimp/importerdesc.h> - -namespace Assimp { - -template<> -const char* LogFunctions<FBXImporter>::Prefix() { - static auto prefix = "FBX: "; - return prefix; -} - -} - -using namespace Assimp; -using namespace Assimp::Formatter; -using namespace Assimp::FBX; - -namespace { - -static const aiImporterDesc desc = { - "Autodesk FBX Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "fbx" -}; -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by #Importer -FBXImporter::FBXImporter() -{ -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FBXImporter::~FBXImporter() -{ -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string& extension = GetExtension(pFile); - if (extension == std::string( desc.mFileExtensions ) ) { - return true; - } - - else if ((!extension.length() || checkSig) && pIOHandler) { - // at least ASCII-FBX files usually have a 'FBX' somewhere in their head - const char* tokens[] = {"fbx"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// List all extensions handled by this loader -const aiImporterDesc* FBXImporter::GetInfo () const -{ - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties for the loader -void FBXImporter::SetupProperties(const Importer* pImp) -{ - settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true); - settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false); - settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true); - settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true); - settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true); - settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true); - settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true); - settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false); - settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); - settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); - settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb")); - if (!stream) { - ThrowException("Could not open file for reading"); - } - - // read entire file into memory - no streaming for this, fbx - // files can grow large, but the assimp output data structure - // then becomes very large, too. Assimp doesn't support - // streaming for its output data structures so the net win with - // streaming input data would be very low. - std::vector<char> contents; - contents.resize(stream->FileSize()+1); - stream->Read( &*contents.begin(), 1, contents.size()-1 ); - contents[ contents.size() - 1 ] = 0; - const char* const begin = &*contents.begin(); - - // broadphase tokenizing pass in which we identify the core - // syntax elements of FBX (brackets, commas, key:value mappings) - TokenList tokens; - try { - - bool is_binary = false; - if (!strncmp(begin,"Kaydara FBX Binary",18)) { - is_binary = true; - TokenizeBinary(tokens,begin,static_cast<unsigned int>(contents.size())); - } - else { - Tokenize(tokens,begin); - } - - // use this information to construct a very rudimentary - // parse-tree representing the FBX scope structure - Parser parser(tokens, is_binary); - - // take the raw parse-tree and convert it to a FBX DOM - Document doc(parser,settings); - - // convert the FBX DOM to aiScene - ConvertToAssimpScene(pScene,doc); - - std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>()); - } - catch(std::exception&) { - std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>()); - throw; - } -} - -#endif // !ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/thirdparty/assimp/code/FBXUtil.cpp b/thirdparty/assimp/code/FBXUtil.cpp deleted file mode 100644 index c184c4a00b..0000000000 --- a/thirdparty/assimp/code/FBXUtil.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** @file FBXUtil.cpp - * @brief Implementation of internal FBX utility functions - */ - -#include "FBXUtil.h" -#include "FBXTokenizer.h" - -#include <assimp/TinyFormatter.h> -#include <string> - -#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER - -namespace Assimp { -namespace FBX { -namespace Util { - -// ------------------------------------------------------------------------------------------------ -const char* TokenTypeString(TokenType t) -{ - switch(t) { - case TokenType_OPEN_BRACKET: - return "TOK_OPEN_BRACKET"; - - case TokenType_CLOSE_BRACKET: - return "TOK_CLOSE_BRACKET"; - - case TokenType_DATA: - return "TOK_DATA"; - - case TokenType_COMMA: - return "TOK_COMMA"; - - case TokenType_KEY: - return "TOK_KEY"; - - case TokenType_BINARY_DATA: - return "TOK_BINARY_DATA"; - } - - ai_assert(false); - return ""; -} - - -// ------------------------------------------------------------------------------------------------ -std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset) -{ - return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) ); -} - -// ------------------------------------------------------------------------------------------------ -std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column) -{ - return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " << col " << column << ") " << text) ); -} - -// ------------------------------------------------------------------------------------------------ -std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok) -{ - if(tok->IsBinary()) { - return static_cast<std::string>( (Formatter::format() << prefix << - " (" << TokenTypeString(tok->Type()) << - ", offset 0x" << std::hex << tok->Offset() << ") " << - text) ); - } - - return static_cast<std::string>( (Formatter::format() << prefix << - " (" << TokenTypeString(tok->Type()) << - ", line " << tok->Line() << - ", col " << tok->Column() << ") " << - text) ); -} - -} // !Util -} // !FBX -} // !Assimp - -#endif diff --git a/thirdparty/assimp/code/FIReader.cpp b/thirdparty/assimp/code/FIReader.cpp deleted file mode 100644 index 2116316ca3..0000000000 --- a/thirdparty/assimp/code/FIReader.cpp +++ /dev/null @@ -1,1834 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -/// \file 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 <assimp/StringUtils.h> - -// Workaround for issue #1361 -// https://github.com/assimp/assimp/issues/1361 -#ifdef __ANDROID__ -# define _GLIBCXX_USE_C99 1 -#endif - -#include <assimp/Exceptional.h> -#include <assimp/IOStream.hpp> -#include <assimp/types.h> -#include <assimp/MemoryIOWrapper.h> -#include <assimp/irrXMLWrapper.h> -#include "../contrib/utf8cpp/source/utf8.h" -#include <assimp/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 ¬ationName =*/ 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/thirdparty/assimp/code/MMDCpp14.h b/thirdparty/assimp/code/MMDCpp14.h deleted file mode 100644 index 638b0bfd2f..0000000000 --- a/thirdparty/assimp/code/MMDCpp14.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#pragma once - -#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/thirdparty/assimp/code/MMDImporter.cpp b/thirdparty/assimp/code/MMDImporter.cpp deleted file mode 100644 index 84b9e35a6b..0000000000 --- a/thirdparty/assimp/code/MMDImporter.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2016, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -#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_strAbsPath("") { - DefaultIOSystem io; - m_strAbsPath = io.getOsSeparator(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -MMDImporter::~MMDImporter() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// 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); - } - - 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 - std::unique_ptr<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.get() + i); - } else { - ppNode[bone.parent_index]->addChildren(1, ppNode.get() + 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; // triangular 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 = new aiVertexWeight[pBone->mNumWeights]; - for (unsigned int j = 0; j < pBone->mNumWeights; j++) { - pBone->mWeights[j] = it->second[j]; - } - } - 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); - - if(pMat->diffuse_texture_index >= 0) { - 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/thirdparty/assimp/code/MMDImporter.h b/thirdparty/assimp/code/MMDImporter.h deleted file mode 100644 index 4ee94eeb00..0000000000 --- a/thirdparty/assimp/code/MMDImporter.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2016, assimp team -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#ifndef MMD_FILE_IMPORTER_H_INC -#define MMD_FILE_IMPORTER_H_INC - -#include <assimp/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
\ No newline at end of file diff --git a/thirdparty/assimp/code/MMDPmdParser.h b/thirdparty/assimp/code/MMDPmdParser.h deleted file mode 100644 index d2f2224aa1..0000000000 --- a/thirdparty/assimp/code/MMDPmdParser.h +++ /dev/null @@ -1,597 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#pragma once - -#include <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/thirdparty/assimp/code/MMDPmxParser.cpp b/thirdparty/assimp/code/MMDPmxParser.cpp deleted file mode 100644 index 7425ceac22..0000000000 --- a/thirdparty/assimp/code/MMDPmxParser.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#include <utility> -#include "MMDPmxParser.h" -#include <assimp/StringUtils.h> -#include "../contrib/utf8cpp/source/utf8.h" -#include <assimp/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 - const uint16_t* sourceStart = (uint16_t*)buffer.data(); - const unsigned int targetSize = size * 3; // enough to encode - char *targetStart = new char[targetSize]; - std::memset(targetStart, 0, targetSize * sizeof(char)); - - utf8::utf16to8( sourceStart, sourceStart + size/2, targetStart ); - - std::string result(targetStart); - delete [] targetStart; - 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 DeadlyImportError("MMD: invalid size"); - } - 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 DeadlyImportError("MMD: unknown morth type"); - } - } - - 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 DeadlyImportError("MMD: Not Implemented Exception"); - } - - 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 DeadlyImportError("MMD: invalid magic number."); - } - 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 DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but " + to_string(version)); - } - 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); - - // read vertices - 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); - } - - // read indices - 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); - } - - // read texture names - 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); - } - - // read materials - 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); - } - - // read bones - 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); - } - - // read morphs - 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); - } - - // read display frames - 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); - } - - // read rigid bodies - 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); - } - - // read joints - 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); - } - } -} diff --git a/thirdparty/assimp/code/MMDPmxParser.h b/thirdparty/assimp/code/MMDPmxParser.h deleted file mode 100644 index cf523a1298..0000000000 --- a/thirdparty/assimp/code/MMDPmxParser.h +++ /dev/null @@ -1,782 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#pragma once - -#include <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; - virtual ~PmxVertexSkinning() {} - }; - - 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/thirdparty/assimp/code/MMDVmdParser.h b/thirdparty/assimp/code/MMDVmdParser.h deleted file mode 100644 index 947c3a2422..0000000000 --- a/thirdparty/assimp/code/MMDVmdParser.h +++ /dev/null @@ -1,376 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#pragma once - -#include <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/thirdparty/assimp/code/MaterialSystem.cpp b/thirdparty/assimp/code/Material/MaterialSystem.cpp index 03d5a18a34..0be6e9f7bb 100644 --- a/thirdparty/assimp/code/MaterialSystem.cpp +++ b/thirdparty/assimp/code/Material/MaterialSystem.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/types.h> #include <assimp/material.h> #include <assimp/DefaultLogger.hpp> -#include <assimp/Macros.h> using namespace Assimp; @@ -96,12 +95,12 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, ai_real* pOut, unsigned int* pMax) { - ai_assert( pOut != NULL ); - ai_assert( pMat != NULL ); + ai_assert( pOut != nullptr ); + ai_assert( pMat != nullptr ); const aiMaterialProperty* prop; aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop); - if (!prop) { + if ( nullptr == prop) { return AI_FAILURE; } @@ -112,9 +111,11 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, if (pMax) { iWrite = std::min(*pMax,iWrite); ; } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] ); + + for (unsigned int a = 0; a < iWrite; ++a) { + pOut[ a ] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] ); } + if (pMax) { *pMax = iWrite; } @@ -543,23 +544,7 @@ aiReturn aiMaterial::AddProperty (const aiString* pInput, unsigned int type, unsigned int index) { - // We don't want to add the whole buffer .. write a 32 bit length - // prefix followed by the zero-terminated UTF8 string. - // (HACK) I don't want to break the ABI now, but we definitely - // ought to change aiString::mLength to uint32_t one day. - if (sizeof(size_t) == 8) { - aiString copy = *pInput; - uint32_t* s = reinterpret_cast<uint32_t*>(©.length); - s[1] = static_cast<uint32_t>(pInput->length); - - return AddBinaryProperty(s+1, - static_cast<unsigned int>(pInput->length+1+4), - pKey, - type, - index, - aiPTI_String); - } - ai_assert(sizeof(size_t)==4); + ai_assert(sizeof(ai_uint32)==4); return AddBinaryProperty(pInput, static_cast<unsigned int>(pInput->length+1+4), pKey, diff --git a/thirdparty/assimp/code/MaterialSystem.h b/thirdparty/assimp/code/Material/MaterialSystem.h index 67d53578cb..67d53578cb 100644 --- a/thirdparty/assimp/code/MaterialSystem.h +++ b/thirdparty/assimp/code/Material/MaterialSystem.h diff --git a/thirdparty/assimp/code/PostProcessing/ArmaturePopulate.cpp b/thirdparty/assimp/code/PostProcessing/ArmaturePopulate.cpp new file mode 100644 index 0000000000..75daeb6b59 --- /dev/null +++ b/thirdparty/assimp/code/PostProcessing/ArmaturePopulate.cpp @@ -0,0 +1,268 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include "ArmaturePopulate.h" + +#include <assimp/BaseImporter.h> +#include <assimp/DefaultLogger.hpp> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <iostream> + +namespace Assimp { + +/// The default class constructor. +ArmaturePopulate::ArmaturePopulate() : BaseProcess() +{} + +/// The class destructor. +ArmaturePopulate::~ArmaturePopulate() +{} + +bool ArmaturePopulate::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_PopulateArmatureData) != 0; +} + +void ArmaturePopulate::SetupProperties(const Importer *pImp) { + // do nothing +} + +void ArmaturePopulate::Execute(aiScene *out) { + + // Now convert all bone positions to the correct mOffsetMatrix + std::vector<aiBone *> bones; + std::vector<aiNode *> nodes; + std::map<aiBone *, aiNode *> bone_stack; + BuildBoneList(out->mRootNode, out->mRootNode, out, bones); + BuildNodeList(out->mRootNode, nodes); + + BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); + + ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size()); + + for (std::pair<aiBone *, aiNode *> kvp : bone_stack) { + aiBone *bone = kvp.first; + aiNode *bone_node = kvp.second; + ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str()); + // lcl transform grab - done in generate_nodes :) + + // bone->mOffsetMatrix = bone_node->mTransformation; + aiNode *armature = GetArmatureRoot(bone_node, bones); + + ai_assert(armature); + + // set up bone armature id + bone->mArmature = armature; + + // set this bone node to be referenced properly + ai_assert(bone_node); + bone->mNode = bone_node; + } +} + + +/* Reprocess all nodes to calculate bone transforms properly based on the REAL + * mOffsetMatrix not the local. */ +/* Before this would use mesh transforms which is wrong for bone transforms */ +/* Before this would work for simple character skeletons but not complex meshes + * with multiple origins */ +/* Source: sketch fab log cutter fbx */ +void ArmaturePopulate::BuildBoneList(aiNode *current_node, + const aiNode *root_node, + const aiScene *scene, + std::vector<aiBone *> &bones) { + ai_assert(scene); + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); + + // check for bones + for (unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) { + ai_assert(child->mMeshes); + unsigned int mesh_index = child->mMeshes[meshId]; + aiMesh *mesh = scene->mMeshes[mesh_index]; + ai_assert(mesh); + + for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) { + aiBone *bone = mesh->mBones[boneId]; + ai_assert(bone); + + // duplicate meshes exist with the same bones sometimes :) + // so this must be detected + if (std::find(bones.begin(), bones.end(), bone) == bones.end()) { + // add the element once + bones.push_back(bone); + } + } + + // find mesh and get bones + // then do recursive lookup for bones in root node hierarchy + } + + BuildBoneList(child, root_node, scene, bones); + } +} + +/* Prepare flat node list which can be used for non recursive lookups later */ +void ArmaturePopulate::BuildNodeList(const aiNode *current_node, + std::vector<aiNode *> &nodes) { + ai_assert(current_node); + + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); + + nodes.push_back(child); + + BuildNodeList(child, nodes); + } +} + +/* A bone stack allows us to have multiple armatures, with the same bone names + * A bone stack allows us also to retrieve bones true transform even with + * duplicate names :) + */ +void ArmaturePopulate::BuildBoneStack(aiNode *current_node, + const aiNode *root_node, + const aiScene *scene, + const std::vector<aiBone *> &bones, + std::map<aiBone *, aiNode *> &bone_stack, + std::vector<aiNode *> &node_stack) { + ai_assert(scene); + ai_assert(root_node); + ai_assert(!node_stack.empty()); + + for (aiBone *bone : bones) { + ai_assert(bone); + aiNode *node = GetNodeFromStack(bone->mName, node_stack); + if (node == nullptr) { + node_stack.clear(); + BuildNodeList(root_node, node_stack); + ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); + + node = GetNodeFromStack(bone->mName, node_stack); + + if (!node) { + ASSIMP_LOG_ERROR("serious import issue node for bone was not detected"); + continue; + } + } + + ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); + + bone_stack.insert(std::pair<aiBone *, aiNode *>(bone, node)); + } +} + + +/* Returns the armature root node */ +/* This is required to be detected for a bone initially, it will recurse up + * until it cannot find another bone and return the node No known failure + * points. (yet) + */ +aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, + std::vector<aiBone *> &bone_list) { + while (bone_node) { + if (!IsBoneNode(bone_node->mName, bone_list)) { + ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); + return bone_node; + } + + bone_node = bone_node->mParent; + } + + ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!"); + + return nullptr; +} + + + +/* Simple IsBoneNode check if this could be a bone */ +bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, + std::vector<aiBone *> &bones) { + for (aiBone *bone : bones) { + if (bone->mName == bone_name) { + return true; + } + } + + return false; +} + +/* Pop this node by name from the stack if found */ +/* Used in multiple armature situations with duplicate node / bone names */ +/* Known flaw: cannot have nodes with bone names, will be fixed in later release + */ +/* (serious to be fixed) Known flaw: nodes which have more than one bone could + * be prematurely dropped from stack */ +aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, + std::vector<aiNode *> &nodes) { + std::vector<aiNode *>::iterator iter; + aiNode *found = nullptr; + for (iter = nodes.begin(); iter < nodes.end(); ++iter) { + aiNode *element = *iter; + ai_assert(element); + // node valid and node name matches + if (element->mName == node_name) { + found = element; + break; + } + } + + if (found != nullptr) { + ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str()); + // now pop the element from the node list + nodes.erase(iter); + + return found; + } + + // unique names can cause this problem + ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!"); + + return nullptr; +} + + + + +} // Namespace Assimp diff --git a/thirdparty/assimp/code/PostProcessing/ArmaturePopulate.h b/thirdparty/assimp/code/PostProcessing/ArmaturePopulate.h new file mode 100644 index 0000000000..aa1ad7c80c --- /dev/null +++ b/thirdparty/assimp/code/PostProcessing/ArmaturePopulate.h @@ -0,0 +1,112 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ARMATURE_POPULATE_H_ +#define ARMATURE_POPULATE_H_ + +#include "Common/BaseProcess.h" +#include <assimp/BaseImporter.h> +#include <vector> +#include <map> + + +struct aiNode; +struct aiBone; + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** Armature Populate: This is a post process designed + * To save you time when importing models into your game engines + * This was originally designed only for fbx but will work with other formats + * it is intended to auto populate aiBone data with armature and the aiNode + * This is very useful when dealing with skinned meshes + * or when dealing with many different skeletons + * It's off by default but recommend that you try it and use it + * It should reduce down any glue code you have in your + * importers + * You can contact RevoluPowered <gordon@gordonite.tech> + * For more info about this +*/ +class ASSIMP_API ArmaturePopulate : public BaseProcess { +public: + /// The default class constructor. + ArmaturePopulate(); + + /// The class destructor. + virtual ~ArmaturePopulate(); + + /// Overwritten, @see BaseProcess + virtual bool IsActive( unsigned int pFlags ) const; + + /// Overwritten, @see BaseProcess + virtual void SetupProperties( const Importer* pImp ); + + /// Overwritten, @see BaseProcess + virtual void Execute( aiScene* pScene ); + + static aiNode *GetArmatureRoot(aiNode *bone_node, + std::vector<aiBone *> &bone_list); + + static bool IsBoneNode(const aiString &bone_name, + std::vector<aiBone *> &bones); + + static aiNode *GetNodeFromStack(const aiString &node_name, + std::vector<aiNode *> &nodes); + + static void BuildNodeList(const aiNode *current_node, + std::vector<aiNode *> &nodes); + + static void BuildBoneList(aiNode *current_node, const aiNode *root_node, + const aiScene *scene, + std::vector<aiBone *> &bones); + + static void BuildBoneStack(aiNode *current_node, const aiNode *root_node, + const aiScene *scene, + const std::vector<aiBone *> &bones, + std::map<aiBone *, aiNode *> &bone_stack, + std::vector<aiNode *> &node_stack); +}; + +} // Namespace Assimp + + +#endif // SCALE_PROCESS_H_
\ No newline at end of file diff --git a/thirdparty/assimp/code/CalcTangentsProcess.cpp b/thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.cpp index b30f39c274..a3f7dd2557 100644 --- a/thirdparty/assimp/code/CalcTangentsProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.cpp @@ -212,7 +212,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // project tangent and bitangent into the plane formed by the vertex' normal aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]); aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]); - localTangent.Normalize(); localBitangent.Normalize(); + localTangent.NormalizeSafe(); localBitangent.NormalizeSafe(); // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z); @@ -220,10 +220,10 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) if (invalid_tangent != invalid_bitangent) { if (invalid_tangent) { localTangent = meshNorm[p] ^ localBitangent; - localTangent.Normalize(); + localTangent.NormalizeSafe(); } else { localBitangent = localTangent ^ meshNorm[p]; - localBitangent.Normalize(); + localBitangent.NormalizeSafe(); } } diff --git a/thirdparty/assimp/code/CalcTangentsProcess.h b/thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.h index 18775abcc7..3568a624f8 100644 --- a/thirdparty/assimp/code/CalcTangentsProcess.h +++ b/thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.h @@ -42,11 +42,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Defines a post processing step to calculate tangents and - bitangents on all imported meshes.*/ + bi-tangents on all imported meshes.*/ #ifndef AI_CALCTANGENTSPROCESS_H_INC #define AI_CALCTANGENTSPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" struct aiMesh; diff --git a/thirdparty/assimp/code/ComputeUVMappingProcess.cpp b/thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.cpp index bb571a551b..df4d44337d 100644 --- a/thirdparty/assimp/code/ComputeUVMappingProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.cpp @@ -354,12 +354,12 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& } else if (axis * base_axis_z >= angle_epsilon) { FindMeshCenter(mesh, center, min, max); - diffu = max.y - min.y; - diffv = max.z - min.z; + diffu = max.x - min.x; + diffv = max.y - min.y; for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.0); + out[pnt].Set((pos.x - min.x) / diffu,(pos.y - min.y) / diffv,0.0); } } // slower code path in case the mapping axis is not one of the coordinate system axes diff --git a/thirdparty/assimp/code/ComputeUVMappingProcess.h b/thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.h index 24f6bb7218..a6d36e06ea 100644 --- a/thirdparty/assimp/code/ComputeUVMappingProcess.h +++ b/thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.h @@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COMPUTEUVMAPPING_H_INC #define AI_COMPUTEUVMAPPING_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/mesh.h> #include <assimp/material.h> #include <assimp/types.h> diff --git a/thirdparty/assimp/code/ConvertToLHProcess.cpp b/thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.cpp index b7cd4f0bc6..b7cd4f0bc6 100644 --- a/thirdparty/assimp/code/ConvertToLHProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.cpp diff --git a/thirdparty/assimp/code/ConvertToLHProcess.h b/thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.h index 63351568d0..f32b91fc39 100644 --- a/thirdparty/assimp/code/ConvertToLHProcess.h +++ b/thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.h @@ -52,7 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_CONVERTTOLHPROCESS_H_INC #include <assimp/types.h> -#include "BaseProcess.h" + +#include "Common/BaseProcess.h" struct aiMesh; struct aiNodeAnim; diff --git a/thirdparty/assimp/code/DeboneProcess.cpp b/thirdparty/assimp/code/PostProcessing/DeboneProcess.cpp index 83b8336bc9..83b8336bc9 100644 --- a/thirdparty/assimp/code/DeboneProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/DeboneProcess.cpp diff --git a/thirdparty/assimp/code/DeboneProcess.h b/thirdparty/assimp/code/PostProcessing/DeboneProcess.h index ba77aba70e..8b64c2acc6 100644 --- a/thirdparty/assimp/code/DeboneProcess.h +++ b/thirdparty/assimp/code/PostProcessing/DeboneProcess.h @@ -44,17 +44,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_DEBONEPROCESS_H_INC #define AI_DEBONEPROCESS_H_INC -#include <vector> -#include <utility> -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/mesh.h> #include <assimp/scene.h> +#include <vector> +#include <utility> + +#// Forward declarations class DeboneTest; -namespace Assimp -{ +namespace Assimp { #if (!defined AI_DEBONE_THRESHOLD) # define AI_DEBONE_THRESHOLD 1.0f @@ -66,14 +67,11 @@ namespace Assimp * the bone are split from the mesh. The split off (new) mesh is boneless. At any * point in time, bones without affect upon a given mesh are to be removed. */ -class DeboneProcess : public BaseProcess -{ +class DeboneProcess : public BaseProcess { public: - DeboneProcess(); ~DeboneProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag. * @param pFlags The processing flags the importer was called with. @@ -91,7 +89,6 @@ public: void SetupProperties(const Importer* pImp); protected: - // ------------------------------------------------------------------- /** Executes the post processing step on the given imported data. * At the moment a process is not supposed to fail. diff --git a/thirdparty/assimp/code/DropFaceNormalsProcess.cpp b/thirdparty/assimp/code/PostProcessing/DropFaceNormalsProcess.cpp index b11615bb82..b11615bb82 100644 --- a/thirdparty/assimp/code/DropFaceNormalsProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/DropFaceNormalsProcess.cpp diff --git a/thirdparty/assimp/code/DropFaceNormalsProcess.h b/thirdparty/assimp/code/PostProcessing/DropFaceNormalsProcess.h index 0d116663b7..c710c5a5ee 100644 --- a/thirdparty/assimp/code/DropFaceNormalsProcess.h +++ b/thirdparty/assimp/code/PostProcessing/DropFaceNormalsProcess.h @@ -44,23 +44,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_DROPFACENORMALPROCESS_H_INC #define AI_DROPFACENORMALPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/mesh.h> -namespace Assimp -{ +namespace Assimp { // --------------------------------------------------------------------------- /** The DropFaceNormalsProcess computes face normals for all faces of all meshes */ -class ASSIMP_API_WINONLY DropFaceNormalsProcess : public BaseProcess -{ +class ASSIMP_API_WINONLY DropFaceNormalsProcess : public BaseProcess { public: - DropFaceNormalsProcess(); ~DropFaceNormalsProcess(); -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/thirdparty/assimp/code/EmbedTexturesProcess.cpp b/thirdparty/assimp/code/PostProcessing/EmbedTexturesProcess.cpp index 739382a057..739382a057 100644 --- a/thirdparty/assimp/code/EmbedTexturesProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/EmbedTexturesProcess.cpp diff --git a/thirdparty/assimp/code/EmbedTexturesProcess.h b/thirdparty/assimp/code/PostProcessing/EmbedTexturesProcess.h index cdf40bef74..3c4b2eab4e 100644 --- a/thirdparty/assimp/code/EmbedTexturesProcess.h +++ b/thirdparty/assimp/code/PostProcessing/EmbedTexturesProcess.h @@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <string> diff --git a/thirdparty/assimp/code/FindDegenerates.cpp b/thirdparty/assimp/code/PostProcessing/FindDegenerates.cpp index 365f5d7447..50fac46dba 100644 --- a/thirdparty/assimp/code/FindDegenerates.cpp +++ b/thirdparty/assimp/code/PostProcessing/FindDegenerates.cpp @@ -228,6 +228,7 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { if ( area < 1e-6 ) { if ( mConfigRemoveDegenerates ) { remove_me[ a ] = true; + ++deg; goto evil_jump_outside; } diff --git a/thirdparty/assimp/code/FindDegenerates.h b/thirdparty/assimp/code/PostProcessing/FindDegenerates.h index 880f5f16a2..7a15e77cf1 100644 --- a/thirdparty/assimp/code/FindDegenerates.h +++ b/thirdparty/assimp/code/PostProcessing/FindDegenerates.h @@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_FINDDEGENERATESPROCESS_H_INC #define AI_FINDDEGENERATESPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/mesh.h> class FindDegeneratesProcessTest; diff --git a/thirdparty/assimp/code/FindInstancesProcess.cpp b/thirdparty/assimp/code/PostProcessing/FindInstancesProcess.cpp index be1138116e..64907458a1 100644 --- a/thirdparty/assimp/code/FindInstancesProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/FindInstancesProcess.cpp @@ -137,6 +137,11 @@ void FindInstancesProcess::Execute( aiScene* pScene) aiMesh* inst = pScene->mMeshes[i]; hashes[i] = GetMeshHash(inst); + // Find an appropriate epsilon + // to compare position differences against + float epsilon = ComputePositionEpsilon(inst); + epsilon *= epsilon; + for (int a = i-1; a >= 0; --a) { if (hashes[i] == hashes[a]) { @@ -154,12 +159,7 @@ void FindInstancesProcess::Execute( aiScene* pScene) orig->mPrimitiveTypes != inst->mPrimitiveTypes) continue; - // up to now the meshes are equal. find an appropriate - // epsilon to compare position differences against - float epsilon = ComputePositionEpsilon(inst); - epsilon *= epsilon; - - // now compare vertex positions, normals, + // up to now the meshes are equal. Now compare vertex positions, normals, // tangents and bitangents using this epsilon. if (orig->HasPositions()) { if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon)) diff --git a/thirdparty/assimp/code/FindInstancesProcess.h b/thirdparty/assimp/code/PostProcessing/FindInstancesProcess.h index ab4a371c71..64b838d7cc 100644 --- a/thirdparty/assimp/code/FindInstancesProcess.h +++ b/thirdparty/assimp/code/PostProcessing/FindInstancesProcess.h @@ -46,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_FINDINSTANCES_H_INC #define AI_FINDINSTANCES_H_INC -#include "BaseProcess.h" -#include "ProcessHelper.h" +#include "Common/BaseProcess.h" +#include "PostProcessing/ProcessHelper.h" class FindInstancesProcessTest; namespace Assimp { diff --git a/thirdparty/assimp/code/FindInvalidDataProcess.cpp b/thirdparty/assimp/code/PostProcessing/FindInvalidDataProcess.cpp index 433f042448..016884c6e7 100644 --- a/thirdparty/assimp/code/FindInvalidDataProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/FindInvalidDataProcess.cpp @@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FindInvalidDataProcess.h" #include "ProcessHelper.h" -#include <assimp/Macros.h> #include <assimp/Exceptional.h> #include <assimp/qnan.h> diff --git a/thirdparty/assimp/code/FindInvalidDataProcess.h b/thirdparty/assimp/code/PostProcessing/FindInvalidDataProcess.h index 8504fb7b1f..ce7375f34f 100644 --- a/thirdparty/assimp/code/FindInvalidDataProcess.h +++ b/thirdparty/assimp/code/PostProcessing/FindInvalidDataProcess.h @@ -46,7 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_FINDINVALIDDATA_H_INC #define AI_FINDINVALIDDATA_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/types.h> #include <assimp/anim.h> diff --git a/thirdparty/assimp/code/FixNormalsStep.cpp b/thirdparty/assimp/code/PostProcessing/FixNormalsStep.cpp index bbbe6899b4..bbbe6899b4 100644 --- a/thirdparty/assimp/code/FixNormalsStep.cpp +++ b/thirdparty/assimp/code/PostProcessing/FixNormalsStep.cpp diff --git a/thirdparty/assimp/code/FixNormalsStep.h b/thirdparty/assimp/code/PostProcessing/FixNormalsStep.h index 6be27faef6..f60ce596a4 100644 --- a/thirdparty/assimp/code/FixNormalsStep.h +++ b/thirdparty/assimp/code/PostProcessing/FixNormalsStep.h @@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_FIXNORMALSPROCESS_H_INC #define AI_FIXNORMALSPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" struct aiMesh; diff --git a/thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.cpp b/thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.cpp new file mode 100644 index 0000000000..c013454fc3 --- /dev/null +++ b/thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.cpp @@ -0,0 +1,115 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS + +#include "PostProcessing/GenBoundingBoxesProcess.h" + +#include <assimp/postprocess.h> +#include <assimp/scene.h> + +namespace Assimp { + +GenBoundingBoxesProcess::GenBoundingBoxesProcess() +: BaseProcess() { + +} + +GenBoundingBoxesProcess::~GenBoundingBoxesProcess() { + // empty +} + +bool GenBoundingBoxesProcess::IsActive(unsigned int pFlags) const { + return 0 != ( pFlags & aiProcess_GenBoundingBoxes ); +} + +void checkMesh(aiMesh* mesh, aiVector3D& min, aiVector3D& max) { + ai_assert(nullptr != mesh); + + if (0 == mesh->mNumVertices) { + return; + } + + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + const aiVector3D &pos = mesh->mVertices[i]; + if (pos.x < min.x) { + min.x = pos.x; + } + if (pos.y < min.y) { + min.y = pos.y; + } + if (pos.z < min.z) { + min.z = pos.z; + } + + if (pos.x > max.x) { + max.x = pos.x; + } + if (pos.y > max.y) { + max.y = pos.y; + } + if (pos.z > max.z) { + max.z = pos.z; + } + } +} + +void GenBoundingBoxesProcess::Execute(aiScene* pScene) { + if (nullptr == pScene) { + return; + } + + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + aiMesh* mesh = pScene->mMeshes[i]; + if (nullptr == mesh) { + continue; + } + + aiVector3D min(999999, 999999, 999999), max(-999999, -999999, -999999); + checkMesh(mesh, min, max); + mesh->mAABB.mMin = min; + mesh->mAABB.mMax = max; + } +} + +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS diff --git a/thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.h b/thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.h new file mode 100644 index 0000000000..4b43c82a42 --- /dev/null +++ b/thirdparty/assimp/code/PostProcessing/GenBoundingBoxesProcess.h @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Defines a post-processing step to generate Axis-aligned bounding + * volumes for all meshes. + */ + +#pragma once + +#ifndef AI_GENBOUNDINGBOXESPROCESS_H_INC +#define AI_GENBOUNDINGBOXESPROCESS_H_INC + +#ifndef ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS + +#include "Common/BaseProcess.h" + +namespace Assimp { + +/** Post-processing process to find axis-aligned bounding volumes for amm meshes + * used in a scene + */ +class ASSIMP_API GenBoundingBoxesProcess : public BaseProcess { +public: + /// The class constructor. + GenBoundingBoxesProcess(); + /// The class destructor. + ~GenBoundingBoxesProcess(); + /// Will return true, if aiProcess_GenBoundingBoxes is defined. + bool IsActive(unsigned int pFlags) const override; + /// The execution callback. + void Execute(aiScene* pScene) override; +}; + +} // Namespace Assimp + +#endif // #ifndef ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS + +#endif // AI_GENBOUNDINGBOXESPROCESS_H_INC diff --git a/thirdparty/assimp/code/GenFaceNormalsProcess.cpp b/thirdparty/assimp/code/PostProcessing/GenFaceNormalsProcess.cpp index 028334dec7..028334dec7 100644 --- a/thirdparty/assimp/code/GenFaceNormalsProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/GenFaceNormalsProcess.cpp diff --git a/thirdparty/assimp/code/GenFaceNormalsProcess.h b/thirdparty/assimp/code/PostProcessing/GenFaceNormalsProcess.h index c80ec9fddc..c641fd6353 100644 --- a/thirdparty/assimp/code/GenFaceNormalsProcess.h +++ b/thirdparty/assimp/code/PostProcessing/GenFaceNormalsProcess.h @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_GENFACENORMALPROCESS_H_INC #define AI_GENFACENORMALPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/mesh.h> namespace Assimp diff --git a/thirdparty/assimp/code/GenVertexNormalsProcess.cpp b/thirdparty/assimp/code/PostProcessing/GenVertexNormalsProcess.cpp index 3f6c2f86bd..3f6c2f86bd 100644 --- a/thirdparty/assimp/code/GenVertexNormalsProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/GenVertexNormalsProcess.cpp diff --git a/thirdparty/assimp/code/GenVertexNormalsProcess.h b/thirdparty/assimp/code/PostProcessing/GenVertexNormalsProcess.h index 9142ad26f5..2ceee17e85 100644 --- a/thirdparty/assimp/code/GenVertexNormalsProcess.h +++ b/thirdparty/assimp/code/PostProcessing/GenVertexNormalsProcess.h @@ -45,24 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_GENVERTEXNORMALPROCESS_H_INC #define AI_GENVERTEXNORMALPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/assbin_chunks.h" +#include "Common/BaseProcess.h" + #include <assimp/mesh.h> +// Forward declarations class GenNormalsTest; namespace Assimp { // --------------------------------------------------------------------------- -/** The GenFaceNormalsProcess computes vertex normals for all vertizes +/** The GenFaceNormalsProcess computes vertex normals for all vertices */ -class ASSIMP_API GenVertexNormalsProcess : public BaseProcess -{ +class ASSIMP_API GenVertexNormalsProcess : public BaseProcess { public: - GenVertexNormalsProcess(); ~GenVertexNormalsProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag. * @param pFlags The processing flags the importer was called with. @@ -88,13 +88,10 @@ public: // setter for configMaxAngle - inline void SetMaxSmoothAngle(ai_real f) - { + inline void SetMaxSmoothAngle(ai_real f) { configMaxAngle =f; } -public: - // ------------------------------------------------------------------- /** Computes normals for a specific mesh * @param pcMesh Mesh @@ -104,7 +101,6 @@ public: bool GenMeshVertexNormals (aiMesh* pcMesh, unsigned int meshIndex); private: - /** Configuration option: maximum smoothing angle, in radians*/ ai_real configMaxAngle; mutable bool force_ = false; diff --git a/thirdparty/assimp/code/ImproveCacheLocality.cpp b/thirdparty/assimp/code/PostProcessing/ImproveCacheLocality.cpp index ace9d95ff8..d0a016fa42 100644 --- a/thirdparty/assimp/code/ImproveCacheLocality.cpp +++ b/thirdparty/assimp/code/PostProcessing/ImproveCacheLocality.cpp @@ -45,14 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * <br> * The algorithm is roughly basing on this paper: * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf - * .. although overdraw rduction isn't implemented yet ... + * .. although overdraw reduction isn't implemented yet ... */ - - // internal headers -#include "ImproveCacheLocality.h" -#include "VertexTriangleAdjacency.h" +#include "PostProcessing/ImproveCacheLocality.h" +#include "Common/VertexTriangleAdjacency.h" + #include <assimp/StringUtils.h> #include <assimp/postprocess.h> #include <assimp/scene.h> @@ -64,36 +63,33 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() { - configCacheDepth = PP_ICL_PTCACHE_SIZE; +ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() +: mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) { + // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess() -{ +ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const -{ +bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_ImproveCacheLocality) != 0; } // ------------------------------------------------------------------------------------------------ // Setup configuration -void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) -{ +void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) { // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer - configCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE); + mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void ImproveCacheLocalityProcess::Execute( aiScene* pScene) -{ +void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { if (!pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes"); return; @@ -103,7 +99,7 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) float out = 0.f; unsigned int numf = 0, numm = 0; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++){ + for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ){ const float res = ProcessMesh( pScene->mMeshes[a],a); if (res) { numf += pScene->mMeshes[a]->mNumFaces; @@ -121,44 +117,41 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ // Improves the cache coherency of a specific mesh -float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum) -{ +ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum) { // TODO: rewrite this to use std::vector or boost::shared_array - ai_assert(NULL != pMesh); + ai_assert(nullptr != pMesh); // Check whether the input data is valid // - there must be vertices and faces // - all faces must be triangulated or we can't operate on them if (!pMesh->HasFaces() || !pMesh->HasPositions()) - return 0.f; + return static_cast<ai_real>(0.f); if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) { ASSIMP_LOG_ERROR("This algorithm works on triangle meshes only"); - return 0.f; + return static_cast<ai_real>(0.f); } - if(pMesh->mNumVertices <= configCacheDepth) { - return 0.f; + if(pMesh->mNumVertices <= mConfigCacheDepth) { + return static_cast<ai_real>(0.f); } - float fACMR = 3.f; + ai_real fACMR = 3.f; const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces; // Input ACMR is for logging purposes only if (!DefaultLogger::isNullLogger()) { - unsigned int* piFIFOStack = new unsigned int[configCacheDepth]; - memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int)); + unsigned int* piFIFOStack = new unsigned int[mConfigCacheDepth]; + memset(piFIFOStack,0xff,mConfigCacheDepth*sizeof(unsigned int)); unsigned int* piCur = piFIFOStack; - const unsigned int* const piCurEnd = piFIFOStack + configCacheDepth; + const unsigned int* const piCurEnd = piFIFOStack + mConfigCacheDepth; // count the number of cache misses unsigned int iCacheMisses = 0; for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) { - for (unsigned int qq = 0; qq < 3;++qq) { bool bInCache = false; - for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) { if (*pp == pcFace->mIndices[qq]) { // the vertex is in cache @@ -176,7 +169,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh } } delete[] piFIFOStack; - fACMR = (float)iCacheMisses / pMesh->mNumFaces; + fACMR = (ai_real) iCacheMisses / pMesh->mNumFaces; if (3.0 == fACMR) { char szBuff[128]; // should be sufficiently large in every case @@ -185,7 +178,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh // smaller than 3.0 ... ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum); ASSIMP_LOG_WARN(szBuff); - return 0.f; + return static_cast<ai_real>(0.f); } } @@ -258,7 +251,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh int ivdx = 0; int ics = 1; - int iStampCnt = configCacheDepth+1; + int iStampCnt = mConfigCacheDepth+1; while (ivdx >= 0) { unsigned int icnt = piNumTriPtrNoModify[ivdx]; @@ -294,7 +287,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh *piCSIter++ = dp; // if the vertex is not yet in cache, set its cache count - if (iStampCnt-piCachingStamps[dp] > configCacheDepth) { + if (iStampCnt-piCachingStamps[dp] > mConfigCacheDepth) { piCachingStamps[dp] = iStampCnt++; ++iCacheMisses; } @@ -319,7 +312,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh // will the vertex be in cache, even after fanning occurs? unsigned int tmp; - if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= configCacheDepth) { + if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= mConfigCacheDepth) { priority = tmp; } @@ -356,7 +349,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh } } } - float fACMR2 = 0.0f; + ai_real fACMR2 = 0.0f; if (!DefaultLogger::isNullLogger()) { fACMR2 = (float)iCacheMisses / pMesh->mNumFaces; diff --git a/thirdparty/assimp/code/ImproveCacheLocality.h b/thirdparty/assimp/code/PostProcessing/ImproveCacheLocality.h index 1b29ee0d6e..de25ecd9fb 100644 --- a/thirdparty/assimp/code/ImproveCacheLocality.h +++ b/thirdparty/assimp/code/PostProcessing/ImproveCacheLocality.h @@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_IMPROVECACHELOCALITY_H_INC #define AI_IMPROVECACHELOCALITY_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/types.h> struct aiMesh; @@ -87,12 +88,12 @@ protected: * @param pMesh The mesh to process. * @param meshNum Index of the mesh to process */ - float ProcessMesh( aiMesh* pMesh, unsigned int meshNum); + ai_real ProcessMesh( aiMesh* pMesh, unsigned int meshNum); private: //! Configuration parameter: specifies the size of the cache to //! optimize the vertex data for. - unsigned int configCacheDepth; + unsigned int mConfigCacheDepth; }; } // end of namespace Assimp diff --git a/thirdparty/assimp/code/JoinVerticesProcess.cpp b/thirdparty/assimp/code/PostProcessing/JoinVerticesProcess.cpp index 914ec05b46..f121fc60d3 100644 --- a/thirdparty/assimp/code/JoinVerticesProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/JoinVerticesProcess.cpp @@ -431,31 +431,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) bone->mWeights = new aiVertexWeight[bone->mNumWeights]; memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight)); } - else { - - /* NOTE: - * - * In the algorithm above we're assuming that there are no vertices - * with a different bone weight setup at the same position. That wouldn't - * make sense, but it is not absolutely impossible. SkeletonMeshBuilder - * for example generates such input data if two skeleton points - * share the same position. Again this doesn't make sense but is - * reality for some model formats (MD5 for example uses these special - * nodes as attachment tags for its weapons). - * - * Then it is possible that a bone has no weights anymore .... as a quick - * workaround, we're just removing these bones. If they're animated, - * model geometry might be modified but at least there's no risk of a crash. - */ - delete bone; - --pMesh->mNumBones; - for (unsigned int n = a; n < pMesh->mNumBones; ++n) { - pMesh->mBones[n] = pMesh->mBones[n+1]; - } - - --a; - ASSIMP_LOG_WARN("Removing bone -> no weights remaining"); - } } return pMesh->mNumVertices; } diff --git a/thirdparty/assimp/code/JoinVerticesProcess.h b/thirdparty/assimp/code/PostProcessing/JoinVerticesProcess.h index 66fa362de2..e017ae62db 100644 --- a/thirdparty/assimp/code/JoinVerticesProcess.h +++ b/thirdparty/assimp/code/PostProcessing/JoinVerticesProcess.h @@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_JOINVERTICESPROCESS_H_INC #define AI_JOINVERTICESPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/types.h> struct aiMesh; @@ -61,13 +62,11 @@ namespace Assimp * erases all but one of the copies. This usually reduces the number of vertices * in a mesh by a serious amount and is the standard form to render a mesh. */ -class ASSIMP_API JoinVerticesProcess : public BaseProcess -{ +class ASSIMP_API JoinVerticesProcess : public BaseProcess { public: JoinVerticesProcess(); ~JoinVerticesProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag field. * @param pFlags The processing flags the importer was called with. A bitwise @@ -83,15 +82,12 @@ public: */ void Execute( aiScene* pScene); -public: // ------------------------------------------------------------------- /** Unites identical vertices in the given mesh. * @param pMesh The mesh to process. * @param meshIndex Index of the mesh to process */ int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex); - -private: }; } // end of namespace Assimp diff --git a/thirdparty/assimp/code/LimitBoneWeightsProcess.cpp b/thirdparty/assimp/code/PostProcessing/LimitBoneWeightsProcess.cpp index d560f19287..d560f19287 100644 --- a/thirdparty/assimp/code/LimitBoneWeightsProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/LimitBoneWeightsProcess.cpp diff --git a/thirdparty/assimp/code/LimitBoneWeightsProcess.h b/thirdparty/assimp/code/PostProcessing/LimitBoneWeightsProcess.h index 3602fd8edf..73c2a68d53 100644 --- a/thirdparty/assimp/code/LimitBoneWeightsProcess.h +++ b/thirdparty/assimp/code/PostProcessing/LimitBoneWeightsProcess.h @@ -44,14 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_LIMITBONEWEIGHTSPROCESS_H_INC #define AI_LIMITBONEWEIGHTSPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" +// Forward declarations struct aiMesh; class LimitBoneWeightsTest; -namespace Assimp -{ +namespace Assimp { // NOTE: If you change these limits, don't forget to change the // corresponding values in all Assimp ports @@ -72,14 +72,11 @@ namespace Assimp * The other weights on this bone are then renormalized to assure the sum weight * to be 1. */ -class ASSIMP_API LimitBoneWeightsProcess : public BaseProcess -{ +class ASSIMP_API LimitBoneWeightsProcess : public BaseProcess { public: - LimitBoneWeightsProcess(); ~LimitBoneWeightsProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag. * @param pFlags The processing flags the importer was called with. @@ -96,8 +93,6 @@ public: */ void SetupProperties(const Importer* pImp); -public: - // ------------------------------------------------------------------- /** Limits the bone weight count for all vertices in the given mesh. * @param pMesh The mesh to process. @@ -111,34 +106,29 @@ public: */ void Execute( aiScene* pScene); - -public: - // ------------------------------------------------------------------- /** Describes a bone weight on a vertex */ - struct Weight - { + struct Weight { unsigned int mBone; ///< Index of the bone float mWeight; ///< Weight of that bone on this vertex Weight() AI_NO_EXCEPT : mBone(0) - , mWeight(0.0f) - { } + , mWeight(0.0f) { + // empty + } Weight( unsigned int pBone, float pWeight) - { - mBone = pBone; - mWeight = pWeight; + : mBone(pBone) + , mWeight(pWeight) { + // empty } /** Comparison operator to sort bone weights by descending weight */ - bool operator < (const Weight& pWeight) const - { + bool operator < (const Weight& pWeight) const { return mWeight > pWeight.mWeight; } }; -public: /** Maximum number of bones influencing any single vertex. */ unsigned int mMaxWeights; }; diff --git a/thirdparty/assimp/code/MakeVerboseFormat.cpp b/thirdparty/assimp/code/PostProcessing/MakeVerboseFormat.cpp index 50ff5ed93d..41f50a5ba5 100644 --- a/thirdparty/assimp/code/MakeVerboseFormat.cpp +++ b/thirdparty/assimp/code/PostProcessing/MakeVerboseFormat.cpp @@ -224,3 +224,32 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) } return (pcMesh->mNumVertices != iOldNumVertices); } + + +// ------------------------------------------------------------------------------------------------ +bool IsMeshInVerboseFormat(const aiMesh* mesh) { + // avoid slow vector<bool> specialization + std::vector<unsigned int> seen(mesh->mNumVertices,0); + for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { + const aiFace& f = mesh->mFaces[i]; + for(unsigned int j = 0; j < f.mNumIndices; ++j) { + if(++seen[f.mIndices[j]] == 2) { + // found a duplicate index + return false; + } + } + } + + return true; +} + +// ------------------------------------------------------------------------------------------------ +bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene* pScene) { + for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + if(!IsMeshInVerboseFormat(pScene->mMeshes[i])) { + return false; + } + } + + return true; +} diff --git a/thirdparty/assimp/code/MakeVerboseFormat.h b/thirdparty/assimp/code/PostProcessing/MakeVerboseFormat.h index d12db63ae1..8565d5933a 100644 --- a/thirdparty/assimp/code/MakeVerboseFormat.h +++ b/thirdparty/assimp/code/PostProcessing/MakeVerboseFormat.h @@ -46,7 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MAKEVERBOSEFORMAT_H_INC #define AI_MAKEVERBOSEFORMAT_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + struct aiMesh; namespace Assimp { @@ -93,6 +94,13 @@ public: * @param pScene The imported data to work at. */ void Execute( aiScene* pScene); +public: + + // ------------------------------------------------------------------- + /** Checks whether the scene is already in verbose format. + * @param pScene The data to check. + * @return true if the scene is already in verbose format. */ + static bool IsVerboseFormat(const aiScene* pScene); private: diff --git a/thirdparty/assimp/code/OptimizeGraph.cpp b/thirdparty/assimp/code/PostProcessing/OptimizeGraph.cpp index add9ab79e1..5db51f58b6 100644 --- a/thirdparty/assimp/code/OptimizeGraph.cpp +++ b/thirdparty/assimp/code/PostProcessing/OptimizeGraph.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/thirdparty/assimp/code/OptimizeGraph.h b/thirdparty/assimp/code/PostProcessing/OptimizeGraph.h index e5bbed7679..82cc5db3fe 100644 --- a/thirdparty/assimp/code/OptimizeGraph.h +++ b/thirdparty/assimp/code/PostProcessing/OptimizeGraph.h @@ -46,13 +46,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_OPTIMIZEGRAPHPROCESS_H_INC #define AI_OPTIMIZEGRAPHPROCESS_H_INC -#include "BaseProcess.h" -#include "ProcessHelper.h" +#include "Common/BaseProcess.h" +#include "PostProcessing/ProcessHelper.h" + #include <assimp/types.h> + #include <set> +// Forward declarations struct aiMesh; + class OptimizeGraphProcessTest; + namespace Assimp { // ----------------------------------------------------------------------------- @@ -64,14 +69,11 @@ namespace Assimp { * @see aiProcess_OptimizeGraph for a detailed description of the * algorithm being applied. */ -class OptimizeGraphProcess : public BaseProcess -{ +class OptimizeGraphProcess : public BaseProcess { public: - OptimizeGraphProcess(); ~OptimizeGraphProcess(); -public: // ------------------------------------------------------------------- bool IsActive( unsigned int pFlags) const; @@ -81,14 +83,12 @@ public: // ------------------------------------------------------------------- void SetupProperties(const Importer* pImp); - // ------------------------------------------------------------------- /** @brief Add a list of node names to be locked and not modified. * @param in List of nodes. See #AI_CONFIG_PP_OG_EXCLUDE_LIST for * format explanations. */ - inline void AddLockedNodeList(std::string& in) - { + inline void AddLockedNodeList(std::string& in) { ConvertListToStrings (in,locked_nodes); } @@ -96,8 +96,7 @@ public: /** @brief Add another node to be locked and not modified. * @param name Name to be locked */ - inline void AddLockedNode(std::string& name) - { + inline void AddLockedNode(std::string& name) { locked_nodes.push_back(name); } @@ -105,25 +104,21 @@ public: /** @brief Remove a node from the list of locked nodes. * @param name Name to be unlocked */ - inline void RemoveLockedNode(std::string& name) - { + inline void RemoveLockedNode(std::string& name) { locked_nodes.remove(name); } protected: - void CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes); void FindInstancedMeshes (aiNode* pNode); private: - #ifdef AI_OG_USE_HASHING typedef std::set<unsigned int> LockedSetType; #else typedef std::set<std::string> LockedSetType; #endif - //! Scene we're working with aiScene* mScene; diff --git a/thirdparty/assimp/code/OptimizeMeshes.cpp b/thirdparty/assimp/code/PostProcessing/OptimizeMeshes.cpp index 3f6765f6ca..3f6765f6ca 100644 --- a/thirdparty/assimp/code/OptimizeMeshes.cpp +++ b/thirdparty/assimp/code/PostProcessing/OptimizeMeshes.cpp diff --git a/thirdparty/assimp/code/OptimizeMeshes.h b/thirdparty/assimp/code/PostProcessing/OptimizeMeshes.h index 9f46f349b4..dec4ab52de 100644 --- a/thirdparty/assimp/code/OptimizeMeshes.h +++ b/thirdparty/assimp/code/PostProcessing/OptimizeMeshes.h @@ -46,8 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_OPTIMIZEMESHESPROCESS_H_INC #define AI_OPTIMIZEMESHESPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/types.h> + #include <vector> struct aiMesh; @@ -64,16 +66,14 @@ namespace Assimp { * * @note Instanced meshes are currently not processed. */ -class OptimizeMeshesProcess : public BaseProcess -{ +class OptimizeMeshesProcess : public BaseProcess { public: /// @brief The class constructor. OptimizeMeshesProcess(); - /// @brief The class destcructor, + /// @brief The class destructor. ~OptimizeMeshesProcess(); - /** @brief Internal utility to store additional mesh info */ struct MeshInfo { diff --git a/thirdparty/assimp/code/PretransformVertices.cpp b/thirdparty/assimp/code/PostProcessing/PretransformVertices.cpp index 52001a0578..52001a0578 100644 --- a/thirdparty/assimp/code/PretransformVertices.cpp +++ b/thirdparty/assimp/code/PostProcessing/PretransformVertices.cpp diff --git a/thirdparty/assimp/code/PretransformVertices.h b/thirdparty/assimp/code/PostProcessing/PretransformVertices.h index b7329af130..b2982951e0 100644 --- a/thirdparty/assimp/code/PretransformVertices.h +++ b/thirdparty/assimp/code/PostProcessing/PretransformVertices.h @@ -47,13 +47,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_PRETRANSFORMVERTICES_H_INC #define AI_PRETRANSFORMVERTICES_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/mesh.h> + #include <list> #include <vector> +// Forward declarations struct aiNode; + class PretransformVerticesTest; + namespace Assimp { // --------------------------------------------------------------------------- @@ -80,10 +85,10 @@ public: // ------------------------------------------------------------------- /** @brief Toggle the 'keep hierarchy' option - * @param d hm ... difficult to guess what this means, hu!? + * @param keep true for keep configuration. */ - void KeepHierarchy(bool d) { - configKeepHierarchy = d; + void KeepHierarchy(bool keep) { + configKeepHierarchy = keep; } // ------------------------------------------------------------------- @@ -148,8 +153,6 @@ private: // Build reference counters for all meshes void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs); - - //! Configuration option: keep scene hierarchy as long as possible bool configKeepHierarchy; bool configNormalize; diff --git a/thirdparty/assimp/code/ProcessHelper.cpp b/thirdparty/assimp/code/PostProcessing/ProcessHelper.cpp index 59869fdff7..59869fdff7 100644 --- a/thirdparty/assimp/code/ProcessHelper.cpp +++ b/thirdparty/assimp/code/PostProcessing/ProcessHelper.cpp diff --git a/thirdparty/assimp/code/ProcessHelper.h b/thirdparty/assimp/code/PostProcessing/ProcessHelper.h index c59f3217bf..0afcc41420 100644 --- a/thirdparty/assimp/code/ProcessHelper.h +++ b/thirdparty/assimp/code/PostProcessing/ProcessHelper.h @@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/scene.h> #include <assimp/SpatialSort.h> -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/ParsingUtils.h> #include <list> diff --git a/thirdparty/assimp/code/RemoveRedundantMaterials.cpp b/thirdparty/assimp/code/PostProcessing/RemoveRedundantMaterials.cpp index 632bdca3fe..49ec8f5c47 100644 --- a/thirdparty/assimp/code/RemoveRedundantMaterials.cpp +++ b/thirdparty/assimp/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "RemoveRedundantMaterials.h" #include <assimp/ParsingUtils.h> #include "ProcessHelper.h" -#include "MaterialSystem.h" +#include "Material/MaterialSystem.h" #include <stdio.h> using namespace Assimp; @@ -57,7 +57,7 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() -: configFixedMaterials() { +: mConfigFixedMaterials() { // nothing to do here } @@ -80,7 +80,7 @@ bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) { // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST - configFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,""); + mConfigFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,""); } // ------------------------------------------------------------------------------------------------ @@ -100,10 +100,10 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // If a list of materials to be excluded was given, match the list with // our imported materials and 'salt' all positive matches to ensure that // we get unique hashes later. - if (configFixedMaterials.length()) { + if (mConfigFixedMaterials.length()) { std::list<std::string> strings; - ConvertListToStrings(configFixedMaterials,strings); + ConvertListToStrings(mConfigFixedMaterials,strings); for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { aiMaterial* mat = pScene->mMaterials[i]; diff --git a/thirdparty/assimp/code/RemoveRedundantMaterials.h b/thirdparty/assimp/code/PostProcessing/RemoveRedundantMaterials.h index dbd4d44cc0..1f32a0abfb 100644 --- a/thirdparty/assimp/code/RemoveRedundantMaterials.h +++ b/thirdparty/assimp/code/PostProcessing/RemoveRedundantMaterials.h @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_REMOVEREDUNDANTMATERIALS_H_INC #define AI_REMOVEREDUNDANTMATERIALS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/mesh.h> class RemoveRedundantMatsTest; @@ -57,8 +57,7 @@ namespace Assimp { /** RemoveRedundantMatsProcess: Post-processing step to remove redundant * materials from the imported scene. */ -class ASSIMP_API RemoveRedundantMatsProcess : public BaseProcess -{ +class ASSIMP_API RemoveRedundantMatsProcess : public BaseProcess { public: /// The default class constructor. RemoveRedundantMatsProcess(); @@ -66,7 +65,6 @@ public: /// The class destructor. ~RemoveRedundantMatsProcess(); -public: // ------------------------------------------------------------------- // Check whether step is active bool IsActive( unsigned int pFlags) const; @@ -79,27 +77,25 @@ public: // Setup import settings void SetupProperties(const Importer* pImp); - // ------------------------------------------------------------------- - /** @brief Set list of fixed (unmutable) materials + /** @brief Set list of fixed (inmutable) materials * @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST */ void SetFixedMaterialsString(const std::string& fixed = "") { - configFixedMaterials = fixed; + mConfigFixedMaterials = fixed; } // ------------------------------------------------------------------- - /** @brief Get list of fixed (unmutable) materials + /** @brief Get list of fixed (inmutable) materials * @return See #AI_CONFIG_PP_RRM_EXCLUDE_LIST */ const std::string& GetFixedMaterialsString() const { - return configFixedMaterials; + return mConfigFixedMaterials; } private: - //! Configuration option: list of all fixed materials - std::string configFixedMaterials; + std::string mConfigFixedMaterials; }; } // end of namespace Assimp diff --git a/thirdparty/assimp/code/RemoveVCProcess.cpp b/thirdparty/assimp/code/PostProcessing/RemoveVCProcess.cpp index 99fd47a3aa..99fd47a3aa 100644 --- a/thirdparty/assimp/code/RemoveVCProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/RemoveVCProcess.cpp diff --git a/thirdparty/assimp/code/RemoveVCProcess.h b/thirdparty/assimp/code/PostProcessing/RemoveVCProcess.h index 617d7b9b20..7bb21a8330 100644 --- a/thirdparty/assimp/code/RemoveVCProcess.h +++ b/thirdparty/assimp/code/PostProcessing/RemoveVCProcess.h @@ -44,7 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_REMOVEVCPROCESS_H_INCLUDED #define AI_REMOVEVCPROCESS_H_INCLUDED -#include "BaseProcess.h" +#include "Common/BaseProcess.h" + #include <assimp/mesh.h> class RemoveVCProcessTest; diff --git a/thirdparty/assimp/code/PostProcessing/ScaleProcess.cpp b/thirdparty/assimp/code/PostProcessing/ScaleProcess.cpp new file mode 100644 index 0000000000..ac770c41f2 --- /dev/null +++ b/thirdparty/assimp/code/PostProcessing/ScaleProcess.cpp @@ -0,0 +1,208 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include "ScaleProcess.h" + +#include <assimp/scene.h> +#include <assimp/postprocess.h> +#include <assimp/BaseImporter.h> + +namespace Assimp { + +ScaleProcess::ScaleProcess() +: BaseProcess() +, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) { +} + +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 ) { + // User scaling + mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 1.0f ); + + // File scaling * Application Scaling + float importerScale = pImp->GetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, 1.0f ); + + // apply scale to the scale + // helps prevent bugs with backward compatibility for anyone using normal scaling. + mScale *= importerScale; +} + +void ScaleProcess::Execute( aiScene* pScene ) { + if(mScale == 1.0f) { + return; // nothing to scale + } + + ai_assert( mScale != 0 ); + ai_assert( nullptr != pScene ); + ai_assert( nullptr != pScene->mRootNode ); + + if ( nullptr == pScene ) { + return; + } + + if ( nullptr == pScene->mRootNode ) { + return; + } + + // Process animations and update position transform to new unit system + for( unsigned int animationID = 0; animationID < pScene->mNumAnimations; animationID++ ) + { + aiAnimation* animation = pScene->mAnimations[animationID]; + + for( unsigned int animationChannel = 0; animationChannel < animation->mNumChannels; animationChannel++) + { + aiNodeAnim* anim = animation->mChannels[animationChannel]; + + for( unsigned int posKey = 0; posKey < anim->mNumPositionKeys; posKey++) + { + aiVectorKey& vectorKey = anim->mPositionKeys[posKey]; + vectorKey.mValue *= mScale; + } + } + } + + for( unsigned int meshID = 0; meshID < pScene->mNumMeshes; meshID++) + { + aiMesh *mesh = pScene->mMeshes[meshID]; + + // Reconstruct mesh vertexes to the new unit system + for( unsigned int vertexID = 0; vertexID < mesh->mNumVertices; vertexID++) + { + aiVector3D& vertex = mesh->mVertices[vertexID]; + vertex *= mScale; + } + + + // bone placement / scaling + for( unsigned int boneID = 0; boneID < mesh->mNumBones; boneID++) + { + // Reconstruct matrix by transform rather than by scale + // This prevent scale values being changed which can + // be meaningful in some cases + // like when you want the modeller to see 1:1 compatibility. + aiBone* bone = mesh->mBones[boneID]; + + aiVector3D pos, scale; + aiQuaternion rotation; + + bone->mOffsetMatrix.Decompose( scale, rotation, pos); + + aiMatrix4x4 translation; + aiMatrix4x4::Translation( pos * mScale, translation ); + + aiMatrix4x4 scaling; + aiMatrix4x4::Scaling( aiVector3D(scale), scaling ); + + aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix()); + + bone->mOffsetMatrix = translation * RotMatrix * scaling; + } + + + // animation mesh processing + // convert by position rather than scale. + for( unsigned int animMeshID = 0; animMeshID < mesh->mNumAnimMeshes; animMeshID++) + { + aiAnimMesh * animMesh = mesh->mAnimMeshes[animMeshID]; + + for( unsigned int vertexID = 0; vertexID < animMesh->mNumVertices; vertexID++) + { + aiVector3D& vertex = animMesh->mVertices[vertexID]; + vertex *= mScale; + } + } + } + + traverseNodes( pScene->mRootNode ); +} + +void ScaleProcess::traverseNodes( aiNode *node, unsigned int nested_node_id ) { + applyScaling( node ); + + for( size_t i = 0; i < node->mNumChildren; i++) + { + // recurse into the tree until we are done! + traverseNodes( node->mChildren[i], nested_node_id+1 ); + } +} + +void ScaleProcess::applyScaling( aiNode *currentNode ) { + if ( nullptr != currentNode ) { + // Reconstruct matrix by transform rather than by scale + // This prevent scale values being changed which can + // be meaningful in some cases + // like when you want the modeller to + // see 1:1 compatibility. + + aiVector3D pos, scale; + aiQuaternion rotation; + currentNode->mTransformation.Decompose( scale, rotation, pos); + + aiMatrix4x4 translation; + aiMatrix4x4::Translation( pos * mScale, translation ); + + aiMatrix4x4 scaling; + + // note: we do not use mScale here, this is on purpose. + aiMatrix4x4::Scaling( scale, scaling ); + + aiMatrix4x4 RotMatrix = aiMatrix4x4 (rotation.GetMatrix()); + + currentNode->mTransformation = translation * RotMatrix * scaling; + } +} + +} // Namespace Assimp diff --git a/thirdparty/assimp/code/ScaleProcess.h b/thirdparty/assimp/code/PostProcessing/ScaleProcess.h index 55146ae064..468a216736 100644 --- a/thirdparty/assimp/code/ScaleProcess.h +++ b/thirdparty/assimp/code/PostProcessing/ScaleProcess.h @@ -39,9 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -#pragma once +#ifndef SCALE_PROCESS_H_ +#define SCALE_PROCESS_H_ -#include "BaseProcess.h" +#include "Common/BaseProcess.h" struct aiNode; @@ -53,6 +54,11 @@ namespace Assimp { // --------------------------------------------------------------------------- /** ScaleProcess: Class to rescale the whole model. + * Now rescales animations, bones, and blend shapes properly. + * Please note this will not write to 'scale' transform it will rewrite mesh + * and matrixes so that your scale values + * from your model package are preserved, so this is completely intentional + * bugs should be reported as soon as they are found. */ class ASSIMP_API ScaleProcess : public BaseProcess { public: @@ -78,7 +84,7 @@ public: virtual void Execute( aiScene* pScene ); private: - void traverseNodes( aiNode *currentNode ); + void traverseNodes( aiNode *currentNode, unsigned int nested_node_id = 0 ); void applyScaling( aiNode *currentNode ); private: @@ -86,3 +92,6 @@ private: }; } // Namespace Assimp + + +#endif // SCALE_PROCESS_H_
\ No newline at end of file diff --git a/thirdparty/assimp/code/SortByPTypeProcess.cpp b/thirdparty/assimp/code/PostProcessing/SortByPTypeProcess.cpp index 2e0cc54004..be8405a17b 100644 --- a/thirdparty/assimp/code/SortByPTypeProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/SortByPTypeProcess.cpp @@ -57,8 +57,8 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer SortByPTypeProcess::SortByPTypeProcess() -{ - configRemoveMeshes = 0; +: mConfigRemoveMeshes( 0 ) { + // empty } // ------------------------------------------------------------------------------------------------ @@ -78,7 +78,7 @@ bool SortByPTypeProcess::IsActive( unsigned int pFlags) const // ------------------------------------------------------------------------------------------------ void SortByPTypeProcess::SetupProperties(const Importer* pImp) { - configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0); + mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0); } // ------------------------------------------------------------------------------------------------ @@ -172,7 +172,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { } if (1 == num) { - if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) { + if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) { *meshIdx = static_cast<unsigned int>( outMeshes.size() ); outMeshes.push_back(mesh); } else { @@ -206,7 +206,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh); for (unsigned int real = 0; real < 4; ++real,++meshIdx) { - if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real)) + if ( !aiNumPerPType[real] || mConfigRemoveMeshes & (1u << real)) { continue; } @@ -392,10 +392,10 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { { char buffer[1024]; ::ai_snprintf(buffer,1024,"Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)", - aiNumMeshesPerPType[0], ((configRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""), - aiNumMeshesPerPType[1], ((configRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""), - aiNumMeshesPerPType[2], ((configRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""), - aiNumMeshesPerPType[3], ((configRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : "")); + aiNumMeshesPerPType[0], ((mConfigRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""), + aiNumMeshesPerPType[1], ((mConfigRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""), + aiNumMeshesPerPType[2], ((mConfigRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""), + aiNumMeshesPerPType[3], ((mConfigRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : "")); ASSIMP_LOG_INFO(buffer); ASSIMP_LOG_DEBUG("SortByPTypeProcess finished"); } diff --git a/thirdparty/assimp/code/SortByPTypeProcess.h b/thirdparty/assimp/code/PostProcessing/SortByPTypeProcess.h index c9d9924d8f..1d7ccfc152 100644 --- a/thirdparty/assimp/code/SortByPTypeProcess.h +++ b/thirdparty/assimp/code/PostProcessing/SortByPTypeProcess.h @@ -45,10 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_SORTBYPTYPEPROCESS_H_INC #define AI_SORTBYPTYPEPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/mesh.h> class SortByPTypeProcessTest; + namespace Assimp { @@ -57,14 +58,11 @@ namespace Assimp { * A mesh with 5 lines, 3 points and 145 triangles would be split in 3 * submeshes. */ -class ASSIMP_API SortByPTypeProcess : public BaseProcess -{ +class ASSIMP_API SortByPTypeProcess : public BaseProcess { public: - SortByPTypeProcess(); ~SortByPTypeProcess(); -public: // ------------------------------------------------------------------- bool IsActive( unsigned int pFlags) const; @@ -75,8 +73,7 @@ public: void SetupProperties(const Importer* pImp); private: - - int configRemoveMeshes; + int mConfigRemoveMeshes; }; diff --git a/thirdparty/assimp/code/SplitLargeMeshes.cpp b/thirdparty/assimp/code/PostProcessing/SplitLargeMeshes.cpp index 1797b28d5a..1797b28d5a 100644 --- a/thirdparty/assimp/code/SplitLargeMeshes.cpp +++ b/thirdparty/assimp/code/PostProcessing/SplitLargeMeshes.cpp diff --git a/thirdparty/assimp/code/SplitLargeMeshes.h b/thirdparty/assimp/code/PostProcessing/SplitLargeMeshes.h index 77f089ce7e..3f90576ea9 100644 --- a/thirdparty/assimp/code/SplitLargeMeshes.h +++ b/thirdparty/assimp/code/PostProcessing/SplitLargeMeshes.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,21 +39,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** @file Defines a post processing step to split large meshes into submeshes +/** @file Defines a post processing step to split large meshes into sub-meshes */ #ifndef AI_SPLITLARGEMESHES_H_INC #define AI_SPLITLARGEMESHES_H_INC #include <vector> -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/mesh.h> #include <assimp/scene.h> +// Forward declarations class SplitLargeMeshesTest; -namespace Assimp -{ +namespace Assimp { class SplitLargeMeshesProcess_Triangle; class SplitLargeMeshesProcess_Vertex; diff --git a/thirdparty/assimp/code/TextureTransform.cpp b/thirdparty/assimp/code/PostProcessing/TextureTransform.cpp index 8ae2ba7218..8ae2ba7218 100644 --- a/thirdparty/assimp/code/TextureTransform.cpp +++ b/thirdparty/assimp/code/PostProcessing/TextureTransform.cpp diff --git a/thirdparty/assimp/code/TextureTransform.h b/thirdparty/assimp/code/PostProcessing/TextureTransform.h index c556ff5d8c..2a5d623d7f 100644 --- a/thirdparty/assimp/code/TextureTransform.h +++ b/thirdparty/assimp/code/PostProcessing/TextureTransform.h @@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_TEXTURE_TRANSFORM_H_INCLUDED #include <assimp/BaseImporter.h> -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include <assimp/material.h> #include <list> diff --git a/thirdparty/assimp/code/TriangulateProcess.cpp b/thirdparty/assimp/code/PostProcessing/TriangulateProcess.cpp index 0f68f47ddb..1040836bbe 100644 --- a/thirdparty/assimp/code/TriangulateProcess.cpp +++ b/thirdparty/assimp/code/PostProcessing/TriangulateProcess.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -60,9 +58,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * a file */ #ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS -#include "TriangulateProcess.h" -#include "ProcessHelper.h" -#include "PolyTools.h" + +#include "PostProcessing/TriangulateProcess.h" +#include "PostProcessing/ProcessHelper.h" +#include "Common/PolyTools.h" + #include <memory> //#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING diff --git a/thirdparty/assimp/code/TriangulateProcess.h b/thirdparty/assimp/code/PostProcessing/TriangulateProcess.h index 47bd2115ad..916b5103dd 100644 --- a/thirdparty/assimp/code/TriangulateProcess.h +++ b/thirdparty/assimp/code/PostProcessing/TriangulateProcess.h @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_TRIANGULATEPROCESS_H_INC #define AI_TRIANGULATEPROCESS_H_INC -#include "BaseProcess.h" +#include "Common/BaseProcess.h" struct aiMesh; @@ -59,14 +59,11 @@ namespace Assimp { * into triangles. You usually want this to happen because the graphics cards * need their data as triangles. */ -class ASSIMP_API TriangulateProcess : public BaseProcess -{ +class ASSIMP_API TriangulateProcess : public BaseProcess { public: - TriangulateProcess(); ~TriangulateProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag field. * @param pFlags The processing flags the importer was called with. A bitwise @@ -82,7 +79,6 @@ public: */ void Execute( aiScene* pScene); -public: // ------------------------------------------------------------------- /** Triangulates the given mesh. * @param pMesh The mesh to triangulate. diff --git a/thirdparty/assimp/code/ValidateDataStructure.cpp b/thirdparty/assimp/code/PostProcessing/ValidateDataStructure.cpp index 657b0361b7..75d1b6ef78 100644 --- a/thirdparty/assimp/code/ValidateDataStructure.cpp +++ b/thirdparty/assimp/code/PostProcessing/ValidateDataStructure.cpp @@ -46,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * the data structure returned by Assimp. */ - - // internal headers #include "ValidateDataStructure.h" #include <assimp/BaseImporter.h> @@ -110,8 +108,8 @@ void ValidateDSProcess::ReportWarning(const char* msg,...) } // ------------------------------------------------------------------------------------------------ -inline int HasNameMatch(const aiString& in, aiNode* node) -{ +inline +int HasNameMatch(const aiString& in, aiNode* node) { int result = (node->mName == in ? 1 : 0 ); for (unsigned int i = 0; i < node->mNumChildren;++i) { result += HasNameMatch(in,node->mChildren[i]); @@ -121,9 +119,8 @@ inline int HasNameMatch(const aiString& in, aiNode* node) // ------------------------------------------------------------------------------------------------ template <typename T> -inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size, - const char* firstName, const char* secondName) -{ +inline +void ValidateDSProcess::DoValidation(T** parray, unsigned int size, const char* firstName, const char* secondName) { // validate all entries if (size) { @@ -181,7 +178,8 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size, // ------------------------------------------------------------------------------------------------ template <typename T> inline -void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, const char* secondName) { +void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, + const char* secondName) { // validate all entries DoValidationEx(array,size,firstName,secondName); @@ -201,9 +199,8 @@ void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void ValidateDSProcess::Execute( aiScene* pScene) -{ - this->mScene = pScene; +void ValidateDSProcess::Execute( aiScene* pScene) { + mScene = pScene; ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin"); // validate the node graph of the scene @@ -516,13 +513,11 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) } // ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMesh* pMesh, - const aiBone* pBone,float* afSum) -{ +void ValidateDSProcess::Validate( const aiMesh* pMesh, const aiBone* pBone,float* afSum) { this->Validate(&pBone->mName); if (!pBone->mNumWeights) { - ReportError("aiBone::mNumWeights is zero"); + //ReportError("aiBone::mNumWeights is zero"); } // check whether all vertices affected by this bone are valid @@ -543,13 +538,17 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation) { Validate(&pAnimation->mName); - // validate all materials - if (pAnimation->mNumChannels) + // validate all animations + if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels) { - if (!pAnimation->mChannels) { + if (!pAnimation->mChannels && pAnimation->mNumChannels) { ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)", pAnimation->mNumChannels); } + if (!pAnimation->mMorphMeshChannels && pAnimation->mNumMorphMeshChannels) { + ReportError("aiAnimation::mMorphMeshChannels is NULL (aiAnimation::mNumMorphMeshChannels is %i)", + pAnimation->mNumMorphMeshChannels); + } for (unsigned int i = 0; i < pAnimation->mNumChannels;++i) { if (!pAnimation->mChannels[i]) @@ -559,13 +558,19 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation) } Validate(pAnimation, pAnimation->mChannels[i]); } + for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels;++i) + { + if (!pAnimation->mMorphMeshChannels[i]) + { + ReportError("aiAnimation::mMorphMeshChannels[%i] is NULL (aiAnimation::mNumMorphMeshChannels is %i)", + i, pAnimation->mNumMorphMeshChannels); + } + Validate(pAnimation, pAnimation->mMorphMeshChannels[i]); + } } else { ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there."); } - - // Animation duration is allowed to be zero in cases where the anim contains only a single key frame. - // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero"); } // ------------------------------------------------------------------------------------------------ @@ -746,8 +751,9 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial) "AI_MATKEY_SHININESS_STRENGTH key is 0.0"); } break; - default: ; - }; + default: + break; + } } if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) { @@ -910,6 +916,48 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, } } +void ValidateDSProcess::Validate( const aiAnimation* pAnimation, + const aiMeshMorphAnim* pMeshMorphAnim) +{ + Validate(&pMeshMorphAnim->mName); + + if (!pMeshMorphAnim->mNumKeys) { + ReportError("Empty mesh morph animation channel"); + } + + // otherwise check whether one of the keys exceeds the total duration of the animation + if (pMeshMorphAnim->mNumKeys) + { + if (!pMeshMorphAnim->mKeys) + { + ReportError("aiMeshMorphAnim::mKeys is NULL (aiMeshMorphAnim::mNumKeys is %i)", + pMeshMorphAnim->mNumKeys); + } + double dLast = -10e10; + for (unsigned int i = 0; i < pMeshMorphAnim->mNumKeys;++i) + { + // ScenePreprocessor will compute the duration if still the default value + // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration, + // seems to be due the compilers register usage/width. + if (pAnimation->mDuration > 0. && pMeshMorphAnim->mKeys[i].mTime > pAnimation->mDuration+0.001) + { + ReportError("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is larger " + "than aiAnimation::mDuration (which is %.5f)",i, + (float)pMeshMorphAnim->mKeys[i].mTime, + (float)pAnimation->mDuration); + } + if (i && pMeshMorphAnim->mKeys[i].mTime <= dLast) + { + ReportWarning("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is smaller " + "than aiMeshMorphAnim::mKeys[%i] (which is %.5f)",i, + (float)pMeshMorphAnim->mKeys[i].mTime, + i-1, (float)dLast); + } + dLast = pMeshMorphAnim->mKeys[i].mTime; + } + } +} + // ------------------------------------------------------------------------------------------------ void ValidateDSProcess::Validate( const aiNode* pNode) { @@ -965,7 +1013,7 @@ void ValidateDSProcess::Validate( const aiString* pString) { if (pString->length > MAXLEN) { - ReportError("aiString::length is too large (%lu, maximum is %lu)", + ReportError("aiString::length is too large (%u, maximum is %lu)", pString->length,MAXLEN); } const char* sz = pString->data; diff --git a/thirdparty/assimp/code/ValidateDataStructure.h b/thirdparty/assimp/code/PostProcessing/ValidateDataStructure.h index bd21e88545..7b309c9251 100644 --- a/thirdparty/assimp/code/ValidateDataStructure.h +++ b/thirdparty/assimp/code/PostProcessing/ValidateDataStructure.h @@ -48,12 +48,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <assimp/types.h> #include <assimp/material.h> -#include "BaseProcess.h" + +#include "Common/BaseProcess.h" struct aiBone; struct aiMesh; struct aiAnimation; struct aiNodeAnim; +struct aiMeshMorphAnim; struct aiTexture; struct aiMaterial; struct aiNode; @@ -149,6 +151,13 @@ protected: void Validate( const aiAnimation* pAnimation, const aiNodeAnim* pBoneAnim); + /** Validates a mesh morph animation channel. + * @param pAnimation Input animation. + * @param pMeshMorphAnim Mesh morph animation channel. + * */ + void Validate( const aiAnimation* pAnimation, + const aiMeshMorphAnim* pMeshMorphAnim); + // ------------------------------------------------------------------- /** Validates a node and all of its subnodes * @param Node Input node*/ diff --git a/thirdparty/assimp/code/RawLoader.cpp b/thirdparty/assimp/code/RawLoader.cpp deleted file mode 100644 index d0da247e47..0000000000 --- a/thirdparty/assimp/code/RawLoader.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/** @file RawLoader.cpp - * @brief Implementation of the RAW importer class - */ - - -#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER - -// internal headers -#include "RawLoader.h" -#include <assimp/ParsingUtils.h> -#include <assimp/fast_atof.h> -#include <memory> -#include <assimp/IOSystem.hpp> -#include <assimp/DefaultLogger.hpp> -#include <assimp/scene.h> -#include <assimp/importerdesc.h> - -using namespace Assimp; - -static const aiImporterDesc desc = { - "Raw Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "raw" -}; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -RAWImporter::RAWImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -RAWImporter::~RAWImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const -{ - return SimpleExtensionCheck(pFile,"raw"); -} - -// ------------------------------------------------------------------------------------------------ -const aiImporterDesc* RAWImporter::GetInfo () const -{ - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void RAWImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open RAW file " + pFile + "."); - } - - // allocate storage and copy the contents of the file to a memory buffer - // (terminate it with zero) - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; - - // list of groups loaded from the file - std::vector< GroupInformation > outGroups(1,GroupInformation("<default>")); - std::vector< GroupInformation >::iterator curGroup = outGroups.begin(); - - // now read all lines - char line[4096]; - while (GetNextLine(buffer,line)) - { - // if the line starts with a non-numeric identifier, it marks - // the beginning of a new group - const char* sz = line;SkipSpaces(&sz); - if (IsLineEnd(*sz))continue; - if (!IsNumeric(*sz)) - { - const char* sz2 = sz; - while (!IsSpaceOrNewLine(*sz2))++sz2; - const unsigned int length = (unsigned int)(sz2-sz); - - // find an existing group with this name - for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); - it != end;++it) - { - if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str())) - { - curGroup = it;sz2 = NULL; - break; - } - } - if (sz2) - { - outGroups.push_back(GroupInformation(std::string(sz,length))); - curGroup = outGroups.end()-1; - } - } - else - { - // there can be maximally 12 floats plus an extra texture file name - float data[12]; - unsigned int num; - for (num = 0; num < 12;++num) - { - if(!SkipSpaces(&sz) || !IsNumeric(*sz))break; - sz = fast_atoreal_move<float>(sz,data[num]); - } - if (num != 12 && num != 9) - { - ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture"); - continue; - } - - MeshInformation* output = NULL; - - const char* sz2 = sz; - unsigned int length; - if (!IsLineEnd(*sz)) - { - while (!IsSpaceOrNewLine(*sz2))++sz2; - length = (unsigned int)(sz2-sz); - } - else if (9 == num) - { - sz = "%default%"; - length = 9; - } - else - { - sz = ""; - length = 0; - } - - // search in the list of meshes whether we have one with this texture - for (auto &mesh : (*curGroup).meshes) - { - if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true)) - { - output = &mesh; - break; - } - } - // if we don't have the mesh, create it - if (!output) - { - (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length))); - output = &((*curGroup).meshes.back()); - } - if (12 == num) - { - aiColor4D v(data[0],data[1],data[2],1.0f); - output->colors.push_back(v); - output->colors.push_back(v); - output->colors.push_back(v); - - output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); - output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); - output->vertices.push_back(aiVector3D(data[9],data[10],data[11])); - } - else - { - output->vertices.push_back(aiVector3D(data[0],data[1],data[2])); - output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); - output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); - } - } - } - - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("<RawRoot>"); - - // count the number of valid groups - // (meshes can't be empty) - for (auto & outGroup : outGroups) - { - if (!outGroup.meshes.empty()) - { - ++pScene->mRootNode->mNumChildren; - pScene->mNumMeshes += (unsigned int) outGroup.meshes.size(); - } - } - - if (!pScene->mNumMeshes) - { - throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty."); - } - - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - aiNode** cc; - if (1 == pScene->mRootNode->mNumChildren) - { - cc = &pScene->mRootNode; - pScene->mRootNode->mNumChildren = 0; - } else { - cc = new aiNode*[pScene->mRootNode->mNumChildren]; - memset(cc, 0, sizeof(aiNode*) * pScene->mRootNode->mNumChildren); - pScene->mRootNode->mChildren = cc; - } - - pScene->mNumMaterials = pScene->mNumMeshes; - aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - - unsigned int meshIdx = 0; - for (auto & outGroup : outGroups) - { - if (outGroup.meshes.empty())continue; - - aiNode* node; - if (pScene->mRootNode->mNumChildren) - { - node = *cc = new aiNode(); - node->mParent = pScene->mRootNode; - } - else node = *cc; - node->mName.Set(outGroup.name); - - // add all meshes - node->mNumMeshes = (unsigned int) outGroup.meshes.size(); - unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ]; - for (std::vector< MeshInformation >::iterator it2 = outGroup.meshes.begin(), - end2 = outGroup.meshes.end(); it2 != end2; ++it2) - { - ai_assert(!(*it2).vertices.empty()); - - // allocate the mesh - *pi++ = meshIdx; - aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh(); - mesh->mMaterialIndex = meshIdx++; - - mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // allocate storage for the vertex components and copy them - mesh->mNumVertices = (unsigned int)(*it2).vertices.size(); - mesh->mVertices = new aiVector3D[ mesh->mNumVertices ]; - ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices); - - if ((*it2).colors.size()) - { - ai_assert((*it2).colors.size() == mesh->mNumVertices); - - mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ]; - ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices); - } - - // generate triangles - ai_assert(0 == mesh->mNumVertices % 3); - aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ]; - aiFace* const fcEnd = fc + mesh->mNumFaces; - unsigned int n = 0; - while (fc != fcEnd) - { - aiFace& f = *fc++; - f.mIndices = new unsigned int[f.mNumIndices = 3]; - for (unsigned int m = 0; m < 3;++m) - f.mIndices[m] = n++; - } - - // generate a material for the mesh - aiMaterial* mat = new aiMaterial(); - - aiColor4D clr(1.0f,1.0f,1.0f,1.0f); - if ("%default%" == (*it2).name) // a gray default material - { - clr.r = clr.g = clr.b = 0.6f; - } - else if ((*it2).name.length() > 0) // a texture - { - aiString s; - s.Set((*it2).name); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - *mats++ = mat; - } - } -} - -#endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER diff --git a/thirdparty/assimp/code/ScaleProcess.cpp b/thirdparty/assimp/code/ScaleProcess.cpp deleted file mode 100644 index 6d458c4b11..0000000000 --- a/thirdparty/assimp/code/ScaleProcess.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2019, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -#ifndef ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS - -#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 ); -} - -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 - -#endif // !! ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS diff --git a/thirdparty/assimp/code/res/resource.h b/thirdparty/assimp/code/res/resource.h deleted file mode 100644 index 37d39284fe..0000000000 --- a/thirdparty/assimp/code/res/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by assimp.rc - -// Nächste Standardwerte für neue Objekte -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/thirdparty/assimp/code/revision.h b/thirdparty/assimp/code/revision.h index 88872aef22..66eb875303 100644 --- a/thirdparty/assimp/code/revision.h +++ b/thirdparty/assimp/code/revision.h @@ -1,7 +1,28 @@ #ifndef ASSIMP_REVISION_H_INC #define ASSIMP_REVISION_H_INC -#define GitVersion 0x00000000 +#define GitVersion 0x308db73d #define GitBranch "master" +#define VER_MAJOR 5 +#define VER_MINOR 0 +#define VER_PATCH 0 +#define VER_BUILD 0 + +#define STR_HELP(x) #x +#define STR(x) STR_HELP(x) + +#define VER_FILEVERSION VER_MAJOR,VER_MINOR,VER_PATCH,VER_BUILD +#if (GitVersion == 0) +#define VER_FILEVERSION_STR STR(VER_MAJOR) "." STR(VER_MINOR) "." STR(VER_PATCH) "." STR(VER_BUILD) +#else +#define VER_FILEVERSION_STR STR(VER_MAJOR) "." STR(VER_MINOR) "." STR(VER_PATCH) "." STR(VER_BUILD) " (Commit 308db73d)" +#endif + +#ifdef NDEBUG +#define VER_ORIGINAL_FILENAME_STR "assimp.dll" +#else +#define VER_ORIGINAL_FILENAME_STR "assimp.dll" +#endif // NDEBUG + #endif // ASSIMP_REVISION_H_INC |