From 1529f9518fcf826c22f2840d584f6c4f39b6b2eb Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sat, 21 Mar 2020 02:34:12 -0400 Subject: [PATCH 001/119] Make file formatting comply with POSIX and Unix standards UTF-8, LF, no BOM, and newlines at the end of files --- INSTALL | 100 +++++++++--------- code/AMF/AMFImporter_Geometry.cpp | 2 +- code/AMF/AMFImporter_Macro.hpp | 2 +- code/AMF/AMFImporter_Material.cpp | 2 +- code/AMF/AMFImporter_Node.hpp | 2 +- code/AMF/AMFImporter_Postprocess.cpp | 2 +- code/Common/ImporterRegistry.cpp | 2 +- code/MMD/MMDImporter.h | 2 +- code/PostProcessing/ArmaturePopulate.h | 2 +- code/PostProcessing/ScaleProcess.h | 2 +- code/PostProcessing/ValidateDataStructure.cpp | 2 +- code/glTF/glTFAsset.h | 2 +- code/glTF/glTFExporter.cpp | 2 +- code/glTF/glTFImporter.cpp | 2 +- code/glTF2/glTF2Asset.h | 2 +- code/glTF2/glTF2Exporter.cpp | 2 +- contrib/Open3DGC/o3dgcSC3DMCDecoder.h | 2 +- contrib/android-cmake/README.md | 2 +- contrib/gtest/docs/Documentation.md | 2 +- contrib/gtest/docs/V1_5_Documentation.md | 2 +- contrib/gtest/docs/V1_5_PumpManual.md | 2 +- contrib/gtest/docs/V1_5_XcodeGuide.md | 2 +- contrib/gtest/docs/V1_6_Documentation.md | 2 +- contrib/gtest/docs/V1_6_XcodeGuide.md | 2 +- contrib/gtest/docs/V1_7_Documentation.md | 2 +- contrib/gtest/docs/V1_7_XcodeGuide.md | 2 +- contrib/gtest/docs/XcodeGuide.md | 2 +- contrib/poly2tri/README | 4 +- contrib/poly2tri/poly2tri/common/shapes.cc | 2 +- contrib/poly2tri/poly2tri/common/shapes.h | 2 +- contrib/poly2tri/poly2tri/poly2tri.h | 2 +- .../poly2tri/sweep/advancing_front.cc | 2 +- .../poly2tri/poly2tri/sweep/advancing_front.h | 2 +- contrib/poly2tri/poly2tri/sweep/cdt.cc | 2 +- contrib/poly2tri/poly2tri/sweep/cdt.h | 2 +- contrib/poly2tri/poly2tri/sweep/sweep.h | 2 +- contrib/stb_image/stb_image.h | 2 +- contrib/zip/.travis.sh | 2 +- contrib/zip/.travis.yml | 2 +- contrib/zlib/contrib/blast/test.txt | 2 +- contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt | 2 +- contrib/zlib/contrib/testzlib/testzlib.txt | 2 +- contrib/zlib_note.txt | 2 +- .../Assimp_Arch_Import.class.violet.html | 2 +- .../Assimp_Arch_export.class.violet.html | 2 +- doc/architecture/assimp.object.violet.html | 2 +- .../assimp_usecase.ucase.violet.html | 2 +- doc/architecture/process.class.violet.html | 2 +- include/assimp/scene.h | 2 +- packaging/windows-innosetup/WEB | 14 ++- .../readme_installer_vieweronly.txt | 2 +- packaging/windows-mkzip/bin_readme.txt | 2 +- port/PyAssimp/pyassimp/errors.py | 22 ++-- .../jassimp/src/jassimp/AiAnimation.java | 2 +- .../jassimp/src/jassimp/AiBlendMode.java | 2 +- .../jassimp/jassimp/src/jassimp/AiCamera.java | 2 +- .../src/jassimp/AiProgressHandler.java | 2 +- .../jassimp/src/jassimp/AiQuaternion.java | 2 +- .../jassimp/src/jassimp/AiTextureType.java | 2 +- port/swig/DONOTUSEYET | 2 +- samples/SimpleAssimpViewX/README | 2 +- .../SimpleTexturedDirectx11/main.cpp | 2 +- .../include/boost_includes.h | 2 +- test/models-nonbsd/3DS/jeep1.3ds.readme.txt | 2 +- test/models-nonbsd/3DS/pyramob.3ds.readme.txt | 2 +- test/models-nonbsd/ASE/Rifle.source.txt | 2 +- test/models-nonbsd/ASE/Rifle2.source.txt | 2 +- test/models-nonbsd/B3D/turtle.source.txt | 2 +- test/models-nonbsd/DXF/rifle.source.txt | 2 +- .../FBX/2013_ASCII/jeep1.fbx.readme.txt | 2 +- .../FBX/2013_ASCII/pyramob.fbx.readme.txt | 2 +- .../FBX/2013_BINARY/jeep1.fbx.readme.txt | 2 +- .../FBX/2013_BINARY/pyramob.fbx.readme.txt | 2 +- test/models-nonbsd/IFC/linklist.txt | 2 +- .../LWO2/LWSReferences/QuickDraw.source.txt | 2 +- test/models-nonbsd/LWO/LWO2/rifle.source.txt | 2 +- .../LWS/QuickDraw v2.2.source.txt | 2 +- .../kt_kubalwagon/readme_kubalwagon.txt | 2 +- test/models-nonbsd/MD3/readme_water.txt | 2 +- test/models-nonbsd/MMD/readme.txt | 2 +- test/models-nonbsd/NFF/NFFSense8/credits.txt | 2 +- test/models-nonbsd/OBJ/rifle.source.txt | 2 +- test/models-nonbsd/OBJ/segment.source.txt | 2 +- test/models-nonbsd/Ogre/OgreSDK/LICENSE | 2 +- test/models-nonbsd/Ogre/OgreSDK/README.md | 2 +- test/models-nonbsd/README.txt | 2 +- test/models/3DS/UVTransformTest/note.txt | 2 +- test/models/3DS/textures.txt | 2 +- test/models/ASE/MotionCaptureROM.source.txt | 2 +- test/models/BLEND/HUMAN.source.txt | 2 +- test/models/BVH/01_nn.bvh.source.txt | 2 +- test/models/CSM/ThomasFechten.source.txt | 2 +- test/models/IRRMesh/credits.txt | 2 +- .../LWO/LWO2/MappingModes/earthCylindric.txt | 2 +- .../MappingModes/earthSpherical.source.txt | 2 +- test/models/LWO/LWO2/concrete.source.txt | 2 +- test/models/LWO/LWO2/uvtest-source.txt | 2 +- test/models/MD2/faerie-source.txt | 2 +- test/models/MD2/sidney-source.txt | 2 +- test/models/MD5/SimpleCube.source.txt | 2 +- .../MDL/MDL3 (3DGS A4)/minigun_readme.txt | 2 +- .../MDL5 (3DGS A5)/minigun_mdl5_readme.txt | 2 +- test/models/MS3D/jeep1.readme.txt | 2 +- test/models/Q3D/E-AT-AT.source.txt | 2 +- test/models/Q3D/earth.source.txt | 2 +- test/models/X/BCN_Epileptic.txt | 2 +- test/models/X/anim_test.txt | 2 +- test/models/X/test.txt | 2 +- test/regression/result_checker.py | 2 +- test/unit/utImproveCacheLocality.cpp | 2 +- tools/assimp_view/Background.cpp | 2 +- tools/assimp_view/Camera.h | 2 +- tools/assimp_view/Display.h | 2 +- tools/assimp_view/Input.cpp | 2 +- tools/assimp_view/LogWindow.h | 2 +- tools/assimp_view/MeshRenderer.cpp | 2 +- tools/assimp_view/MeshRenderer.h | 2 +- tools/assimp_view/NOTE@help.rtf.txt | 2 +- tools/assimp_view/RenderOptions.h | 2 +- tools/assimp_view/SceneAnimator.h | 2 +- tools/assimp_view/Shaders.cpp | 2 +- tools/assimp_view/assimp_view.h | 2 +- 122 files changed, 187 insertions(+), 189 deletions(-) diff --git a/INSTALL b/INSTALL index 350a5f109..ecec2585b 100644 --- a/INSTALL +++ b/INSTALL @@ -1,50 +1,50 @@ - -======================================================================== -Open Asset Import Library (assimp) INSTALL -======================================================================== - ------------------------------- -Getting the documentation ------------------------------- - -A regularly-updated copy is available at -http://assimp.sourceforge.net/lib_html/index.html - -A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm. -To build the doxygen documentation on your own, follow these steps: - -a) download & install latest doxygen -b) make sure doxygen is in the executable search path -c) navigate to ./doc -d) and run 'doxygen' - -Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice. -Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop' -and configure the path to it in the DOXYFILE first. - ------------------------------- -Building Assimp ------------------------------- - -More detailed build instructions can be found in the documentation, -this section is just for the inpatient among you. - -CMake is the preferred build system for Assimp. The minimum required version -is 2.6. If you don't have it yet, downloads for CMake can be found on -http://www.cmake.org/. - -For Unix: - -1. mkdir build && cd build -2. cmake .. -G 'Unix Makefiles' -3. make -j4 - -For Windows: -1. Open a command prompt -2. mkdir build -3. cd build -4. cmake .. -5. cmake --build . - -For iOS: -Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS + +======================================================================== +Open Asset Import Library (assimp) INSTALL +======================================================================== + +------------------------------ +Getting the documentation +------------------------------ + +A regularly-updated copy is available at +http://assimp.sourceforge.net/lib_html/index.html + +A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm. +To build the doxygen documentation on your own, follow these steps: + +a) download & install latest doxygen +b) make sure doxygen is in the executable search path +c) navigate to ./doc +d) and run 'doxygen' + +Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice. +Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop' +and configure the path to it in the DOXYFILE first. + +------------------------------ +Building Assimp +------------------------------ + +More detailed build instructions can be found in the documentation, +this section is just for the inpatient among you. + +CMake is the preferred build system for Assimp. The minimum required version +is 2.6. If you don't have it yet, downloads for CMake can be found on +http://www.cmake.org/. + +For Unix: + +1. mkdir build && cd build +2. cmake .. -G 'Unix Makefiles' +3. make -j4 + +For Windows: +1. Open a command prompt +2. mkdir build +3. cd build +4. cmake .. +5. cmake --build . + +For iOS: +Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS diff --git a/code/AMF/AMFImporter_Geometry.cpp b/code/AMF/AMFImporter_Geometry.cpp index e9a50b656..45be05df1 100644 --- a/code/AMF/AMFImporter_Geometry.cpp +++ b/code/AMF/AMFImporter_Geometry.cpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/AMF/AMFImporter_Macro.hpp b/code/AMF/AMFImporter_Macro.hpp index ec06cb999..5877a62d2 100644 --- a/code/AMF/AMFImporter_Macro.hpp +++ b/code/AMF/AMFImporter_Macro.hpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/AMF/AMFImporter_Material.cpp b/code/AMF/AMFImporter_Material.cpp index 64da12dda..7ab5710da 100644 --- a/code/AMF/AMFImporter_Material.cpp +++ b/code/AMF/AMFImporter_Material.cpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/AMF/AMFImporter_Node.hpp b/code/AMF/AMFImporter_Node.hpp index b7b7836f3..ea65e106b 100644 --- a/code/AMF/AMFImporter_Node.hpp +++ b/code/AMF/AMFImporter_Node.hpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/AMF/AMFImporter_Postprocess.cpp b/code/AMF/AMFImporter_Postprocess.cpp index 8496d8ded..bdf13ac60 100644 --- a/code/AMF/AMFImporter_Postprocess.cpp +++ b/code/AMF/AMFImporter_Postprocess.cpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/Common/ImporterRegistry.cpp b/code/Common/ImporterRegistry.cpp index 41aa21979..4b9416663 100644 --- a/code/Common/ImporterRegistry.cpp +++ b/code/Common/ImporterRegistry.cpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/MMD/MMDImporter.h b/code/MMD/MMDImporter.h index 1cc91c782..b1fdb9f6a 100644 --- a/code/MMD/MMDImporter.h +++ b/code/MMD/MMDImporter.h @@ -93,4 +93,4 @@ private: } // Namespace Assimp -#endif \ No newline at end of file +#endif diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index 8985e1d1d..877d8b0d1 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -109,4 +109,4 @@ public: } // Namespace Assimp -#endif // SCALE_PROCESS_H_ \ No newline at end of file +#endif // SCALE_PROCESS_H_ diff --git a/code/PostProcessing/ScaleProcess.h b/code/PostProcessing/ScaleProcess.h index 9cc664c6a..5799dd22c 100644 --- a/code/PostProcessing/ScaleProcess.h +++ b/code/PostProcessing/ScaleProcess.h @@ -94,4 +94,4 @@ private: } // Namespace Assimp -#endif // SCALE_PROCESS_H_ \ No newline at end of file +#endif // SCALE_PROCESS_H_ diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index 6212bfb69..93f10598a 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/code/glTF/glTFAsset.h b/code/glTF/glTFAsset.h index b918d456b..fdda6a615 100644 --- a/code/glTF/glTFAsset.h +++ b/code/glTF/glTFAsset.h @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 7c21b738b..e863b3f24 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index b410e1002..1f18850d2 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index d3c1654d0..2514a6fae 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 7894f8adb..c4decdb49 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- diff --git a/contrib/Open3DGC/o3dgcSC3DMCDecoder.h b/contrib/Open3DGC/o3dgcSC3DMCDecoder.h index f3f1617c4..e6f803b94 100644 --- a/contrib/Open3DGC/o3dgcSC3DMCDecoder.h +++ b/contrib/Open3DGC/o3dgcSC3DMCDecoder.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/contrib/android-cmake/README.md b/contrib/android-cmake/README.md index ee6302128..395131daf 100644 --- a/contrib/android-cmake/README.md +++ b/contrib/android-cmake/README.md @@ -237,4 +237,4 @@ The _android-cmake_ should correctly handle projects with assembler sources (`*. ## Copying -_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) \ No newline at end of file +_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) diff --git a/contrib/gtest/docs/Documentation.md b/contrib/gtest/docs/Documentation.md index 8ca1aac75..e5d041f3a 100644 --- a/contrib/gtest/docs/Documentation.md +++ b/contrib/gtest/docs/Documentation.md @@ -11,4 +11,4 @@ documentation for that specific version instead.** To contribute code to Google Test, read: * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch. - * [PumpManual](PumpManual.md) -- how we generate some of Google Test's source files. \ No newline at end of file + * [PumpManual](PumpManual.md) -- how we generate some of Google Test's source files. diff --git a/contrib/gtest/docs/V1_5_Documentation.md b/contrib/gtest/docs/V1_5_Documentation.md index 46bba2ec8..6febc65c9 100644 --- a/contrib/gtest/docs/V1_5_Documentation.md +++ b/contrib/gtest/docs/V1_5_Documentation.md @@ -9,4 +9,4 @@ This page lists all official documentation wiki pages for Google Test **1.5.0** To contribute code to Google Test, read: * DevGuide -- read this _before_ writing your first patch. - * [PumpManual](V1_5_PumpManual.md) -- how we generate some of Google Test's source files. \ No newline at end of file + * [PumpManual](V1_5_PumpManual.md) -- how we generate some of Google Test's source files. diff --git a/contrib/gtest/docs/V1_5_PumpManual.md b/contrib/gtest/docs/V1_5_PumpManual.md index 15710789d..e6485a01d 100644 --- a/contrib/gtest/docs/V1_5_PumpManual.md +++ b/contrib/gtest/docs/V1_5_PumpManual.md @@ -174,4 +174,4 @@ You can find real-world applications of Pump in [Google Test](http://www.google. ## Tips ## * If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1. - * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line. \ No newline at end of file + * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line. diff --git a/contrib/gtest/docs/V1_5_XcodeGuide.md b/contrib/gtest/docs/V1_5_XcodeGuide.md index bf24bf51b..21d7f5c05 100644 --- a/contrib/gtest/docs/V1_5_XcodeGuide.md +++ b/contrib/gtest/docs/V1_5_XcodeGuide.md @@ -90,4 +90,4 @@ The Debugger has exited with status 0. # Summary # -Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. \ No newline at end of file +Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. diff --git a/contrib/gtest/docs/V1_6_Documentation.md b/contrib/gtest/docs/V1_6_Documentation.md index ca924660a..1085673d1 100644 --- a/contrib/gtest/docs/V1_6_Documentation.md +++ b/contrib/gtest/docs/V1_6_Documentation.md @@ -11,4 +11,4 @@ documentation for that specific version instead.** To contribute code to Google Test, read: * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch. - * [PumpManual](V1_6_PumpManual.md) -- how we generate some of Google Test's source files. \ No newline at end of file + * [PumpManual](V1_6_PumpManual.md) -- how we generate some of Google Test's source files. diff --git a/contrib/gtest/docs/V1_6_XcodeGuide.md b/contrib/gtest/docs/V1_6_XcodeGuide.md index bf24bf51b..21d7f5c05 100644 --- a/contrib/gtest/docs/V1_6_XcodeGuide.md +++ b/contrib/gtest/docs/V1_6_XcodeGuide.md @@ -90,4 +90,4 @@ The Debugger has exited with status 0. # Summary # -Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. \ No newline at end of file +Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. diff --git a/contrib/gtest/docs/V1_7_Documentation.md b/contrib/gtest/docs/V1_7_Documentation.md index 282697a50..6dc7d05b4 100644 --- a/contrib/gtest/docs/V1_7_Documentation.md +++ b/contrib/gtest/docs/V1_7_Documentation.md @@ -11,4 +11,4 @@ documentation for that specific version instead.** To contribute code to Google Test, read: * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch. - * [PumpManual](V1_7_PumpManual.md) -- how we generate some of Google Test's source files. \ No newline at end of file + * [PumpManual](V1_7_PumpManual.md) -- how we generate some of Google Test's source files. diff --git a/contrib/gtest/docs/V1_7_XcodeGuide.md b/contrib/gtest/docs/V1_7_XcodeGuide.md index bf24bf51b..21d7f5c05 100644 --- a/contrib/gtest/docs/V1_7_XcodeGuide.md +++ b/contrib/gtest/docs/V1_7_XcodeGuide.md @@ -90,4 +90,4 @@ The Debugger has exited with status 0. # Summary # -Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. \ No newline at end of file +Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. diff --git a/contrib/gtest/docs/XcodeGuide.md b/contrib/gtest/docs/XcodeGuide.md index bf24bf51b..21d7f5c05 100644 --- a/contrib/gtest/docs/XcodeGuide.md +++ b/contrib/gtest/docs/XcodeGuide.md @@ -90,4 +90,4 @@ The Debugger has exited with status 0. # Summary # -Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. \ No newline at end of file +Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment. diff --git a/contrib/poly2tri/README b/contrib/poly2tri/README index 2857e2983..883e9a581 100644 --- a/contrib/poly2tri/README +++ b/contrib/poly2tri/README @@ -1,4 +1,4 @@ -================== +================== INSTALLATION GUIDE ================== @@ -48,4 +48,4 @@ Examples: ./p2t nazca_monkey.dat 0 0 9 ./p2t random 10 100 5.0 - ./p2t random 1000 20000 0.025 \ No newline at end of file + ./p2t random 1000 20000 0.025 diff --git a/contrib/poly2tri/poly2tri/common/shapes.cc b/contrib/poly2tri/poly2tri/common/shapes.cc index d0de13e64..c94e11c03 100644 --- a/contrib/poly2tri/poly2tri/common/shapes.cc +++ b/contrib/poly2tri/poly2tri/common/shapes.cc @@ -362,4 +362,4 @@ void Triangle::DebugPrint() cout << points_[2]->x << "," << points_[2]->y << endl; } -} \ No newline at end of file +} diff --git a/contrib/poly2tri/poly2tri/common/shapes.h b/contrib/poly2tri/poly2tri/common/shapes.h index ac7389a2d..d3660f716 100644 --- a/contrib/poly2tri/poly2tri/common/shapes.h +++ b/contrib/poly2tri/poly2tri/common/shapes.h @@ -324,4 +324,4 @@ inline void Triangle::IsInterior(bool b) } -#endif \ No newline at end of file +#endif diff --git a/contrib/poly2tri/poly2tri/poly2tri.h b/contrib/poly2tri/poly2tri/poly2tri.h index 29a08d052..ba5cc159e 100644 --- a/contrib/poly2tri/poly2tri/poly2tri.h +++ b/contrib/poly2tri/poly2tri/poly2tri.h @@ -35,4 +35,4 @@ #include "common/shapes.h" #include "sweep/cdt.h" -#endif \ No newline at end of file +#endif diff --git a/contrib/poly2tri/poly2tri/sweep/advancing_front.cc b/contrib/poly2tri/poly2tri/sweep/advancing_front.cc index 38723beef..9739babce 100644 --- a/contrib/poly2tri/poly2tri/sweep/advancing_front.cc +++ b/contrib/poly2tri/poly2tri/sweep/advancing_front.cc @@ -105,4 +105,4 @@ AdvancingFront::~AdvancingFront() { } -} \ No newline at end of file +} diff --git a/contrib/poly2tri/poly2tri/sweep/advancing_front.h b/contrib/poly2tri/poly2tri/sweep/advancing_front.h index 645dcec97..3bfec5368 100644 --- a/contrib/poly2tri/poly2tri/sweep/advancing_front.h +++ b/contrib/poly2tri/poly2tri/sweep/advancing_front.h @@ -115,4 +115,4 @@ inline void AdvancingFront::set_search(Node* node) } -#endif \ No newline at end of file +#endif diff --git a/contrib/poly2tri/poly2tri/sweep/cdt.cc b/contrib/poly2tri/poly2tri/sweep/cdt.cc index 09d088ae3..b79f5a8de 100644 --- a/contrib/poly2tri/poly2tri/sweep/cdt.cc +++ b/contrib/poly2tri/poly2tri/sweep/cdt.cc @@ -68,4 +68,4 @@ CDT::~CDT() delete sweep_; } -} \ No newline at end of file +} diff --git a/contrib/poly2tri/poly2tri/sweep/cdt.h b/contrib/poly2tri/poly2tri/sweep/cdt.h index ea3286d9a..4a9a292d3 100644 --- a/contrib/poly2tri/poly2tri/sweep/cdt.h +++ b/contrib/poly2tri/poly2tri/sweep/cdt.h @@ -102,4 +102,4 @@ public: } -#endif \ No newline at end of file +#endif diff --git a/contrib/poly2tri/poly2tri/sweep/sweep.h b/contrib/poly2tri/poly2tri/sweep/sweep.h index 33e34a714..ad429fd96 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep.h +++ b/contrib/poly2tri/poly2tri/sweep/sweep.h @@ -282,4 +282,4 @@ private: } -#endif \ No newline at end of file +#endif diff --git a/contrib/stb_image/stb_image.h b/contrib/stb_image/stb_image.h index 571b0dcea..d9c21bc81 100644 --- a/contrib/stb_image/stb_image.h +++ b/contrib/stb_image/stb_image.h @@ -7459,4 +7459,4 @@ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ -*/ \ No newline at end of file +*/ diff --git a/contrib/zip/.travis.sh b/contrib/zip/.travis.sh index 22974b1ff..9cb03ee87 100755 --- a/contrib/zip/.travis.sh +++ b/contrib/zip/.travis.sh @@ -15,4 +15,4 @@ else make -j 8 make install ASAN_OPTIONS=detect_leaks=0 LSAN_OPTIONS=verbosity=1:log_threads=1 ctest -V -fi \ No newline at end of file +fi diff --git a/contrib/zip/.travis.yml b/contrib/zip/.travis.yml index 86bac1cca..42f84dd25 100644 --- a/contrib/zip/.travis.yml +++ b/contrib/zip/.travis.yml @@ -19,4 +19,4 @@ after_success: - make - make test # Uploading report to CodeCov - - bash <(curl -s https://codecov.io/bash) \ No newline at end of file + - bash <(curl -s https://codecov.io/bash) diff --git a/contrib/zlib/contrib/blast/test.txt b/contrib/zlib/contrib/blast/test.txt index bfdf1c5dc..159002de5 100644 --- a/contrib/zlib/contrib/blast/test.txt +++ b/contrib/zlib/contrib/blast/test.txt @@ -1 +1 @@ -AIAIAIAIAIAIA \ No newline at end of file +AIAIAIAIAIAIA diff --git a/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt b/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt index 127a5bc39..36b7cd93c 100644 --- a/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt +++ b/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt @@ -20,4 +20,4 @@ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file +DEALINGS IN THE SOFTWARE. diff --git a/contrib/zlib/contrib/testzlib/testzlib.txt b/contrib/zlib/contrib/testzlib/testzlib.txt index e508bb22f..ba1bb3db6 100644 --- a/contrib/zlib/contrib/testzlib/testzlib.txt +++ b/contrib/zlib/contrib/testzlib/testzlib.txt @@ -7,4 +7,4 @@ copy to a directory file from : - contrib/masmx64 - contrib/vstudio/vc7 -and open testzlib8.sln \ No newline at end of file +and open testzlib8.sln diff --git a/contrib/zlib_note.txt b/contrib/zlib_note.txt index cc274f0bf..a7ca98634 100644 --- a/contrib/zlib_note.txt +++ b/contrib/zlib_note.txt @@ -8,4 +8,4 @@ This is a heavily modified and shrinked version of zlib 1.2.3 Assimp itself does not use the compression part yet, so it needn't be compiled (trees.c, deflate.c, compress.c). -Currently these units are just used by assimp_cmd. \ No newline at end of file +Currently these units are just used by assimp_cmd. diff --git a/doc/architecture/Assimp_Arch_Import.class.violet.html b/doc/architecture/Assimp_Arch_Import.class.violet.html index 264468f98..b4e3a9a6e 100644 --- a/doc/architecture/Assimp_Arch_Import.class.violet.html +++ b/doc/architecture/Assimp_Arch_Import.class.violet.html @@ -351,4 +351,4 @@ BI8AxOURXedNEuG6jMiRPHKQsuuS4BGAuDzS0NCQlZV18JFlRI7qkRRdlwSPAHzCIynKaa5LgkcA ETwCgEfwCAAewSMAeASP4BEAPIJHAPAIHgFItrEBsYNHAD7BK4gZPAKAR/AIAB7BIwCQBvwfU/j0 jy2hMWgAAAAASUVORK5C" /> - \ No newline at end of file + diff --git a/doc/architecture/Assimp_Arch_export.class.violet.html b/doc/architecture/Assimp_Arch_export.class.violet.html index 85f68d68d..ee567caaa 100644 --- a/doc/architecture/Assimp_Arch_export.class.violet.html +++ b/doc/architecture/Assimp_Arch_export.class.violet.html @@ -645,4 +645,4 @@ tQ2gtkFtg9oGQG2jtkFtA6C2UduA2gZQ26C2QW0DoLZR26C2AVDbqG1AbQMoKg8CahvUNgBqG7UN ahsAtY3aBtQ2AGobtQ1qGwC1jdoGtQ2A2kZtA2obALWN2ga1DUA1igr2o7ZBbQPw0/wD+/DsALUN gNpGbYPaBkBto7ZBbQMAAD/R/wDNluGGIxSgmAAAAABJRU5ErkJg" /> - \ No newline at end of file + diff --git a/doc/architecture/assimp.object.violet.html b/doc/architecture/assimp.object.violet.html index 1d82fa05f..dee9d2208 100644 --- a/doc/architecture/assimp.object.violet.html +++ b/doc/architecture/assimp.object.violet.html @@ -104,4 +104,4 @@ tfMWuhaZfgHUw0Q32sDAwIcPH4I/C1fbaJVKRX0GBwft4RA5hXdkNepJqndpKD2R7TlrjeqmxkKh oLOf5O8VrfC7XlrtOvYCO77PYocddthhhx122GGHHXbYYYcddthhhx122GGHHXbYYYdd29q1c83s I9m5B21Yuxg77FJtRzQV/wEjVLA5JUDyfgAAAABJRU5ErkJg" /> - \ No newline at end of file + diff --git a/doc/architecture/assimp_usecase.ucase.violet.html b/doc/architecture/assimp_usecase.ucase.violet.html index 3045add42..c4df02533 100644 --- a/doc/architecture/assimp_usecase.ucase.violet.html +++ b/doc/architecture/assimp_usecase.ucase.violet.html @@ -872,4 +872,4 @@ DYMQQgghNAxCCCGEEBoGIYQQQmgYhBBCCKFhEEIIIYTQMAghhBBCwyCEEEIIDYMQQgghNAxCCCGE EBoGIYQQQmgYhBBCCKFhEEIIIYTQMAghhBBCwyCEEEJI/PP/A0zci3P89Qf2AAAAAElFTkSuQmCC " /> - \ No newline at end of file + diff --git a/doc/architecture/process.class.violet.html b/doc/architecture/process.class.violet.html index d4f77d909..662daf4a8 100644 --- a/doc/architecture/process.class.violet.html +++ b/doc/architecture/process.class.violet.html @@ -334,4 +334,4 @@ CQCsyZpgTQCsyZpgTQCsyZpgTQCsyZpgTQCsCdZkTQBgTdZkTQBgTdZkTQBgTdYEawJgTdYEawJg TdYEawJgTbAmawIAa7ImawIAa7ImawIAa7ImWBMAa7ImWBMAa7ImWBPAvDIByoc1WRMA/uU3lI1q YU0ArAnWZE0AYE3WZE0AABY4/wVVY1WTrOVxIAAAAABJRU5ErkJg" /> - \ No newline at end of file + diff --git a/include/assimp/scene.h b/include/assimp/scene.h index 93d04eee6..a189f5700 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -1,4 +1,4 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- diff --git a/packaging/windows-innosetup/WEB b/packaging/windows-innosetup/WEB index 8840d232d..d14d6ed9a 100644 --- a/packaging/windows-innosetup/WEB +++ b/packaging/windows-innosetup/WEB @@ -1,8 +1,6 @@ - -Project home page: -http://assimp.sourceforge.net - -Sourceforge.net project page: -http://www.sourceforge.net/projects/assimp - - + +Project home page: +http://assimp.sourceforge.net + +Sourceforge.net project page: +http://www.sourceforge.net/projects/assimp diff --git a/packaging/windows-innosetup/readme_installer_vieweronly.txt b/packaging/windows-innosetup/readme_installer_vieweronly.txt index bfa4f8c9e..1e84c577d 100644 --- a/packaging/windows-innosetup/readme_installer_vieweronly.txt +++ b/packaging/windows-innosetup/readme_installer_vieweronly.txt @@ -29,4 +29,4 @@ Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending o Add it to PATH. That's not a bug, the installer does not alter the PATH. 4. Crashes immediately -You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. \ No newline at end of file +You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. diff --git a/packaging/windows-mkzip/bin_readme.txt b/packaging/windows-mkzip/bin_readme.txt index 10839a3d9..5cff1f30e 100644 --- a/packaging/windows-mkzip/bin_readme.txt +++ b/packaging/windows-mkzip/bin_readme.txt @@ -26,4 +26,4 @@ Install the latest DirectX runtime or grab the file from somewhere (that's evil (Re)install Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) 3. Crashes immediately -You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. \ No newline at end of file +You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. diff --git a/port/PyAssimp/pyassimp/errors.py b/port/PyAssimp/pyassimp/errors.py index 9d776860f..e017b5145 100644 --- a/port/PyAssimp/pyassimp/errors.py +++ b/port/PyAssimp/pyassimp/errors.py @@ -1,11 +1,11 @@ -#-*- coding: UTF-8 -*- - -""" -All possible errors. -""" - -class AssimpError(BaseException): - """ - If an internal error occurs. - """ - pass \ No newline at end of file +#-*- coding: UTF-8 -*- + +""" +All possible errors. +""" + +class AssimpError(BaseException): + """ + If an internal error occurs. + """ + pass diff --git a/port/jassimp/jassimp/src/jassimp/AiAnimation.java b/port/jassimp/jassimp/src/jassimp/AiAnimation.java index 239820aaf..856b918dd 100644 --- a/port/jassimp/jassimp/src/jassimp/AiAnimation.java +++ b/port/jassimp/jassimp/src/jassimp/AiAnimation.java @@ -172,4 +172,4 @@ public final class AiAnimation { public List getMeshChannels() { throw new UnsupportedOperationException("not implemented yet"); } -} \ No newline at end of file +} diff --git a/port/jassimp/jassimp/src/jassimp/AiBlendMode.java b/port/jassimp/jassimp/src/jassimp/AiBlendMode.java index 78cc5a5ed..d3a0e0e96 100644 --- a/port/jassimp/jassimp/src/jassimp/AiBlendMode.java +++ b/port/jassimp/jassimp/src/jassimp/AiBlendMode.java @@ -114,4 +114,4 @@ public enum AiBlendMode { * The mapped c/c++ integer enum value. */ private final int m_rawValue; -} \ No newline at end of file +} diff --git a/port/jassimp/jassimp/src/jassimp/AiCamera.java b/port/jassimp/jassimp/src/jassimp/AiCamera.java index 4445c34fc..b0f692eda 100644 --- a/port/jassimp/jassimp/src/jassimp/AiCamera.java +++ b/port/jassimp/jassimp/src/jassimp/AiCamera.java @@ -300,4 +300,4 @@ public final class AiCamera { * Aspect ratio. */ private final float m_aspect; -} \ No newline at end of file +} diff --git a/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java b/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java index 7998d1bcc..2987e5976 100644 --- a/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java +++ b/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java @@ -43,4 +43,4 @@ package jassimp; public interface AiProgressHandler { boolean update(float percentage); -} \ No newline at end of file +} diff --git a/port/jassimp/jassimp/src/jassimp/AiQuaternion.java b/port/jassimp/jassimp/src/jassimp/AiQuaternion.java index af10e6f91..a9ca7be79 100644 --- a/port/jassimp/jassimp/src/jassimp/AiQuaternion.java +++ b/port/jassimp/jassimp/src/jassimp/AiQuaternion.java @@ -162,4 +162,4 @@ public final class AiQuaternion { return "[" + getX() + ", " + getY() + ", " + getZ() + ", " + getW() + "]"; } -} \ No newline at end of file +} diff --git a/port/jassimp/jassimp/src/jassimp/AiTextureType.java b/port/jassimp/jassimp/src/jassimp/AiTextureType.java index 85b559c30..6b3e642e0 100644 --- a/port/jassimp/jassimp/src/jassimp/AiTextureType.java +++ b/port/jassimp/jassimp/src/jassimp/AiTextureType.java @@ -209,4 +209,4 @@ public enum AiTextureType { * The mapped c/c++ integer enum value. */ private final int m_rawValue; -} \ No newline at end of file +} diff --git a/port/swig/DONOTUSEYET b/port/swig/DONOTUSEYET index be9103007..87c6e0699 100644 --- a/port/swig/DONOTUSEYET +++ b/port/swig/DONOTUSEYET @@ -1 +1 @@ -The interface files are by no means complete yet and only work with the not-yet-released D SWIG backend, although adding support for other languages should not be too much of problem via #ifdefs. +The interface files are by no means complete yet and only work with the not-yet-released D SWIG backend, although adding support for other languages should not be too much of problem via #ifdefs. diff --git a/samples/SimpleAssimpViewX/README b/samples/SimpleAssimpViewX/README index 701a7cdce..dc513d7aa 100644 --- a/samples/SimpleAssimpViewX/README +++ b/samples/SimpleAssimpViewX/README @@ -19,4 +19,4 @@ Troubleshooting: - OSX workspaces are not updated too frequently, so same files may be missing. If you have any problems which you can't solve on your own, -please report them on the thread above. \ No newline at end of file +please report them on the thread above. diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp index 781fe89e5..3aad81838 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- // Simple Assimp Directx11 Sample // This is a very basic sample and only reads diffuse texture // but this can load both embedded textures in fbx and non-embedded textures diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/include/boost_includes.h b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/include/boost_includes.h index 7b9c0860e..2ff6aff04 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/include/boost_includes.h +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/include/boost_includes.h @@ -1 +1 @@ -#include \ No newline at end of file +#include diff --git a/test/models-nonbsd/3DS/jeep1.3ds.readme.txt b/test/models-nonbsd/3DS/jeep1.3ds.readme.txt index d17d5e0e9..f52ada0cc 100644 --- a/test/models-nonbsd/3DS/jeep1.3ds.readme.txt +++ b/test/models-nonbsd/3DS/jeep1.3ds.readme.txt @@ -12,4 +12,4 @@ http://xu1productions.com/3dstudio/index.html - 3D Game Resources http://www.psionicdesign.com - My Main 2D/3D Digital Art site -Psionic 2002 \ No newline at end of file +Psionic 2002 diff --git a/test/models-nonbsd/3DS/pyramob.3ds.readme.txt b/test/models-nonbsd/3DS/pyramob.3ds.readme.txt index bf1858410..2bf93aa64 100644 --- a/test/models-nonbsd/3DS/pyramob.3ds.readme.txt +++ b/test/models-nonbsd/3DS/pyramob.3ds.readme.txt @@ -9,4 +9,4 @@ http://www.elektrobar.com/lux/ or mail to: lux@elektrobar.com -have fun.....VIRLUX \ No newline at end of file +have fun.....VIRLUX diff --git a/test/models-nonbsd/ASE/Rifle.source.txt b/test/models-nonbsd/ASE/Rifle.source.txt index 04d40a85d..1b96f8564 100644 --- a/test/models-nonbsd/ASE/Rifle.source.txt +++ b/test/models-nonbsd/ASE/Rifle.source.txt @@ -22,4 +22,4 @@ tutorials. INFO ==== -CONVERTED FROM 3DS TO ASE WITH AC3D \ No newline at end of file +CONVERTED FROM 3DS TO ASE WITH AC3D diff --git a/test/models-nonbsd/ASE/Rifle2.source.txt b/test/models-nonbsd/ASE/Rifle2.source.txt index 2072ddf13..3fa628db4 100644 --- a/test/models-nonbsd/ASE/Rifle2.source.txt +++ b/test/models-nonbsd/ASE/Rifle2.source.txt @@ -21,4 +21,4 @@ tutorials. INFO ==== -CONVERTED FROM 3DS TO ASE WITH AC3D \ No newline at end of file +CONVERTED FROM 3DS TO ASE WITH AC3D diff --git a/test/models-nonbsd/B3D/turtle.source.txt b/test/models-nonbsd/B3D/turtle.source.txt index fab387bdc..cd93aa3d6 100644 --- a/test/models-nonbsd/B3D/turtle.source.txt +++ b/test/models-nonbsd/B3D/turtle.source.txt @@ -8,4 +8,4 @@ RESTRICTIONS: This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- **You may not sell/re-sell this model pack or claim it as your own. -***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. \ No newline at end of file +***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. diff --git a/test/models-nonbsd/DXF/rifle.source.txt b/test/models-nonbsd/DXF/rifle.source.txt index 3e88f009f..a2585afad 100644 --- a/test/models-nonbsd/DXF/rifle.source.txt +++ b/test/models-nonbsd/DXF/rifle.source.txt @@ -20,4 +20,4 @@ tutorials. INFO ==== -COnverted from 3ds to DXF with Ac3D \ No newline at end of file +COnverted from 3ds to DXF with Ac3D diff --git a/test/models-nonbsd/FBX/2013_ASCII/jeep1.fbx.readme.txt b/test/models-nonbsd/FBX/2013_ASCII/jeep1.fbx.readme.txt index d17d5e0e9..f52ada0cc 100644 --- a/test/models-nonbsd/FBX/2013_ASCII/jeep1.fbx.readme.txt +++ b/test/models-nonbsd/FBX/2013_ASCII/jeep1.fbx.readme.txt @@ -12,4 +12,4 @@ http://xu1productions.com/3dstudio/index.html - 3D Game Resources http://www.psionicdesign.com - My Main 2D/3D Digital Art site -Psionic 2002 \ No newline at end of file +Psionic 2002 diff --git a/test/models-nonbsd/FBX/2013_ASCII/pyramob.fbx.readme.txt b/test/models-nonbsd/FBX/2013_ASCII/pyramob.fbx.readme.txt index bf1858410..2bf93aa64 100644 --- a/test/models-nonbsd/FBX/2013_ASCII/pyramob.fbx.readme.txt +++ b/test/models-nonbsd/FBX/2013_ASCII/pyramob.fbx.readme.txt @@ -9,4 +9,4 @@ http://www.elektrobar.com/lux/ or mail to: lux@elektrobar.com -have fun.....VIRLUX \ No newline at end of file +have fun.....VIRLUX diff --git a/test/models-nonbsd/FBX/2013_BINARY/jeep1.fbx.readme.txt b/test/models-nonbsd/FBX/2013_BINARY/jeep1.fbx.readme.txt index d17d5e0e9..f52ada0cc 100644 --- a/test/models-nonbsd/FBX/2013_BINARY/jeep1.fbx.readme.txt +++ b/test/models-nonbsd/FBX/2013_BINARY/jeep1.fbx.readme.txt @@ -12,4 +12,4 @@ http://xu1productions.com/3dstudio/index.html - 3D Game Resources http://www.psionicdesign.com - My Main 2D/3D Digital Art site -Psionic 2002 \ No newline at end of file +Psionic 2002 diff --git a/test/models-nonbsd/FBX/2013_BINARY/pyramob.fbx.readme.txt b/test/models-nonbsd/FBX/2013_BINARY/pyramob.fbx.readme.txt index bf1858410..2bf93aa64 100644 --- a/test/models-nonbsd/FBX/2013_BINARY/pyramob.fbx.readme.txt +++ b/test/models-nonbsd/FBX/2013_BINARY/pyramob.fbx.readme.txt @@ -9,4 +9,4 @@ http://www.elektrobar.com/lux/ or mail to: lux@elektrobar.com -have fun.....VIRLUX \ No newline at end of file +have fun.....VIRLUX diff --git a/test/models-nonbsd/IFC/linklist.txt b/test/models-nonbsd/IFC/linklist.txt index 06ad3844b..6971b7a45 100644 --- a/test/models-nonbsd/IFC/linklist.txt +++ b/test/models-nonbsd/IFC/linklist.txt @@ -1,4 +1,4 @@ Good IFC test cases =================== -http://www.iai.fzk.de/www-extern/index.php?id=1135 \ No newline at end of file +http://www.iai.fzk.de/www-extern/index.php?id=1135 diff --git a/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt b/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt index bb07f8e24..aaa244217 100644 --- a/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt +++ b/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt @@ -28,4 +28,4 @@ INFO These files belong to the QuickDraw model in the LWS folder - they are referenced -and loaded into the LWS scene. \ No newline at end of file +and loaded into the LWS scene. diff --git a/test/models-nonbsd/LWO/LWO2/rifle.source.txt b/test/models-nonbsd/LWO/LWO2/rifle.source.txt index 34576f0ca..5523bbc0c 100644 --- a/test/models-nonbsd/LWO/LWO2/rifle.source.txt +++ b/test/models-nonbsd/LWO/LWO2/rifle.source.txt @@ -21,4 +21,4 @@ tutorials. INFO ==== -CONVERTED FROM 3DS TO LWO2 WITH AC3D \ No newline at end of file +CONVERTED FROM 3DS TO LWO2 WITH AC3D diff --git a/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt b/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt index e0c7d0f7c..92ac5d882 100644 --- a/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt +++ b/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt @@ -12,4 +12,4 @@ In the future more 3d formats will be added and some other sections such as wall CHANGES: -Paths have been modified \ No newline at end of file +Paths have been modified diff --git a/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt b/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt index e0a978ee0..54fbcbd7f 100644 --- a/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt +++ b/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt @@ -23,4 +23,4 @@ ID software, eskimo roll, EMSIPE, QkenneyQ DISTRIBUTION as long as this readme is included...! --------------------------------------------------------------------------- \ No newline at end of file +-------------------------------------------------------------------------- diff --git a/test/models-nonbsd/MD3/readme_water.txt b/test/models-nonbsd/MD3/readme_water.txt index cdc318ff8..c5346261d 100644 --- a/test/models-nonbsd/MD3/readme_water.txt +++ b/test/models-nonbsd/MD3/readme_water.txt @@ -23,4 +23,4 @@ ID software, eskimo roll, EMSIPE, QkenneyQ DISTRIBUTION as long as this readme is included...! --------------------------------------------------------------------------- \ No newline at end of file +-------------------------------------------------------------------------- diff --git a/test/models-nonbsd/MMD/readme.txt b/test/models-nonbsd/MMD/readme.txt index d8c882420..909beee00 100644 --- a/test/models-nonbsd/MMD/readme.txt +++ b/test/models-nonbsd/MMD/readme.txt @@ -46,4 +46,4 @@ version 4 ◯ クレジット 企画: 株式会社ドワンゴ キャラクターデザイン: 黒星紅白 -モデリング: 雨刻 \ No newline at end of file +モデリング: 雨刻 diff --git a/test/models-nonbsd/NFF/NFFSense8/credits.txt b/test/models-nonbsd/NFF/NFFSense8/credits.txt index ff169151d..f3cef4d09 100644 --- a/test/models-nonbsd/NFF/NFFSense8/credits.txt +++ b/test/models-nonbsd/NFF/NFFSense8/credits.txt @@ -1,4 +1,4 @@ teapot.nff, home4.nff - http://www.martinreddy.net/ukvrsig/wtk.html cokecan.nff -www.vrupl.evl.uic.edu/Eng591_Pages/cokecan.nff -TODO: License status to be confirmed \ No newline at end of file +TODO: License status to be confirmed diff --git a/test/models-nonbsd/OBJ/rifle.source.txt b/test/models-nonbsd/OBJ/rifle.source.txt index b09dcda8c..1d2cec5cf 100644 --- a/test/models-nonbsd/OBJ/rifle.source.txt +++ b/test/models-nonbsd/OBJ/rifle.source.txt @@ -24,4 +24,4 @@ tutorials. INFO ==== -Converted from 3DS to OBJ with AC3D \ No newline at end of file +Converted from 3DS to OBJ with AC3D diff --git a/test/models-nonbsd/OBJ/segment.source.txt b/test/models-nonbsd/OBJ/segment.source.txt index 978d72d26..204bc140e 100644 --- a/test/models-nonbsd/OBJ/segment.source.txt +++ b/test/models-nonbsd/OBJ/segment.source.txt @@ -1,4 +1,4 @@ Obj exported from Blender http://toychest.in.tum.de/wiki/projects:kuka_lwr -License: Creative-Commons-by-Attribution-3.0 \ No newline at end of file +License: Creative-Commons-by-Attribution-3.0 diff --git a/test/models-nonbsd/Ogre/OgreSDK/LICENSE b/test/models-nonbsd/Ogre/OgreSDK/LICENSE index e7e8f4280..ccdfb00fa 100644 --- a/test/models-nonbsd/Ogre/OgreSDK/LICENSE +++ b/test/models-nonbsd/Ogre/OgreSDK/LICENSE @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/test/models-nonbsd/Ogre/OgreSDK/README.md b/test/models-nonbsd/Ogre/OgreSDK/README.md index e7a838cb0..864536558 100644 --- a/test/models-nonbsd/Ogre/OgreSDK/README.md +++ b/test/models-nonbsd/Ogre/OgreSDK/README.md @@ -7,4 +7,4 @@ This asset set is used to test the full functionality of both binary and XML Ass * Material file was created by copying the relevant material parts from the sample sources. See the file for further information. * Some textures were converted from .png to .jpg to reduce the file size. -See the LICENSE file in this folder for further copyright information about these assets. \ No newline at end of file +See the LICENSE file in this folder for further copyright information about these assets. diff --git a/test/models-nonbsd/README.txt b/test/models-nonbsd/README.txt index 8b244d2aa..aac170708 100644 --- a/test/models-nonbsd/README.txt +++ b/test/models-nonbsd/README.txt @@ -1,3 +1,3 @@ These models are not generally redistributable under the terms of Assimp's BSD license. Usually, an additional requirement on the use of the data is imposed (i.e. no commercial use, need credits, some creative commons variants, ...). -So, if you re-package Assimp for use in a 'clean' OSS package, consider removing this directory. \ No newline at end of file +So, if you re-package Assimp for use in a 'clean' OSS package, consider removing this directory. diff --git a/test/models/3DS/UVTransformTest/note.txt b/test/models/3DS/UVTransformTest/note.txt index dc4bd0789..4c8bfedd2 100644 --- a/test/models/3DS/UVTransformTest/note.txt +++ b/test/models/3DS/UVTransformTest/note.txt @@ -8,4 +8,4 @@ In other words: TO DO, but only if someone REALLY needs it. To see how it should look like - test/ReferenceImages Note that the viewer has no 'decal' texture mapping mode, so -the usual clamping is used. \ No newline at end of file +the usual clamping is used. diff --git a/test/models/3DS/textures.txt b/test/models/3DS/textures.txt index 18bbd8f90..136322bea 100644 --- a/test/models/3DS/textures.txt +++ b/test/models/3DS/textures.txt @@ -1 +1 @@ -All textures are from cgtextures.com and are free for commercial use \ No newline at end of file +All textures are from cgtextures.com and are free for commercial use diff --git a/test/models/ASE/MotionCaptureROM.source.txt b/test/models/ASE/MotionCaptureROM.source.txt index 222a3afbb..2b961906a 100644 --- a/test/models/ASE/MotionCaptureROM.source.txt +++ b/test/models/ASE/MotionCaptureROM.source.txt @@ -1,3 +1,3 @@ "MotionCaptureROM.ase" - Free for any purpose. -NOTE: The errors in the middle of the animation are caused by problems during recording, it's not an importer issue. \ No newline at end of file +NOTE: The errors in the middle of the animation are caused by problems during recording, it's not an importer issue. diff --git a/test/models/BLEND/HUMAN.source.txt b/test/models/BLEND/HUMAN.source.txt index 9409b46d3..a19c52468 100644 --- a/test/models/BLEND/HUMAN.source.txt +++ b/test/models/BLEND/HUMAN.source.txt @@ -1,3 +1,3 @@ HUMAN.blend (c) 2010, Tobias Rittig -Redistribution and reuse allowed for any purpose, credits appreciated. \ No newline at end of file +Redistribution and reuse allowed for any purpose, credits appreciated. diff --git a/test/models/BVH/01_nn.bvh.source.txt b/test/models/BVH/01_nn.bvh.source.txt index e538020a2..fc450d15d 100644 --- a/test/models/BVH/01_nn.bvh.source.txt +++ b/test/models/BVH/01_nn.bvh.source.txt @@ -47,4 +47,4 @@ Here's the relevant paragraph from mocap.cs.cmu.edu: obtained from mocap.cs.cmu.edu. The database was created with funding from NSF EIA-0196217." -[...] \ No newline at end of file +[...] diff --git a/test/models/CSM/ThomasFechten.source.txt b/test/models/CSM/ThomasFechten.source.txt index 529560ced..cf60674d8 100644 --- a/test/models/CSM/ThomasFechten.source.txt +++ b/test/models/CSM/ThomasFechten.source.txt @@ -1 +1 @@ -Recorded with vicon IQ, july 2008. Free for any purpose. \ No newline at end of file +Recorded with vicon IQ, july 2008. Free for any purpose. diff --git a/test/models/IRRMesh/credits.txt b/test/models/IRRMesh/credits.txt index a12163233..504746814 100644 --- a/test/models/IRRMesh/credits.txt +++ b/test/models/IRRMesh/credits.txt @@ -1,2 +1,2 @@ cellar.irrmesh - From irrlight/irrEdit. Irrlicht/irredit license (which?) -Textures resized to 400*400, improved JPEG compression to make them smaller \ No newline at end of file +Textures resized to 400*400, improved JPEG compression to make them smaller diff --git a/test/models/LWO/LWO2/MappingModes/earthCylindric.txt b/test/models/LWO/LWO2/MappingModes/earthCylindric.txt index 46660a486..18ea94ea2 100644 --- a/test/models/LWO/LWO2/MappingModes/earthCylindric.txt +++ b/test/models/LWO/LWO2/MappingModes/earthCylindric.txt @@ -2,4 +2,4 @@ Wikipedia Commons, downloaded November 25th 08 -http://upload.wikimedia.org/wikipedia/commons/0/01/Lambert-cylindrical-equal-area-projection.jpg \ No newline at end of file +http://upload.wikimedia.org/wikipedia/commons/0/01/Lambert-cylindrical-equal-area-projection.jpg diff --git a/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt b/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt index 218b339e1..db055ea0f 100644 --- a/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt +++ b/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt @@ -6,4 +6,4 @@ http://earthobservatory.nasa.gov/Features/BlueMarble/BlueMarble_monthlies.php Downloaded November 24, 08. -Rescaled to 2048 * 1024 with GIMP \ No newline at end of file +Rescaled to 2048 * 1024 with GIMP diff --git a/test/models/LWO/LWO2/concrete.source.txt b/test/models/LWO/LWO2/concrete.source.txt index 2904ae998..90fc73e2d 100644 --- a/test/models/LWO/LWO2/concrete.source.txt +++ b/test/models/LWO/LWO2/concrete.source.txt @@ -1,2 +1,2 @@ cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for more details. -Great source for free textures, btw! \ No newline at end of file +Great source for free textures, btw! diff --git a/test/models/LWO/LWO2/uvtest-source.txt b/test/models/LWO/LWO2/uvtest-source.txt index 75e4878a7..654d62180 100644 --- a/test/models/LWO/LWO2/uvtest-source.txt +++ b/test/models/LWO/LWO2/uvtest-source.txt @@ -1,2 +1,2 @@ Regression file. -by Tom Speed, see http://groups.google.com/group/bmx3d/browse_thread/thread/36db3b191f81be36 \ No newline at end of file +by Tom Speed, see http://groups.google.com/group/bmx3d/browse_thread/thread/36db3b191f81be36 diff --git a/test/models/MD2/faerie-source.txt b/test/models/MD2/faerie-source.txt index ef0e4f196..4906ff4d1 100644 --- a/test/models/MD2/faerie-source.txt +++ b/test/models/MD2/faerie-source.txt @@ -21,4 +21,4 @@ The Irrlicht Engine License appreciated but is not required. 2. Altered source versions must be clearly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. \ No newline at end of file + 3. This notice may not be removed or altered from any source distribution. diff --git a/test/models/MD2/sidney-source.txt b/test/models/MD2/sidney-source.txt index ef0e4f196..4906ff4d1 100644 --- a/test/models/MD2/sidney-source.txt +++ b/test/models/MD2/sidney-source.txt @@ -21,4 +21,4 @@ The Irrlicht Engine License appreciated but is not required. 2. Altered source versions must be clearly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. \ No newline at end of file + 3. This notice may not be removed or altered from any source distribution. diff --git a/test/models/MD5/SimpleCube.source.txt b/test/models/MD5/SimpleCube.source.txt index 6f51bc1cf..77d151ed7 100644 --- a/test/models/MD5/SimpleCube.source.txt +++ b/test/models/MD5/SimpleCube.source.txt @@ -1 +1 @@ -From http://www.doom3world.org/phpbb2/viewtopic.php?f=3&t=16842 (thanks, Rayne, whoever you are) \ No newline at end of file +From http://www.doom3world.org/phpbb2/viewtopic.php?f=3&t=16842 (thanks, Rayne, whoever you are) diff --git a/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt b/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt index c2ca7c696..4d36f8cbb 100644 --- a/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt +++ b/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt @@ -3,4 +3,4 @@ Hi everybody!!! This is my first published model so it isn't very good,but i'm still learning!.. This model is free for everybody,but credit will be nice! You may reach me at rojkov91@mail.ru -P.S: Excuse my bad english \ No newline at end of file +P.S: Excuse my bad english diff --git a/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt b/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt index c2ca7c696..4d36f8cbb 100644 --- a/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt +++ b/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt @@ -3,4 +3,4 @@ Hi everybody!!! This is my first published model so it isn't very good,but i'm still learning!.. This model is free for everybody,but credit will be nice! You may reach me at rojkov91@mail.ru -P.S: Excuse my bad english \ No newline at end of file +P.S: Excuse my bad english diff --git a/test/models/MS3D/jeep1.readme.txt b/test/models/MS3D/jeep1.readme.txt index d17d5e0e9..f52ada0cc 100644 --- a/test/models/MS3D/jeep1.readme.txt +++ b/test/models/MS3D/jeep1.readme.txt @@ -12,4 +12,4 @@ http://xu1productions.com/3dstudio/index.html - 3D Game Resources http://www.psionicdesign.com - My Main 2D/3D Digital Art site -Psionic 2002 \ No newline at end of file +Psionic 2002 diff --git a/test/models/Q3D/E-AT-AT.source.txt b/test/models/Q3D/E-AT-AT.source.txt index 56a96f7d5..2df8826f1 100644 --- a/test/models/Q3D/E-AT-AT.source.txt +++ b/test/models/Q3D/E-AT-AT.source.txt @@ -5,4 +5,4 @@ Downloaded 4th November 08 (Obama ftw!) Copyright notice found on the page: Where do the models in the archive come from? -All 3D files available from the3darchive.com are from the public domain. \ No newline at end of file +All 3D files available from the3darchive.com are from the public domain. diff --git a/test/models/Q3D/earth.source.txt b/test/models/Q3D/earth.source.txt index 56a96f7d5..2df8826f1 100644 --- a/test/models/Q3D/earth.source.txt +++ b/test/models/Q3D/earth.source.txt @@ -5,4 +5,4 @@ Downloaded 4th November 08 (Obama ftw!) Copyright notice found on the page: Where do the models in the archive come from? -All 3D files available from the3darchive.com are from the public domain. \ No newline at end of file +All 3D files available from the3darchive.com are from the public domain. diff --git a/test/models/X/BCN_Epileptic.txt b/test/models/X/BCN_Epileptic.txt index 1538e59fb..398d21b86 100644 --- a/test/models/X/BCN_Epileptic.txt +++ b/test/models/X/BCN_Epileptic.txt @@ -1 +1 @@ -A human body separated into three meshes: lower body, upper body, head. A common bone hierarchy for all three meshes, plus an test animation that makes the body sort of jump. No material information exported. \ No newline at end of file +A human body separated into three meshes: lower body, upper body, head. A common bone hierarchy for all three meshes, plus an test animation that makes the body sort of jump. No material information exported. diff --git a/test/models/X/anim_test.txt b/test/models/X/anim_test.txt index 637ea0581..3d270dc7d 100644 --- a/test/models/X/anim_test.txt +++ b/test/models/X/anim_test.txt @@ -6,4 +6,4 @@ Frame 18 - 24: Zylinder-Spitze bewegt sich zu Position in Richtung x+ Remarks: The exporter failed here for some reasons... although the mesh referres to four bones, only two of them are stored in the corresponding node hierarchy. So you have a mesh with 4 bones, a hirarchy with 2 nodes and a animation that affects only those two nodes. -There is no timing given for the animation. You have to scale the animation manually. For this file, the timing seems to be 24 ticks per second. \ No newline at end of file +There is no timing given for the animation. You have to scale the animation manually. For this file, the timing seems to be 24 ticks per second. diff --git a/test/models/X/test.txt b/test/models/X/test.txt index 7a5e8e74b..eaf9d9c3c 100644 --- a/test/models/X/test.txt +++ b/test/models/X/test.txt @@ -1,3 +1,3 @@ Simple textured test cube exported from Maya. Has a texture that does label each cube side uniquely, but the sides do not match DirectX coordinate space. -Is not readable using D3DXLoadFrameHierarchy, needs custom text parsing. \ No newline at end of file +Is not readable using D3DXLoadFrameHierarchy, needs custom text parsing. diff --git a/test/regression/result_checker.py b/test/regression/result_checker.py index 19772f8af..1b01c52e6 100644 --- a/test/regression/result_checker.py +++ b/test/regression/result_checker.py @@ -110,4 +110,4 @@ def run(): if __name__ == "__main__": sys.exit(run()) -# vim: ai ts=4 sts=4 et sw=4 \ No newline at end of file +# vim: ai ts=4 sts=4 et sw=4 diff --git a/test/unit/utImproveCacheLocality.cpp b/test/unit/utImproveCacheLocality.cpp index 66ce0d6d8..803562dd2 100644 --- a/test/unit/utImproveCacheLocality.cpp +++ b/test/unit/utImproveCacheLocality.cpp @@ -41,4 +41,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -#include "UnitTestPCH.h" \ No newline at end of file +#include "UnitTestPCH.h" diff --git a/tools/assimp_view/Background.cpp b/tools/assimp_view/Background.cpp index e5f4e2b96..33bb81f2e 100644 --- a/tools/assimp_view/Background.cpp +++ b/tools/assimp_view/Background.cpp @@ -468,4 +468,4 @@ void CBackgroundPainter::RecreateNativeResource() piSkyBoxEffect->SetTechnique("RenderImage2D"); } } -}; \ No newline at end of file +}; diff --git a/tools/assimp_view/Camera.h b/tools/assimp_view/Camera.h index dd82af029..9c3103827 100644 --- a/tools/assimp_view/Camera.h +++ b/tools/assimp_view/Camera.h @@ -82,4 +82,4 @@ class Camera } ; -#endif // !!IG \ No newline at end of file +#endif // !!IG diff --git a/tools/assimp_view/Display.h b/tools/assimp_view/Display.h index f52e65e42..1ca29f498 100644 --- a/tools/assimp_view/Display.h +++ b/tools/assimp_view/Display.h @@ -539,4 +539,4 @@ namespace AssimpView }; } -#endif // AV_DISPLAY_H_INCLUDE \ No newline at end of file +#endif // AV_DISPLAY_H_INCLUDE diff --git a/tools/assimp_view/Input.cpp b/tools/assimp_view/Input.cpp index 505433404..f9f463412 100644 --- a/tools/assimp_view/Input.cpp +++ b/tools/assimp_view/Input.cpp @@ -369,4 +369,4 @@ void HandleKeyboardInputTextureView( void ) if( keys[VK_RIGHT] & 0x80 ) CDisplay::Instance().SetTextureViewOffsetX ( -g_fElpasedTime * 150.0f ); } -}; \ No newline at end of file +}; diff --git a/tools/assimp_view/LogWindow.h b/tools/assimp_view/LogWindow.h index 671d8be8f..5b2a3d2d3 100644 --- a/tools/assimp_view/LogWindow.h +++ b/tools/assimp_view/LogWindow.h @@ -130,4 +130,4 @@ namespace AssimpView } -#endif // AV_LOG_DISPLA \ No newline at end of file +#endif // AV_LOG_DISPLA diff --git a/tools/assimp_view/MeshRenderer.cpp b/tools/assimp_view/MeshRenderer.cpp index 27bc6704f..d93bb4aea 100644 --- a/tools/assimp_view/MeshRenderer.cpp +++ b/tools/assimp_view/MeshRenderer.cpp @@ -161,4 +161,4 @@ int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld) { return 1; } -}; \ No newline at end of file +}; diff --git a/tools/assimp_view/MeshRenderer.h b/tools/assimp_view/MeshRenderer.h index 38cfa6326..d756a9984 100644 --- a/tools/assimp_view/MeshRenderer.h +++ b/tools/assimp_view/MeshRenderer.h @@ -96,4 +96,4 @@ namespace AssimpView { }; } -#endif //!! include guard \ No newline at end of file +#endif //!! include guard diff --git a/tools/assimp_view/NOTE@help.rtf.txt b/tools/assimp_view/NOTE@help.rtf.txt index f00962db6..dd20078e9 100644 --- a/tools/assimp_view/NOTE@help.rtf.txt +++ b/tools/assimp_view/NOTE@help.rtf.txt @@ -1,2 +1,2 @@ text1.bin is the corresponding bin file to be included with the executable file. -When updating the rich formatted text inside Visual Studio, a terminating 0 character must be appended \ No newline at end of file +When updating the rich formatted text inside Visual Studio, a terminating 0 character must be appended diff --git a/tools/assimp_view/RenderOptions.h b/tools/assimp_view/RenderOptions.h index bd9e8a871..69297419e 100644 --- a/tools/assimp_view/RenderOptions.h +++ b/tools/assimp_view/RenderOptions.h @@ -110,4 +110,4 @@ class RenderOptions bool bCulling,bSkeleton; }; -#endif // !! IG \ No newline at end of file +#endif // !! IG diff --git a/tools/assimp_view/SceneAnimator.h b/tools/assimp_view/SceneAnimator.h index 956edb3e3..82f3616c5 100644 --- a/tools/assimp_view/SceneAnimator.h +++ b/tools/assimp_view/SceneAnimator.h @@ -246,4 +246,4 @@ protected: } // end of namespace AssimpView -#endif // AV_SCENEANIMATOR_H_INCLUDED \ No newline at end of file +#endif // AV_SCENEANIMATOR_H_INCLUDED diff --git a/tools/assimp_view/Shaders.cpp b/tools/assimp_view/Shaders.cpp index f129b7cc6..9d80ac227 100644 --- a/tools/assimp_view/Shaders.cpp +++ b/tools/assimp_view/Shaders.cpp @@ -1407,4 +1407,4 @@ std::string g_szCheckerBackgroundShader = std::string( "}\n" "};\n" ); - }; \ No newline at end of file + }; diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 3c519bb92..6b00f7f8c 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -279,4 +279,4 @@ enum EClickPos extern bool nopointslines; } -#endif // !! AV_MAIN_H_INCLUDED \ No newline at end of file +#endif // !! AV_MAIN_H_INCLUDED From 5e93b9ea8b7750e024d05d3991730ef04104a68d Mon Sep 17 00:00:00 2001 From: Alexey Medvedev Date: Mon, 30 Mar 2020 12:42:32 -0700 Subject: [PATCH 002/119] Fixed bone splitting with excessive amount of bones with 0 weight --- .../SplitByBoneCountProcess.cpp | 48 ++++++------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index ab7a1fe00..3ac0fe557 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -188,9 +189,6 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumFaces); // accumulated vertex count of all the faces in this submesh unsigned int numSubMeshVertices = 0; - // a small local array of new bones for the current face. State of all used bones for that face - // can only be updated AFTER the face is completely analysed. Thanks to imre for the fix. - std::vector newBonesAtCurrentFace; // add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit for( unsigned int a = 0; a < pMesh->mNumFaces; ++a) @@ -200,33 +198,21 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector newBonesAtCurrentFace; + const aiFace& face = pMesh->mFaces[a]; // check every vertex if its bones would still fit into the current submesh for( unsigned int b = 0; b < face.mNumIndices; ++b ) { - const std::vector& vb = vertexBones[face.mIndices[b]]; - for( unsigned int c = 0; c < vb.size(); ++c) - { - unsigned int boneIndex = vb[c].first; - // if the bone is already used in this submesh, it's ok - if( isBoneUsed[boneIndex] ) - { - continue; - } - - // if it's not used, yet, we would need to add it. Store its bone index - if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() ) - { - newBonesAtCurrentFace.push_back( boneIndex); - } - } + const std::vector& vb = vertexBones[face.mIndices[b]]; + for( unsigned int c = 0; c < vb.size(); ++c) + { + newBonesAtCurrentFace.insert(vb[c].first); + } } - if (newBonesAtCurrentFace.size() > mMaxBoneCount) - { - throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); - } // leave out the face if the new bones required for this face don't fit the bone count limit anymore if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount ) { @@ -234,17 +220,13 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector::iterator it = newBonesAtCurrentFace.begin(); it != newBonesAtCurrentFace.end(); ++it) { - unsigned int newIndex = newBonesAtCurrentFace.back(); - newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear() - if( isBoneUsed[newIndex] ) - { - continue; - } - - isBoneUsed[newIndex] = true; + if (!isBoneUsed[*it]) + { + isBoneUsed[*it] = true; numBones++; + } } // store the face index and the vertex count From 3ef46b0eddbfdcd914da75c06b299e494a093317 Mon Sep 17 00:00:00 2001 From: Alexey Medvedev Date: Mon, 30 Mar 2020 16:56:33 -0700 Subject: [PATCH 003/119] Weights and bones count checks --- code/PostProcessing/SplitByBoneCountProcess.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index 3ac0fe557..015ba9bf6 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -173,7 +173,15 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormBones[a]; for( unsigned int b = 0; b < bone->mNumWeights; ++b) { - vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight)); + if (bone->mWeights[b].mWeight > 0.0f) + { + int vertexId = bone->mWeights[b].mVertexId; + vertexBones[vertexId].push_back( BoneWeight( a, bone->mWeights[b].mWeight)); + if (vertexBones[vertexId].size() > mMaxBoneCount) + { + throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); + } + } } } From 87e2d3a54de9379675d0cf8899ebd1e2db750902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gy=C3=B6rgy=20Straub?= <> Date: Mon, 30 Mar 2020 14:30:33 +0100 Subject: [PATCH 004/119] Added support for glTF2 sparse accessors. Refactored Accessors, pulling out reusable bits between those and sparse accessors' indices / values. --- code/glTF2/glTF2Asset.h | 88 +++++++++++++++++++++++++++++--- code/glTF2/glTF2Asset.inl | 102 +++++++++++++++++++++++++++----------- 2 files changed, 154 insertions(+), 36 deletions(-) diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index c27522df3..1df87ace3 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -357,24 +357,46 @@ struct Object { // Classes for each glTF top-level object type // +//! Base class for types that access binary data from a BufferView, such as accessors +//! or sparse accessors' indices. +//! N.B. not a virtual class. All owned pointers to BufferViewClient instances should +//! be to their most derived types (which may of course be just BufferViewClient). +struct BufferViewClient : public Object { + Ref bufferView; //!< The ID of the bufferView. (required) + size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) + + inline uint8_t *GetPointer(); + + void Read(Value &obj, Asset &r); +}; + +//! BufferViewClient with component type information. +//! N.B. not a virtual class. All owned pointers to ComponentTypedBufferViewClient +//! instances should be to their most derived types (which may of course be just +//! ComponentTypedBufferViewClient). +struct ComponentTypedBufferViewClient : public BufferViewClient { + ComponentType componentType; //!< The datatype of components in the attribute. (required) + + unsigned int GetBytesPerComponent(); + + void Read(Value &obj, Asset &r); +}; + //! A typed view into a BufferView. A BufferView contains raw binary data. //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. -struct Accessor : public Object { - Ref bufferView; //!< The ID of the bufferView. (required) - size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) - ComponentType componentType; //!< The datatype of components in the attribute. (required) +struct Accessor : public ComponentTypedBufferViewClient { + struct Sparse; + size_t count; //!< The number of attributes referenced by this accessor. (required) AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. + std::unique_ptr sparse; //!< Sparse accessor information unsigned int GetNumComponents(); - unsigned int GetBytesPerComponent(); unsigned int GetElementSize(); - inline uint8_t *GetPointer(); - template bool ExtractData(T *&outData); @@ -405,11 +427,63 @@ struct Accessor : public Object { } }; + //! Sparse accessor information + struct Sparse { + size_t count; + ComponentTypedBufferViewClient indices; + BufferViewClient values; + + std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it. + + inline void PopulateData(size_t numBytes, uint8_t *bytes) { + if (bytes) { + data.assign(bytes, bytes + numBytes); + } else { + data.resize(numBytes, 0x00); + } + } + + inline void PatchData(unsigned int elementSize) + { + uint8_t *pIndices = indices.GetPointer(); + const unsigned int indexSize = indices.GetBytesPerComponent(); + uint8_t *indicesEnd = pIndices + count * indexSize; + + uint8_t *pValues = values.GetPointer(); + while (pIndices != indicesEnd) { + size_t offset; + switch (indices.componentType) { + case ComponentType_UNSIGNED_BYTE: + offset = *pIndices; + break; + case ComponentType_UNSIGNED_SHORT: + offset = *reinterpret_cast(pIndices); + break; + case ComponentType_UNSIGNED_INT: + offset = *reinterpret_cast(pIndices); + break; + default: + // have fun with float and negative values from signed types as indices. + throw DeadlyImportError("Unsupported component type in index."); + } + + offset *= elementSize; + std::memcpy(data.data() + offset, pValues, elementSize); + + pValues += elementSize; + pIndices += indexSize; + } + } + }; + inline Indexer GetIndexer() { return Indexer(*this); } Accessor() {} + + inline uint8_t *GetPointer(); + void Read(Value &obj, Asset &r); }; diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index f9c3aa805..79725bace 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -540,36 +540,10 @@ inline void BufferView::Read(Value &obj, Asset &r) { } // -// struct Accessor +// struct BufferViewClient // -inline void Accessor::Read(Value &obj, Asset &r) { - - if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { - bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); - } - - byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); - componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); - count = MemberOrDefault(obj, "count", size_t(0)); - - const char *typestr; - type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; -} - -inline unsigned int Accessor::GetNumComponents() { - return AttribType::GetNumComponents(type); -} - -inline unsigned int Accessor::GetBytesPerComponent() { - return int(ComponentTypeSize(componentType)); -} - -inline unsigned int Accessor::GetElementSize() { - return GetNumComponents() * GetBytesPerComponent(); -} - -inline uint8_t *Accessor::GetPointer() { +inline uint8_t *BufferViewClient::GetPointer() { if (!bufferView || !bufferView->buffer) return 0; uint8_t *basePtr = bufferView->buffer->GetPointer(); if (!basePtr) return 0; @@ -588,6 +562,76 @@ inline uint8_t *Accessor::GetPointer() { return basePtr + offset; } +inline void BufferViewClient::Read(Value &obj, Asset &r) { + + if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { + bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); +} + +// +// struct ComponentTypedBufferViewClient +// + +inline unsigned int ComponentTypedBufferViewClient::GetBytesPerComponent() { + return int(ComponentTypeSize(componentType)); +} + +inline void ComponentTypedBufferViewClient::Read(Value &obj, Asset &r) { + + BufferViewClient::Read(obj, r); + + componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); +} + +// +// struct Accessor +// + +inline uint8_t *Accessor::GetPointer() { + if (!sparse) return BufferViewClient::GetPointer(); + + return sparse->data.data(); +} + +inline void Accessor::Read(Value &obj, Asset &r) { + + ComponentTypedBufferViewClient::Read(obj, r); + + count = MemberOrDefault(obj, "count", size_t(0)); + + const char *typestr; + type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; + + if (Value *sparseValue = FindObject(obj, "sparse")) { + sparse.reset(new Sparse); + ReadMember(*sparseValue, "count", sparse->count); + + if (Value *indicesValue = FindObject(*sparseValue, "indices")) { + sparse->indices.Read(*indicesValue, r); + } + + if (Value *valuesValue = FindObject(*sparseValue, "values")) { + sparse->values.Read(*valuesValue, r); + } + + const unsigned int elementSize = GetElementSize(); + const size_t dataSize = count * elementSize; + sparse->PopulateData(dataSize, BufferViewClient::GetPointer()); + sparse->PatchData(elementSize); + } +} + +inline unsigned int Accessor::GetNumComponents() { + return AttribType::GetNumComponents(type); +} + +inline unsigned int Accessor::GetElementSize() { + return GetNumComponents() * GetBytesPerComponent(); +} + namespace { inline void CopyData(size_t count, const uint8_t *src, size_t src_stride, @@ -621,7 +665,7 @@ bool Accessor::ExtractData(T *&outData) { const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); - ai_assert(count * stride <= bufferView->byteLength); + ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; if (stride == elemSize && targetElemSize == elemSize) { From 53990ffa4243014692b3d325cbe7c18efa911459 Mon Sep 17 00:00:00 2001 From: Alexey Medvedev Date: Tue, 31 Mar 2020 14:18:51 -0700 Subject: [PATCH 005/119] Check for existed bone --- code/PostProcessing/SplitByBoneCountProcess.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index 015ba9bf6..1fd26c757 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -217,7 +217,11 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector& vb = vertexBones[face.mIndices[b]]; for( unsigned int c = 0; c < vb.size(); ++c) { - newBonesAtCurrentFace.insert(vb[c].first); + unsigned int boneIndex = vb[c].first; + if( !isBoneUsed[boneIndex] ) + { + newBonesAtCurrentFace.insert(boneIndex); + } } } From 74c8d09bd8b9da85862173c10b51fdc6ab77d29c Mon Sep 17 00:00:00 2001 From: Peter Seiderer Date: Sun, 12 Apr 2020 18:19:13 +0200 Subject: [PATCH 006/119] contrib/zlib: disable dynamic library building Fixes compile failure for static only toolchains (and assimp links against the static one). --- contrib/zlib/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt index c90996c0b..664c83a71 100644 --- a/contrib/zlib/CMakeLists.txt +++ b/contrib/zlib/CMakeLists.txt @@ -196,10 +196,7 @@ if(MINGW) set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) endif(MINGW) -add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) -set_target_properties(zlib PROPERTIES SOVERSION 1) INSTALL( TARGETS zlibstatic LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} From 0f32f59dc3d1fa11f6b3afb53c2900d9150c474e Mon Sep 17 00:00:00 2001 From: jess Date: Wed, 15 Apr 2020 13:24:22 -0700 Subject: [PATCH 007/119] Add Open Collective MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi, I'm making updates for Open Collective. Either you or another core contributor signed this repository up for Open Collective. This pull request adds financial contributors from your Open Collective https://opencollective.com/assimp ❤️ What it does: - adds a badge to show the latest number of financial contributors - adds a banner displaying contributors to the project on GitHub - adds a banner displaying all individuals contributing financially on Open Collective - adds a section displaying all organizations contributing financially on Open Collective, with their logo and a link to their website P.S: As with any pull request, feel free to comment or suggest changes. Thank you for your great contribution to the Open Source community. You are awesome! 🙌 And welcome to the Open Collective community! 😊 Come chat with us in the #opensource channel on https://slack.opencollective.com - great place to ask questions and share best practices with other Open Source sustainers! --- Readme.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Readme.md b/Readme.md index 61fff538f..15e76b9d2 100644 --- a/Readme.md +++ b/Readme.md @@ -2,6 +2,7 @@ Open Asset Import Library (assimp) ================================== A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data. ### Current project status ### +[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg) [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp) @@ -179,6 +180,28 @@ And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/a Contributions to assimp are highly appreciated. The easiest way to get involved is to submit a pull request with your changes against the main repository's `master` branch. +## Contributors + +### Code Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + + + +### Financial Contributors + +Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/assimp/contribute)] + +#### Individuals + + + +#### Organizations + +Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)] + + + ### License ### Our license is based on the modified, __3-clause BSD__-License. From 45e33ce1bf8ed719531aa0a71c2f63bf26d16a13 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 24 Apr 2020 16:36:44 -0400 Subject: [PATCH 008/119] first commit --- port/AssimpRs/Cargo.toml | 9 +++++++++ port/AssimpRs/src/lib.rs | 7 +++++++ 2 files changed, 16 insertions(+) create mode 100644 port/AssimpRs/Cargo.toml create mode 100644 port/AssimpRs/src/lib.rs diff --git a/port/AssimpRs/Cargo.toml b/port/AssimpRs/Cargo.toml new file mode 100644 index 000000000..705699b23 --- /dev/null +++ b/port/AssimpRs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "AssimpRs" +version = "0.1.0" +authors = ["David Golembiowski "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/port/AssimpRs/src/lib.rs b/port/AssimpRs/src/lib.rs new file mode 100644 index 000000000..31e1bb209 --- /dev/null +++ b/port/AssimpRs/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} From df57ee6cb618a45872210f2a9019cc0b866ca6ca Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 24 Apr 2020 16:49:38 -0400 Subject: [PATCH 009/119] laying out the submodules --- port/AssimpRs/src/camera/mod.rs | 0 port/AssimpRs/src/core/mod.rs | 0 port/AssimpRs/src/errors/mod.rs | 0 port/AssimpRs/src/formats/mod.rs | 0 port/AssimpRs/src/material/mod.rs | 0 port/AssimpRs/src/postprocess/mod.rs | 0 port/AssimpRs/src/shims/mod.rs | 0 port/AssimpRs/src/socket/mod.rs | 0 port/AssimpRs/src/structs/mod.rs | 0 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 port/AssimpRs/src/camera/mod.rs create mode 100644 port/AssimpRs/src/core/mod.rs create mode 100644 port/AssimpRs/src/errors/mod.rs create mode 100644 port/AssimpRs/src/formats/mod.rs create mode 100644 port/AssimpRs/src/material/mod.rs create mode 100644 port/AssimpRs/src/postprocess/mod.rs create mode 100644 port/AssimpRs/src/shims/mod.rs create mode 100644 port/AssimpRs/src/socket/mod.rs create mode 100644 port/AssimpRs/src/structs/mod.rs diff --git a/port/AssimpRs/src/camera/mod.rs b/port/AssimpRs/src/camera/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/core/mod.rs b/port/AssimpRs/src/core/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/errors/mod.rs b/port/AssimpRs/src/errors/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/formats/mod.rs b/port/AssimpRs/src/formats/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/material/mod.rs b/port/AssimpRs/src/material/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/postprocess/mod.rs b/port/AssimpRs/src/postprocess/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/shims/mod.rs b/port/AssimpRs/src/shims/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/socket/mod.rs b/port/AssimpRs/src/socket/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/AssimpRs/src/structs/mod.rs b/port/AssimpRs/src/structs/mod.rs new file mode 100644 index 000000000..e69de29bb From 5d05c536e7a6421b347142450f5149058c1f48d2 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 24 Apr 2020 17:02:36 -0400 Subject: [PATCH 010/119] updated gitignore and made port library name compliant with cargo --- port/AssimpRs/Cargo.toml | 9 --------- port/AssimpRs/src/camera/mod.rs | 0 port/AssimpRs/src/core/mod.rs | 0 port/AssimpRs/src/errors/mod.rs | 0 port/AssimpRs/src/formats/mod.rs | 0 port/AssimpRs/src/lib.rs | 7 ------- port/AssimpRs/src/material/mod.rs | 0 port/AssimpRs/src/postprocess/mod.rs | 0 port/AssimpRs/src/shims/mod.rs | 0 port/AssimpRs/src/socket/mod.rs | 0 port/AssimpRs/src/structs/mod.rs | 0 11 files changed, 16 deletions(-) delete mode 100644 port/AssimpRs/Cargo.toml delete mode 100644 port/AssimpRs/src/camera/mod.rs delete mode 100644 port/AssimpRs/src/core/mod.rs delete mode 100644 port/AssimpRs/src/errors/mod.rs delete mode 100644 port/AssimpRs/src/formats/mod.rs delete mode 100644 port/AssimpRs/src/lib.rs delete mode 100644 port/AssimpRs/src/material/mod.rs delete mode 100644 port/AssimpRs/src/postprocess/mod.rs delete mode 100644 port/AssimpRs/src/shims/mod.rs delete mode 100644 port/AssimpRs/src/socket/mod.rs delete mode 100644 port/AssimpRs/src/structs/mod.rs diff --git a/port/AssimpRs/Cargo.toml b/port/AssimpRs/Cargo.toml deleted file mode 100644 index 705699b23..000000000 --- a/port/AssimpRs/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "AssimpRs" -version = "0.1.0" -authors = ["David Golembiowski "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/port/AssimpRs/src/camera/mod.rs b/port/AssimpRs/src/camera/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/core/mod.rs b/port/AssimpRs/src/core/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/errors/mod.rs b/port/AssimpRs/src/errors/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/formats/mod.rs b/port/AssimpRs/src/formats/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/lib.rs b/port/AssimpRs/src/lib.rs deleted file mode 100644 index 31e1bb209..000000000 --- a/port/AssimpRs/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} diff --git a/port/AssimpRs/src/material/mod.rs b/port/AssimpRs/src/material/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/postprocess/mod.rs b/port/AssimpRs/src/postprocess/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/shims/mod.rs b/port/AssimpRs/src/shims/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/socket/mod.rs b/port/AssimpRs/src/socket/mod.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/AssimpRs/src/structs/mod.rs b/port/AssimpRs/src/structs/mod.rs deleted file mode 100644 index e69de29bb..000000000 From 6363bf34c0f80ac41acd4fbd0a8b1b11f2533654 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 24 Apr 2020 17:03:41 -0400 Subject: [PATCH 011/119] see git commit message rust-port 5d05c536 --- .gitignore | 6 ++++++ port/assimp_rs/Cargo.lock | 6 ++++++ port/assimp_rs/Cargo.toml | 9 +++++++++ port/assimp_rs/src/camera/mod.rs | 0 port/assimp_rs/src/core/mod.rs | 0 port/assimp_rs/src/errors/mod.rs | 0 port/assimp_rs/src/formats/mod.rs | 0 port/assimp_rs/src/lib.rs | 17 +++++++++++++++++ port/assimp_rs/src/material/mod.rs | 0 port/assimp_rs/src/postprocess/mod.rs | 0 port/assimp_rs/src/shims/mod.rs | 0 port/assimp_rs/src/socket/mod.rs | 0 port/assimp_rs/src/structs/mod.rs | 0 13 files changed, 38 insertions(+) create mode 100644 port/assimp_rs/Cargo.lock create mode 100644 port/assimp_rs/Cargo.toml create mode 100644 port/assimp_rs/src/camera/mod.rs create mode 100644 port/assimp_rs/src/core/mod.rs create mode 100644 port/assimp_rs/src/errors/mod.rs create mode 100644 port/assimp_rs/src/formats/mod.rs create mode 100644 port/assimp_rs/src/lib.rs create mode 100644 port/assimp_rs/src/material/mod.rs create mode 100644 port/assimp_rs/src/postprocess/mod.rs create mode 100644 port/assimp_rs/src/shims/mod.rs create mode 100644 port/assimp_rs/src/socket/mod.rs create mode 100644 port/assimp_rs/src/structs/mod.rs diff --git a/.gitignore b/.gitignore index e975976bf..fe59f9a70 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,12 @@ test/gtest/src/gtest-stamp/Debug/ tools/assimp_view/assimp_viewer.vcxproj.user *.pyc +### Rust ### +# Generated by Cargo; will have compiled files and executables +port/assimp_rs/target/ +# Backup files generated by rustfmt +port/assimp_rs/**/*.rs.bk + # Unix editor backups *~ test/gtest/src/gtest-stamp/gtest-gitinfo.txt diff --git a/port/assimp_rs/Cargo.lock b/port/assimp_rs/Cargo.lock new file mode 100644 index 000000000..4f571f362 --- /dev/null +++ b/port/assimp_rs/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "assimp_rs" +version = "0.1.0" + diff --git a/port/assimp_rs/Cargo.toml b/port/assimp_rs/Cargo.toml new file mode 100644 index 000000000..073a2b283 --- /dev/null +++ b/port/assimp_rs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "assimp_rs" +version = "0.1.0" +authors = ["David Golembiowski "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/port/assimp_rs/src/camera/mod.rs b/port/assimp_rs/src/camera/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/core/mod.rs b/port/assimp_rs/src/core/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/errors/mod.rs b/port/assimp_rs/src/errors/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/formats/mod.rs b/port/assimp_rs/src/formats/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/lib.rs b/port/assimp_rs/src/lib.rs new file mode 100644 index 000000000..dbb648876 --- /dev/null +++ b/port/assimp_rs/src/lib.rs @@ -0,0 +1,17 @@ +pub mod camera; +pub mod core; +pub mod errors; +pub mod formats; +pub mod material; +pub mod postprocess; +pub mod shims; +pub mod socket; +pub mod structs; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(true, true); + } +} diff --git a/port/assimp_rs/src/material/mod.rs b/port/assimp_rs/src/material/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/postprocess/mod.rs b/port/assimp_rs/src/postprocess/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/shims/mod.rs b/port/assimp_rs/src/shims/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/socket/mod.rs b/port/assimp_rs/src/socket/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/mod.rs b/port/assimp_rs/src/structs/mod.rs new file mode 100644 index 000000000..e69de29bb From 2108e08c900a624ae9a0a858860e7932635ee9a9 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 24 Apr 2020 18:15:51 -0400 Subject: [PATCH 012/119] adding structs --- port/assimp_rs/src/structs/mod.rs | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/port/assimp_rs/src/structs/mod.rs b/port/assimp_rs/src/structs/mod.rs index e69de29bb..fd9087648 100644 --- a/port/assimp_rs/src/structs/mod.rs +++ b/port/assimp_rs/src/structs/mod.rs @@ -0,0 +1,61 @@ +mod anim; +/* Animation + * NodeAnim + * MeshAnim + * MeshMorphAnim + */ +mod blob; +/* ExportDataBlob + */ +mod vec; +/* Vector2d + * Vector3d + * */ +mod matrix; +/* Matrix3by3 + * Matrix4by4 + */ +mod camera; +/* Camera */ +mod color; +/* Color3d + * Color4d + */ +mod key; +/* MeshKey + * MeshMorphKey + * QuatKey + * VectorKey + */ +mod texel; +mod plane; +mod string; +/* String + */ +mod material; +/* Material + * MaterialPropery + * MaterialPropertyString + */ +mod mem; +mod quaternion; +mod face; +mod vertex_weight; +mod mesh; +/* Mesh + */ +mod meta; +/* Metadata + * MetadataEntry + */ +mod node; +/* Node + * */ +mod light; +mod texture; +mod ray; +mod transform; +/* UVTransform */ +mod bone; +mod scene; +/* Scene */ From 060c45fcf3b4019446560c079adafb8a5b894f40 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 24 Apr 2020 22:15:32 -0400 Subject: [PATCH 013/119] initial layout for anim.rs --- port/assimp_rs/src/structs/anim.rs | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 port/assimp_rs/src/structs/anim.rs diff --git a/port/assimp_rs/src/structs/anim.rs b/port/assimp_rs/src/structs/anim.rs new file mode 100644 index 000000000..5374151eb --- /dev/null +++ b/port/assimp_rs/src/structs/anim.rs @@ -0,0 +1,44 @@ +pub struct Animation<'mA, 'mMA, 'nA> { + /* The name of the animation. If the modeling package this data was + * exported from does support only a single animation channel, this + * name is usually empty (length is zero). + */ + m_name: Option, + // Duration of the animation in ticks + m_duration: f64, + // Ticks per second. Zero (0.000... ticks/second) if not + // specified in the imported file + m_ticks_per_second: Option, + /* Number of bone animation channels. + Each channel affects a single node. + */ + m_num_channels: u64, + /* Node animation channels. Each channel + affects a single node. + ?? -> The array is m_num_channels in size. + (maybe refine to a derivative type of usize?) + */ + m_channels: &'nA NodeAnim, + /* Number of mesh animation channels. Each + channel affects a single mesh and defines + vertex-based animation. + */ + m_num_mesh_channels: u64, + /* The mesh animation channels. Each channel + affects a single mesh. + The array is m_num_mesh_channels in size + (maybe refine to a derivative of usize?) + */ + m_mesh_channels: &'mA MeshAnim, + /* The number of mesh animation channels. Each channel + affects a single mesh and defines some morphing animation. + */ + m_num_morph_mesh_channels: u64, + /* The morph mesh animation channels. Each channel affects a single mesh. + The array is mNumMorphMeshChannels in size. + */ + m_morph_mesh_channels: &'mMA MeshMorphAnim +} +pub struct NodeAnim {} +pub struct MeshAnim {} +pub struct MeshMorphAnim {} From e438310d8cc3718fdc32d62462b8217569f9c766 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Sat, 25 Apr 2020 00:12:58 -0400 Subject: [PATCH 014/119] should have added these earlier --- port/assimp_rs/src/structs/blob.rs | 0 port/assimp_rs/src/structs/bone.rs | 0 port/assimp_rs/src/structs/camera.rs | 0 port/assimp_rs/src/structs/color.rs | 0 port/assimp_rs/src/structs/face.rs | 0 port/assimp_rs/src/structs/key.rs | 0 port/assimp_rs/src/structs/light.rs | 0 port/assimp_rs/src/structs/material.rs | 0 port/assimp_rs/src/structs/matrix.rs | 0 port/assimp_rs/src/structs/mem.rs | 0 port/assimp_rs/src/structs/mesh.rs | 0 port/assimp_rs/src/structs/meta.rs | 0 port/assimp_rs/src/structs/node.rs | 0 port/assimp_rs/src/structs/plane.rs | 0 port/assimp_rs/src/structs/quaternion.rs | 0 port/assimp_rs/src/structs/ray.rs | 0 port/assimp_rs/src/structs/scene.rs | 0 port/assimp_rs/src/structs/string.rs | 0 port/assimp_rs/src/structs/texel.rs | 0 port/assimp_rs/src/structs/texture.rs | 0 port/assimp_rs/src/structs/transform.rs | 0 port/assimp_rs/src/structs/vec.rs | 0 port/assimp_rs/src/structs/vertex_weight.rs | 0 23 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 port/assimp_rs/src/structs/blob.rs create mode 100644 port/assimp_rs/src/structs/bone.rs create mode 100644 port/assimp_rs/src/structs/camera.rs create mode 100644 port/assimp_rs/src/structs/color.rs create mode 100644 port/assimp_rs/src/structs/face.rs create mode 100644 port/assimp_rs/src/structs/key.rs create mode 100644 port/assimp_rs/src/structs/light.rs create mode 100644 port/assimp_rs/src/structs/material.rs create mode 100644 port/assimp_rs/src/structs/matrix.rs create mode 100644 port/assimp_rs/src/structs/mem.rs create mode 100644 port/assimp_rs/src/structs/mesh.rs create mode 100644 port/assimp_rs/src/structs/meta.rs create mode 100644 port/assimp_rs/src/structs/node.rs create mode 100644 port/assimp_rs/src/structs/plane.rs create mode 100644 port/assimp_rs/src/structs/quaternion.rs create mode 100644 port/assimp_rs/src/structs/ray.rs create mode 100644 port/assimp_rs/src/structs/scene.rs create mode 100644 port/assimp_rs/src/structs/string.rs create mode 100644 port/assimp_rs/src/structs/texel.rs create mode 100644 port/assimp_rs/src/structs/texture.rs create mode 100644 port/assimp_rs/src/structs/transform.rs create mode 100644 port/assimp_rs/src/structs/vec.rs create mode 100644 port/assimp_rs/src/structs/vertex_weight.rs diff --git a/port/assimp_rs/src/structs/blob.rs b/port/assimp_rs/src/structs/blob.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/bone.rs b/port/assimp_rs/src/structs/bone.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/camera.rs b/port/assimp_rs/src/structs/camera.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/color.rs b/port/assimp_rs/src/structs/color.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/face.rs b/port/assimp_rs/src/structs/face.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/key.rs b/port/assimp_rs/src/structs/key.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/light.rs b/port/assimp_rs/src/structs/light.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/material.rs b/port/assimp_rs/src/structs/material.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/matrix.rs b/port/assimp_rs/src/structs/matrix.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/mem.rs b/port/assimp_rs/src/structs/mem.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/mesh.rs b/port/assimp_rs/src/structs/mesh.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/meta.rs b/port/assimp_rs/src/structs/meta.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/node.rs b/port/assimp_rs/src/structs/node.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/plane.rs b/port/assimp_rs/src/structs/plane.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/quaternion.rs b/port/assimp_rs/src/structs/quaternion.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/ray.rs b/port/assimp_rs/src/structs/ray.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/scene.rs b/port/assimp_rs/src/structs/scene.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/string.rs b/port/assimp_rs/src/structs/string.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/texel.rs b/port/assimp_rs/src/structs/texel.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/texture.rs b/port/assimp_rs/src/structs/texture.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/transform.rs b/port/assimp_rs/src/structs/transform.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/vec.rs b/port/assimp_rs/src/structs/vec.rs new file mode 100644 index 000000000..e69de29bb diff --git a/port/assimp_rs/src/structs/vertex_weight.rs b/port/assimp_rs/src/structs/vertex_weight.rs new file mode 100644 index 000000000..e69de29bb From 629320a3a0b8ae742b8c1760f49f63cd698c4fa9 Mon Sep 17 00:00:00 2001 From: Inho Lee Date: Mon, 27 Apr 2020 11:52:04 +0200 Subject: [PATCH 015/119] Add timescale for collada --- code/Collada/ColladaExporter.cpp | 4 +++- code/Collada/ColladaLoader.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index e27e7aa90..cb5d8323b 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -1314,6 +1314,8 @@ void ColladaExporter::WriteSceneLibrary() // ------------------------------------------------------------------------------------------------ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { + static const float kSecondsFromMilliseconds = .001f; + const aiAnimation * anim = mScene->mAnimations[pIndex]; if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) @@ -1351,7 +1353,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) std::vector frames; for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime)); + frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime) * kSecondsFromMilliseconds); } WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size()); diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index b78fc0e3b..e93550116 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -107,6 +107,8 @@ ColladaLoader::~ColladaLoader() { // empty } +static const float kMillisecondsFromSeconds = 1000.f; + // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool ColladaLoader::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { @@ -1420,9 +1422,9 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse double time = double(mat.d4); // remember? time is stored in mat.d4 mat.d4 = 1.0f; - dstAnim->mPositionKeys[a].mTime = time; - dstAnim->mRotationKeys[a].mTime = time; - dstAnim->mScalingKeys[a].mTime = time; + dstAnim->mPositionKeys[a].mTime = time * kMillisecondsFromSeconds ; + dstAnim->mRotationKeys[a].mTime = time * kMillisecondsFromSeconds ; + dstAnim->mScalingKeys[a].mTime = time * kMillisecondsFromSeconds ; mat.Decompose(dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue); } @@ -1484,7 +1486,7 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()]; morphAnim->mKeys[key].mWeights = new double[morphChannels.size()]; - morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime; + morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime * kMillisecondsFromSeconds ; for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++) { morphAnim->mKeys[key].mValues[valueIndex] = valueIndex; From 4c3aee1968c9fdb8f01d3da5850b1550df959607 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Mon, 27 Apr 2020 12:54:17 +0200 Subject: [PATCH 016/119] add opencollective to funding --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index e0c2bec9e..84e3123fe 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,3 @@ patreon: assimp custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4 +open_collective: assimp From b0c97118946c2d138985df1908638614350c1863 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 27 Apr 2020 15:16:57 +0200 Subject: [PATCH 017/119] Small format finding --- code/Collada/ColladaExporter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index cb5d8323b..6faa229c8 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -1316,10 +1315,11 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { static const float kSecondsFromMilliseconds = .001f; - const aiAnimation * anim = mScene->mAnimations[pIndex]; + const aiAnimation * anim = mScene->mAnimations[pIndex]; - if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) - return; + if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) { + return; + } const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); std::string idstr = anim->mName.C_Str(); From 7db73182b025a079f27c4dc5e63e7afd1257ece2 Mon Sep 17 00:00:00 2001 From: luca <681992+lukka@users.noreply.github.com> Date: Mon, 27 Apr 2020 09:51:02 -0700 Subject: [PATCH 018/119] enable gcc build on Linux --- .github/workflows/ccpp.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index dca0c3bea..ccfe31db3 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -8,13 +8,13 @@ on: jobs: job: - name: ${{ matrix.os }}-build-and-test + name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - # For Windows msvc, for Linux and macOS let's use the clang compiler + # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. include: - os: windows-latest cxx: cl.exe @@ -22,6 +22,9 @@ jobs: - os: ubuntu-latest cxx: clang++ cc: clang + - os: ubuntu-latest + cxx: g++ + cc: gcc - os: macos-latest cxx: clang++ cc: clang From 603a1200a2e0e7bcd0a60744c0c75501db786408 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 27 Apr 2020 19:51:59 +0200 Subject: [PATCH 019/119] add gcc build target --- .github/workflows/ccpp.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index dca0c3bea..bdc6c9ec0 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -19,9 +19,12 @@ jobs: - os: windows-latest cxx: cl.exe cc: cl.exe - - os: ubuntu-latest + - os: ubuntu-latest.clang cxx: clang++ cc: clang + - os: ubuntu-latest.gcc + cxx: g++ + cc: gcc - os: macos-latest cxx: clang++ cc: clang From c1c80801438d913b59a093d3bc043f5e97b15b39 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 27 Apr 2020 19:55:58 +0200 Subject: [PATCH 020/119] Use correct name --- .github/workflows/ccpp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index bdc6c9ec0..f61d99bb8 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -19,10 +19,10 @@ jobs: - os: windows-latest cxx: cl.exe cc: cl.exe - - os: ubuntu-latest.clang + - os: ubuntu-latest cxx: clang++ cc: clang - - os: ubuntu-latest.gcc + - os: ubuntu-latest cxx: g++ cc: gcc - os: macos-latest From 625cc9d096f59ff79c872ef3d7e1e5a1658ead0e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 27 Apr 2020 21:30:06 +0200 Subject: [PATCH 021/119] Remove useless comparison --- contrib/irrXML/irrString.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/contrib/irrXML/irrString.h b/contrib/irrXML/irrString.h index 1abf22b78..246348891 100644 --- a/contrib/irrXML/irrString.h +++ b/contrib/irrXML/irrString.h @@ -635,9 +635,6 @@ private: s32 amount = used < new_size ? used : new_size; for (s32 i=0; i Date: Tue, 28 Apr 2020 10:07:56 +1000 Subject: [PATCH 022/119] Fix reading of orthographic camera data. Fixes #3028. --- code/glTF2/glTF2Asset.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index ed23b388a..ea0b17dcd 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -1068,10 +1068,10 @@ inline void Camera::Read(Value &obj, Asset & /*r*/) { cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f); } else { - cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); - cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); - cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); - cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); + cameraProperties.ortographic.xmag = MemberOrDefault(*it, "xmag", 1.f); + cameraProperties.ortographic.ymag = MemberOrDefault(*it, "ymag", 1.f); + cameraProperties.ortographic.zfar = MemberOrDefault(*it, "zfar", 100.f); + cameraProperties.ortographic.znear = MemberOrDefault(*it, "znear", 0.01f); } } From 4488e3e7451b0c00d5461657cb453e1c0666371f Mon Sep 17 00:00:00 2001 From: luca <681992+lukka@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:39:13 -0700 Subject: [PATCH 023/119] build on Linux with gcc and clang; warning as error only for 'assimp' target --- .github/workflows/ccpp.yml | 18 +++++++++++------- CMakeLists.txt | 14 +++----------- code/ASE/ASEParser.cpp | 4 ++-- code/Blender/BlenderBMesh.cpp | 1 + code/CApi/AssimpCExport.cpp | 6 +++--- code/CMakeLists.txt | 7 +++++++ code/Common/SceneCombiner.cpp | 22 +++++++++++----------- code/M3D/m3d.h | 6 +++--- contrib/irrXML/irrString.h | 3 --- 9 files changed, 41 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index ccfe31db3..08292d55f 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -13,21 +13,25 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang] # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. include: - - os: windows-latest + - name: windows-msvc + os: windows-latest cxx: cl.exe cc: cl.exe - - os: ubuntu-latest + - name: ubuntu-clang + os: ubuntu-latest cxx: clang++ cc: clang - - os: ubuntu-latest + - name: macos-clang + os: macos-latest + cxx: clang++ + cc: clang + - name: ubuntu-gcc + os: ubuntu-latest cxx: g++ cc: gcc - - os: macos-latest - cxx: clang++ - cc: clang steps: - uses: actions/checkout@v2 diff --git a/CMakeLists.txt b/CMakeLists.txt index d15e58dd4..c631b7685 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,22 +239,14 @@ IF( UNIX ) INCLUDE(GNUInstallDirs) ENDIF() -# enable warnings as errors ######################################## -IF (MSVC) - ADD_COMPILE_OPTIONS(/WX) -ELSE() - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") -ENDIF() - # Grouped compiler settings ######################################## IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) IF(NOT ASSIMP_HUNTER_ENABLED) - SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}") - SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") + SET(CMAKE_CXX_STANDARD 11) + SET(CMAKE_POSITION_INDEPENDENT_CODE ON) ENDIF() # hide all not-exported symbols - SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}") SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}") SET(LIBSTDC++_LIBRARIES -lstdc++) ELSEIF(MSVC) diff --git a/code/ASE/ASEParser.cpp b/code/ASE/ASEParser.cpp index efc6ecd0d..72e8b3373 100644 --- a/code/ASE/ASEParser.cpp +++ b/code/ASE/ASEParser.cpp @@ -142,11 +142,11 @@ void Parser::LogWarning(const char* szWarn) { ai_assert(NULL != szWarn); - char szTemp[1024]; + char szTemp[2048]; #if _MSC_VER >= 1400 sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn); #else - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn); + ai_snprintf(szTemp,sizeof(szTemp),"Line %u: %s",iLineNumber,szWarn); #endif // output the warning to the logger ... diff --git a/code/Blender/BlenderBMesh.cpp b/code/Blender/BlenderBMesh.cpp index 039302e12..174725e82 100644 --- a/code/Blender/BlenderBMesh.cpp +++ b/code/Blender/BlenderBMesh.cpp @@ -181,6 +181,7 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 ) face.v2 = v2; face.v3 = v3; face.v4 = v4; + face.flag = 0; // TODO - Work out how materials work face.mat_nr = 0; triMesh->mface.push_back( face ); diff --git a/code/CApi/AssimpCExport.cpp b/code/CApi/AssimpCExport.cpp index 137cc2894..a6e7a304f 100644 --- a/code/CApi/AssimpCExport.cpp +++ b/code/CApi/AssimpCExport.cpp @@ -73,11 +73,11 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) aiExportFormatDesc *desc = new aiExportFormatDesc; desc->description = new char[ strlen( orig->description ) + 1 ](); - ::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) ); + ::memcpy( (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 ) ); + ::memcpy( ( 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 ) ); + ::memcpy( ( char* ) desc->id, orig->id, strlen( orig->id ) ); return desc; } diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 49583c0c8..6afed40f9 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1134,6 +1134,13 @@ ENDIF () ADD_LIBRARY( assimp ${assimp_src} ) ADD_LIBRARY(assimp::assimp ALIAS assimp) +# enable warnings as errors ######################################## +IF (MSVC) + TARGET_COMPILE_OPTIONS(assimp PRIVATE /WX) +ELSE() + TARGET_COMPILE_OPTIONS(assimp PRIVATE -Werror) +ENDIF() + TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC $ $ diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index b7511ff4e..62efe2ece 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -979,7 +979,7 @@ void GetArrayCopy(Type*& dest, ai_uint num ) { dest = new Type[num]; ::memcpy(dest, old, sizeof(Type) * num); -} + } // ------------------------------------------------------------------------------------------------ void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) { @@ -1065,7 +1065,7 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) { aiMesh* dest = *_dest = new aiMesh(); // get a flat copy - ::memcpy(dest,src,sizeof(aiMesh)); + *dest = *src; // and reallocate all arrays GetArrayCopy( dest->mVertices, dest->mNumVertices ); @@ -1104,7 +1104,7 @@ void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) { aiAnimMesh* dest = *_dest = new aiAnimMesh(); // get a flat copy - ::memcpy(dest, src, sizeof(aiAnimMesh)); + *dest = *src; // and reallocate all arrays GetArrayCopy(dest->mVertices, dest->mNumVertices); @@ -1161,7 +1161,7 @@ void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) { aiTexture* dest = *_dest = new aiTexture(); // get a flat copy - ::memcpy(dest,src,sizeof(aiTexture)); + *dest = *src; // and reallocate all arrays. We must do it manually here const char* old = (const char*)dest->pcData; @@ -1191,7 +1191,7 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) { aiAnimation* dest = *_dest = new aiAnimation(); // get a flat copy - ::memcpy(dest,src,sizeof(aiAnimation)); + *dest = *src; // and reallocate all arrays CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels ); @@ -1207,7 +1207,7 @@ void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) { aiNodeAnim* dest = *_dest = new aiNodeAnim(); // get a flat copy - ::memcpy(dest,src,sizeof(aiNodeAnim)); + *dest = *src; // and reallocate all arrays GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys ); @@ -1223,7 +1223,7 @@ void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) { aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim(); // get a flat copy - ::memcpy(dest,src,sizeof(aiMeshMorphAnim)); + *dest = *src; // and reallocate all arrays GetArrayCopy( dest->mKeys, dest->mNumKeys ); @@ -1244,7 +1244,7 @@ void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) { aiCamera* dest = *_dest = new aiCamera(); // get a flat copy, that's already OK - ::memcpy(dest,src,sizeof(aiCamera)); + *dest = *src; } // ------------------------------------------------------------------------------------------------ @@ -1256,7 +1256,7 @@ void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) { aiLight* dest = *_dest = new aiLight(); // get a flat copy, that's already OK - ::memcpy(dest,src,sizeof(aiLight)); + *dest = *src; } // ------------------------------------------------------------------------------------------------ @@ -1268,7 +1268,7 @@ void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) { aiBone* dest = *_dest = new aiBone(); // get a flat copy - ::memcpy(dest,src,sizeof(aiBone)); + *dest = *src; // and reallocate all arrays GetArrayCopy( dest->mWeights, dest->mNumWeights ); @@ -1282,7 +1282,7 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src) aiNode* dest = *_dest = new aiNode(); // get a flat copy - ::memcpy(dest,src,sizeof(aiNode)); + *dest = *src; if (src->mMetaData) { Copy(&dest->mMetaData, src->mMetaData); diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 83c8d8a52..75bcdfeb7 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -1556,7 +1556,7 @@ static int _m3dstbi__create_png_image(_m3dstbi__png *a, unsigned char *image_dat return 1; } -static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char tc[3], int out_n) { +static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char* tc, int out_n) { _m3dstbi__context *s = z->s; _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y; unsigned char *p = z->out; @@ -1639,7 +1639,7 @@ static int _m3dstbi__expand_png_palette(_m3dstbi__png *a, unsigned char *palette static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) { unsigned char palette[1024], pal_img_n = 0; - unsigned char has_trans = 0, tc[3]; + unsigned char has_trans = 0, tc[3] = {}; _m3dstbi__uint16 tc16[3]; _m3dstbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0; int first = 1, k, interlace = 0, color = 0; @@ -4350,7 +4350,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL; uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0; uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL; - uint8_t *opa; + uint8_t *opa = nullptr; m3dcd_t *cd; m3dc_t *cmd; m3dstr_t *str = NULL; diff --git a/contrib/irrXML/irrString.h b/contrib/irrXML/irrString.h index 1abf22b78..246348891 100644 --- a/contrib/irrXML/irrString.h +++ b/contrib/irrXML/irrString.h @@ -635,9 +635,6 @@ private: s32 amount = used < new_size ? used : new_size; for (s32 i=0; i Date: Tue, 28 Apr 2020 09:14:53 +0200 Subject: [PATCH 024/119] Retrigger build --- code/Blender/BlenderBMesh.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/Blender/BlenderBMesh.cpp b/code/Blender/BlenderBMesh.cpp index 174725e82..937d9d073 100644 --- a/code/Blender/BlenderBMesh.cpp +++ b/code/Blender/BlenderBMesh.cpp @@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Conversion of Blender's new BMesh stuff */ - #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #include "BlenderDNA.h" From 9107402bda805fee74da3e7fea9261b4d304548e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 14:22:00 +0200 Subject: [PATCH 025/119] Add sanitizer job --- .github/workflows/ccpp.yml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 08292d55f..46f060836 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,13 +7,13 @@ on: branches: [ master ] jobs: - job: + job-build: name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang] + name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang, ubuntu-memory-sanitizer] # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. include: - name: windows-msvc @@ -57,3 +57,27 @@ jobs: - name: test run: cd build/bin && ./unit shell: bash + + job-sanitizer: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: lukka/get-cmake@latest + - uses: ilammy/msvc-dev-cmd@v1 + - uses: lukka/set-shell-env@v1 + with: + CXX: clang++ + CC: clang + + - name: configure and build + uses: lukka/run-cmake@v2 + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' + buildWithCMakeArgs: '-- -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: test + run: cd build/bin && ./unit + shell: bash From 24fc16336ac8d5089c530008d288e740f5f03112 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 14:24:21 +0200 Subject: [PATCH 026/119] Add build-dependency --- .github/workflows/ccpp.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 46f060836..a1d81d0cc 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -59,6 +59,7 @@ jobs: shell: bash job-sanitizer: + needs: job-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 43df1d676a1871de9147f8ac6ea696c64b38db78 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 14:27:02 +0200 Subject: [PATCH 027/119] Fix dependency --- .github/workflows/ccpp.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index a1d81d0cc..c96a628ce 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,7 +7,7 @@ on: branches: [ master ] jobs: - job-build: + job: name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: @@ -58,8 +58,7 @@ jobs: run: cd build/bin && ./unit shell: bash - job-sanitizer: - needs: job-build + sanitizer: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 8240a11e1578c05aee6de9fa0bce68963a1b4eb9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 14:41:44 +0200 Subject: [PATCH 028/119] Add undefined behavior sanitizer job --- .github/workflows/ccpp.yml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index c96a628ce..0a3ca72ec 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -58,7 +58,31 @@ jobs: run: cd build/bin && ./unit shell: bash - sanitizer: + adress-sanitizer: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: lukka/get-cmake@latest + - uses: ilammy/msvc-dev-cmd@v1 + - uses: lukka/set-shell-env@v1 + with: + CXX: clang++ + CC: clang + + - name: configure and build + uses: lukka/run-cmake@v2 + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' + buildWithCMakeArgs: '-- -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: test + run: cd build/bin && ./unit + shell: bash + + undefined-behavior-sanitizer: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 5cb4ac843d8434a6aaf9c5356f00324a34b55d11 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 14:43:12 +0200 Subject: [PATCH 029/119] Update ccpp.yml --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 0a3ca72ec..418c100f3 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,7 +7,7 @@ on: branches: [ master ] jobs: - job: + builds: name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: From 8085e7555e378e7e975d123949b7d69517edf5b6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 14:53:19 +0200 Subject: [PATCH 030/119] try something out to get builds back to job-list --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 418c100f3..0a3ca72ec 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,7 +7,7 @@ on: branches: [ master ] jobs: - builds: + job: name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: From 8224cbeaad58c2d0b4d83af9e4ff85fecff1a53e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 20:25:48 +0200 Subject: [PATCH 031/119] Try a different naming schema --- .github/workflows/ccpp.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 0a3ca72ec..6d54e289e 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,7 +7,7 @@ on: branches: [ master ] jobs: - job: + job1: name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: @@ -58,7 +58,8 @@ jobs: run: cd build/bin && ./unit shell: bash - adress-sanitizer: + job2: + name: adress-sanitizer runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -82,7 +83,8 @@ jobs: run: cd build/bin && ./unit shell: bash - undefined-behavior-sanitizer: + job3: + name: undefined-behavior-sanitizer runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 8888495d124636d8ca0d44febe87996a62cb0d72 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 20:30:59 +0200 Subject: [PATCH 032/119] Create sanitizer.yml --- .github/workflows/sanitizer.yml | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/sanitizer.yml diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml new file mode 100644 index 000000000..d6f09367f --- /dev/null +++ b/.github/workflows/sanitizer.yml @@ -0,0 +1,58 @@ +name: C/C++ CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + job1: + name: adress-sanitizer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: lukka/get-cmake@latest + - uses: ilammy/msvc-dev-cmd@v1 + - uses: lukka/set-shell-env@v1 + with: + CXX: clang++ + CC: clang + + - name: configure and build + uses: lukka/run-cmake@v2 + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' + buildWithCMakeArgs: '-- -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: test + run: cd build/bin && ./unit + shell: bash + + job2: + name: undefined-behavior-sanitizer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: lukka/get-cmake@latest + - uses: ilammy/msvc-dev-cmd@v1 + - uses: lukka/set-shell-env@v1 + with: + CXX: clang++ + CC: clang + + - name: configure and build + uses: lukka/run-cmake@v2 + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' + buildWithCMakeArgs: '-- -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: test + run: cd build/bin && ./unit + shell: bash From a5a38c02a5b7d70facf97a58dc90271982fd0b00 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 20:31:42 +0200 Subject: [PATCH 033/119] move sanitizer into its own file --- .github/workflows/ccpp.yml | 50 -------------------------------------- 1 file changed, 50 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 6d54e289e..d46dbe6a0 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -57,53 +57,3 @@ jobs: - name: test run: cd build/bin && ./unit shell: bash - - job2: - name: adress-sanitizer - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: lukka/get-cmake@latest - - uses: ilammy/msvc-dev-cmd@v1 - - uses: lukka/set-shell-env@v1 - with: - CXX: clang++ - CC: clang - - - name: configure and build - uses: lukka/run-cmake@v2 - with: - cmakeListsOrSettingsJson: CMakeListsTxtAdvanced - cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' - cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' - buildWithCMakeArgs: '-- -v' - buildDirectory: '${{ github.workspace }}/build/' - - - name: test - run: cd build/bin && ./unit - shell: bash - - job3: - name: undefined-behavior-sanitizer - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: lukka/get-cmake@latest - - uses: ilammy/msvc-dev-cmd@v1 - - uses: lukka/set-shell-env@v1 - with: - CXX: clang++ - CC: clang - - - name: configure and build - uses: lukka/run-cmake@v2 - with: - cmakeListsOrSettingsJson: CMakeListsTxtAdvanced - cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' - cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' - buildWithCMakeArgs: '-- -v' - buildDirectory: '${{ github.workspace }}/build/' - - - name: test - run: cd build/bin && ./unit - shell: bash From 4dfdbbf171674756f281dbad07e335bb5e4d989d Mon Sep 17 00:00:00 2001 From: qarmin Date: Tue, 28 Apr 2020 20:31:59 +0200 Subject: [PATCH 034/119] Check index before using --- code/glTF/glTFCommon.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/glTF/glTFCommon.cpp b/code/glTF/glTFCommon.cpp index 1c662a16a..17da49fb8 100644 --- a/code/glTF/glTFCommon.cpp +++ b/code/glTF/glTFCommon.cpp @@ -145,13 +145,13 @@ bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out) { size_t i = 5, j; if (uri[i] != ';' && uri[i] != ',') { // has media type? uri[1] = char(i); - for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) { + for (;i < uriLen && uri[i] != ';' && uri[i] != ','; ++i) { // nothing to do! } } - while (uri[i] == ';' && i < uriLen) { + while (i < uriLen && uri[i] == ';') { uri[i++] = '\0'; - for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) { + for (j = i; i < uriLen && uri[i] != ';' && uri[i] != ','; ++i) { // nothing to do! } From 4afbe35e0775de4b31f88c790db5ee76b28cf93f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 20:32:55 +0200 Subject: [PATCH 035/119] Use unique name for the sanitizer check --- .github/workflows/sanitizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index d6f09367f..7a8eb17fa 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -1,4 +1,4 @@ -name: C/C++ CI +name: C/C++ Sanitizer on: push: From 7b4ff0cb1c9775ee1fe899ea8e9b9ed8485afec0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 20:39:13 +0200 Subject: [PATCH 036/119] Fix name --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index d46dbe6a0..36fca3f29 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,7 +7,7 @@ on: branches: [ master ] jobs: - job1: + job: name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test runs-on: ${{ matrix.os }} strategy: From 68efdcde883cf5f9e1b9cb42b4da211e443ee1fb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 20:41:02 +0200 Subject: [PATCH 037/119] Remove deprecated step --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 36fca3f29..08292d55f 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang, ubuntu-memory-sanitizer] + name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang] # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. include: - name: windows-msvc From 1a440834ae455bf4d592500959cbee7559b1a69b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Apr 2020 21:11:21 +0200 Subject: [PATCH 038/119] Use debug configuration --- .github/workflows/sanitizer.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index 7a8eb17fa..bfcad7867 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -24,7 +24,7 @@ jobs: with: cmakeListsOrSettingsJson: CMakeListsTxtAdvanced cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' - cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Debug -DASSIMP_ASAN=ON' buildWithCMakeArgs: '-- -v' buildDirectory: '${{ github.workspace }}/build/' @@ -49,7 +49,7 @@ jobs: with: cmakeListsOrSettingsJson: CMakeListsTxtAdvanced cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' - cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release -DASSIMP_ASAN=ON' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Debug -DASSIMP_ASAN=ON' buildWithCMakeArgs: '-- -v' buildDirectory: '${{ github.workspace }}/build/' From fcdf88a74a948cf7c47e583bc0de524c3da15355 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 13:41:40 +0200 Subject: [PATCH 039/119] Use correct sanitizer --- .github/workflows/sanitizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index bfcad7867..c1fa62ff3 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -49,7 +49,7 @@ jobs: with: cmakeListsOrSettingsJson: CMakeListsTxtAdvanced cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' - cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Debug -DASSIMP_ASAN=ON' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Debug -DASSIMP_UBSAN=ON' buildWithCMakeArgs: '-- -v' buildDirectory: '${{ github.workspace }}/build/' From b9c597d0553d5996c54ce414efb572d4c7778453 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 13:46:01 +0200 Subject: [PATCH 040/119] Fix review finding. --- .github/workflows/sanitizer.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index c1fa62ff3..9bba5f6fd 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -13,7 +13,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: lukka/get-cmake@latest - - uses: ilammy/msvc-dev-cmd@v1 - uses: lukka/set-shell-env@v1 with: CXX: clang++ @@ -38,7 +37,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: lukka/get-cmake@latest - - uses: ilammy/msvc-dev-cmd@v1 - uses: lukka/set-shell-env@v1 with: CXX: clang++ From 2c6ac23a4e04127838b03eb4589861d9e22ef0f4 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 28 Apr 2020 17:46:07 +0100 Subject: [PATCH 041/119] Apply Assimp clangformat to touched Collada files --- code/Collada/ColladaExporter.cpp | 1545 ++++++++++++++--------------- code/Collada/ColladaExporter.h | 135 +-- code/Collada/ColladaHelper.cpp | 23 +- code/Collada/ColladaHelper.h | 403 ++++---- code/Collada/ColladaLoader.cpp | 692 ++++++------- code/Collada/ColladaParser.cpp | 1572 +++++++++++------------------- code/Collada/ColladaParser.h | 503 +++++----- 7 files changed, 2103 insertions(+), 2770 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index e27e7aa90..0026fda26 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -45,24 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ColladaExporter.h" #include -#include +#include #include -#include #include #include #include -#include -#include -#include +#include +#include #include +#include +#include #include -#include #include +#include +#include #include #include -#include using namespace Assimp; @@ -70,32 +70,32 @@ namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp -void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { +void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) { std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); // invoke the exporter - ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file); - + ColladaExporter iDoTheExportThing(pScene, pIOSystem, path, file); + if (iDoTheExportThing.mOutput.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); } // we're still here - export successfully completed. Write result to the given IOSYstem - std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + std::unique_ptr outfile(pIOSystem->Open(pFile, "wt")); + if (outfile == NULL) { throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); } // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. - outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast(iDoTheExportThing.mOutput.tellp()),1); + outfile->Write(iDoTheExportThing.mOutput.str().c_str(), static_cast(iDoTheExportThing.mOutput.tellp()), 1); } } // end of namespace Assimp // ------------------------------------------------------------------------------------------------ // Encodes a string into a valid XML ID using the xsd:ID schema qualifications. -static const std::string XMLIDEncode(const std::string& name) { +static const std::string XMLIDEncode(const std::string &name) { const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-."; const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char); @@ -115,7 +115,7 @@ static const std::string XMLIDEncode(const std::string& name) { if (strchr(XML_ID_CHARS, *it) != nullptr) { idEncoded << *it; } else { - // Select placeholder character based on invalid character to prevent name collisions + // Select placeholder character based on invalid character to prevent name collisions idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; } } @@ -125,12 +125,12 @@ static const std::string XMLIDEncode(const std::string& name) { // ------------------------------------------------------------------------------------------------ // Constructor for a specific scene to export -ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) -: mIOSystem(pIOSystem) -, mPath(path) -, mFile(file) { +ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file) : + mIOSystem(pIOSystem), + mPath(path), + mFile(file) { // make sure that all formatting happens using the standard, C locale and not the user's current locale - mOutput.imbue( std::locale("C") ); + mOutput.imbue(std::locale("C")); mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); mScene = pScene; @@ -146,7 +146,7 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co // ------------------------------------------------------------------------------------------------ // Destructor ColladaExporter::~ColladaExporter() { - if ( mSceneOwned ) { + if (mSceneOwned) { delete mScene; } } @@ -170,9 +170,9 @@ void ColladaExporter::WriteFile() { WriteControllerLibrary(); WriteSceneLibrary(); - - // customized, Writes the animation library - WriteAnimationsLibrary(); + + // customized, Writes the animation library + WriteAnimationsLibrary(); // useless Collada fu at the end, just in case we haven't had enough indirections, yet. mOutput << startstr << "" << endstr; @@ -189,17 +189,17 @@ void ColladaExporter::WriteFile() { void ColladaExporter::WriteHeader() { static const ai_real epsilon = Math::getEpsilon(); static const aiQuaternion x_rot(aiMatrix3x3( - 0, -1, 0, - 1, 0, 0, - 0, 0, 1)); + 0, -1, 0, + 1, 0, 0, + 0, 0, 1)); static const aiQuaternion y_rot(aiMatrix3x3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1)); + 1, 0, 0, + 0, 1, 0, + 0, 0, 1)); static const aiQuaternion z_rot(aiMatrix3x3( - 1, 0, 0, - 0, 0, 1, - 0, -1, 0)); + 1, 0, 0, + 0, 0, 1, + 0, -1, 0)); static const unsigned int date_nb_chars = 20; char date_str[date_nb_chars]; @@ -215,39 +215,39 @@ void ColladaExporter::WriteHeader() { bool add_root_node = false; ai_real scale = 1.0; - if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { - scale = (ai_real) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0); + if (std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { + scale = (ai_real)((((double)scaling.x) + ((double)scaling.y) + ((double)scaling.z)) / 3.0); } else { add_root_node = true; } std::string up_axis = "Y_UP"; - if(rotation.Equal(x_rot, epsilon)) { + if (rotation.Equal(x_rot, epsilon)) { up_axis = "X_UP"; - } else if(rotation.Equal(y_rot, epsilon)) { + } else if (rotation.Equal(y_rot, epsilon)) { up_axis = "Y_UP"; - } else if(rotation.Equal(z_rot, epsilon)) { + } else if (rotation.Equal(z_rot, epsilon)) { up_axis = "Z_UP"; } else { add_root_node = true; } - if(! position.Equal(aiVector3D(0, 0, 0))) { + if (!position.Equal(aiVector3D(0, 0, 0))) { add_root_node = true; } - if(mScene->mRootNode->mNumChildren == 0) { + if (mScene->mRootNode->mNumChildren == 0) { add_root_node = true; } - if(add_root_node) { - aiScene* scene; + if (add_root_node) { + aiScene *scene; SceneCombiner::CopyScene(&scene, mScene); - aiNode* root = new aiNode("Scene"); + aiNode *root = new aiNode("Scene"); root->mNumChildren = 1; - root->mChildren = new aiNode*[root->mNumChildren]; + root->mChildren = new aiNode *[root->mNumChildren]; root->mChildren[0] = scene->mRootNode; scene->mRootNode->mParent = root; @@ -266,20 +266,24 @@ void ColladaExporter::WriteHeader() { PushTag(); // If no Scene metadata, use root node metadata - aiMetadata* meta = mScene->mMetaData; + aiMetadata *meta = mScene->mMetaData; if (nullptr == meta) { meta = mScene->mRootNode->mMetaData; } aiString value; if (!meta || !meta->Get("Author", value)) { - mOutput << startstr << "" << "Assimp" << "" << endstr; + mOutput << startstr << "" + << "Assimp" + << "" << endstr; } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; } if (nullptr == meta || !meta->Get(AI_METADATA_SOURCE_GENERATOR, value)) { - mOutput << startstr << "" << "Assimp Exporter" << "" << endstr; + mOutput << startstr << "" + << "Assimp Exporter" + << "" << endstr; } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; } @@ -336,26 +340,26 @@ void ColladaExporter::WriteTextures() { char str[buffer_size]; if (mScene->HasTextures()) { - for(unsigned int i = 0; i < mScene->mNumTextures; i++) { + for (unsigned int i = 0; i < mScene->mNumTextures; i++) { // It would be great to be able to create a directory in portable standard C++, but it's not the case, // so we just write the textures in the current directory. - aiTexture* texture = mScene->mTextures[i]; - if ( nullptr == texture ) { + aiTexture *texture = mScene->mTextures[i]; + if (nullptr == texture) { continue; } ASSIMP_itoa10(str, buffer_size, i + 1); - std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); + std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint); std::unique_ptr outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb")); - if(outfile == NULL) { + if (outfile == NULL) { throw DeadlyExportError("could not open output texture file: " + mPath + name); } - if(texture->mHeight == 0) { - outfile->Write((void*) texture->pcData, texture->mWidth, 1); + if (texture->mHeight == 0) { + outfile->Write((void *)texture->pcData, texture->mWidth, 1); } else { Bitmap::Save(texture, outfile.get()); } @@ -370,21 +374,20 @@ void ColladaExporter::WriteTextures() { // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteCamerasLibrary() { - if(mScene->HasCameras()) { + if (mScene->HasCameras()) { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumCameras; ++a) - WriteCamera( a); + for (size_t a = 0; a < mScene->mNumCameras; ++a) + WriteCamera(a); PopTag(); mOutput << startstr << "" << endstr; - } } -void ColladaExporter::WriteCamera(size_t pIndex){ +void ColladaExporter::WriteCamera(size_t pIndex) { const aiCamera *cam = mScene->mCameras[pIndex]; const std::string cameraName = XMLEscape(cam->mName.C_Str()); @@ -400,18 +403,17 @@ void ColladaExporter::WriteCamera(size_t pIndex){ //always perspective mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << ""<< - AI_RAD_TO_DEG(cam->mHorizontalFOV) - <<"" << endstr; + mOutput << startstr << "" << AI_RAD_TO_DEG(cam->mHorizontalFOV) + << "" << endstr; mOutput << startstr << "" - << cam->mAspect - << "" << endstr; + << cam->mAspect + << "" << endstr; mOutput << startstr << "" - << cam->mClipPlaneNear - << "" << endstr; + << cam->mClipPlaneNear + << "" << endstr; mOutput << startstr << "" - << cam->mClipPlaneFar - << "" << endstr; + << cam->mClipPlaneFar + << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -420,28 +422,25 @@ void ColladaExporter::WriteCamera(size_t pIndex){ mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } - // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteLightsLibrary() { - if(mScene->HasLights()) { + if (mScene->HasLights()) { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumLights; ++a) - WriteLight( a); + for (size_t a = 0; a < mScene->mNumLights; ++a) + WriteLight(a); PopTag(); mOutput << startstr << "" << endstr; - } } -void ColladaExporter::WriteLight(size_t pIndex){ +void ColladaExporter::WriteLight(size_t pIndex) { const aiLight *light = mScene->mLights[pIndex]; const std::string lightName = XMLEscape(light->mName.C_Str()); @@ -452,116 +451,111 @@ void ColladaExporter::WriteLight(size_t pIndex){ PushTag(); mOutput << startstr << "" << endstr; PushTag(); - switch(light->mType){ - case aiLightSource_AMBIENT: - WriteAmbienttLight(light); - break; - case aiLightSource_DIRECTIONAL: - WriteDirectionalLight(light); - break; - case aiLightSource_POINT: - WritePointLight(light); - break; - case aiLightSource_SPOT: - WriteSpotLight(light); - break; - case aiLightSource_AREA: - case aiLightSource_UNDEFINED: - case _aiLightSource_Force32Bit: - break; + switch (light->mType) { + case aiLightSource_AMBIENT: + WriteAmbienttLight(light); + break; + case aiLightSource_DIRECTIONAL: + WriteDirectionalLight(light); + break; + case aiLightSource_POINT: + WritePointLight(light); + break; + case aiLightSource_SPOT: + WriteSpotLight(light); + break; + case aiLightSource_AREA: + case aiLightSource_UNDEFINED: + case _aiLightSource_Force32Bit: + break; } PopTag(); mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } -void ColladaExporter::WritePointLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; +void ColladaExporter::WritePointLight(const aiLight *const light) { + const aiColor3D &color = light->mColorDiffuse; mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" - << color.r<<" "<" << endstr; + << color.r << " " << color.g << " " << color.b + << "" << endstr; mOutput << startstr << "" - << light->mAttenuationConstant - <<"" << endstr; + << light->mAttenuationConstant + << "" << endstr; mOutput << startstr << "" - << light->mAttenuationLinear - <<"" << endstr; + << light->mAttenuationLinear + << "" << endstr; mOutput << startstr << "" - << light->mAttenuationQuadratic - <<"" << endstr; + << light->mAttenuationQuadratic + << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } -void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; +void ColladaExporter::WriteDirectionalLight(const aiLight *const light) { + const aiColor3D &color = light->mColorDiffuse; mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" - << color.r<<" "<" << endstr; + << color.r << " " << color.g << " " << color.b + << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } -void ColladaExporter::WriteSpotLight(const aiLight *const light){ +void ColladaExporter::WriteSpotLight(const aiLight *const light) { - const aiColor3D &color= light->mColorDiffuse; + const aiColor3D &color = light->mColorDiffuse; mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" - << color.r<<" "<" << endstr; + << color.r << " " << color.g << " " << color.b + << "" << endstr; mOutput << startstr << "" - << light->mAttenuationConstant - <<"" << endstr; + << light->mAttenuationConstant + << "" << endstr; mOutput << startstr << "" - << light->mAttenuationLinear - <<"" << endstr; + << light->mAttenuationLinear + << "" << endstr; mOutput << startstr << "" - << light->mAttenuationQuadratic - <<"" << endstr; + << light->mAttenuationQuadratic + << "" << endstr; /* out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+ srcLight->mFalloffAngle); */ const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone); - mOutput << startstr <<"" - << fallOffAngle - <<"" << endstr; - double temp = light->mAngleOuterCone-light->mAngleInnerCone; + mOutput << startstr << "" + << fallOffAngle + << "" << endstr; + double temp = light->mAngleOuterCone - light->mAngleInnerCone; temp = std::cos(temp); - temp = std::log(temp)/std::log(0.1); - temp = 1/temp; + temp = std::log(temp) / std::log(0.1); + temp = 1 / temp; mOutput << startstr << "" - << temp - <<"" << endstr; - + << temp + << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } -void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ +void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { - const aiColor3D &color= light->mColorAmbient; + const aiColor3D &color = light->mColorAmbient; mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" - << color.r<<" "<" << endstr; + << color.r << " " << color.g << " " << color.b + << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; @@ -569,130 +563,121 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys -void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, - aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { - if( pSrcMat->GetTextureCount( pTexture) > 0 ) { - aiString texfile; - unsigned int uvChannel = 0; - pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); +void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial *pSrcMat, + aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) { + if (pSrcMat->GetTextureCount(pTexture) > 0) { + aiString texfile; + unsigned int uvChannel = 0; + pSrcMat->GetTexture(pTexture, 0, &texfile, NULL, &uvChannel); - std::string index_str(texfile.C_Str()); + std::string index_str(texfile.C_Str()); - if(index_str.size() != 0 && index_str[0] == '*') { - unsigned int index; + if (index_str.size() != 0 && index_str[0] == '*') { + unsigned int index; - index_str = index_str.substr(1, std::string::npos); + index_str = index_str.substr(1, std::string::npos); - try { - index = (unsigned int) strtoul10_64(index_str.c_str()); - } catch(std::exception& error) { - throw DeadlyExportError(error.what()); - } + try { + index = (unsigned int)strtoul10_64(index_str.c_str()); + } catch (std::exception &error) { + throw DeadlyExportError(error.what()); + } - std::map::const_iterator name = textures.find(index); + std::map::const_iterator name = textures.find(index); - if(name != textures.end()) { - poSurface.texture = name->second; + if (name != textures.end()) { + poSurface.texture = name->second; + } else { + throw DeadlyExportError("could not find embedded texture at index " + index_str); + } } else { - throw DeadlyExportError("could not find embedded texture at index " + index_str); + poSurface.texture = texfile.C_Str(); } - } else { - poSurface.texture = texfile.C_Str(); - } - poSurface.channel = uvChannel; - poSurface.exist = true; - } else { - if( pKey ) - poSurface.exist = pSrcMat->Get( pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; - } + poSurface.channel = uvChannel; + poSurface.exist = true; + } else { + if (pKey) + poSurface.exist = pSrcMat->Get(pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; + } } // ------------------------------------------------------------------------------------------------ // Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version. static bool isalnum_C(char c) { - return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) ); + return (nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", c)); } // ------------------------------------------------------------------------------------------------ // Writes an image entry for the given surface -void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) { - if( !pSurface.texture.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << ""; +void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &pNameAdd) { + if (!pSurface.texture.empty()) { + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << ""; - // URL encode image file name first, then XML encode on top - std::stringstream imageUrlEncoded; - for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) - { - if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' ) - imageUrlEncoded << *it; - else - imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; + // URL encode image file name first, then XML encode on top + std::stringstream imageUrlEncoded; + for (std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it) { + if (isalnum_C((unsigned char)*it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\') + imageUrlEncoded << *it; + else + imageUrlEncoded << '%' << std::hex << size_t((unsigned char)*it) << std::dec; + } + mOutput << XMLEscape(imageUrlEncoded.str()); + mOutput << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; } - mOutput << XMLEscape(imageUrlEncoded.str()); - mOutput << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes a color-or-texture entry into an effect definition -void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) -{ - if(pSurface.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - if( pSurface.texture.empty() ) - { - mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; +void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pImageName) { + if (pSurface.exist) { + mOutput << startstr << "<" << pTypeName << ">" << endstr; + PushTag(); + if (pSurface.texture.empty()) { + mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; + } else { + mOutput << startstr << "" << endstr; + } + PopTag(); + mOutput << startstr << "" << endstr; } - else - { - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes the two parameters necessary for referencing a texture in an effect entry -void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) -{ - // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture - if( !pSurface.texture.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; +void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pMatName) { + // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture + if (!pSurface.texture.empty()) { + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + } } // ------------------------------------------------------------------------------------------------ // Writes a scalar property -void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) -{ - if(pProperty.exist) { +void ColladaExporter::WriteFloatEntry(const Property &pProperty, const std::string &pTypeName) { + if (pProperty.exist) { mOutput << startstr << "<" << pTypeName << ">" << endstr; PushTag(); mOutput << startstr << "" << pProperty.value << "" << endstr; @@ -703,170 +688,162 @@ void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::str // ------------------------------------------------------------------------------------------------ // Writes the material setup -void ColladaExporter::WriteMaterials() -{ - materials.resize( mScene->mNumMaterials); +void ColladaExporter::WriteMaterials() { + materials.resize(mScene->mNumMaterials); - /// collect all materials from the scene - size_t numTextures = 0; - for( size_t a = 0; a < mScene->mNumMaterials; ++a ) - { - const aiMaterial* mat = mScene->mMaterials[a]; + /// collect all materials from the scene + size_t numTextures = 0; + for (size_t a = 0; a < mScene->mNumMaterials; ++a) { + const aiMaterial *mat = mScene->mMaterials[a]; - aiString name; - if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { - name = "mat"; - materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); - } else { - // try to use the material's name if no other material has already taken it, else append # - std::string testName = name.C_Str(); - size_t materialCountWithThisName = 0; - for( size_t i = 0; i < a; i ++ ) { - if( materials[i].name == testName ) { - materialCountWithThisName ++; + aiString name; + if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) { + name = "mat"; + materials[a].name = std::string("m") + to_string(a) + name.C_Str(); + } else { + // try to use the material's name if no other material has already taken it, else append # + std::string testName = name.C_Str(); + size_t materialCountWithThisName = 0; + for (size_t i = 0; i < a; i++) { + if (materials[i].name == testName) { + materialCountWithThisName++; + } + } + if (materialCountWithThisName == 0) { + materials[a].name = name.C_Str(); + } else { + materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); + } } - } - if( materialCountWithThisName == 0 ) { - materials[a].name = name.C_Str(); - } else { - materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); - } - } - aiShadingMode shading = aiShadingMode_Flat; - materials[a].shading_model = "phong"; - if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { - if(shading == aiShadingMode_Phong) { - materials[a].shading_model = "phong"; - } else if(shading == aiShadingMode_Blinn) { - materials[a].shading_model = "blinn"; - } else if(shading == aiShadingMode_NoShading) { - materials[a].shading_model = "constant"; - } else if(shading == aiShadingMode_Gouraud) { - materials[a].shading_model = "lambert"; + aiShadingMode shading = aiShadingMode_Flat; + materials[a].shading_model = "phong"; + if (mat->Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { + if (shading == aiShadingMode_Phong) { + materials[a].shading_model = "phong"; + } else if (shading == aiShadingMode_Blinn) { + materials[a].shading_model = "blinn"; + } else if (shading == aiShadingMode_NoShading) { + materials[a].shading_model = "constant"; + } else if (shading == aiShadingMode_Gouraud) { + materials[a].shading_model = "lambert"; + } } + + ReadMaterialSurface(materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + if (!materials[a].ambient.texture.empty()) numTextures++; + ReadMaterialSurface(materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + if (!materials[a].diffuse.texture.empty()) numTextures++; + ReadMaterialSurface(materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); + if (!materials[a].specular.texture.empty()) numTextures++; + ReadMaterialSurface(materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); + if (!materials[a].emissive.texture.empty()) numTextures++; + ReadMaterialSurface(materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); + if (!materials[a].reflective.texture.empty()) numTextures++; + ReadMaterialSurface(materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); + if (!materials[a].transparent.texture.empty()) numTextures++; + ReadMaterialSurface(materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); + if (!materials[a].normal.texture.empty()) numTextures++; + + materials[a].shininess.exist = mat->Get(AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; + materials[a].transparency.exist = mat->Get(AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; + materials[a].index_refraction.exist = mat->Get(AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; } - ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - if( !materials[a].ambient.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - if( !materials[a].diffuse.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - if( !materials[a].specular.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); - if( !materials[a].emissive.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); - if( !materials[a].reflective.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); - if( !materials[a].transparent.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); - if( !materials[a].normal.texture.empty() ) numTextures++; - - materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; - materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; - materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; - } - - // output textures if present - if( numTextures > 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); - WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); - WriteImageEntry( mat.specular, mat.name + "-specular-image"); - WriteImageEntry( mat.emissive, mat.name + "-emission-image"); - WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); - WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); - WriteImageEntry( mat.normal, mat.name + "-normal-image"); + // output textures if present + if (numTextures > 0) { + mOutput << startstr << "" << endstr; + PushTag(); + for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { + const Material &mat = *it; + WriteImageEntry(mat.ambient, mat.name + "-ambient-image"); + WriteImageEntry(mat.diffuse, mat.name + "-diffuse-image"); + WriteImageEntry(mat.specular, mat.name + "-specular-image"); + WriteImageEntry(mat.emissive, mat.name + "-emission-image"); + WriteImageEntry(mat.reflective, mat.name + "-reflective-image"); + WriteImageEntry(mat.transparent, mat.name + "-transparent-image"); + WriteImageEntry(mat.normal, mat.name + "-normal-image"); + } + PopTag(); + mOutput << startstr << "" << endstr; } - PopTag(); - mOutput << startstr << "" << endstr; - } - // output effects - those are the actual carriers of information - if( !materials.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); + // output effects - those are the actual carriers of information + if (!materials.empty()) { + mOutput << startstr << "" << endstr; + PushTag(); + for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { + const Material &mat = *it; + // this is so ridiculous it must be right + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); - // write sampler- and surface params for the texture entries - WriteTextureParamEntry( mat.emissive, "emission", mat.name); - WriteTextureParamEntry( mat.ambient, "ambient", mat.name); - WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); - WriteTextureParamEntry( mat.specular, "specular", mat.name); - WriteTextureParamEntry( mat.reflective, "reflective", mat.name); - WriteTextureParamEntry( mat.transparent, "transparent", mat.name); - WriteTextureParamEntry( mat.normal, "normal", mat.name); + // write sampler- and surface params for the texture entries + WriteTextureParamEntry(mat.emissive, "emission", mat.name); + WriteTextureParamEntry(mat.ambient, "ambient", mat.name); + WriteTextureParamEntry(mat.diffuse, "diffuse", mat.name); + WriteTextureParamEntry(mat.specular, "specular", mat.name); + WriteTextureParamEntry(mat.reflective, "reflective", mat.name); + WriteTextureParamEntry(mat.transparent, "transparent", mat.name); + WriteTextureParamEntry(mat.normal, "normal", mat.name); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "<" << mat.shading_model << ">" << endstr; - PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "<" << mat.shading_model << ">" << endstr; + PushTag(); - WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); - WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); - WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); - WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); - WriteFloatEntry(mat.shininess, "shininess"); - WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); - WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); - WriteFloatEntry(mat.transparency, "transparency"); - WriteFloatEntry(mat.index_refraction, "index_of_refraction"); + WriteTextureColorEntry(mat.emissive, "emission", mat.name + "-emission-sampler"); + WriteTextureColorEntry(mat.ambient, "ambient", mat.name + "-ambient-sampler"); + WriteTextureColorEntry(mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); + WriteTextureColorEntry(mat.specular, "specular", mat.name + "-specular-sampler"); + WriteFloatEntry(mat.shininess, "shininess"); + WriteTextureColorEntry(mat.reflective, "reflective", mat.name + "-reflective-sampler"); + WriteTextureColorEntry(mat.transparent, "transparent", mat.name + "-transparent-sampler"); + WriteFloatEntry(mat.transparency, "transparency"); + WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - if(! mat.normal.texture.empty()) { - WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); - } + if (!mat.normal.texture.empty()) { + WriteTextureColorEntry(mat.normal, "bump", mat.name + "-normal-sampler"); + } - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + } + PopTag(); + mOutput << startstr << "" << endstr; + + // write materials - they're just effect references + mOutput << startstr << "" << endstr; + PushTag(); + for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { + const Material &mat = *it; + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + } + PopTag(); + mOutput << startstr << "" << endstr; } - PopTag(); - mOutput << startstr << "" << endstr; - - // write materials - they're just effect references - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes the controller library -void ColladaExporter::WriteControllerLibrary() -{ +void ColladaExporter::WriteControllerLibrary() { mOutput << startstr << "" << endstr; PushTag(); - - for( size_t a = 0; a < mScene->mNumMeshes; ++a) { - WriteController( a); + + for (size_t a = 0; a < mScene->mNumMeshes; ++a) { + WriteController(a); } PopTag(); @@ -875,20 +852,19 @@ void ColladaExporter::WriteControllerLibrary() // ------------------------------------------------------------------------------------------------ // Writes a skin controller of the given mesh -void ColladaExporter::WriteController( size_t pIndex) -{ - const aiMesh* mesh = mScene->mMeshes[pIndex]; +void ColladaExporter::WriteController(size_t pIndex) { + const aiMesh *mesh = mScene->mMeshes[pIndex]; const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); const std::string idstrEscaped = XMLIDEncode(idstr); - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) return; - if ( mesh->mNumBones == 0 ) + if (mesh->mNumBones == 0) return; mOutput << startstr << ""<< endstr; + mOutput << "name=\"skinCluster" << pIndex << "\">" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -913,14 +889,14 @@ void ColladaExporter::WriteController( size_t pIndex) mOutput << startstr << "mNumBones << "\">"; - for( size_t i = 0; i < mesh->mNumBones; ++i ) + for (size_t i = 0; i < mesh->mNumBones; ++i) mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; mOutput << "" << endstr; mOutput << startstr << "" << endstr; PushTag(); - + mOutput << startstr << "mNumBones << "\" stride=\"" << 1 << "\">" << endstr; PushTag(); @@ -937,21 +913,21 @@ void ColladaExporter::WriteController( size_t pIndex) std::vector bind_poses; bind_poses.reserve(mesh->mNumBones * 16); - for(unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned int j = 0; j < 4; ++j) + for (unsigned int i = 0; i < mesh->mNumBones; ++i) + for (unsigned int j = 0; j < 4; ++j) bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); - WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); + WriteFloatArray(idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real *)bind_poses.data(), bind_poses.size() / 16); bind_poses.clear(); - + std::vector skin_weights; skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + for (size_t i = 0; i < mesh->mNumBones; ++i) + for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight); - WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size()); + WriteFloatArray(idstr + "-skin-weights", FloatType_Weight, (const ai_real *)skin_weights.data(), skin_weights.size()); skin_weights.clear(); @@ -973,11 +949,11 @@ void ColladaExporter::WriteController( size_t pIndex) mOutput << startstr << ""; std::vector num_influences(mesh->mNumVertices, (ai_uint)0); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + for (size_t i = 0; i < mesh->mNumBones; ++i) + for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId]; - for( size_t i = 0; i < mesh->mNumVertices; ++i) + for (size_t i = 0; i < mesh->mNumVertices; ++i) mOutput << num_influences[i] << " "; mOutput << "" << endstr; @@ -987,22 +963,18 @@ void ColladaExporter::WriteController( size_t pIndex) ai_uint joint_weight_indices_length = 0; std::vector accum_influences; accum_influences.reserve(num_influences.size()); - for( size_t i = 0; i < num_influences.size(); ++i) - { + for (size_t i = 0; i < num_influences.size(); ++i) { accum_influences.push_back(joint_weight_indices_length); joint_weight_indices_length += num_influences[i]; } ai_uint weight_index = 0; std::vector joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); - for( unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - { + for (unsigned int i = 0; i < mesh->mNumBones; ++i) + for (unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) { unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; - for( ai_uint k = 0; k < num_influences[vId]; ++k) - { - if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) - { + for (ai_uint k = 0; k < num_influences[vId]; ++k) { + if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) { joint_weight_indices[2 * (accum_influences[vId] + k)] = i; joint_weight_indices[2 * (accum_influences[vId] + k) + 1] = weight_index; break; @@ -1011,7 +983,7 @@ void ColladaExporter::WriteController( size_t pIndex) ++weight_index; } - for( size_t i = 0; i < joint_weight_indices.size(); ++i) + for (size_t i = 0; i < joint_weight_indices.size(); ++i) mOutput << joint_weight_indices[i] << " "; num_influences.clear(); @@ -1025,20 +997,19 @@ void ColladaExporter::WriteController( size_t pIndex) PopTag(); mOutput << startstr << "" << endstr; - + PopTag(); mOutput << startstr << "" << endstr; } // ------------------------------------------------------------------------------------------------ // Writes the geometry library -void ColladaExporter::WriteGeometryLibrary() -{ +void ColladaExporter::WriteGeometryLibrary() { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteGeometry( a); + for (size_t a = 0; a < mScene->mNumMeshes; ++a) + WriteGeometry(a); PopTag(); mOutput << startstr << "" << endstr; @@ -1046,14 +1017,13 @@ void ColladaExporter::WriteGeometryLibrary() // ------------------------------------------------------------------------------------------------ // Writes the given mesh -void ColladaExporter::WriteGeometry( size_t pIndex) -{ - const aiMesh* mesh = mScene->mMeshes[pIndex]; +void ColladaExporter::WriteGeometry(size_t pIndex) { + const aiMesh *mesh = mScene->mMeshes[pIndex]; const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); const std::string geometryName = XMLEscape(idstr); const std::string geometryId = XMLIDEncode(idstr); - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) return; // opening tag @@ -1064,31 +1034,29 @@ void ColladaExporter::WriteGeometry( size_t pIndex) PushTag(); // Positions - WriteFloatArray( idstr + "-positions", FloatType_Vector, (ai_real*) mesh->mVertices, mesh->mNumVertices); + WriteFloatArray(idstr + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices); // Normals, if any - if( mesh->HasNormals() ) - WriteFloatArray( idstr + "-normals", FloatType_Vector, (ai_real*) mesh->mNormals, mesh->mNumVertices); + if (mesh->HasNormals()) + WriteFloatArray(idstr + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices); // texture coords - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - { - WriteFloatArray( idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, - (ai_real*) mesh->mTextureCoords[a], mesh->mNumVertices); + for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (mesh->HasTextureCoords(static_cast(a))) { + WriteFloatArray(idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, + (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices); } } // vertex colors - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasVertexColors(static_cast(a)) ) - WriteFloatArray( idstr + "-color" + to_string(a), FloatType_Color, (ai_real*) mesh->mColors[a], mesh->mNumVertices); + for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (mesh->HasVertexColors(static_cast(a))) + WriteFloatArray(idstr + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices); } // assemble vertex structure // Only write input for POSITION since we will write other as shared inputs in polygon definition - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -1097,37 +1065,38 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // count the number of lines, triangles and polygon meshes int countLines = 0; int countPoly = 0; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices == 2) countLines++; - else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++; + for (size_t a = 0; a < mesh->mNumFaces; ++a) { + if (mesh->mFaces[a].mNumIndices == 2) + countLines++; + else if (mesh->mFaces[a].mNumIndices >= 3) + countPoly++; } // lines - if (countLines) - { + if (countLines) { mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) + if (mesh->HasNormals()) mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; + for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (mesh->HasTextureCoords(static_cast(a))) + mOutput << startstr << "" << endstr; } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + for (size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { + if (mesh->HasVertexColors(static_cast(a))) + mOutput << startstr << "" << endstr; } mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; + for (size_t a = 0; a < mesh->mNumFaces; ++a) { + const aiFace &face = mesh->mFaces[a]; if (face.mNumIndices != 2) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) + for (size_t b = 0; b < face.mNumIndices; ++b) mOutput << face.mIndices[b] << " "; } mOutput << "

" << endstr; @@ -1138,38 +1107,37 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // triangle - don't use it, because compatibility problems // polygons - if (countPoly) - { + if (countPoly) { mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) + if (mesh->HasNormals()) mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; + for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (mesh->HasTextureCoords(static_cast(a))) + mOutput << startstr << "" << endstr; } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + for (size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { + if (mesh->HasVertexColors(static_cast(a))) + mOutput << startstr << "" << endstr; } mOutput << startstr << ""; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { + for (size_t a = 0; a < mesh->mNumFaces; ++a) { if (mesh->mFaces[a].mNumIndices < 3) continue; mOutput << mesh->mFaces[a].mNumIndices << " "; } mOutput << "" << endstr; mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; + for (size_t a = 0; a < mesh->mNumFaces; ++a) { + const aiFace &face = mesh->mFaces[a]; if (face.mNumIndices < 3) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) + for (size_t b = 0; b < face.mNumIndices; ++b) mOutput << face.mIndices[b] << " "; } mOutput << "

" << endstr; @@ -1186,20 +1154,18 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // ------------------------------------------------------------------------------------------------ // Writes a float array of the given type -void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) -{ +void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount) { size_t floatsPerElement = 0; - switch( pType ) - { - case FloatType_Vector: floatsPerElement = 3; break; - case FloatType_TexCoord2: floatsPerElement = 2; break; - case FloatType_TexCoord3: floatsPerElement = 3; break; - case FloatType_Color: floatsPerElement = 3; break; - case FloatType_Mat4x4: floatsPerElement = 16; break; - case FloatType_Weight: floatsPerElement = 1; break; - case FloatType_Time: floatsPerElement = 1; break; - default: - return; + switch (pType) { + case FloatType_Vector: floatsPerElement = 3; break; + case FloatType_TexCoord2: floatsPerElement = 2; break; + case FloatType_TexCoord3: floatsPerElement = 3; break; + case FloatType_Color: floatsPerElement = 3; break; + case FloatType_Mat4x4: floatsPerElement = 16; break; + case FloatType_Weight: floatsPerElement = 1; break; + case FloatType_Time: floatsPerElement = 1; break; + default: + return; } std::string arrayId = XMLIDEncode(pIdString) + "-array"; @@ -1211,26 +1177,19 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << " "; PushTag(); - if( pType == FloatType_TexCoord2 ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { - mOutput << pData[a*3+0] << " "; - mOutput << pData[a*3+1] << " "; + if (pType == FloatType_TexCoord2) { + for (size_t a = 0; a < pElementCount; ++a) { + mOutput << pData[a * 3 + 0] << " "; + mOutput << pData[a * 3 + 1] << " "; } - } - else if( pType == FloatType_Color ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { - mOutput << pData[a*4+0] << " "; - mOutput << pData[a*4+1] << " "; - mOutput << pData[a*4+2] << " "; + } else if (pType == FloatType_Color) { + for (size_t a = 0; a < pElementCount; ++a) { + mOutput << pData[a * 4 + 0] << " "; + mOutput << pData[a * 4 + 1] << " "; + mOutput << pData[a * 4 + 2] << " "; } - } - else - { - for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) + } else { + for (size_t a = 0; a < pElementCount * floatsPerElement; ++a) mOutput << pData[a] << " "; } mOutput << "" << endstr; @@ -1242,45 +1201,43 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << "" << endstr; PushTag(); - switch( pType ) - { - case FloatType_Vector: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; + switch (pType) { + case FloatType_Vector: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; - case FloatType_TexCoord2: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; + case FloatType_TexCoord2: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; - case FloatType_TexCoord3: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; + case FloatType_TexCoord3: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; - case FloatType_Color: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; + case FloatType_Color: + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + break; - case FloatType_Mat4x4: - mOutput << startstr << "" << endstr; - break; + case FloatType_Mat4x4: + mOutput << startstr << "" << endstr; + break; - case FloatType_Weight: - mOutput << startstr << "" << endstr; - break; + case FloatType_Weight: + mOutput << startstr << "" << endstr; + break; - // customized, add animation related - case FloatType_Time: - mOutput << startstr << "" << endstr; - break; - - } + // customized, add animation related + case FloatType_Time: + mOutput << startstr << "" << endstr; + break; + } PopTag(); mOutput << startstr << "" << endstr; @@ -1292,8 +1249,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy // ------------------------------------------------------------------------------------------------ // Writes the scene library -void ColladaExporter::WriteSceneLibrary() -{ +void ColladaExporter::WriteSceneLibrary() { const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str()); const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str()); @@ -1303,8 +1259,8 @@ void ColladaExporter::WriteSceneLibrary() PushTag(); // start recursive write at the root node - for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a ) - WriteNode( mScene, mScene->mRootNode->mChildren[a]); + for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a) + WriteNode(mScene, mScene->mRootNode->mChildren[a]); PopTag(); mOutput << startstr << "" << endstr; @@ -1312,182 +1268,180 @@ void ColladaExporter::WriteSceneLibrary() mOutput << startstr << "" << endstr; } // ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationLibrary(size_t pIndex) -{ - const aiAnimation * anim = mScene->mAnimations[pIndex]; - - if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) - return; - - const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); - std::string idstr = anim->mName.C_Str(); - std::string ending = std::string( "AnimId" ) + to_string(pIndex); - if (idstr.length() >= ending.length()) { - if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) { - idstr = idstr + ending; - } - } else { - idstr = idstr + ending; - } +void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { + const aiAnimation *anim = mScene->mAnimations[pIndex]; - const std::string idstrEscaped = XMLIDEncode(idstr); - - mOutput << startstr << "" << endstr; - PushTag(); + if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0) + return; + + const std::string animation_name_escaped = XMLEscape(anim->mName.C_Str()); + std::string idstr = anim->mName.C_Str(); + std::string ending = std::string("AnimId") + to_string(pIndex); + if (idstr.length() >= ending.length()) { + if (0 != idstr.compare(idstr.length() - ending.length(), ending.length(), ending)) { + idstr = idstr + ending; + } + } else { + idstr = idstr + ending; + } + + const std::string idstrEscaped = XMLIDEncode(idstr); + + mOutput << startstr << "" << endstr; + PushTag(); std::string cur_node_idstr; - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - // sanity check + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim *nodeAnim = anim->mChannels[a]; + + // sanity check if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) { continue; } - - { + + { cur_node_idstr.clear(); cur_node_idstr += nodeAnim->mNodeName.data; cur_node_idstr += std::string("_matrix-input"); - std::vector frames; - for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime)); - } - - WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size()); - frames.clear(); - } - - { + std::vector frames; + for (size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime)); + } + + WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size()); + frames.clear(); + } + + { cur_node_idstr.clear(); cur_node_idstr += nodeAnim->mNodeName.data; cur_node_idstr += std::string("_matrix-output"); - - std::vector keyframes; - keyframes.reserve(nodeAnim->mNumPositionKeys * 16); - for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; - aiMatrix4x4 ScalingM; // identity - ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; - - aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue; - aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() ); - aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1); - - aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue; - aiMatrix4x4 TranslationM; // identity - TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z; - - // Combine the above transformations - aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; - - for( unsigned int j = 0; j < 4; ++j) { - keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); + + std::vector keyframes; + keyframes.reserve(nodeAnim->mNumPositionKeys * 16); + for (size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; + aiMatrix4x4 ScalingM; // identity + ScalingM[0][0] = Scaling.x; + ScalingM[1][1] = Scaling.y; + ScalingM[2][2] = Scaling.z; + + aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue; + aiMatrix4x4 s = aiMatrix4x4(RotationQ.GetMatrix()); + aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1); + + aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue; + aiMatrix4x4 TranslationM; // identity + TranslationM[0][3] = Translation.x; + TranslationM[1][3] = Translation.y; + TranslationM[2][3] = Translation.z; + + // Combine the above transformations + aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; + + for (unsigned int j = 0; j < 4; ++j) { + keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); } - } - - WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16); - } - - { - std::vector names; - for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT - || nodeAnim->mPreState == aiAnimBehaviour_LINEAR - || nodeAnim->mPreState == aiAnimBehaviour_REPEAT - ) { - names.push_back( "LINEAR" ); - } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) { - names.push_back( "STEP" ); - } - } - - const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); - std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array"; - - mOutput << startstr << "" << endstr; - PushTag(); - - // source array - mOutput << startstr << " "; - for( size_t aa = 0; aa < names.size(); ++aa ) { - mOutput << names[aa] << " "; } - mOutput << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; + WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16); + } - PopTag(); - mOutput << startstr << "" << endstr; - } - } - - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - { - // samplers - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - } - } - - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - { - // channels - mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLIDEncode(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; - } - } - - PopTag(); - mOutput << startstr << "" << endstr; - + { + std::vector names; + for (size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + if (nodeAnim->mPreState == aiAnimBehaviour_DEFAULT || nodeAnim->mPreState == aiAnimBehaviour_LINEAR || nodeAnim->mPreState == aiAnimBehaviour_REPEAT) { + names.push_back("LINEAR"); + } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) { + names.push_back("STEP"); + } + } + + const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); + std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array"; + + mOutput << startstr << "" << endstr; + PushTag(); + + // source array + mOutput << startstr << " "; + for (size_t aa = 0; aa < names.size(); ++aa) { + mOutput << names[aa] << " "; + } + mOutput << "" << endstr; + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + } + } + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim *nodeAnim = anim->mChannels[a]; + + { + // samplers + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "mNodeName.data + std::string("_matrix-input")) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-output")) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation")) << "\"/>" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + } + } + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim *nodeAnim = anim->mChannels[a]; + + { + // channels + mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler")) << "\" target=\"" << XMLIDEncode(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; + } + } + + PopTag(); + mOutput << startstr << "" << endstr; } // ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationsLibrary() -{ - if ( mScene->mNumAnimations > 0 ) { - mOutput << startstr << "" << endstr; - PushTag(); - - // start recursive write at the root node - for( size_t a = 0; a < mScene->mNumAnimations; ++a) - WriteAnimationLibrary( a ); +void ColladaExporter::WriteAnimationsLibrary() { + if (mScene->mNumAnimations > 0) { + mOutput << startstr << "" << endstr; + PushTag(); - PopTag(); - mOutput << startstr << "" << endstr; - } + // start recursive write at the root node + for (size_t a = 0; a < mScene->mNumAnimations; ++a) + WriteAnimationLibrary(a); + + PopTag(); + mOutput << startstr << "" << endstr; + } } // ------------------------------------------------------------------------------------------------ // Helper to find a bone by name in the scene -aiBone* findBone( const aiScene* scene, const char * name) { - for (size_t m=0; mmNumMeshes; m++) { - aiMesh * mesh = scene->mMeshes[m]; - for (size_t b=0; bmNumBones; b++) { - aiBone * bone = mesh->mBones[b]; +aiBone *findBone(const aiScene *scene, const char *name) { + for (size_t m = 0; m < scene->mNumMeshes; m++) { + aiMesh *mesh = scene->mMeshes[m]; + for (size_t b = 0; b < mesh->mNumBones; b++) { + aiBone *bone = mesh->mBones[b]; if (0 == strcmp(name, bone->mName.C_Str())) { return bone; } @@ -1497,65 +1451,61 @@ aiBone* findBone( const aiScene* scene, const char * name) { } // ------------------------------------------------------------------------------------------------ -const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) -{ - if ( aNode && bone && aNode->mName == bone->mName ) { - return aNode; - } - - if ( aNode && bone ) { - for (unsigned int i=0; i < aNode->mNumChildren; ++i) { - aiNode * aChild = aNode->mChildren[i]; - const aiNode * foundFromChild = 0; - if ( aChild ) { - foundFromChild = findBoneNode( aChild, bone ); - if ( foundFromChild ) return foundFromChild; - } - } - } - - return NULL; +const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) { + if (aNode && bone && aNode->mName == bone->mName) { + return aNode; + } + + if (aNode && bone) { + for (unsigned int i = 0; i < aNode->mNumChildren; ++i) { + aiNode *aChild = aNode->mChildren[i]; + const aiNode *foundFromChild = 0; + if (aChild) { + foundFromChild = findBoneNode(aChild, bone); + if (foundFromChild) return foundFromChild; + } + } + } + + return NULL; } -const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) -{ - std::set topParentBoneNodes; - if ( mesh && mesh->mNumBones > 0 ) { - for (unsigned int i=0; i < mesh->mNumBones; ++i) { - aiBone * bone = mesh->mBones[i]; +const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) { + std::set topParentBoneNodes; + if (mesh && mesh->mNumBones > 0) { + for (unsigned int i = 0; i < mesh->mNumBones; ++i) { + aiBone *bone = mesh->mBones[i]; - const aiNode * node = findBoneNode( scene->mRootNode, bone); - if ( node ) { - while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) { - node = node->mParent; - } - topParentBoneNodes.insert( node ); - } - } - } - - if ( !topParentBoneNodes.empty() ) { - const aiNode * parentBoneNode = *topParentBoneNodes.begin(); - if ( topParentBoneNodes.size() == 1 ) { - return parentBoneNode; - } else { - for (auto it : topParentBoneNodes) { - if ( it->mParent ) return it->mParent; - } - return parentBoneNode; - } - } - - return NULL; + const aiNode *node = findBoneNode(scene->mRootNode, bone); + if (node) { + while (node->mParent && findBone(scene, node->mParent->mName.C_Str()) != 0) { + node = node->mParent; + } + topParentBoneNodes.insert(node); + } + } + } + + if (!topParentBoneNodes.empty()) { + const aiNode *parentBoneNode = *topParentBoneNodes.begin(); + if (topParentBoneNodes.size() == 1) { + return parentBoneNode; + } else { + for (auto it : topParentBoneNodes) { + if (it->mParent) return it->mParent; + } + return parentBoneNode; + } + } + + return NULL; } // ------------------------------------------------------------------------------------------------ // Recursively writes the given node -void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) -{ +void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { // the node must have a name - if (pNode->mName.length == 0) - { + if (pNode->mName.length == 0) { std::stringstream ss; ss << "Node_" << pNode; pNode->mName.Set(ss.str()); @@ -1563,7 +1513,7 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // If the node is associated with a bone, it is a joint node (JOINT) // otherwise it is a normal node (NODE) - const char * node_type; + const char *node_type; bool is_joint, is_skeleton_root = false; if (nullptr == findBone(pScene, pNode->mName.C_Str())) { node_type = "NODE"; @@ -1578,14 +1528,14 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) const std::string node_id = XMLIDEncode(pNode->mName.data); const std::string node_name = XMLEscape(pNode->mName.data); - mOutput << startstr << "" << endstr; @@ -1599,8 +1549,8 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // When importing from Collada, the mLookAt is set to 0, 0, -1, and the node transform is unchanged. // When importing from a different format, mLookAt is set to 0, 0, 1. Therefore, the local camera // coordinate system must be changed to matche the Collada specification. - for (size_t i = 0; imNumCameras; i++){ - if (mScene->mCameras[i]->mName == pNode->mName){ + for (size_t i = 0; i < mScene->mNumCameras; i++) { + if (mScene->mCameras[i]->mName == pNode->mName) { aiMatrix4x4 sourceView; mScene->mCameras[i]->GetCameraMatrix(sourceView); @@ -1610,95 +1560,90 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) break; } } - - // customized, sid should be 'matrix' to match with loader code. + + // customized, sid should be 'matrix' to match with loader code. //mOutput << startstr << ""; - mOutput << startstr << ""; - + mOutput << startstr << ""; + mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4; mOutput << "" << endstr; - if(pNode->mNumMeshes==0){ + if (pNode->mNumMeshes == 0) { //check if it is a camera node - for(size_t i=0; imNumCameras; i++){ - if(mScene->mCameras[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; + for (size_t i = 0; i < mScene->mNumCameras; i++) { + if (mScene->mCameras[i]->mName == pNode->mName) { + mOutput << startstr << "" << endstr; break; } } //check if it is a light node - for(size_t i=0; imNumLights; i++){ - if(mScene->mLights[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; + for (size_t i = 0; i < mScene->mNumLights; i++) { + if (mScene->mLights[i]->mName == pNode->mName) { + mOutput << startstr << "" << endstr; break; } } - }else - // instance every geometry - for( size_t a = 0; a < pNode->mNumMeshes; ++a ) - { - const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; - // do not instantiate mesh if empty. I wonder how this could happen - if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - continue; + } else + // instance every geometry + for (size_t a = 0; a < pNode->mNumMeshes; ++a) { + const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[a]]; + // do not instantiate mesh if empty. I wonder how this could happen + if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) + continue; - const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); + const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); - if( mesh->mNumBones == 0 ) - { - mOutput << startstr << "" << endstr; + if (mesh->mNumBones == 0) { + mOutput << startstr << "" << endstr; + PushTag(); + } else { + mOutput << startstr + << "" + << endstr; + PushTag(); + + // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. + // use the first bone to find skeleton root + const aiNode *skeletonRootBoneNode = findSkeletonRootNode(pScene, mesh); + if (skeletonRootBoneNode) { + mFoundSkeletonRootNodeID = XMLIDEncode(skeletonRootBoneNode->mName.C_Str()); + } + mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; + } + mOutput << startstr << "" << endstr; PushTag(); - } - else - { - mOutput << startstr - << "" - << endstr; + mOutput << startstr << "" << endstr; PushTag(); + mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; + PushTag(); + for (size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa) { + if (mesh->HasTextureCoords(static_cast(aa))) + // semantic as in + // input_semantic as in + // input_set as in + mOutput << startstr << "" << endstr; + } + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; - // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. - // use the first bone to find skeleton root - const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh ); - if ( skeletonRootBoneNode ) { - mFoundSkeletonRootNodeID = XMLIDEncode( skeletonRootBoneNode->mName.C_Str() ); - } - mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; + PopTag(); + if (mesh->mNumBones == 0) + mOutput << startstr << "" << endstr; + else + mOutput << startstr << "" << endstr; } - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; - PushTag(); - for( size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa ) - { - if( mesh->HasTextureCoords( static_cast(aa) ) ) - // semantic as in - // input_semantic as in - // input_set as in - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - if( mesh->mNumBones == 0) - mOutput << startstr << "" << endstr; - else - mOutput << startstr << "" << endstr; - } // recurse into subnodes - for( size_t a = 0; a < pNode->mNumChildren; ++a ) - WriteNode( pScene, pNode->mChildren[a]); + for (size_t a = 0; a < pNode->mNumChildren; ++a) + WriteNode(pScene, pNode->mChildren[a]); PopTag(); mOutput << startstr << "" << endstr; diff --git a/code/Collada/ColladaExporter.h b/code/Collada/ColladaExporter.h index f6c66e279..fa7e6ee80 100644 --- a/code/Collada/ColladaExporter.h +++ b/code/Collada/ColladaExporter.h @@ -47,29 +47,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_COLLADAEXPORTER_H_INC #include +#include #include #include -#include #include +#include #include #include -#include #include struct aiScene; struct aiNode; -namespace Assimp -{ +namespace Assimp { /// Helper class to export a given scene to a Collada file. Just for my personal /// comfort when implementing it. -class ColladaExporter -{ +class ColladaExporter { public: /// Constructor for a specific scene to export - ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file); + ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file); /// Destructor virtual ~ColladaExporter(); @@ -107,43 +105,49 @@ protected: void WriteControllerLibrary(); /// Writes a skin controller of the given mesh - void WriteController( size_t pIndex); + void WriteController(size_t pIndex); /// Writes the geometry library void WriteGeometryLibrary(); /// Writes the given mesh - void WriteGeometry( size_t pIndex); + void WriteGeometry(size_t pIndex); //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight }; // customized to add animation related type - enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time }; + enum FloatDataType { FloatType_Vector, + FloatType_TexCoord2, + FloatType_TexCoord3, + FloatType_Color, + FloatType_Mat4x4, + FloatType_Weight, + FloatType_Time }; /// Writes a float array of the given type - void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount); + void WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount); /// Writes the scene library void WriteSceneLibrary(); - // customized, Writes the animation library - void WriteAnimationsLibrary(); - void WriteAnimationLibrary( size_t pIndex); - std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call. - + // customized, Writes the animation library + void WriteAnimationsLibrary(); + void WriteAnimationLibrary(size_t pIndex); + std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call. + /// Recursively writes the given node - void WriteNode( const aiScene* scene, aiNode* pNode); + void WriteNode(const aiScene *scene, aiNode *pNode); /// Enters a new xml element, which increases the indentation - void PushTag() { startstr.append( " "); } + void PushTag() { startstr.append(" "); } /// Leaves an element, decreasing the indentation - void PopTag() { - ai_assert( startstr.length() > 1); - startstr.erase( startstr.length() - 2); + void PopTag() { + ai_assert(startstr.length() > 1); + startstr.erase(startstr.length() - 2); } /// Creates a mesh ID for the given mesh - std::string GetMeshId( size_t pIndex) const { - return std::string( "meshId" ) + to_string(pIndex); + std::string GetMeshId(size_t pIndex) const { + return std::string("meshId") + to_string(pIndex); } public: @@ -151,7 +155,7 @@ public: std::stringstream mOutput; /// The IOSystem for output - IOSystem* mIOSystem; + IOSystem *mIOSystem; /// Path of the directory where the scene will be exported const std::string mPath; @@ -160,7 +164,7 @@ public: const std::string mFile; /// The scene to be written - const aiScene* mScene; + const aiScene *mScene; bool mSceneOwned; /// current line start string, contains the current indentation for simple stream insertion @@ -168,55 +172,54 @@ public: /// current line end string for simple stream insertion std::string endstr; - // pair of color and texture - texture precedences color - struct Surface - { - bool exist; - aiColor4D color; - std::string texture; - size_t channel; - Surface() { exist = false; channel = 0; } - }; + // pair of color and texture - texture precedences color + struct Surface { + bool exist; + aiColor4D color; + std::string texture; + size_t channel; + Surface() { + exist = false; + channel = 0; + } + }; - struct Property - { - bool exist; - ai_real value; - Property() - : exist(false) - , value(0.0) - {} - }; + struct Property { + bool exist; + ai_real value; + Property() : + exist(false), + value(0.0) {} + }; - // summarize a material in an convenient way. - struct Material - { - std::string name; - std::string shading_model; - Surface ambient, diffuse, specular, emissive, reflective, transparent, normal; - Property shininess, transparency, index_refraction; + // summarize a material in an convenient way. + struct Material { + std::string name; + std::string shading_model; + Surface ambient, diffuse, specular, emissive, reflective, transparent, normal; + Property shininess, transparency, index_refraction; - Material() {} - }; + Material() {} + }; - std::vector materials; + std::vector materials; - std::map textures; + std::map textures; public: - /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions - /// Reads a single surface entry from the given material keys - void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex); - /// Writes an image entry for the given surface - void WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd); - /// Writes the two parameters necessary for referencing a texture in an effect entry - void WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName); - /// Writes a color-or-texture entry into an effect definition - void WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName); - /// Writes a scalar property - void WriteFloatEntry( const Property& pProperty, const std::string& pTypeName); + /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions + /// Reads a single surface entry from the given material keys + void ReadMaterialSurface(Surface &poSurface, const aiMaterial *pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex); + /// Writes an image entry for the given surface + void WriteImageEntry(const Surface &pSurface, const std::string &pNameAdd); + /// Writes the two parameters necessary for referencing a texture in an effect entry + void WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pMatName); + /// Writes a color-or-texture entry into an effect definition + void WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pImageName); + /// Writes a scalar property + void WriteFloatEntry(const Property &pProperty, const std::string &pTypeName); }; -} +} // namespace Assimp #endif // !! AI_COLLADAEXPORTER_H_INC diff --git a/code/Collada/ColladaHelper.cpp b/code/Collada/ColladaHelper.cpp index 6f1fed366..50d70e640 100644 --- a/code/Collada/ColladaHelper.cpp +++ b/code/Collada/ColladaHelper.cpp @@ -43,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ColladaHelper.h" -#include #include +#include namespace Assimp { namespace Collada { @@ -63,42 +63,35 @@ const MetaKeyPairVector &GetColladaAssimpMetaKeys() { const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() { MetaKeyPairVector result = MakeColladaAssimpMetaKeys(); - for (auto &val : result) - { + for (auto &val : result) { ToCamelCase(val.first); } return result; }; -const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase() -{ +const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase() { static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase(); return result; } // ------------------------------------------------------------------------------------------------ // Convert underscore_separated to CamelCase: "authoring_tool" becomes "AuthoringTool" -void ToCamelCase(std::string &text) -{ +void ToCamelCase(std::string &text) { if (text.empty()) return; // Capitalise first character auto it = text.begin(); (*it) = ToUpper(*it); ++it; - for (/*started above*/ ; it != text.end(); /*iterated below*/) - { - if ((*it) == '_') - { + for (/*started above*/; it != text.end(); /*iterated below*/) { + if ((*it) == '_') { it = text.erase(it); if (it != text.end()) (*it) = ToUpper(*it); - } - else - { + } else { // Make lower case (*it) = ToLower(*it); - ++it; + ++it; } } } diff --git a/code/Collada/ColladaHelper.h b/code/Collada/ColladaHelper.h index c6e2e7ddd..3eb073cd9 100644 --- a/code/Collada/ColladaHelper.h +++ b/code/Collada/ColladaHelper.h @@ -45,31 +45,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COLLADAHELPER_H_INC #define AI_COLLADAHELPER_H_INC -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include struct aiMaterial; -namespace Assimp { -namespace Collada { +namespace Assimp { +namespace Collada { /** Collada file versions which evolved during the years ... */ -enum FormatVersion -{ +enum FormatVersion { FV_1_5_n, FV_1_4_n, FV_1_3_n }; - /** Transformation types that can be applied to a node */ -enum TransformType -{ +enum TransformType { TF_LOOKAT, TF_ROTATE, TF_TRANSLATE, @@ -79,10 +76,9 @@ enum TransformType }; /** Different types of input data to a vertex or face */ -enum InputType -{ +enum InputType { IT_Invalid, - IT_Vertex, // special type for per-index data referring to the element carrying the per-vertex data. + IT_Vertex, // special type for per-index data referring to the element carrying the per-vertex data. IT_Position, IT_Normal, IT_Texcoord, @@ -92,15 +88,13 @@ enum InputType }; /** Supported controller types */ -enum ControllerType -{ +enum ControllerType { Skin, Morph }; /** Supported morph methods */ -enum MorphMethod -{ +enum MorphMethod { Normalized, Relative }; @@ -118,24 +112,21 @@ const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase(); void ToCamelCase(std::string &text); /** Contains all data for one of the different transformation types */ -struct Transform -{ - std::string mID; ///< SID of the transform step, by which anim channels address their target node +struct Transform { + std::string mID; ///< SID of the transform step, by which anim channels address their target node TransformType mType; ai_real f[16]; ///< Interpretation of data depends on the type of the transformation }; /** A collada camera. */ -struct Camera -{ - Camera() - : mOrtho (false) - , mHorFov (10e10f) - , mVerFov (10e10f) - , mAspect (10e10f) - , mZNear (0.1f) - , mZFar (1000.f) - {} +struct Camera { + Camera() : + mOrtho(false), + mHorFov(10e10f), + mVerFov(10e10f), + mAspect(10e10f), + mZNear(0.1f), + mZFar(1000.f) {} // Name of camera std::string mName; @@ -159,19 +150,17 @@ struct Camera #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f /** A collada light source. */ -struct Light -{ - Light() - : mType (aiLightSource_UNDEFINED) - , mAttConstant (1.f) - , mAttLinear (0.f) - , mAttQuadratic (0.f) - , mFalloffAngle (180.f) - , mFalloffExponent (0.f) - , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) - , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) - , mIntensity (1.f) - {} +struct Light { + Light() : + mType(aiLightSource_UNDEFINED), + mAttConstant(1.f), + mAttLinear(0.f), + mAttQuadratic(0.f), + mFalloffAngle(180.f), + mFalloffExponent(0.f), + mPenumbraAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET), + mOuterAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET), + mIntensity(1.f) {} //! Type of the light source aiLightSourceType + ambient unsigned int mType; @@ -180,7 +169,7 @@ struct Light aiColor3D mColor; //! Light attenuation - ai_real mAttConstant,mAttLinear,mAttQuadratic; + ai_real mAttConstant, mAttLinear, mAttQuadratic; //! Spot light falloff ai_real mFalloffAngle; @@ -198,12 +187,10 @@ struct Light }; /** Short vertex index description */ -struct InputSemanticMapEntry -{ - InputSemanticMapEntry() - : mSet(0) - , mType(IT_Invalid) - {} +struct InputSemanticMapEntry { + InputSemanticMapEntry() : + mSet(0), + mType(IT_Invalid) {} //! Index of set, optional unsigned int mSet; @@ -213,8 +200,7 @@ struct InputSemanticMapEntry }; /** Table to map from effect to vertex input semantics */ -struct SemanticMappingTable -{ +struct SemanticMappingTable { //! Name of material std::string mMatName; @@ -222,7 +208,7 @@ struct SemanticMappingTable std::map mMap; //! For std::find - bool operator == (const std::string& s) const { + bool operator==(const std::string &s) const { return s == mMatName; } }; @@ -230,8 +216,7 @@ struct SemanticMappingTable /** A reference to a mesh inside a node, including materials assigned to the various subgroups. * The ID refers to either a mesh or a controller which specifies the mesh */ -struct MeshInstance -{ +struct MeshInstance { ///< ID of the mesh or controller to be instanced std::string mMeshOrController; @@ -240,34 +225,30 @@ struct MeshInstance }; /** A reference to a camera inside a node*/ -struct CameraInstance -{ - ///< ID of the camera +struct CameraInstance { + ///< ID of the camera std::string mCamera; }; /** A reference to a light inside a node*/ -struct LightInstance -{ - ///< ID of the camera +struct LightInstance { + ///< ID of the camera std::string mLight; }; /** A reference to a node inside a node*/ -struct NodeInstance -{ - ///< ID of the node +struct NodeInstance { + ///< ID of the node std::string mNode; }; /** A node in a scene hierarchy */ -struct Node -{ +struct Node { std::string mName; std::string mID; std::string mSID; - Node* mParent; - std::vector mChildren; + Node *mParent; + std::vector mChildren; /** Operations in order to calculate the resulting transformation to parent. */ std::vector mTransforms; @@ -288,77 +269,78 @@ struct Node std::string mPrimaryCamera; //! Constructor. Begin with a zero parent - Node() - : mParent( nullptr ){ + Node() : + mParent(nullptr) { // empty } //! Destructor: delete all children subsequently ~Node() { - for( std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) + for (std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; } }; /** Data source array: either floats or strings */ -struct Data -{ +struct Data { bool mIsStringArray; std::vector mValues; std::vector mStrings; }; /** Accessor to a data array */ -struct Accessor -{ - size_t mCount; // in number of objects - size_t mSize; // size of an object, in elements (floats or strings, mostly 1) - size_t mOffset; // in number of values - size_t mStride; // Stride in number of values +struct Accessor { + size_t mCount; // in number of objects + size_t mSize; // size of an object, in elements (floats or strings, mostly 1) + size_t mOffset; // in number of values + size_t mStride; // Stride in number of values std::vector mParams; // names of the data streams in the accessors. Empty string tells to ignore. size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on. - // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. - std::string mSource; // URL of the source array - mutable const Data* mData; // Pointer to the source array, if resolved. NULL else + // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. + std::string mSource; // URL of the source array + mutable const Data *mData; // Pointer to the source array, if resolved. NULL else - Accessor() - { - mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL; + Accessor() { + mCount = 0; + mSize = 0; + mOffset = 0; + mStride = 0; + mData = NULL; mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; } }; /** A single face in a mesh */ -struct Face -{ +struct Face { std::vector mIndices; }; /** An input channel for mesh data, referring to a single accessor */ -struct InputChannel -{ - InputType mType; // Type of the data - size_t mIndex; // Optional index, if multiple sets of the same data type are given - size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. +struct InputChannel { + InputType mType; // Type of the data + size_t mIndex; // Optional index, if multiple sets of the same data type are given + size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. std::string mAccessor; // ID of the accessor where to read the actual values from. - mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else + mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. NULL else - InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; } + InputChannel() { + mType = IT_Invalid; + mIndex = 0; + mOffset = 0; + mResolved = NULL; + } }; /** Subset of a mesh with a certain material */ -struct SubMesh -{ +struct SubMesh { std::string mMaterial; ///< subgroup identifier size_t mNumFaces; ///< number of faces in this submesh }; /** Contains data for a single mesh */ -struct Mesh -{ - Mesh() - { - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) +struct Mesh { + Mesh() { + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) mNumUVComponents[i] = 2; } @@ -377,7 +359,7 @@ struct Mesh std::vector mTangents; std::vector mBitangents; std::vector mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - std::vector mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; + std::vector mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; @@ -394,8 +376,7 @@ struct Mesh }; /** Which type of primitives the ReadPrimitives() function is going to read */ -enum PrimitiveType -{ +enum PrimitiveType { Prim_Invalid, Prim_Lines, Prim_LineStrip, @@ -407,8 +388,7 @@ enum PrimitiveType }; /** A skeleton controller to deform a mesh with the use of joints */ -struct Controller -{ +struct Controller { // controller type ControllerType mType; @@ -436,36 +416,32 @@ struct Controller std::vector mWeightCounts; // JointIndex-WeightIndex pairs for all vertices - std::vector< std::pair > mWeights; + std::vector> mWeights; std::string mMorphTarget; std::string mMorphWeight; }; /** A collada material. Pretty much the only member is a reference to an effect. */ -struct Material -{ +struct Material { std::string mName; std::string mEffect; }; /** Type of the effect param */ -enum ParamType -{ +enum ParamType { Param_Sampler, Param_Surface }; /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */ -struct EffectParam -{ +struct EffectParam { ParamType mType; std::string mReference; // to which other thing the param is referring to. }; /** Shading type supported by the standard effect spec of Collada */ -enum ShadeType -{ +enum ShadeType { Shade_Invalid, Shade_Constant, Shade_Lambert, @@ -474,18 +450,16 @@ enum ShadeType }; /** Represents a texture sampler in collada */ -struct Sampler -{ - Sampler() - : mWrapU (true) - , mWrapV (true) - , mMirrorU () - , mMirrorV () - , mOp (aiTextureOp_Multiply) - , mUVId (UINT_MAX) - , mWeighting (1.f) - , mMixWithPrevious (1.f) - {} +struct Sampler { + Sampler() : + mWrapU(true), + mWrapV(true), + mMirrorU(), + mMirrorV(), + mOp(aiTextureOp_Multiply), + mUVId(UINT_MAX), + mWeighting(1.f), + mMixWithPrevious(1.f) {} /** Name of image reference */ @@ -537,18 +511,17 @@ struct Sampler /** A collada effect. Can contain about anything according to the Collada spec, but we limit our version to a reasonable subset. */ -struct Effect -{ +struct Effect { // Shading mode ShadeType mShadeType; // Colors aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular, - mTransparent, mReflective; + mTransparent, mReflective; // Textures Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular, - mTexTransparent, mTexBump, mTexReflective; + mTexTransparent, mTexBump, mTexReflective; // Scalar factory ai_real mShininess, mRefractIndex, mReflectivity; @@ -566,30 +539,28 @@ struct Effect // Double-sided? bool mDoubleSided, mWireframe, mFaceted; - Effect() - : mShadeType (Shade_Phong) - , mEmissive ( 0, 0, 0, 1) - , mAmbient ( 0.1f, 0.1f, 0.1f, 1) - , mDiffuse ( 0.6f, 0.6f, 0.6f, 1) - , mSpecular ( 0.4f, 0.4f, 0.4f, 1) - , mTransparent ( 0, 0, 0, 1) - , mShininess (10.0f) - , mRefractIndex (1.f) - , mReflectivity (0.f) - , mTransparency (1.f) - , mHasTransparency (false) - , mRGBTransparency(false) - , mInvertTransparency(false) - , mDoubleSided (false) - , mWireframe (false) - , mFaceted (false) - { + Effect() : + mShadeType(Shade_Phong), + mEmissive(0, 0, 0, 1), + mAmbient(0.1f, 0.1f, 0.1f, 1), + mDiffuse(0.6f, 0.6f, 0.6f, 1), + mSpecular(0.4f, 0.4f, 0.4f, 1), + mTransparent(0, 0, 0, 1), + mShininess(10.0f), + mRefractIndex(1.f), + mReflectivity(0.f), + mTransparency(1.f), + mHasTransparency(false), + mRGBTransparency(false), + mInvertTransparency(false), + mDoubleSided(false), + mWireframe(false), + mFaceted(false) { } }; /** An image, meaning texture */ -struct Image -{ +struct Image { std::string mFileName; /** Embedded image data */ @@ -600,8 +571,7 @@ struct Image }; /** An animation channel. */ -struct AnimationChannel -{ +struct AnimationChannel { /** URL of the data to animate. Could be about anything, but we support only the * "NodeID/TransformID.SubElement" notation */ @@ -620,8 +590,7 @@ struct AnimationChannel }; /** An animation. Container for 0-x animation channels or 0-x animations */ -struct Animation -{ +struct Animation { /** Anim name */ std::string mName; @@ -629,96 +598,86 @@ struct Animation std::vector mChannels; /** the sub-animations, if any */ - std::vector mSubAnims; + std::vector mSubAnims; /** Destructor */ - ~Animation() - { - for( std::vector::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) + ~Animation() { + for (std::vector::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) delete *it; } - /** Collect all channels in the animation hierarchy into a single channel list. */ - void CollectChannelsRecursively(std::vector &channels) - { - channels.insert(channels.end(), mChannels.begin(), mChannels.end()); + /** Collect all channels in the animation hierarchy into a single channel list. */ + void CollectChannelsRecursively(std::vector &channels) { + channels.insert(channels.end(), mChannels.begin(), mChannels.end()); - for (std::vector::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) - { - Animation *pAnim = (*it); + for (std::vector::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) { + Animation *pAnim = (*it); - pAnim->CollectChannelsRecursively(channels); - } - } + pAnim->CollectChannelsRecursively(channels); + } + } - /** Combine all single-channel animations' channel into the same (parent) animation channel list. */ - void CombineSingleChannelAnimations() - { - CombineSingleChannelAnimationsRecursively(this); - } + /** Combine all single-channel animations' channel into the same (parent) animation channel list. */ + void CombineSingleChannelAnimations() { + CombineSingleChannelAnimationsRecursively(this); + } - void CombineSingleChannelAnimationsRecursively(Animation *pParent) - { - std::set childrenTargets; - bool childrenAnimationsHaveDifferentChannels = true; + void CombineSingleChannelAnimationsRecursively(Animation *pParent) { + std::set childrenTargets; + bool childrenAnimationsHaveDifferentChannels = true; - for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) - { - Animation *anim = *it; - CombineSingleChannelAnimationsRecursively(anim); + for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) { + Animation *anim = *it; + CombineSingleChannelAnimationsRecursively(anim); - if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 && - childrenTargets.find(anim->mChannels[0].mTarget) == childrenTargets.end()) { - childrenTargets.insert(anim->mChannels[0].mTarget); - } else { - childrenAnimationsHaveDifferentChannels = false; - } + if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 && + childrenTargets.find(anim->mChannels[0].mTarget) == childrenTargets.end()) { + childrenTargets.insert(anim->mChannels[0].mTarget); + } else { + childrenAnimationsHaveDifferentChannels = false; + } - ++it; - } + ++it; + } - // We only want to combine animations if they have different channels - if (childrenAnimationsHaveDifferentChannels) - { - for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) - { - Animation *anim = *it; + // We only want to combine animations if they have different channels + if (childrenAnimationsHaveDifferentChannels) { + for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) { + Animation *anim = *it; - pParent->mChannels.push_back(anim->mChannels[0]); + pParent->mChannels.push_back(anim->mChannels[0]); - it = pParent->mSubAnims.erase(it); + it = pParent->mSubAnims.erase(it); - delete anim; - continue; - } - } - } + delete anim; + continue; + } + } + } }; /** Description of a collada animation channel which has been determined to affect the current node */ -struct ChannelEntry -{ - const Collada::AnimationChannel* mChannel; ///> the source channel +struct ChannelEntry { + const Collada::AnimationChannel *mChannel; ///> the source channel std::string mTargetId; - std::string mTransformId; // the ID of the transformation step of the node which is influenced + std::string mTransformId; // the ID of the transformation step of the node which is influenced size_t mTransformIndex; // Index into the node's transform chain to apply the channel to size_t mSubElement; // starting index inside the transform data // resolved data references - const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values - const Collada::Data* mTimeData; ///> Source data array for the time values - const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values - const Collada::Data* mValueData; ///> Source datat array for the key value values + const Collada::Accessor *mTimeAccessor; ///> Collada accessor to the time values + const Collada::Data *mTimeData; ///> Source data array for the time values + const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values + const Collada::Data *mValueData; ///> Source datat array for the key value values - ChannelEntry() - : mChannel() - , mTransformIndex() - , mSubElement() - , mTimeAccessor() - , mTimeData() - , mValueAccessor() - , mValueData() - {} + ChannelEntry() : + mChannel(), + mTransformIndex(), + mSubElement(), + mTimeAccessor(), + mTimeData(), + mValueAccessor(), + mValueData() {} }; } // end of namespace Collada diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index b78fc0e3b..44d65e40d 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -46,27 +46,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ColladaLoader.h" #include "ColladaParser.h" +#include #include +#include #include #include #include -#include -#include -#include +#include #include #include -#include #include +#include -#include "time.h" #include "math.h" +#include "time.h" #include -#include #include +#include namespace Assimp { - + using namespace Assimp::Formatter; static const aiImporterDesc desc = { @@ -84,20 +84,20 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -ColladaLoader::ColladaLoader() - : mFileName() - , mMeshIndexByID() - , mMaterialIndexByName() - , mMeshes() - , newMats() - , mCameras() - , mLights() - , mTextures() - , mAnims() - , noSkeletonMesh(false) - , ignoreUpDirection(false) - , useColladaName(false) - , mNodeNameCounter(0) { +ColladaLoader::ColladaLoader() : + mFileName(), + mMeshIndexByID(), + mMaterialIndexByName(), + mMeshes(), + newMats(), + mCameras(), + mLights(), + mTextures(), + mAnims(), + noSkeletonMesh(false), + ignoreUpDirection(false), + useColladaName(false), + mNodeNameCounter(0) { // empty } @@ -109,7 +109,7 @@ ColladaLoader::~ColladaLoader() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool ColladaLoader::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { +bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { // check file extension const std::string extension = GetExtension(pFile); @@ -137,7 +137,7 @@ bool ColladaLoader::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool if (!pIOHandler) { return true; } - static const char* tokens[] = { "GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0; ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0; useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0; @@ -153,13 +153,13 @@ void ColladaLoader::SetupProperties(const Importer* pImp) { // ------------------------------------------------------------------------------------------------ // Get file extension list -const aiImporterDesc* ColladaLoader::GetInfo() const { +const aiImporterDesc *ColladaLoader::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { +void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { mFileName = pFile; // clean all member arrays - just for safety, it should work even if we did not @@ -176,14 +176,13 @@ void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IO // parse the input file ColladaParser parser(pIOHandler, pFile); - - if( !parser.mRootNode) { - throw DeadlyImportError( "Collada: File came out empty. Something is wrong here."); + if (!parser.mRootNode) { + throw DeadlyImportError("Collada: File came out empty. Something is wrong here."); } // reserve some storage to avoid unnecessary reallocs - newMats.reserve(parser.mMaterialLibrary.size()*2u); - mMeshes.reserve(parser.mMeshLibrary.size()*2u); + newMats.reserve(parser.mMaterialLibrary.size() * 2u); + mMeshes.reserve(parser.mMeshLibrary.size() * 2u); mCameras.reserve(parser.mCameraLibrary.size()); mLights.reserve(parser.mLightLibrary.size()); @@ -199,24 +198,24 @@ void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IO // Apply unit-size scale calculation - pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0, - 0, parser.mUnitSize, 0, 0, - 0, 0, parser.mUnitSize, 0, - 0, 0, 0, 1); - if( !ignoreUpDirection ) { + pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0, + 0, parser.mUnitSize, 0, 0, + 0, 0, parser.mUnitSize, 0, + 0, 0, 0, 1); + if (!ignoreUpDirection) { // Convert to Y_UP, if different orientation - if( parser.mUpDirection == ColladaParser::UP_X) { + if (parser.mUpDirection == ColladaParser::UP_X) { pScene->mRootNode->mTransformation *= aiMatrix4x4( - 0, -1, 0, 0, - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } else if( parser.mUpDirection == ColladaParser::UP_Z) { + 0, -1, 0, 0, + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + } else if (parser.mUpDirection == ColladaParser::UP_Z) { pScene->mRootNode->mTransformation *= aiMatrix4x4( - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, -1, 0, 0, - 0, 0, 0, 1); + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, -1, 0, 0, + 0, 0, 0, 1); } } @@ -249,7 +248,7 @@ void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IO StoreAnimations(pScene, parser); // If no meshes have been loaded, it's probably just an animated skeleton. - if ( 0u == pScene->mNumMeshes) { + if (0u == pScene->mNumMeshes) { if (!noSkeletonMesh) { SkeletonMeshBuilder hero(pScene); @@ -260,9 +259,9 @@ void ColladaLoader::InternReadFile(const std::string& pFile, aiScene* pScene, IO // ------------------------------------------------------------------------------------------------ // Recursively constructs a scene node for the given parser node and returns it. -aiNode* ColladaLoader::BuildHierarchy(const ColladaParser& pParser, const Collada::Node* pNode) { +aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode) { // create a node for it - aiNode* node = new aiNode(); + aiNode *node = new aiNode(); // find a name for the new node. It's more complicated than you might think node->mName.Set(FindNameForNode(pNode)); @@ -271,12 +270,12 @@ aiNode* ColladaLoader::BuildHierarchy(const ColladaParser& pParser, const Collad node->mTransformation = pParser.CalculateResultTransform(pNode->mTransforms); // now resolve node instances - std::vector instances; + std::vector instances; ResolveNodeInstances(pParser, pNode, instances); // add children. first the *real* ones node->mNumChildren = static_cast(pNode->mChildren.size() + instances.size()); - node->mChildren = new aiNode*[node->mNumChildren]; + node->mChildren = new aiNode *[node->mNumChildren]; for (size_t a = 0; a < pNode->mChildren.size(); ++a) { node->mChildren[a] = BuildHierarchy(pParser, pNode->mChildren[a]); @@ -303,8 +302,8 @@ aiNode* ColladaLoader::BuildHierarchy(const ColladaParser& pParser, const Collad // ------------------------------------------------------------------------------------------------ // Resolve node instances -void ColladaLoader::ResolveNodeInstances(const ColladaParser& pParser, const Collada::Node* pNode, - std::vector& resolved) { +void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Collada::Node *pNode, + std::vector &resolved) { // reserve enough storage resolved.reserve(pNode->mNodeInstances.size()); @@ -312,7 +311,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser& pParser, const Col for (const auto &nodeInst : pNode->mNodeInstances) { // find the corresponding node in the library const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode); - const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second; + const Collada::Node *nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second; // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632 // need to check for both name and ID to catch all. To avoid breaking valid files, @@ -331,9 +330,9 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser& pParser, const Col // ------------------------------------------------------------------------------------------------ // Resolve UV channels -void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler, +void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler, - const Collada::SemanticMappingTable& table) { + const Collada::SemanticMappingTable &table) { std::map::const_iterator it = table.mMap.find(sampler.mUVChannel); if (it != table.mMap.end()) { if (it->second.mType != Collada::IT_Texcoord) { @@ -346,18 +345,18 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler // ------------------------------------------------------------------------------------------------ // Builds lights for the given node and references them -void ColladaLoader::BuildLightsForNode(const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) { - for (const Collada::LightInstance& lid : pNode->mLights) { +void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Collada::Node *pNode, aiNode *pTarget) { + for (const Collada::LightInstance &lid : pNode->mLights) { // find the referred light ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight); if (srcLightIt == pParser.mLightLibrary.end()) { ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping."); continue; } - const Collada::Light* srcLight = &srcLightIt->second; + const Collada::Light *srcLight = &srcLightIt->second; // now fill our ai data structure - aiLight* out = new aiLight(); + aiLight *out = new aiLight(); out->mName = pTarget->mName; out->mType = (aiLightSourceType)srcLight->mType; @@ -368,14 +367,13 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser& pParser, const Colla out->mAttenuationLinear = srcLight->mAttLinear; out->mAttenuationQuadratic = srcLight->mAttQuadratic; - out->mColorDiffuse = out->mColorSpecular = out->mColorAmbient = srcLight->mColor*srcLight->mIntensity; + out->mColorDiffuse = out->mColorSpecular = out->mColorAmbient = srcLight->mColor * srcLight->mIntensity; if (out->mType == aiLightSource_AMBIENT) { out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0); - out->mColorAmbient = srcLight->mColor*srcLight->mIntensity; - } - else { + out->mColorAmbient = srcLight->mColor * srcLight->mIntensity; + } else { // collada doesn't differentiate between these color types - out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity; + out->mColorDiffuse = out->mColorSpecular = srcLight->mColor * srcLight->mIntensity; out->mColorAmbient = aiColor3D(0, 0, 0); } @@ -390,15 +388,13 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser& pParser, const Colla // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess .... // epsilon chosen to be 0.1 out->mAngleOuterCone = std::acos(std::pow(0.1f, 1.f / srcLight->mFalloffExponent)) + - out->mAngleInnerCone; - } - else { + out->mAngleInnerCone; + } else { out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD(srcLight->mPenumbraAngle); if (out->mAngleOuterCone < out->mAngleInnerCone) std::swap(out->mAngleInnerCone, out->mAngleOuterCone); } - } - else { + } else { out->mAngleOuterCone = AI_DEG_TO_RAD(srcLight->mOuterAngle); } } @@ -410,15 +406,15 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser& pParser, const Colla // ------------------------------------------------------------------------------------------------ // Builds cameras for the given node and references them -void ColladaLoader::BuildCamerasForNode(const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) { - for (const Collada::CameraInstance& cid : pNode->mCameras) { +void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Collada::Node *pNode, aiNode *pTarget) { + for (const Collada::CameraInstance &cid : pNode->mCameras) { // find the referred light ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera); if (srcCameraIt == pParser.mCameraLibrary.end()) { ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping."); continue; } - const Collada::Camera* srcCamera = &srcCameraIt->second; + const Collada::Camera *srcCamera = &srcCameraIt->second; // orthographic cameras not yet supported in Assimp if (srcCamera->mOrtho) { @@ -426,7 +422,7 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser& pParser, const Coll } // now fill our ai data structure - aiCamera* out = new aiCamera(); + aiCamera *out = new aiCamera(); out->mName = pTarget->mName; // collada cameras point in -Z by default, rest is specified in node transform @@ -447,12 +443,12 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser& pParser, const Coll if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) { out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) / - std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov)); + std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov)); } - } else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) { + } else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) { out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect * - std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f))); + std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f))); } // Collada uses degrees, we use radians @@ -465,15 +461,15 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser& pParser, const Coll // ------------------------------------------------------------------------------------------------ // Builds meshes for the given node and references them -void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) { +void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Collada::Node *pNode, aiNode *pTarget) { // accumulated mesh references by this node std::vector newMeshRefs; newMeshRefs.reserve(pNode->mMeshes.size()); // add a mesh for each subgroup in each collada mesh - for (const Collada::MeshInstance& mid : pNode->mMeshes) { - const Collada::Mesh* srcMesh = nullptr; - const Collada::Controller* srcController = nullptr; + for (const Collada::MeshInstance &mid : pNode->mMeshes) { + const Collada::Mesh *srcMesh = nullptr; + const Collada::Controller *srcController = nullptr; // find the referred mesh ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController); @@ -488,13 +484,11 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla } } - - if( nullptr == srcMesh) { - ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." ); + if (nullptr == srcMesh) { + ASSIMP_LOG_WARN_F("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping."); continue; } - } - else { + } else { // ID found in the mesh library -> direct reference to an unskinned mesh srcMesh = srcMeshIt->second; } @@ -502,23 +496,22 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla // build a mesh for each of its subgroups size_t vertexStart = 0, faceStart = 0; for (size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm) { - const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm]; + const Collada::SubMesh &submesh = srcMesh->mSubMeshes[sm]; if (submesh.mNumFaces == 0) { continue; } // find material assigned to this submesh std::string meshMaterial; - std::map::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial); + std::map::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial); - const Collada::SemanticMappingTable* table = nullptr; + const Collada::SemanticMappingTable *table = nullptr; if (meshMatIt != mid.mMaterials.end()) { table = &meshMatIt->second; meshMaterial = table->mMatName; - } - else { + } else { ASSIMP_LOG_WARN_F("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", - mid.mMeshOrController, ">."); + mid.mMeshOrController, ">."); if (!mid.mMaterials.empty()) { meshMaterial = mid.mMaterials.begin()->second.mMatName; } @@ -533,7 +526,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla } if (table && !table->mMap.empty()) { - std::pair& mat = newMats[matIdx]; + std::pair &mat = newMats[matIdx]; // Iterate through all texture channels assigned to the effect and // check whether we have mapping information for it. @@ -552,16 +545,16 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla std::map::const_iterator dstMeshIt = mMeshIndexByID.find(index); if (dstMeshIt != mMeshIndexByID.end()) { newMeshRefs.push_back(dstMeshIt->second); - } - else { + } else { // else we have to add the mesh to the collection and store its newly assigned index at the node - aiMesh* dstMesh = CreateMesh(pParser, srcMesh, submesh, srcController, vertexStart, faceStart); + aiMesh *dstMesh = CreateMesh(pParser, srcMesh, submesh, srcController, vertexStart, faceStart); // store the mesh, and store its new index in the node newMeshRefs.push_back(mMeshes.size()); mMeshIndexByID[index] = mMeshes.size(); mMeshes.push_back(dstMesh); - vertexStart += dstMesh->mNumVertices; faceStart += submesh.mNumFaces; + vertexStart += dstMesh->mNumVertices; + faceStart += submesh.mNumFaces; // assign the material index dstMesh->mMaterialIndex = matIdx; @@ -576,7 +569,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla pTarget->mNumMeshes = static_cast(newMeshRefs.size()); if (newMeshRefs.size()) { struct UIntTypeConverter { - unsigned int operator()(const size_t& v) const { + unsigned int operator()(const size_t &v) const { return static_cast(v); } }; @@ -588,7 +581,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla // ------------------------------------------------------------------------------------------------ // Find mesh from either meshes or morph target meshes -aiMesh *ColladaLoader::findMesh(const std::string& meshid) { +aiMesh *ColladaLoader::findMesh(const std::string &meshid) { for (unsigned int i = 0; i < mMeshes.size(); ++i) { if (std::string(mMeshes[i]->mName.data) == meshid) { return mMeshes[i]; @@ -606,43 +599,39 @@ aiMesh *ColladaLoader::findMesh(const std::string& meshid) { // ------------------------------------------------------------------------------------------------ // Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh -aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, - const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace) { +aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::Mesh *pSrcMesh, const Collada::SubMesh &pSubMesh, + const Collada::Controller *pSrcController, size_t pStartVertex, size_t pStartFace) { std::unique_ptr dstMesh(new aiMesh); dstMesh->mName = pSrcMesh->mName; // count the vertices addressed by its faces const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace, - pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0)); + pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0)); // copy positions dstMesh->mNumVertices = static_cast(numVertices); dstMesh->mVertices = new aiVector3D[numVertices]; - std::copy(pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() + - pStartVertex + numVertices, dstMesh->mVertices); + std::copy(pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() + pStartVertex + numVertices, dstMesh->mVertices); // normals, if given. HACK: (thom) Due to the glorious Collada spec we never // know if we have the same number of normals as there are positions. So we // also ignore any vertex attribute if it has a different count if (pSrcMesh->mNormals.size() >= pStartVertex + numVertices) { dstMesh->mNormals = new aiVector3D[numVertices]; - std::copy(pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() + - pStartVertex + numVertices, dstMesh->mNormals); + std::copy(pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() + pStartVertex + numVertices, dstMesh->mNormals); } // tangents, if given. if (pSrcMesh->mTangents.size() >= pStartVertex + numVertices) { dstMesh->mTangents = new aiVector3D[numVertices]; - std::copy(pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + - pStartVertex + numVertices, dstMesh->mTangents); + std::copy(pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + pStartVertex + numVertices, dstMesh->mTangents); } // bitangents, if given. if (pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) { dstMesh->mBitangents = new aiVector3D[numVertices]; - std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + - pStartVertex + numVertices, dstMesh->mBitangents); + std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + pStartVertex + numVertices, dstMesh->mBitangents); } // same for texturecoords, as many as we have @@ -674,7 +663,7 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M dstMesh->mFaces = new aiFace[dstMesh->mNumFaces]; for (size_t a = 0; a < dstMesh->mNumFaces; ++a) { size_t s = pSrcMesh->mFaceSize[pStartFace + a]; - aiFace& face = dstMesh->mFaces[a]; + aiFace &face = dstMesh->mFaces[a]; face.mNumIndices = static_cast(s); face.mIndices = new unsigned int[s]; for (size_t b = 0; b < s; ++b) { @@ -683,20 +672,20 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M } // create morph target meshes if any - std::vector targetMeshes; + std::vector targetMeshes; std::vector targetWeights; Collada::MorphMethod method = Collada::Normalized; for (std::map::const_iterator it = pParser.mControllerLibrary.begin(); - it != pParser.mControllerLibrary.end(); ++it) { + it != pParser.mControllerLibrary.end(); ++it) { const Collada::Controller &c = it->second; - const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId); + const Collada::Mesh *baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId); if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) { - const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, c.mMorphTarget); - const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, c.mMorphWeight); - const Collada::Data& targetData = pParser.ResolveLibraryReference(pParser.mDataLibrary, targetAccessor.mSource); - const Collada::Data& weightData = pParser.ResolveLibraryReference(pParser.mDataLibrary, weightAccessor.mSource); + const Collada::Accessor &targetAccessor = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, c.mMorphTarget); + const Collada::Accessor &weightAccessor = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, c.mMorphWeight); + const Collada::Data &targetData = pParser.ResolveLibraryReference(pParser.mDataLibrary, targetAccessor.mSource); + const Collada::Data &weightData = pParser.ResolveLibraryReference(pParser.mDataLibrary, weightAccessor.mSource); // take method method = c.mMethod; @@ -709,7 +698,7 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M } for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) { - const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i)); + const Collada::Mesh *targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i)); aiMesh *aimesh = findMesh(targetMesh->mName); if (!aimesh) { @@ -727,19 +716,17 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M } } if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) { - std::vector animMeshes; + std::vector animMeshes; for (unsigned int i = 0; i < targetMeshes.size(); ++i) { - aiMesh* targetMesh = targetMeshes.at(i); + aiMesh *targetMesh = targetMeshes.at(i); aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh); float weight = targetWeights[i]; animMesh->mWeight = weight == 0 ? 1.0f : weight; animMesh->mName = targetMesh->mName; animMeshes.push_back(animMesh); } - dstMesh->mMethod = (method == Collada::Relative) - ? aiMorphingMethod_MORPH_RELATIVE - : aiMorphingMethod_MORPH_NORMALIZED; - dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()]; + dstMesh->mMethod = (method == Collada::Relative) ? aiMorphingMethod_MORPH_RELATIVE : aiMorphingMethod_MORPH_NORMALIZED; + dstMesh->mAnimMeshes = new aiAnimMesh *[animMeshes.size()]; dstMesh->mNumAnimMeshes = static_cast(animMeshes.size()); for (unsigned int i = 0; i < animMeshes.size(); ++i) { dstMesh->mAnimMeshes[i] = animMeshes.at(i); @@ -749,18 +736,18 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M // create bones if given if (pSrcController && pSrcController->mType == Collada::Skin) { // resolve references - joint names - const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mJointNameSource); - const Collada::Data& jointNames = pParser.ResolveLibraryReference(pParser.mDataLibrary, jointNamesAcc.mSource); + const Collada::Accessor &jointNamesAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mJointNameSource); + const Collada::Data &jointNames = pParser.ResolveLibraryReference(pParser.mDataLibrary, jointNamesAcc.mSource); // joint offset matrices - const Collada::Accessor& jointMatrixAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mJointOffsetMatrixSource); - const Collada::Data& jointMatrices = pParser.ResolveLibraryReference(pParser.mDataLibrary, jointMatrixAcc.mSource); + const Collada::Accessor &jointMatrixAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mJointOffsetMatrixSource); + const Collada::Data &jointMatrices = pParser.ResolveLibraryReference(pParser.mDataLibrary, jointMatrixAcc.mSource); // joint vertex_weight name list - should refer to the same list as the joint names above. If not, report and reconsider - const Collada::Accessor& weightNamesAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mWeightInputJoints.mAccessor); + const Collada::Accessor &weightNamesAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mWeightInputJoints.mAccessor); if (&weightNamesAcc != &jointNamesAcc) throw DeadlyImportError("Temporary implementational laziness. If you read this, please report to the author."); // vertex weights - const Collada::Accessor& weightsAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor); - const Collada::Data& weights = pParser.ResolveLibraryReference(pParser.mDataLibrary, weightsAcc.mSource); + const Collada::Accessor &weightsAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor); + const Collada::Data &weights = pParser.ResolveLibraryReference(pParser.mDataLibrary, weightsAcc.mSource); if (!jointNames.mIsStringArray || jointMatrices.mIsStringArray || weights.mIsStringArray) throw DeadlyImportError("Data type mismatch while resolving mesh joints"); @@ -770,10 +757,10 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M // create containers to collect the weights for each bone size_t numBones = jointNames.mStrings.size(); - std::vector > dstBones(numBones); + std::vector> dstBones(numBones); // build a temporary array of pointers to the start of each vertex's weights - typedef std::vector< std::pair > IndexPairVector; + typedef std::vector> IndexPairVector; std::vector weightStartPerVertex; weightStartPerVertex.resize(pSrcController->mWeightCounts.size(), pSrcController->mWeights.end()); @@ -792,18 +779,16 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex]; size_t pairCount = pSrcController->mWeightCounts[orgIndex]; - - for( size_t b = 0; b < pairCount; ++b, ++iit) { + for (size_t b = 0; b < pairCount; ++b, ++iit) { const size_t jointIndex = iit->first; - const size_t vertexIndex = iit->second; + const size_t vertexIndex = iit->second; ai_real weight = 1.0f; if (!weights.mValues.empty()) { weight = ReadFloat(weightsAcc, weights, vertexIndex, 0); } // one day I gonna kill that XSI Collada exporter - if (weight > 0.0f) - { + if (weight > 0.0f) { aiVertexWeight w; w.mVertexId = static_cast(a - pStartVertex); w.mWeight = weight; @@ -814,24 +799,24 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M // count the number of bones which influence vertices of the current submesh size_t numRemainingBones = 0; - for( std::vector >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) { - if( it->size() > 0) { + for (std::vector>::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) { + if (it->size() > 0) { ++numRemainingBones; } } // create bone array and copy bone weights one by one dstMesh->mNumBones = static_cast(numRemainingBones); - dstMesh->mBones = new aiBone*[numRemainingBones]; + dstMesh->mBones = new aiBone *[numRemainingBones]; size_t boneCount = 0; - for( size_t a = 0; a < numBones; ++a) { + for (size_t a = 0; a < numBones; ++a) { // omit bones without weights - if( dstBones[a].empty() ) { + if (dstBones[a].empty()) { continue; } // create bone with its weights - aiBone* bone = new aiBone; + aiBone *bone = new aiBone; bone->mName = ReadString(jointNamesAcc, jointNames, a); bone->mOffsetMatrix.a1 = ReadFloat(jointMatrixAcc, jointMatrices, a, 0); bone->mOffsetMatrix.a2 = ReadFloat(jointMatrixAcc, jointMatrices, a, 1); @@ -873,16 +858,16 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M // Therefore I added a little name replacement here: I search for the bone's node by either name, ID or SID, // and replace the bone's name by the node's name so that the user can use the standard // find-by-name method to associate nodes with bones. - const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data); - if( !bnode) { - bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data); + const Collada::Node *bnode = FindNode(pParser.mRootNode, bone->mName.data); + if (!bnode) { + bnode = FindNodeBySID(pParser.mRootNode, bone->mName.data); } // assign the name that we would have assigned for the source node - if( bnode) { - bone->mName.Set( FindNameForNode( bnode)); + if (bnode) { + bone->mName.Set(FindNameForNode(bnode)); } else { - ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." ); + ASSIMP_LOG_WARN_F("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"."); } // and insert bone @@ -895,61 +880,61 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M // ------------------------------------------------------------------------------------------------ // Stores all meshes in the given scene -void ColladaLoader::StoreSceneMeshes( aiScene* pScene) { +void ColladaLoader::StoreSceneMeshes(aiScene *pScene) { pScene->mNumMeshes = static_cast(mMeshes.size()); - if( mMeshes.empty() ) { + if (mMeshes.empty()) { return; } - pScene->mMeshes = new aiMesh*[mMeshes.size()]; - std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes); + pScene->mMeshes = new aiMesh *[mMeshes.size()]; + std::copy(mMeshes.begin(), mMeshes.end(), pScene->mMeshes); mMeshes.clear(); } // ------------------------------------------------------------------------------------------------ // Stores all cameras in the given scene -void ColladaLoader::StoreSceneCameras( aiScene* pScene) { +void ColladaLoader::StoreSceneCameras(aiScene *pScene) { pScene->mNumCameras = static_cast(mCameras.size()); - if( mCameras.empty() ) { + if (mCameras.empty()) { return; } - pScene->mCameras = new aiCamera*[mCameras.size()]; - std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras); + pScene->mCameras = new aiCamera *[mCameras.size()]; + std::copy(mCameras.begin(), mCameras.end(), pScene->mCameras); mCameras.clear(); } // ------------------------------------------------------------------------------------------------ // Stores all lights in the given scene -void ColladaLoader::StoreSceneLights( aiScene* pScene) { +void ColladaLoader::StoreSceneLights(aiScene *pScene) { pScene->mNumLights = static_cast(mLights.size()); - if( mLights.empty() ) { + if (mLights.empty()) { return; } - pScene->mLights = new aiLight*[mLights.size()]; - std::copy( mLights.begin(), mLights.end(), pScene->mLights); + pScene->mLights = new aiLight *[mLights.size()]; + std::copy(mLights.begin(), mLights.end(), pScene->mLights); mLights.clear(); } // ------------------------------------------------------------------------------------------------ // Stores all textures in the given scene -void ColladaLoader::StoreSceneTextures( aiScene* pScene) { +void ColladaLoader::StoreSceneTextures(aiScene *pScene) { pScene->mNumTextures = static_cast(mTextures.size()); - if( mTextures.empty() ) { + if (mTextures.empty()) { return; } - pScene->mTextures = new aiTexture*[mTextures.size()]; - std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures); + pScene->mTextures = new aiTexture *[mTextures.size()]; + std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures); mTextures.clear(); } // ------------------------------------------------------------------------------------------------ // Stores all materials in the given scene -void ColladaLoader::StoreSceneMaterials( aiScene* pScene) { +void ColladaLoader::StoreSceneMaterials(aiScene *pScene) { pScene->mNumMaterials = static_cast(newMats.size()); - if (newMats.empty() ) { + if (newMats.empty()) { return; } - pScene->mMaterials = new aiMaterial*[newMats.size()]; - for (unsigned int i = 0; i < newMats.size();++i) { + pScene->mMaterials = new aiMaterial *[newMats.size()]; + for (unsigned int i = 0; i < newMats.size(); ++i) { pScene->mMaterials[i] = newMats[i].second; } newMats.clear(); @@ -957,53 +942,51 @@ void ColladaLoader::StoreSceneMaterials( aiScene* pScene) { // ------------------------------------------------------------------------------------------------ // Stores all animations -void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) { +void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParser) { // recursively collect all animations from the collada scene StoreAnimations(pScene, pParser, &pParser.mAnims, ""); // catch special case: many animations with the same length, each affecting only a single node. // we need to unite all those single-node-anims to a proper combined animation - for(size_t a = 0; a < mAnims.size(); ++a) { - aiAnimation* templateAnim = mAnims[a]; + for (size_t a = 0; a < mAnims.size(); ++a) { + aiAnimation *templateAnim = mAnims[a]; if (templateAnim->mNumChannels == 1) { // search for other single-channel-anims with the same duration std::vector collectedAnimIndices; - for( size_t b = a+1; b < mAnims.size(); ++b) { - aiAnimation* other = mAnims[b]; + for (size_t b = a + 1; b < mAnims.size(); ++b) { + aiAnimation *other = mAnims[b]; if (other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && - other->mTicksPerSecond == templateAnim->mTicksPerSecond) - collectedAnimIndices.push_back(b); + other->mTicksPerSecond == templateAnim->mTicksPerSecond) + collectedAnimIndices.push_back(b); } - // We only want to combine the animations if they have different channels - std::set animTargets; - animTargets.insert(templateAnim->mChannels[0]->mNodeName.C_Str()); - bool collectedAnimationsHaveDifferentChannels = true; - for (size_t b = 0; b < collectedAnimIndices.size(); ++b) - { - aiAnimation* srcAnimation = mAnims[collectedAnimIndices[b]]; - std::string channelName = std::string(srcAnimation->mChannels[0]->mNodeName.C_Str()); - if (animTargets.find(channelName) == animTargets.end()) { - animTargets.insert(channelName); - } else { - collectedAnimationsHaveDifferentChannels = false; - break; - } - } + // We only want to combine the animations if they have different channels + std::set animTargets; + animTargets.insert(templateAnim->mChannels[0]->mNodeName.C_Str()); + bool collectedAnimationsHaveDifferentChannels = true; + for (size_t b = 0; b < collectedAnimIndices.size(); ++b) { + aiAnimation *srcAnimation = mAnims[collectedAnimIndices[b]]; + std::string channelName = std::string(srcAnimation->mChannels[0]->mNodeName.C_Str()); + if (animTargets.find(channelName) == animTargets.end()) { + animTargets.insert(channelName); + } else { + collectedAnimationsHaveDifferentChannels = false; + break; + } + } - if (!collectedAnimationsHaveDifferentChannels) - continue; + if (!collectedAnimationsHaveDifferentChannels) + continue; // if there are other animations which fit the template anim, combine all channels into a single anim - if (!collectedAnimIndices.empty()) - { - aiAnimation* combinedAnim = new aiAnimation(); + if (!collectedAnimIndices.empty()) { + aiAnimation *combinedAnim = new aiAnimation(); combinedAnim->mName = aiString(std::string("combinedAnim_") + char('0' + a)); combinedAnim->mDuration = templateAnim->mDuration; combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond; combinedAnim->mNumChannels = static_cast(collectedAnimIndices.size() + 1); - combinedAnim->mChannels = new aiNodeAnim*[combinedAnim->mNumChannels]; + combinedAnim->mChannels = new aiNodeAnim *[combinedAnim->mNumChannels]; // add the template anim as first channel by moving its aiNodeAnim to the combined animation combinedAnim->mChannels[0] = templateAnim->mChannels[0]; templateAnim->mChannels[0] = NULL; @@ -1012,9 +995,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars mAnims[a] = combinedAnim; // move the memory of all other anims to the combined anim and erase them from the source anims - for (size_t b = 0; b < collectedAnimIndices.size(); ++b) - { - aiAnimation* srcAnimation = mAnims[collectedAnimIndices[b]]; + for (size_t b = 0; b < collectedAnimIndices.size(); ++b) { + aiAnimation *srcAnimation = mAnims[collectedAnimIndices[b]]; combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0]; srcAnimation->mChannels[0] = NULL; delete srcAnimation; @@ -1022,8 +1004,7 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars // in a second go, delete all the single-channel-anims that we've stripped from their channels // back to front to preserve indices - you know, removing an element from a vector moves all elements behind the removed one - while (!collectedAnimIndices.empty()) - { + while (!collectedAnimIndices.empty()) { mAnims.erase(mAnims.begin() + collectedAnimIndices.back()); collectedAnimIndices.pop_back(); } @@ -1032,10 +1013,9 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars } // now store all anims in the scene - if (!mAnims.empty()) - { + if (!mAnims.empty()) { pScene->mNumAnimations = static_cast(mAnims.size()); - pScene->mAnimations = new aiAnimation*[mAnims.size()]; + pScene->mAnimations = new aiAnimation *[mAnims.size()]; std::copy(mAnims.begin(), mAnims.end(), pScene->mAnimations); } @@ -1044,12 +1024,11 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars // ------------------------------------------------------------------------------------------------ // Constructs the animations for the given source anim -void ColladaLoader::StoreAnimations(aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string &pPrefix) -{ +void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParser, const Collada::Animation *pSrcAnim, const std::string &pPrefix) { std::string animName = pPrefix.empty() ? pSrcAnim->mName : pPrefix + "_" + pSrcAnim->mName; // create nested animations, if given - for (std::vector::const_iterator it = pSrcAnim->mSubAnims.begin(); it != pSrcAnim->mSubAnims.end(); ++it) + for (std::vector::const_iterator it = pSrcAnim->mSubAnims.begin(); it != pSrcAnim->mSubAnims.end(); ++it) StoreAnimations(pScene, pParser, *it, animName); // create animation channels, if any @@ -1057,47 +1036,38 @@ void ColladaLoader::StoreAnimations(aiScene* pScene, const ColladaParser& pParse CreateAnimation(pScene, pParser, pSrcAnim, animName); } -struct MorphTimeValues -{ +struct MorphTimeValues { float mTime; - struct key - { + struct key { float mWeight; unsigned int mValue; }; std::vector mKeys; }; -void insertMorphTimeValue(std::vector &values, float time, float weight, unsigned int value) -{ +void insertMorphTimeValue(std::vector &values, float time, float weight, unsigned int value) { MorphTimeValues::key k; k.mValue = value; k.mWeight = weight; - if (values.size() == 0 || time < values[0].mTime) - { + if (values.size() == 0 || time < values[0].mTime) { MorphTimeValues val; val.mTime = time; val.mKeys.push_back(k); values.insert(values.begin(), val); return; } - if (time > values.back().mTime) - { + if (time > values.back().mTime) { MorphTimeValues val; val.mTime = time; val.mKeys.push_back(k); values.insert(values.end(), val); return; } - for (unsigned int i = 0; i < values.size(); i++) - { - if (std::abs(time - values[i].mTime) < 1e-6f) - { + for (unsigned int i = 0; i < values.size(); i++) { + if (std::abs(time - values[i].mTime) < 1e-6f) { values[i].mKeys.push_back(k); return; - } - else if (time > values[i].mTime && time < values[i + 1].mTime) - { + } else if (time > values[i].mTime && time < values[i + 1].mTime) { MorphTimeValues val; val.mTime = time; val.mKeys.push_back(k); @@ -1108,10 +1078,8 @@ void insertMorphTimeValue(std::vector &values, float time, floa // should not get here } -float getWeightAtKey(const std::vector &values, int key, unsigned int value) -{ - for (unsigned int i = 0; i < values[key].mKeys.size(); i++) - { +float getWeightAtKey(const std::vector &values, int key, unsigned int value) { + for (unsigned int i = 0; i < values[key].mKeys.size(); i++) { if (values[key].mKeys[i].mValue == value) return values[key].mKeys[i].mWeight; } @@ -1122,23 +1090,21 @@ float getWeightAtKey(const std::vector &values, int key, unsign // ------------------------------------------------------------------------------------------------ // Constructs the animation for the given source anim -void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName) -{ +void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParser, const Collada::Animation *pSrcAnim, const std::string &pName) { // collect a list of animatable nodes - std::vector nodes; + std::vector nodes; CollectNodes(pScene->mRootNode, nodes); - std::vector anims; - std::vector morphAnims; + std::vector anims; + std::vector morphAnims; - for (std::vector::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit) - { + for (std::vector::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit) { // find all the collada anim channels which refer to the current node std::vector entries; std::string nodeName = (*nit)->mName.data; // find the collada node corresponding to the aiNode - const Collada::Node* srcNode = FindNode(pParser.mRootNode, nodeName); + const Collada::Node *srcNode = FindNode(pParser.mRootNode, nodeName); // ai_assert( srcNode != NULL); if (!srcNode) continue; @@ -1146,16 +1112,14 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse // now check all channels if they affect the current node std::string targetID, subElement; for (std::vector::const_iterator cit = pSrcAnim->mChannels.begin(); - cit != pSrcAnim->mChannels.end(); ++cit) - { - const Collada::AnimationChannel& srcChannel = *cit; + cit != pSrcAnim->mChannels.end(); ++cit) { + const Collada::AnimationChannel &srcChannel = *cit; Collada::ChannelEntry entry; // we expect the animation target to be of type "nodeName/transformID.subElement". Ignore all others // find the slash that separates the node name - there should be only one std::string::size_type slashPos = srcChannel.mTarget.find('/'); - if (slashPos == std::string::npos) - { + if (slashPos == std::string::npos) { std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID); if (targetPos == std::string::npos) continue; @@ -1163,7 +1127,7 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse // not node transform, but something else. store as unknown animation channel for now entry.mChannel = &(*cit); entry.mTargetId = srcChannel.mTarget.substr(targetPos + pSrcAnim->mName.length(), - srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length()); + srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length()); if (entry.mTargetId.front() == '-') entry.mTargetId = entry.mTargetId.substr(1); entries.push_back(entry); @@ -1179,8 +1143,7 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse // find the dot that separates the transformID - there should be only one or zero std::string::size_type dotPos = srcChannel.mTarget.find('.'); - if (dotPos != std::string::npos) - { + if (dotPos != std::string::npos) { if (srcChannel.mTarget.find('.', dotPos + 1) != std::string::npos) continue; @@ -1198,15 +1161,13 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse entry.mSubElement = 2; else ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring"); - } - else { + } else { // no subelement following, transformId is remaining string entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1); } std::string::size_type bracketPos = srcChannel.mTarget.find('('); - if (bracketPos != std::string::npos) - { + if (bracketPos != std::string::npos) { entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1); subElement.clear(); subElement = srcChannel.mTarget.substr(bracketPos); @@ -1251,14 +1212,11 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse if (srcNode->mTransforms[a].mID == entry.mTransformId) entry.mTransformIndex = a; - if (entry.mTransformIndex == SIZE_MAX) - { - if (entry.mTransformId.find("morph-weights") != std::string::npos) - { + if (entry.mTransformIndex == SIZE_MAX) { + if (entry.mTransformId.find("morph-weights") != std::string::npos) { entry.mTargetId = entry.mTransformId; entry.mTransformId = ""; - } - else + } else continue; } @@ -1272,9 +1230,8 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse // resolve the data pointers for all anim channels. Find the minimum time while we're at it ai_real startTime = ai_real(1e20), endTime = ai_real(-1e20); - for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& e = *it; + for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) { + Collada::ChannelEntry &e = *it; e.mTimeAccessor = &pParser.ResolveLibraryReference(pParser.mAccessorLibrary, e.mChannel->mSourceTimes); e.mTimeData = &pParser.ResolveLibraryReference(pParser.mDataLibrary, e.mTimeAccessor->mSource); e.mValueAccessor = &pParser.ResolveLibraryReference(pParser.mAccessorLibrary, e.mChannel->mSourceValues); @@ -1284,8 +1241,7 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse if (e.mTimeAccessor->mCount != e.mValueAccessor->mCount) throw DeadlyImportError(format() << "Time count / value count mismatch in animation channel \"" << e.mChannel->mTarget << "\"."); - if (e.mTimeAccessor->mCount > 0) - { + if (e.mTimeAccessor->mCount > 0) { // find bounding times startTime = std::min(startTime, ReadFloat(*e.mTimeAccessor, *e.mTimeData, 0, 0)); endTime = std::max(endTime, ReadFloat(*e.mTimeAccessor, *e.mTimeData, e.mTimeAccessor->mCount - 1, 0)); @@ -1293,25 +1249,21 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse } std::vector resultTrafos; - if (!entries.empty() && entries.front().mTimeAccessor->mCount > 0) - { + if (!entries.empty() && entries.front().mTimeAccessor->mCount > 0) { // create a local transformation chain of the node's transforms std::vector transforms = srcNode->mTransforms; // now for every unique point in time, find or interpolate the key values for that time // and apply them to the transform chain. Then the node's present transformation can be calculated. ai_real time = startTime; - while (1) - { - for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& e = *it; + while (1) { + for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) { + Collada::ChannelEntry &e = *it; // find the keyframe behind the current point in time size_t pos = 0; ai_real postTime = 0.0; - while (1) - { + while (1) { if (pos >= e.mTimeAccessor->mCount) break; postTime = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos, 0); @@ -1328,13 +1280,11 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse temp[c] = ReadFloat(*e.mValueAccessor, *e.mValueData, pos, c); // if not exactly at the key time, interpolate with previous value set - if (postTime > time && pos > 0) - { + if (postTime > time && pos > 0) { ai_real preTime = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos - 1, 0); ai_real factor = (time - postTime) / (preTime - postTime); - for (size_t c = 0; c < e.mValueAccessor->mSize; ++c) - { + for (size_t c = 0; c < e.mValueAccessor->mSize; ++c) { ai_real v = ReadFloat(*e.mValueAccessor, *e.mValueData, pos - 1, c); temp[c] += (v - temp[c]) * factor; } @@ -1353,17 +1303,14 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse // find next point in time to evaluate. That's the closest frame larger than the current in any channel ai_real nextTime = ai_real(1e20); - for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& channelElement = *it; + for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) { + Collada::ChannelEntry &channelElement = *it; // find the next time value larger than the current size_t pos = 0; - while (pos < channelElement.mTimeAccessor->mCount) - { + while (pos < channelElement.mTimeAccessor->mCount) { const ai_real t = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0); - if (t > time) - { + if (t > time) { nextTime = std::min(nextTime, t); break; } @@ -1400,12 +1347,11 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse } // there should be some keyframes, but we aren't that fixated on valid input data -// ai_assert( resultTrafos.size() > 0); + // ai_assert( resultTrafos.size() > 0); // build an animation channel for the given node out of these trafo keys - if (!resultTrafos.empty()) - { - aiNodeAnim* dstAnim = new aiNodeAnim; + if (!resultTrafos.empty()) { + aiNodeAnim *dstAnim = new aiNodeAnim; dstAnim->mNodeName = nodeName; dstAnim->mNumPositionKeys = static_cast(resultTrafos.size()); dstAnim->mNumRotationKeys = static_cast(resultTrafos.size()); @@ -1414,8 +1360,7 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()]; dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()]; - for (size_t a = 0; a < resultTrafos.size(); ++a) - { + for (size_t a = 0; a < resultTrafos.size(); ++a) { aiMatrix4x4 mat = resultTrafos[a]; double time = double(mat.d4); // remember? time is stored in mat.d4 mat.d4 = 1.0f; @@ -1427,18 +1372,14 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse } anims.push_back(dstAnim); - } - else - { + } else { ASSIMP_LOG_WARN("Collada loader: found empty animation channel, ignored. Please check your exporter."); } - if (!entries.empty() && entries.front().mTimeAccessor->mCount > 0) - { + if (!entries.empty() && entries.front().mTimeAccessor->mCount > 0) { std::vector morphChannels; - for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& e = *it; + for (std::vector::iterator it = entries.begin(); it != entries.end(); ++it) { + Collada::ChannelEntry &e = *it; // skip non-transform types if (e.mTargetId.empty()) @@ -1447,8 +1388,7 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse if (e.mTargetId.find("morph-weights") != std::string::npos) morphChannels.push_back(e); } - if (morphChannels.size() > 0) - { + if (morphChannels.size() > 0) { // either 1) morph weight animation count should contain morph target count channels // or 2) one channel with morph target count arrays // assume first @@ -1459,9 +1399,8 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse std::vector morphTimeValues; int morphAnimChannelIndex = 0; - for (std::vector::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it) - { - Collada::ChannelEntry& e = *it; + for (std::vector::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it) { + Collada::ChannelEntry &e = *it; std::string::size_type apos = e.mTargetId.find('('); std::string::size_type bpos = e.mTargetId.find(')'); if (apos == std::string::npos || bpos == std::string::npos) @@ -1478,15 +1417,13 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse morphAnim->mNumKeys = static_cast(morphTimeValues.size()); morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys]; - for (unsigned int key = 0; key < morphAnim->mNumKeys; key++) - { + for (unsigned int key = 0; key < morphAnim->mNumKeys; key++) { morphAnim->mKeys[key].mNumValuesAndWeights = static_cast(morphChannels.size()); morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()]; morphAnim->mKeys[key].mWeights = new double[morphChannels.size()]; morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime; - for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++) - { + for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++) { morphAnim->mKeys[key].mValues[valueIndex] = valueIndex; morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex); } @@ -1497,31 +1434,26 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse } } - if (!anims.empty() || !morphAnims.empty()) - { - aiAnimation* anim = new aiAnimation; + if (!anims.empty() || !morphAnims.empty()) { + aiAnimation *anim = new aiAnimation; anim->mName.Set(pName); anim->mNumChannels = static_cast(anims.size()); - if (anim->mNumChannels > 0) - { - anim->mChannels = new aiNodeAnim*[anims.size()]; + if (anim->mNumChannels > 0) { + anim->mChannels = new aiNodeAnim *[anims.size()]; std::copy(anims.begin(), anims.end(), anim->mChannels); } anim->mNumMorphMeshChannels = static_cast(morphAnims.size()); - if (anim->mNumMorphMeshChannels > 0) - { - anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels]; + if (anim->mNumMorphMeshChannels > 0) { + anim->mMorphMeshChannels = new aiMeshMorphAnim *[anim->mNumMorphMeshChannels]; std::copy(morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels); } anim->mDuration = 0.0f; - for (size_t a = 0; a < anims.size(); ++a) - { + for (size_t a = 0; a < anims.size(); ++a) { anim->mDuration = std::max(anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys - 1].mTime); anim->mDuration = std::max(anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys - 1].mTime); anim->mDuration = std::max(anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys - 1].mTime); } - for (size_t a = 0; a < morphAnims.size(); ++a) - { + for (size_t a = 0; a < morphAnims.size(); ++a) { anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys - 1].mTime); } anim->mTicksPerSecond = 1; @@ -1531,11 +1463,10 @@ void ColladaLoader::CreateAnimation(aiScene* pScene, const ColladaParser& pParse // ------------------------------------------------------------------------------------------------ // Add a texture to a material structure -void ColladaLoader::AddTexture(aiMaterial& mat, const ColladaParser& pParser, - const Collada::Effect& effect, - const Collada::Sampler& sampler, - aiTextureType type, unsigned int idx) -{ +void ColladaLoader::AddTexture(aiMaterial &mat, const ColladaParser &pParser, + const Collada::Effect &effect, + const Collada::Sampler &sampler, + aiTextureType type, unsigned int idx) { // first of all, basic file name const aiString name = FindFilenameForEffectTexture(pParser, effect, sampler.mName); mat.AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, type, idx); @@ -1559,15 +1490,15 @@ void ColladaLoader::AddTexture(aiMaterial& mat, const ColladaParser& pParser, // UV transformation mat.AddProperty(&sampler.mTransform, 1, - _AI_MATKEY_UVTRANSFORM_BASE, type, idx); + _AI_MATKEY_UVTRANSFORM_BASE, type, idx); // Blend mode - mat.AddProperty((int*)&sampler.mOp, 1, - _AI_MATKEY_TEXBLEND_BASE, type, idx); + mat.AddProperty((int *)&sampler.mOp, 1, + _AI_MATKEY_TEXBLEND_BASE, type, idx); // Blend factor - mat.AddProperty((ai_real*)&sampler.mWeighting, 1, - _AI_MATKEY_TEXBLEND_BASE, type, idx); + mat.AddProperty((ai_real *)&sampler.mWeighting, 1, + _AI_MATKEY_TEXBLEND_BASE, type, idx); // UV source index ... if we didn't resolve the mapping, it is actually just // a guess but it works in most cases. We search for the frst occurrence of a @@ -1594,20 +1525,17 @@ void ColladaLoader::AddTexture(aiMaterial& mat, const ColladaParser& pParser, // ------------------------------------------------------------------------------------------------ // Fills materials from the collada material definitions -void ColladaLoader::FillMaterials(const ColladaParser& pParser, aiScene* /*pScene*/) -{ - for (auto &elem : newMats) - { - aiMaterial& mat = (aiMaterial&)*elem.second; - Collada::Effect& effect = *elem.first; +void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pScene*/) { + for (auto &elem : newMats) { + aiMaterial &mat = (aiMaterial &)*elem.second; + Collada::Effect &effect = *elem.first; // resolve shading mode int shadeMode; if (effect.mFaceted) /* fixme */ shadeMode = aiShadingMode_Flat; else { - switch (effect.mShadeType) - { + switch (effect.mShadeType) { case Collada::Shade_Constant: shadeMode = aiShadingMode_NoShading; break; @@ -1657,17 +1585,14 @@ void ColladaLoader::FillMaterials(const ColladaParser& pParser, aiScene* /*pScen // handle RGB transparency completely, cf Collada specs 1.5.0 pages 249 and 304 if (effect.mRGBTransparency) { // use luminance as defined by ISO/CIE color standards (see ITU-R Recommendation BT.709-4) - effect.mTransparency *= ( - 0.212671f * effect.mTransparent.r + - 0.715160f * effect.mTransparent.g + - 0.072169f * effect.mTransparent.b - ); + effect.mTransparency *= (0.212671f * effect.mTransparent.r + + 0.715160f * effect.mTransparent.g + + 0.072169f * effect.mTransparent.b); effect.mTransparent.a = 1.f; mat.AddProperty(&effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT); - } - else { + } else { effect.mTransparency *= effect.mTransparent.a; } @@ -1709,27 +1634,26 @@ void ColladaLoader::FillMaterials(const ColladaParser& pParser, aiScene* /*pScen // ------------------------------------------------------------------------------------------------ // Constructs materials from the collada material definitions -void ColladaLoader::BuildMaterials(ColladaParser& pParser, aiScene* /*pScene*/) -{ +void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/) { newMats.reserve(pParser.mMaterialLibrary.size()); for (ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); - matIt != pParser.mMaterialLibrary.end(); ++matIt) { - const Collada::Material& material = matIt->second; + matIt != pParser.mMaterialLibrary.end(); ++matIt) { + const Collada::Material &material = matIt->second; // a material is only a reference to an effect ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect); if (effIt == pParser.mEffectLibrary.end()) continue; - Collada::Effect& effect = effIt->second; + Collada::Effect &effect = effIt->second; // create material - aiMaterial* mat = new aiMaterial; + aiMaterial *mat = new aiMaterial; aiString name(material.mName.empty() ? matIt->first : material.mName); mat->AddProperty(&name, AI_MATKEY_NAME); // store the material mMaterialIndexByName[matIt->first] = newMats.size(); - newMats.push_back(std::pair(&effect, mat)); + newMats.push_back(std::pair(&effect, mat)); } // ScenePreprocessor generates a default material automatically if none is there. // All further code here in this loader works well without a valid material so @@ -1755,16 +1679,14 @@ void ColladaLoader::BuildMaterials(ColladaParser& pParser, aiScene* /*pScene*/) // ------------------------------------------------------------------------------------------------ // Resolves the texture name for the given effect texture entry -// and loads the texture data -aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParser, - const Collada::Effect& pEffect, const std::string& pName) -{ +// and loads the texture data +aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParser, + const Collada::Effect &pEffect, const std::string &pName) { aiString result; // recurse through the param references until we end up at an image std::string name = pName; - while (1) - { + while (1) { // the given string is a param entry. Find it Collada::Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name); // if not found, we're at the end of the recursion. The resulting string should be the image ID @@ -1777,8 +1699,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse // find the image referred by this name in the image library of the scene ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name); - if (imIt == pParser.mImageLibrary.end()) - { + if (imIt == pParser.mImageLibrary.end()) { ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\"."); //set default texture file name @@ -1788,18 +1709,16 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse } // if this is an embedded texture image setup an aiTexture for it - if (!imIt->second.mImageData.empty()) - { - aiTexture* tex = new aiTexture(); + if (!imIt->second.mImageData.empty()) { + aiTexture *tex = new aiTexture(); // Store embedded texture name reference tex->mFilename.Set(imIt->second.mFileName.c_str()); result.Set(imIt->second.mFileName); // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" -// result.data[0] = '*'; -// result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast(MAXLEN - 1), static_cast(mTextures.size())); - + // result.data[0] = '*'; + // result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast(MAXLEN - 1), static_cast(mTextures.size())); // setup format hint if (imIt->second.mEmbeddedFormat.length() >= HINTMAXTEXTURELEN) { @@ -1810,14 +1729,12 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse // and copy texture data tex->mHeight = 0; tex->mWidth = static_cast(imIt->second.mImageData.size()); - tex->pcData = (aiTexel*)new char[tex->mWidth]; + tex->pcData = (aiTexel *)new char[tex->mWidth]; memcpy(tex->pcData, &imIt->second.mImageData[0], tex->mWidth); // and add this texture to the list mTextures.push_back(tex); - } - else - { + } else { if (imIt->second.mFileName.empty()) { throw DeadlyImportError("Collada: Invalid texture, no data or file reference given"); } @@ -1829,8 +1746,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse // ------------------------------------------------------------------------------------------------ // Reads a float value from an accessor and its data array. -ai_real ColladaLoader::ReadFloat(const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const -{ +ai_real ColladaLoader::ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const { // FIXME: (thom) Test for data type here in every access? For the moment, I leave this to the caller size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset; ai_assert(pos < pData.mValues.size()); @@ -1839,8 +1755,7 @@ ai_real ColladaLoader::ReadFloat(const Collada::Accessor& pAccessor, const Colla // ------------------------------------------------------------------------------------------------ // Reads a string value from an accessor and its data array. -const std::string& ColladaLoader::ReadString(const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const -{ +const std::string &ColladaLoader::ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const { size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset; ai_assert(pos < pData.mStrings.size()); return pData.mStrings[pos]; @@ -1848,8 +1763,7 @@ const std::string& ColladaLoader::ReadString(const Collada::Accessor& pAccessor, // ------------------------------------------------------------------------------------------------ // Collects all nodes into the given array -void ColladaLoader::CollectNodes(const aiNode* pNode, std::vector& poNodes) const -{ +void ColladaLoader::CollectNodes(const aiNode *pNode, std::vector &poNodes) const { poNodes.push_back(pNode); for (size_t a = 0; a < pNode->mNumChildren; ++a) { CollectNodes(pNode->mChildren[a], poNodes); @@ -1858,14 +1772,12 @@ void ColladaLoader::CollectNodes(const aiNode* pNode, std::vector // ------------------------------------------------------------------------------------------------ // Finds a node in the collada scene by the given name -const Collada::Node* ColladaLoader::FindNode(const Collada::Node* pNode, const std::string& pName) const -{ +const Collada::Node *ColladaLoader::FindNode(const Collada::Node *pNode, const std::string &pName) const { if (pNode->mName == pName || pNode->mID == pName) return pNode; - for (size_t a = 0; a < pNode->mChildren.size(); ++a) - { - const Collada::Node* node = FindNode(pNode->mChildren[a], pName); + for (size_t a = 0; a < pNode->mChildren.size(); ++a) { + const Collada::Node *node = FindNode(pNode->mChildren[a], pName); if (node) return node; } @@ -1875,7 +1787,7 @@ const Collada::Node* ColladaLoader::FindNode(const Collada::Node* pNode, const s // ------------------------------------------------------------------------------------------------ // Finds a node in the collada scene by the given SID -const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const { +const Collada::Node *ColladaLoader::FindNodeBySID(const Collada::Node *pNode, const std::string &pSID) const { if (nullptr == pNode) { return nullptr; } @@ -1884,8 +1796,8 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c return pNode; } - for( size_t a = 0; a < pNode->mChildren.size(); ++a) { - const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID); + for (size_t a = 0; a < pNode->mChildren.size(); ++a) { + const Collada::Node *node = FindNodeBySID(pNode->mChildren[a], pSID); if (node) { return node; } @@ -1897,28 +1809,22 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c // ------------------------------------------------------------------------------------------------ // Finds a proper unique name for a node derived from the collada-node's properties. // The name must be unique for proper node-bone association. -std::string ColladaLoader::FindNameForNode(const Collada::Node* pNode) -{ +std::string ColladaLoader::FindNameForNode(const Collada::Node *pNode) { // If explicitly requested, just use the collada name. - if (useColladaName) - { + if (useColladaName) { if (!pNode->mName.empty()) { return pNode->mName; - } - else { + } else { return format() << "$ColladaAutoName$_" << mNodeNameCounter++; } - } - else - { + } else { // Now setup the name of the assimp node. The collada name might not be // unique, so we use the collada ID. if (!pNode->mID.empty()) return pNode->mID; else if (!pNode->mSID.empty()) return pNode->mSID; - else - { + else { // No need to worry. Unnamed nodes are no problem at all, except // if cameras or lights need to be assigned to them. return format() << "$ColladaAutoName$_" << mNodeNameCounter++; diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index 25ee2bc3c..5080094c1 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -47,18 +47,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER -#include -#include #include "ColladaParser.h" -#include -#include #include #include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include #include @@ -68,24 +68,24 @@ using namespace Assimp::Formatter; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile) - : mFileName(pFile) - , mReader(nullptr) - , mDataLibrary() - , mAccessorLibrary() - , mMeshLibrary() - , mNodeLibrary() - , mImageLibrary() - , mEffectLibrary() - , mMaterialLibrary() - , mLightLibrary() - , mCameraLibrary() - , mControllerLibrary() - , mRootNode(nullptr) - , mAnims() - , mUnitSize(1.0f) - , mUpDirection(UP_Y) - , mFormat(FV_1_5_n) // We assume the newest file format by default +ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) : + mFileName(pFile), + mReader(nullptr), + mDataLibrary(), + mAccessorLibrary(), + mMeshLibrary(), + mNodeLibrary(), + mImageLibrary(), + mEffectLibrary(), + mMaterialLibrary(), + mLightLibrary(), + mCameraLibrary(), + mControllerLibrary(), + mRootNode(nullptr), + mAnims(), + mUnitSize(1.0f), + mUpDirection(UP_Y), + mFormat(FV_1_5_n) // We assume the newest file format by default { // validate io-handler instance if (nullptr == pIOHandler) { @@ -112,8 +112,7 @@ ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile) if (daefile == nullptr) { ThrowException(std::string("Invalid ZAE manifest: '") + std::string(dae_filename) + std::string("' is missing")); } - } - else { + } else { // attempt to open the file directly daefile.reset(pIOHandler->Open(pFile)); if (daefile.get() == nullptr) { @@ -139,8 +138,7 @@ ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile) // ------------------------------------------------------------------------------------------------ // Destructor, private as well -ColladaParser::~ColladaParser() -{ +ColladaParser::~ColladaParser() { delete mReader; for (NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it) delete it->second; @@ -153,8 +151,7 @@ ColladaParser::~ColladaParser() std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) { // Open the manifest std::unique_ptr manifestfile(zip_archive.Open("manifest.xml")); - if (manifestfile == nullptr) - { + if (manifestfile == nullptr) { // No manifest, hope there is only one .DAE inside std::vector file_list; zip_archive.getFileListExtension(file_list, "dae"); @@ -168,19 +165,16 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) { std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(manifestfile.get())); std::unique_ptr manifest_reader(irr::io::createIrrXMLReader(mIOWrapper.get())); - while (manifest_reader->read()) - { + while (manifest_reader->read()) { // find the manifest "dae_root" element - if (manifest_reader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (::strcmp(manifest_reader->getNodeName(), "dae_root") == 0) - { + if (manifest_reader->getNodeType() == irr::io::EXN_ELEMENT) { + if (::strcmp(manifest_reader->getNodeName(), "dae_root") == 0) { if (!manifest_reader->read()) return std::string(); if (manifest_reader->getNodeType() != irr::io::EXN_TEXT && manifest_reader->getNodeType() != irr::io::EXN_CDATA) return std::string(); - const char* filepath = manifest_reader->getNodeData(); + const char *filepath = manifest_reader->getNodeData(); if (filepath == nullptr) return std::string(); @@ -196,14 +190,12 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) { // ------------------------------------------------------------------------------------------------ // Convert a path read from a collada file to the usual representation -void ColladaParser::UriDecodePath(aiString& ss) -{ +void ColladaParser::UriDecodePath(aiString &ss) { // TODO: collada spec, p 22. Handle URI correctly. // For the moment we're just stripping the file:// away to make it work. // Windows doesn't seem to be able to find stuff like // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg' - if (0 == strncmp(ss.data, "file://", 7)) - { + if (0 == strncmp(ss.data, "file://", 7)) { ss.length -= 7; memmove(ss.data, ss.data + 7, ss.length); ss.data[ss.length] = '\0'; @@ -211,7 +203,7 @@ void ColladaParser::UriDecodePath(aiString& ss) // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes... // I need to filter it without destroying linux paths starting with "/somewhere" -#if defined( _MSC_VER ) +#if defined(_MSC_VER) if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { #else if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') { @@ -222,19 +214,15 @@ void ColladaParser::UriDecodePath(aiString& ss) } // find and convert all %xy special chars - char* out = ss.data; - for (const char* it = ss.data; it != ss.data + ss.length; /**/) - { - if (*it == '%' && (it + 3) < ss.data + ss.length) - { + char *out = ss.data; + for (const char *it = ss.data; it != ss.data + ss.length; /**/) { + if (*it == '%' && (it + 3) < ss.data + ss.length) { // separate the number to avoid dragging in chars from behind into the parsing char mychar[3] = { it[1], it[2], 0 }; size_t nbr = strtoul16(mychar); it += 3; *out++ = (char)(nbr & 0xFF); - } - else - { + } else { *out++ = *it++; } } @@ -247,10 +235,9 @@ void ColladaParser::UriDecodePath(aiString& ss) // ------------------------------------------------------------------------------------------------ // Read bool from text contents of current element -bool ColladaParser::ReadBoolFromTextContent() -{ - const char* cur = GetTextContent(); - if ( nullptr == cur) { +bool ColladaParser::ReadBoolFromTextContent() { + const char *cur = GetTextContent(); + if (nullptr == cur) { return false; } return (!ASSIMP_strincmp(cur, "true", 4) || '0' != *cur); @@ -258,10 +245,9 @@ bool ColladaParser::ReadBoolFromTextContent() // ------------------------------------------------------------------------------------------------ // Read float from text contents of current element -ai_real ColladaParser::ReadFloatFromTextContent() -{ - const char* cur = GetTextContent(); - if ( nullptr == cur ) { +ai_real ColladaParser::ReadFloatFromTextContent() { + const char *cur = GetTextContent(); + if (nullptr == cur) { return 0.0; } return fast_atof(cur); @@ -269,49 +255,39 @@ ai_real ColladaParser::ReadFloatFromTextContent() // ------------------------------------------------------------------------------------------------ // Reads the contents of the file -void ColladaParser::ReadContents() -{ - while (mReader->read()) - { +void ColladaParser::ReadContents() { + while (mReader->read()) { // handle the root element "COLLADA" - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("COLLADA")) - { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("COLLADA")) { // check for 'version' attribute const int attrib = TestAttribute("version"); if (attrib != -1) { - const char* version = mReader->getAttributeValue(attrib); + const char *version = mReader->getAttributeValue(attrib); // Store declared format version string aiString v; v.Set(version); - mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v ); + mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v); if (!::strncmp(version, "1.5", 3)) { mFormat = FV_1_5_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n"); - } - else if (!::strncmp(version, "1.4", 3)) { + } else if (!::strncmp(version, "1.4", 3)) { mFormat = FV_1_4_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n"); - } - else if (!::strncmp(version, "1.3", 3)) { + } else if (!::strncmp(version, "1.3", 3)) { mFormat = FV_1_3_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n"); } } ReadStructure(); - } - else - { + } else { ASSIMP_LOG_DEBUG_F("Ignoring global element <", mReader->getNodeName(), ">."); SkipElement(); } - } - else - { + } else { // skip everything else silently } } @@ -319,13 +295,10 @@ void ColladaParser::ReadContents() // ------------------------------------------------------------------------------------------------ // Reads the structure of the file -void ColladaParser::ReadStructure() -{ - while (mReader->read()) - { +void ColladaParser::ReadStructure() { + while (mReader->read()) { // beginning of elements - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("asset")) ReadAssetInfo(); else if (IsElement("library_animations")) @@ -354,9 +327,7 @@ void ColladaParser::ReadStructure() ReadScene(); else SkipElement(); - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { break; } } @@ -367,34 +338,27 @@ void ColladaParser::ReadStructure() // ------------------------------------------------------------------------------------------------ // Reads asset information such as coordinate system information and legal blah -void ColladaParser::ReadAssetInfo() -{ +void ColladaParser::ReadAssetInfo() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("unit")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("unit")) { // read unit data from the element's attributes const int attrIndex = TestAttribute("meter"); if (attrIndex == -1) { mUnitSize = 1.f; - } - else { + } else { mUnitSize = mReader->getAttributeValueAsFloat(attrIndex); } // consume the trailing stuff if (!mReader->isEmptyElement()) SkipElement(); - } - else if (IsElement("up_axis")) - { + } else if (IsElement("up_axis")) { // read content, strip whitespace, compare - const char* content = GetTextContent(); + const char *content = GetTextContent(); if (strncmp(content, "X_UP", 4) == 0) mUpDirection = UP_X; else if (strncmp(content, "Z_UP", 4) == 0) @@ -404,18 +368,12 @@ void ColladaParser::ReadAssetInfo() // check element end TestClosing("up_axis"); - } - else if (IsElement("contributor")) - { + } else if (IsElement("contributor")) { ReadContributorInfo(); - } - else - { + } else { ReadMetaDataItem(mAssetMetaData); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "asset") != 0) ThrowException("Expected end of element."); @@ -426,19 +384,14 @@ void ColladaParser::ReadAssetInfo() // ------------------------------------------------------------------------------------------------ // Reads the contributor info -void ColladaParser::ReadContributorInfo() -{ +void ColladaParser::ReadContributorInfo() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { ReadMetaDataItem(mAssetMetaData); - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "contributor") != 0) ThrowException("Expected end of element."); break; @@ -448,11 +401,11 @@ void ColladaParser::ReadContributorInfo() static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) { for (size_t i = 0; i < key_renaming.size(); ++i) { - if (key_renaming[i].first == collada_key) { + if (key_renaming[i].first == collada_key) { found_index = i; return true; - } - } + } + } found_index = std::numeric_limits::max(); return false; } @@ -461,44 +414,39 @@ static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVecto // Reads a single string metadata item void ColladaParser::ReadMetaDataItem(StringMetaData &metadata) { const Collada::MetaKeyPairVector &key_renaming = GetColladaAssimpMetaKeysCamelCase(); - // Metadata such as created, keywords, subject etc - const char *key_char = mReader->getNodeName(); - if (key_char != nullptr) { + // Metadata such as created, keywords, subject etc + const char *key_char = mReader->getNodeName(); + if (key_char != nullptr) { const std::string key_str(key_char); - const char *value_char = TestTextContent(); - if (value_char != nullptr) { + const char *value_char = TestTextContent(); + if (value_char != nullptr) { aiString aistr; - aistr.Set(value_char); + aistr.Set(value_char); std::string camel_key_str(key_str); - ToCamelCase(camel_key_str); + ToCamelCase(camel_key_str); - size_t found_index; - if (FindCommonKey(camel_key_str, key_renaming, found_index)) { + size_t found_index; + if (FindCommonKey(camel_key_str, key_renaming, found_index)) { metadata.emplace(key_renaming[found_index].second, aistr); } else { - metadata.emplace(camel_key_str, aistr); - } + metadata.emplace(camel_key_str, aistr); + } } TestClosing(key_str.c_str()); - } - else + } else SkipElement(); } // ------------------------------------------------------------------------------------------------ // Reads the animation clips -void ColladaParser::ReadAnimationClipLibrary() -{ +void ColladaParser::ReadAnimationClipLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("animation_clip")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("animation_clip")) { // optional name given as an attribute std::string animName; int indexName = TestAttribute("name"); @@ -510,20 +458,16 @@ void ColladaParser::ReadAnimationClipLibrary() else animName = std::string("animation_") + to_string(mAnimationClipLibrary.size()); - std::pair > clip; + std::pair> clip; clip.first = animName; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("instance_animation")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("instance_animation")) { int indexUrl = TestAttribute("url"); - if (indexUrl >= 0) - { - const char* url = mReader->getAttributeValue(indexUrl); + if (indexUrl >= 0) { + const char *url = mReader->getAttributeValue(indexUrl); if (url[0] != '#') ThrowException("Unknown reference format"); @@ -531,15 +475,11 @@ void ColladaParser::ReadAnimationClipLibrary() clip.second.push_back(url); } - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "animation_clip") != 0) ThrowException("Expected end of element."); @@ -547,19 +487,14 @@ void ColladaParser::ReadAnimationClipLibrary() } } - if (clip.second.size() > 0) - { + if (clip.second.size() > 0) { mAnimationClipLibrary.push_back(clip); } - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_animation_clips") != 0) ThrowException("Expected end of element."); @@ -568,8 +503,7 @@ void ColladaParser::ReadAnimationClipLibrary() } } -void ColladaParser::PostProcessControllers() -{ +void ColladaParser::PostProcessControllers() { std::string meshId; for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) { meshId = it->second.mMeshId; @@ -585,14 +519,11 @@ void ColladaParser::PostProcessControllers() // ------------------------------------------------------------------------------------------------ // Re-build animations from animation clip library, if present, otherwise combine single-channel animations -void ColladaParser::PostProcessRootAnimations() -{ - if (mAnimationClipLibrary.size() > 0) - { +void ColladaParser::PostProcessRootAnimations() { + if (mAnimationClipLibrary.size() > 0) { Animation temp; - for (AnimationClipLibrary::iterator it = mAnimationClipLibrary.begin(); it != mAnimationClipLibrary.end(); ++it) - { + for (AnimationClipLibrary::iterator it = mAnimationClipLibrary.begin(); it != mAnimationClipLibrary.end(); ++it) { std::string clipName = it->first; Animation *clip = new Animation(); @@ -600,14 +531,12 @@ void ColladaParser::PostProcessRootAnimations() temp.mSubAnims.push_back(clip); - for (std::vector::iterator a = it->second.begin(); a != it->second.end(); ++a) - { + for (std::vector::iterator a = it->second.begin(); a != it->second.end(); ++a) { std::string animationID = *a; AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID); - if (animation != mAnimationLibrary.end()) - { + if (animation != mAnimationLibrary.end()) { Animation *pSourceAnimation = animation->second; pSourceAnimation->CollectChannelsRecursively(clip->mChannels); @@ -619,37 +548,27 @@ void ColladaParser::PostProcessRootAnimations() // Ensure no double deletes. temp.mSubAnims.clear(); - } - else - { + } else { mAnims.CombineSingleChannelAnimations(); } } // ------------------------------------------------------------------------------------------------ // Reads the animation library -void ColladaParser::ReadAnimationLibrary() -{ +void ColladaParser::ReadAnimationLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("animation")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("animation")) { // delegate the reading. Depending on the inner elements it will be a container or a anim channel ReadAnimation(&mAnims); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_animations") != 0) ThrowException("Expected end of element."); @@ -660,8 +579,7 @@ void ColladaParser::ReadAnimationLibrary() // ------------------------------------------------------------------------------------------------ // Reads an animation into the given parent structure -void ColladaParser::ReadAnimation(Collada::Animation* pParent) -{ +void ColladaParser::ReadAnimation(Collada::Animation *pParent) { if (mReader->isEmptyElement()) return; @@ -670,7 +588,7 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) typedef std::map ChannelMap; ChannelMap channels; // this is the anim container in case we're a container - Animation* anim = NULL; + Animation *anim = NULL; // optional name given as an attribute std::string animName; @@ -688,16 +606,12 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) else animName = "animation"; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // we have subanimations - if (IsElement("animation")) - { + if (IsElement("animation")) { // create container from our element - if (!anim) - { + if (!anim) { anim = new Animation; anim->mName = animName; pParent->mSubAnims.push_back(anim); @@ -705,14 +619,10 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) // recurse into the subelement ReadAnimation(anim); - } - else if (IsElement("source")) - { + } else if (IsElement("source")) { // possible animation data - we'll never know. Better store it ReadSource(); - } - else if (IsElement("sampler")) - { + } else if (IsElement("sampler")) { // read the ID to assign the corresponding collada channel afterwards. int indexId = GetAttribute("id"); std::string id = mReader->getAttributeValue(indexId); @@ -720,15 +630,13 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) // have it read into a channel ReadAnimationSampler(newChannel->second); - } - else if (IsElement("channel")) - { + } else if (IsElement("channel")) { // the binding element whose whole purpose is to provide the target to animate // Thanks, Collada! A directly posted information would have been too simple, I guess. // Better add another indirection to that! Can't have enough of those. int indexTarget = GetAttribute("target"); int indexSource = GetAttribute("source"); - const char* sourceId = mReader->getAttributeValue(indexSource); + const char *sourceId = mReader->getAttributeValue(indexSource); if (sourceId[0] == '#') sourceId++; ChannelMap::iterator cit = channels.find(sourceId); @@ -737,15 +645,11 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) if (!mReader->isEmptyElement()) SkipElement(); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "animation") != 0) ThrowException("Expected end of element."); @@ -754,15 +658,14 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) } // it turned out to have channels - add them - if (!channels.empty()) - { + if (!channels.empty()) { // FIXME: Is this essentially doing the same as "single-anim-node" codepath in // ColladaLoader::StoreAnimations? For now, this has been deferred to after // all animations and all clips have been read. Due to handling of // this cannot be done here, as the channel owner // is lost, and some exporters make up animations by referring to multiple // single-channel animations from an . -/* + /* // special filtering for stupid exporters packing each channel into a separate animation if( channels.size() == 1) { @@ -771,8 +674,7 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) */ { // else create the animation, if not done yet, and store the channels - if (!anim) - { + if (!anim) { anim = new Animation; anim->mName = animName; pParent->mSubAnims.push_back(anim); @@ -780,8 +682,7 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) for (ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it) anim->mChannels.push_back(it->second); - if (indexID >= 0) - { + if (indexID >= 0) { mAnimationLibrary[animID] = anim; } } @@ -790,18 +691,14 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) // ------------------------------------------------------------------------------------------------ // Reads an animation sampler into the given anim channel -void ColladaParser::ReadAnimationSampler(Collada::AnimationChannel& pChannel) -{ - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("input")) - { +void ColladaParser::ReadAnimationSampler(Collada::AnimationChannel &pChannel) { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("input")) { int indexSemantic = GetAttribute("semantic"); - const char* semantic = mReader->getAttributeValue(indexSemantic); + const char *semantic = mReader->getAttributeValue(indexSemantic); int indexSource = GetAttribute("source"); - const char* source = mReader->getAttributeValue(indexSource); + const char *source = mReader->getAttributeValue(indexSource); if (source[0] != '#') ThrowException("Unsupported URL format"); source++; @@ -819,15 +716,11 @@ void ColladaParser::ReadAnimationSampler(Collada::AnimationChannel& pChannel) if (!mReader->isEmptyElement()) SkipElement(); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "sampler") != 0) ThrowException("Expected end of element."); @@ -838,17 +731,13 @@ void ColladaParser::ReadAnimationSampler(Collada::AnimationChannel& pChannel) // ------------------------------------------------------------------------------------------------ // Reads the skeleton controller library -void ColladaParser::ReadControllerLibrary() -{ +void ColladaParser::ReadControllerLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("controller")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("controller")) { // read ID. Ask the spec if it's necessary or optional... you might be surprised. int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); @@ -858,15 +747,11 @@ void ColladaParser::ReadControllerLibrary() // read on from there ReadController(mControllerLibrary[id]); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_controllers") != 0) ThrowException("Expected end of element."); @@ -877,18 +762,14 @@ void ColladaParser::ReadControllerLibrary() // ------------------------------------------------------------------------------------------------ // Reads a controller into the given mesh structure -void ColladaParser::ReadController(Collada::Controller& pController) -{ +void ColladaParser::ReadController(Collada::Controller &pController) { // initial values pController.mType = Skin; pController.mMethod = Normalized; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other - if (IsElement("morph")) - { + if (IsElement("morph")) { pController.mType = Morph; int baseIndex = GetAttribute("source"); pController.mMeshId = mReader->getAttributeValue(baseIndex) + 1; @@ -898,22 +779,17 @@ void ColladaParser::ReadController(Collada::Controller& pController) if (strcmp(method, "RELATIVE") == 0) pController.mMethod = Relative; } - } - else if (IsElement("skin")) - { + } else if (IsElement("skin")) { // read the mesh it refers to. According to the spec this could also be another // controller, but I refuse to implement every single idea they've come up with int sourceIndex = GetAttribute("source"); pController.mMeshId = mReader->getAttributeValue(sourceIndex) + 1; - } - else if (IsElement("bind_shape_matrix")) - { + } else if (IsElement("bind_shape_matrix")) { // content is 16 floats to define a matrix... it seems to be important for some models - const char* content = GetTextContent(); + const char *content = GetTextContent(); // read the 16 floats - for (unsigned int a = 0; a < 16; a++) - { + for (unsigned int a = 0; a < 16; a++) { // read a number content = fast_atoreal_move(content, pController.mBindShapeMatrix[a]); // skip whitespace after it @@ -921,22 +797,14 @@ void ColladaParser::ReadController(Collada::Controller& pController) } TestClosing("bind_shape_matrix"); - } - else if (IsElement("source")) - { + } else if (IsElement("source")) { // data array - we have specialists to handle this ReadSource(); - } - else if (IsElement("joints")) - { + } else if (IsElement("joints")) { ReadControllerJoints(pController); - } - else if (IsElement("vertex_weights")) - { + } else if (IsElement("vertex_weights")) { ReadControllerWeights(pController); - } - else if (IsElement("targets")) - { + } else if (IsElement("targets")) { while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("input")) { @@ -947,29 +815,22 @@ void ColladaParser::ReadController(Collada::Controller& pController) const char *source = mReader->getAttributeValue(sourceIndex); if (strcmp(semantics, "MORPH_TARGET") == 0) { pController.mMorphTarget = source + 1; - } - else if (strcmp(semantics, "MORPH_WEIGHT") == 0) - { + } else if (strcmp(semantics, "MORPH_WEIGHT") == 0) { pController.mMorphWeight = source + 1; } } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "targets") == 0) break; else ThrowException("Expected end of element."); } } - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "controller") == 0) break; else if (strcmp(mReader->getNodeName(), "skin") != 0 && strcmp(mReader->getNodeName(), "morph") != 0) @@ -980,19 +841,15 @@ void ColladaParser::ReadController(Collada::Controller& pController) // ------------------------------------------------------------------------------------------------ // Reads the joint definitions for the given controller -void ColladaParser::ReadControllerJoints(Collada::Controller& pController) -{ - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { +void ColladaParser::ReadControllerJoints(Collada::Controller &pController) { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX" - if (IsElement("input")) - { + if (IsElement("input")) { int indexSemantic = GetAttribute("semantic"); - const char* attrSemantic = mReader->getAttributeValue(indexSemantic); + const char *attrSemantic = mReader->getAttributeValue(indexSemantic); int indexSource = GetAttribute("source"); - const char* attrSource = mReader->getAttributeValue(indexSource); + const char *attrSource = mReader->getAttributeValue(indexSource); // local URLS always start with a '#'. We don't support global URLs if (attrSource[0] != '#') @@ -1010,15 +867,11 @@ void ColladaParser::ReadControllerJoints(Collada::Controller& pController) // skip inner data, if present if (!mReader->isEmptyElement()) SkipElement(); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "joints") != 0) ThrowException("Expected end of element."); @@ -1029,26 +882,22 @@ void ColladaParser::ReadControllerJoints(Collada::Controller& pController) // ------------------------------------------------------------------------------------------------ // Reads the joint weights for the given controller -void ColladaParser::ReadControllerWeights(Collada::Controller& pController) -{ +void ColladaParser::ReadControllerWeights(Collada::Controller &pController) { // read vertex count from attributes and resize the array accordingly int indexCount = GetAttribute("count"); size_t vertexCount = (size_t)mReader->getAttributeValueAsInt(indexCount); pController.mWeightCounts.resize(vertexCount); - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT" - if (IsElement("input") && vertexCount > 0) - { + if (IsElement("input") && vertexCount > 0) { InputChannel channel; int indexSemantic = GetAttribute("semantic"); - const char* attrSemantic = mReader->getAttributeValue(indexSemantic); + const char *attrSemantic = mReader->getAttributeValue(indexSemantic); int indexSource = GetAttribute("source"); - const char* attrSource = mReader->getAttributeValue(indexSource); + const char *attrSource = mReader->getAttributeValue(indexSource); int indexOffset = TestAttribute("offset"); if (indexOffset >= 0) channel.mOffset = mReader->getAttributeValueAsInt(indexOffset); @@ -1069,14 +918,11 @@ void ColladaParser::ReadControllerWeights(Collada::Controller& pController) // skip inner data, if present if (!mReader->isEmptyElement()) SkipElement(); - } - else if (IsElement("vcount") && vertexCount > 0) - { + } else if (IsElement("vcount") && vertexCount > 0) { // read weight count per vertex - const char* text = GetTextContent(); + const char *text = GetTextContent(); size_t numWeights = 0; - for (std::vector::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) - { + for (std::vector::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) { if (*text == 0) ThrowException("Out of data while reading "); @@ -1089,14 +935,11 @@ void ColladaParser::ReadControllerWeights(Collada::Controller& pController) // reserve weight count pController.mWeights.resize(numWeights); - } - else if (IsElement("v") && vertexCount > 0) - { + } else if (IsElement("v") && vertexCount > 0) { // read JointIndex - WeightIndex pairs - const char* text = GetTextContent(); + const char *text = GetTextContent(); - for (std::vector< std::pair >::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) - { + for (std::vector>::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) { if (*text == 0) ThrowException("Out of data while reading "); it->first = strtoul10(text, &text); @@ -1108,15 +951,11 @@ void ColladaParser::ReadControllerWeights(Collada::Controller& pController) } TestClosing("v"); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "vertex_weights") != 0) ThrowException("Expected end of element."); @@ -1127,16 +966,13 @@ void ColladaParser::ReadControllerWeights(Collada::Controller& pController) // ------------------------------------------------------------------------------------------------ // Reads the image library contents -void ColladaParser::ReadImageLibrary() -{ +void ColladaParser::ReadImageLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("image")) - { + if (IsElement("image")) { // read ID. Another entry which is "optional" by design but obligatory in reality int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); @@ -1146,14 +982,11 @@ void ColladaParser::ReadImageLibrary() // read on from there ReadImage(mImageLibrary[id]); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_images") != 0) ThrowException("Expected end of element."); @@ -1164,25 +997,19 @@ void ColladaParser::ReadImageLibrary() // ------------------------------------------------------------------------------------------------ // Reads an image entry into the given image -void ColladaParser::ReadImage(Collada::Image& pImage) -{ - while (mReader->read()) - { +void ColladaParser::ReadImage(Collada::Image &pImage) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // Need to run different code paths here, depending on the Collada XSD version if (IsElement("image")) { SkipElement(); - } - else if (IsElement("init_from")) - { - if (mFormat == FV_1_4_n) - { + } else if (IsElement("init_from")) { + if (mFormat == FV_1_4_n) { // FIX: C4D exporter writes empty tags if (!mReader->isEmptyElement()) { // element content is filename - hopefully - const char* sz = TestTextContent(); - if (sz) - { + const char *sz = TestTextContent(); + if (sz) { aiString filepath(sz); UriDecodePath(filepath); pImage.mFileName = filepath.C_Str(); @@ -1192,9 +1019,7 @@ void ColladaParser::ReadImage(Collada::Image& pImage) if (!pImage.mFileName.length()) { pImage.mFileName = "unknown_texture"; } - } - else if (mFormat == FV_1_5_n) - { + } else if (mFormat == FV_1_5_n) { // make sure we skip over mip and array initializations, which // we don't support, but which could confuse the loader if // they're not skipped. @@ -1212,35 +1037,31 @@ void ColladaParser::ReadImage(Collada::Image& pImage) // TODO: correctly jump over cube and volume maps? } - } - else if (mFormat == FV_1_5_n) - { - if (IsElement("ref")) - { + } else if (mFormat == FV_1_5_n) { + if (IsElement("ref")) { // element content is filename - hopefully - const char* sz = TestTextContent(); - if (sz) - { + const char *sz = TestTextContent(); + if (sz) { aiString filepath(sz); UriDecodePath(filepath); pImage.mFileName = filepath.C_Str(); } TestClosing("ref"); - } - else if (IsElement("hex") && !pImage.mFileName.length()) - { + } else if (IsElement("hex") && !pImage.mFileName.length()) { // embedded image. get format const int attrib = TestAttribute("format"); if (-1 == attrib) ASSIMP_LOG_WARN("Collada: Unknown image file format"); - else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib); + else + pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib); - const char* data = GetTextContent(); + const char *data = GetTextContent(); // hexadecimal-encoded binary octets. First of all, find the // required buffer size to reserve enough storage. - const char* cur = data; - while (!IsSpaceOrNewLine(*cur)) cur++; + const char *cur = data; + while (!IsSpaceOrNewLine(*cur)) + cur++; const unsigned int size = (unsigned int)(cur - data) * 2; pImage.mImageData.resize(size); @@ -1249,14 +1070,11 @@ void ColladaParser::ReadImage(Collada::Image& pImage) TestClosing("hex"); } - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "image") == 0) break; } @@ -1265,18 +1083,14 @@ void ColladaParser::ReadImage(Collada::Image& pImage) // ------------------------------------------------------------------------------------------------ // Reads the material library -void ColladaParser::ReadMaterialLibrary() -{ +void ColladaParser::ReadMaterialLibrary() { if (mReader->isEmptyElement()) return; std::map names; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("material")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("material")) { // read ID. By now you probably know my opinion about this "specification" int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); @@ -1289,17 +1103,13 @@ void ColladaParser::ReadMaterialLibrary() // create an entry and store it in the library under its ID mMaterialLibrary[id] = Material(); - if (!name.empty()) - { + if (!name.empty()) { std::map::iterator it = names.find(name); - if (it != names.end()) - { + if (it != names.end()) { std::ostringstream strStream; strStream << ++it->second; name.append(" " + strStream.str()); - } - else - { + } else { names[name] = 0; } @@ -1307,15 +1117,11 @@ void ColladaParser::ReadMaterialLibrary() } ReadMaterial(mMaterialLibrary[id]); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_materials") != 0) ThrowException("Expected end of element."); @@ -1326,16 +1132,13 @@ void ColladaParser::ReadMaterialLibrary() // ------------------------------------------------------------------------------------------------ // Reads the light library -void ColladaParser::ReadLightLibrary() -{ +void ColladaParser::ReadLightLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("light")) - { + if (IsElement("light")) { // read ID. By now you probably know my opinion about this "specification" int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); @@ -1343,14 +1146,11 @@ void ColladaParser::ReadLightLibrary() // create an entry and store it in the library under its ID ReadLight(mLightLibrary[id] = Light()); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_lights") != 0) ThrowException("Expected end of element."); @@ -1361,36 +1161,30 @@ void ColladaParser::ReadLightLibrary() // ------------------------------------------------------------------------------------------------ // Reads the camera library -void ColladaParser::ReadCameraLibrary() -{ +void ColladaParser::ReadCameraLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("camera")) - { + if (IsElement("camera")) { // read ID. By now you probably know my opinion about this "specification" int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); // create an entry and store it in the library under its ID - Camera& cam = mCameraLibrary[id]; + Camera &cam = mCameraLibrary[id]; attrID = TestAttribute("name"); if (attrID != -1) cam.mName = mReader->getAttributeValue(attrID); ReadCamera(cam); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_cameras") != 0) ThrowException("Expected end of element."); @@ -1401,33 +1195,26 @@ void ColladaParser::ReadCameraLibrary() // ------------------------------------------------------------------------------------------------ // Reads a material entry into the given material -void ColladaParser::ReadMaterial(Collada::Material& pMaterial) -{ - while (mReader->read()) - { +void ColladaParser::ReadMaterial(Collada::Material &pMaterial) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("material")) { SkipElement(); - } - else if (IsElement("instance_effect")) - { + } else if (IsElement("instance_effect")) { // referred effect by URL int attrUrl = GetAttribute("url"); - const char* url = mReader->getAttributeValue(attrUrl); + const char *url = mReader->getAttributeValue(attrUrl); if (url[0] != '#') ThrowException("Unknown reference format"); pMaterial.mEffect = url + 1; SkipElement(); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "material") != 0) ThrowException("Expected end of element."); @@ -1438,58 +1225,46 @@ void ColladaParser::ReadMaterial(Collada::Material& pMaterial) // ------------------------------------------------------------------------------------------------ // Reads a light entry into the given light -void ColladaParser::ReadLight(Collada::Light& pLight) -{ - while (mReader->read()) - { +void ColladaParser::ReadLight(Collada::Light &pLight) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("light")) { SkipElement(); - } - else if (IsElement("spot")) { + } else if (IsElement("spot")) { pLight.mType = aiLightSource_SPOT; - } - else if (IsElement("ambient")) { + } else if (IsElement("ambient")) { pLight.mType = aiLightSource_AMBIENT; - } - else if (IsElement("directional")) { + } else if (IsElement("directional")) { pLight.mType = aiLightSource_DIRECTIONAL; - } - else if (IsElement("point")) { + } else if (IsElement("point")) { pLight.mType = aiLightSource_POINT; - } - else if (IsElement("color")) { + } else if (IsElement("color")) { // text content contains 3 floats - const char* content = GetTextContent(); + const char *content = GetTextContent(); - content = fast_atoreal_move(content, (ai_real&)pLight.mColor.r); + content = fast_atoreal_move(content, (ai_real &)pLight.mColor.r); SkipSpacesAndLineEnd(&content); - content = fast_atoreal_move(content, (ai_real&)pLight.mColor.g); + content = fast_atoreal_move(content, (ai_real &)pLight.mColor.g); SkipSpacesAndLineEnd(&content); - content = fast_atoreal_move(content, (ai_real&)pLight.mColor.b); + content = fast_atoreal_move(content, (ai_real &)pLight.mColor.b); SkipSpacesAndLineEnd(&content); TestClosing("color"); - } - else if (IsElement("constant_attenuation")) { + } else if (IsElement("constant_attenuation")) { pLight.mAttConstant = ReadFloatFromTextContent(); TestClosing("constant_attenuation"); - } - else if (IsElement("linear_attenuation")) { + } else if (IsElement("linear_attenuation")) { pLight.mAttLinear = ReadFloatFromTextContent(); TestClosing("linear_attenuation"); - } - else if (IsElement("quadratic_attenuation")) { + } else if (IsElement("quadratic_attenuation")) { pLight.mAttQuadratic = ReadFloatFromTextContent(); TestClosing("quadratic_attenuation"); - } - else if (IsElement("falloff_angle")) { + } else if (IsElement("falloff_angle")) { pLight.mFalloffAngle = ReadFloatFromTextContent(); TestClosing("falloff_angle"); - } - else if (IsElement("falloff_exponent")) { + } else if (IsElement("falloff_exponent")) { pLight.mFalloffExponent = ReadFloatFromTextContent(); TestClosing("falloff_exponent"); } @@ -1503,16 +1278,13 @@ void ColladaParser::ReadLight(Collada::Light& pLight) else if (IsElement("penumbra_angle")) { pLight.mPenumbraAngle = ReadFloatFromTextContent(); TestClosing("penumbra_angle"); - } - else if (IsElement("intensity")) { + } else if (IsElement("intensity")) { pLight.mIntensity = ReadFloatFromTextContent(); TestClosing("intensity"); - } - else if (IsElement("falloff")) { + } else if (IsElement("falloff")) { pLight.mOuterAngle = ReadFloatFromTextContent(); TestClosing("falloff"); - } - else if (IsElement("hotspot_beam")) { + } else if (IsElement("hotspot_beam")) { pLight.mFalloffAngle = ReadFloatFromTextContent(); TestClosing("hotspot_beam"); } @@ -1522,8 +1294,7 @@ void ColladaParser::ReadLight(Collada::Light& pLight) pLight.mOuterAngle = ReadFloatFromTextContent(); TestClosing("decay_falloff"); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "light") == 0) break; } @@ -1532,39 +1303,30 @@ void ColladaParser::ReadLight(Collada::Light& pLight) // ------------------------------------------------------------------------------------------------ // Reads a camera entry into the given light -void ColladaParser::ReadCamera(Collada::Camera& pCamera) -{ - while (mReader->read()) - { +void ColladaParser::ReadCamera(Collada::Camera &pCamera) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("camera")) { SkipElement(); - } - else if (IsElement("orthographic")) { + } else if (IsElement("orthographic")) { pCamera.mOrtho = true; - } - else if (IsElement("xfov") || IsElement("xmag")) { + } else if (IsElement("xfov") || IsElement("xmag")) { pCamera.mHorFov = ReadFloatFromTextContent(); TestClosing((pCamera.mOrtho ? "xmag" : "xfov")); - } - else if (IsElement("yfov") || IsElement("ymag")) { + } else if (IsElement("yfov") || IsElement("ymag")) { pCamera.mVerFov = ReadFloatFromTextContent(); TestClosing((pCamera.mOrtho ? "ymag" : "yfov")); - } - else if (IsElement("aspect_ratio")) { + } else if (IsElement("aspect_ratio")) { pCamera.mAspect = ReadFloatFromTextContent(); TestClosing("aspect_ratio"); - } - else if (IsElement("znear")) { + } else if (IsElement("znear")) { pCamera.mZNear = ReadFloatFromTextContent(); TestClosing("znear"); - } - else if (IsElement("zfar")) { + } else if (IsElement("zfar")) { pCamera.mZFar = ReadFloatFromTextContent(); TestClosing("zfar"); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "camera") == 0) break; } @@ -1573,17 +1335,14 @@ void ColladaParser::ReadCamera(Collada::Camera& pCamera) // ------------------------------------------------------------------------------------------------ // Reads the effect library -void ColladaParser::ReadEffectLibrary() -{ +void ColladaParser::ReadEffectLibrary() { if (mReader->isEmptyElement()) { return; } - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("effect")) - { + if (IsElement("effect")) { // read ID. Do I have to repeat my ranting about "optional" attributes? int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); @@ -1592,14 +1351,11 @@ void ColladaParser::ReadEffectLibrary() mEffectLibrary[id] = Effect(); // read on from there ReadEffect(mEffectLibrary[id]); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_effects") != 0) ThrowException("Expected end of element."); @@ -1610,20 +1366,15 @@ void ColladaParser::ReadEffectLibrary() // ------------------------------------------------------------------------------------------------ // Reads an effect entry into the given effect -void ColladaParser::ReadEffect(Collada::Effect& pEffect) -{ +void ColladaParser::ReadEffect(Collada::Effect &pEffect) { // for the moment we don't support any other type of effect. - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("profile_COMMON")) ReadEffectProfileCommon(pEffect); else SkipElement(); - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "effect") != 0) ThrowException("Expected end of element."); @@ -1634,26 +1385,20 @@ void ColladaParser::ReadEffect(Collada::Effect& pEffect) // ------------------------------------------------------------------------------------------------ // Reads an COMMON effect profile -void ColladaParser::ReadEffectProfileCommon(Collada::Effect& pEffect) -{ - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { +void ColladaParser::ReadEffectProfileCommon(Collada::Effect &pEffect) { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("newparam")) { // save ID int attrSID = GetAttribute("sid"); std::string sid = mReader->getAttributeValue(attrSID); pEffect.mParams[sid] = EffectParam(); ReadEffectParam(pEffect.mParams[sid]); - } - else if (IsElement("technique") || IsElement("extra")) - { + } else if (IsElement("technique") || IsElement("extra")) { // just syntactic sugar } - else if (mFormat == FV_1_4_n && IsElement("image")) - { + else if (mFormat == FV_1_4_n && IsElement("image")) { // read ID. Another entry which is "optional" by design but obligatory in reality int attrID = GetAttribute("id"); std::string id = mReader->getAttributeValue(attrID); @@ -1686,11 +1431,10 @@ void ColladaParser::ReadEffectProfileCommon(Collada::Effect& pEffect) ReadEffectColor(pEffect.mSpecular, pEffect.mTexSpecular); else if (IsElement("reflective")) { ReadEffectColor(pEffect.mReflective, pEffect.mTexReflective); - } - else if (IsElement("transparent")) { + } else if (IsElement("transparent")) { pEffect.mHasTransparency = true; - const char* opaque = mReader->getAttributeValueSafe("opaque"); + const char *opaque = mReader->getAttributeValueSafe("opaque"); if (::strcmp(opaque, "RGB_ZERO") == 0 || ::strcmp(opaque, "RGB_ONE") == 0) { pEffect.mRGBTransparency = true; @@ -1702,8 +1446,7 @@ void ColladaParser::ReadEffectProfileCommon(Collada::Effect& pEffect) } ReadEffectColor(pEffect.mTransparent, pEffect.mTexTransparent); - } - else if (IsElement("shininess")) + } else if (IsElement("shininess")) ReadEffectFloat(pEffect.mShininess); else if (IsElement("reflectivity")) ReadEffectFloat(pEffect.mReflectivity); @@ -1731,20 +1474,15 @@ void ColladaParser::ReadEffectProfileCommon(Collada::Effect& pEffect) else if (IsElement("wireframe")) { pEffect.mWireframe = ReadBoolFromTextContent(); TestClosing("wireframe"); - } - else if (IsElement("faceted")) { + } else if (IsElement("faceted")) { pEffect.mFaceted = ReadBoolFromTextContent(); TestClosing("faceted"); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if (strcmp(mReader->getNodeName(), "profile_COMMON") == 0) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + if (strcmp(mReader->getNodeName(), "profile_COMMON") == 0) { break; } } @@ -1753,14 +1491,12 @@ void ColladaParser::ReadEffectProfileCommon(Collada::Effect& pEffect) // ------------------------------------------------------------------------------------------------ // Read texture wrapping + UV transform settings from a profile==Maya chunk -void ColladaParser::ReadSamplerProperties(Sampler& out) -{ +void ColladaParser::ReadSamplerProperties(Sampler &out) { if (mReader->isEmptyElement()) { return; } - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // MAYA extensions @@ -1768,42 +1504,33 @@ void ColladaParser::ReadSamplerProperties(Sampler& out) if (IsElement("wrapU")) { out.mWrapU = ReadBoolFromTextContent(); TestClosing("wrapU"); - } - else if (IsElement("wrapV")) { + } else if (IsElement("wrapV")) { out.mWrapV = ReadBoolFromTextContent(); TestClosing("wrapV"); - } - else if (IsElement("mirrorU")) { + } else if (IsElement("mirrorU")) { out.mMirrorU = ReadBoolFromTextContent(); TestClosing("mirrorU"); - } - else if (IsElement("mirrorV")) { + } else if (IsElement("mirrorV")) { out.mMirrorV = ReadBoolFromTextContent(); TestClosing("mirrorV"); - } - else if (IsElement("repeatU")) { + } else if (IsElement("repeatU")) { out.mTransform.mScaling.x = ReadFloatFromTextContent(); TestClosing("repeatU"); - } - else if (IsElement("repeatV")) { + } else if (IsElement("repeatV")) { out.mTransform.mScaling.y = ReadFloatFromTextContent(); TestClosing("repeatV"); - } - else if (IsElement("offsetU")) { + } else if (IsElement("offsetU")) { out.mTransform.mTranslation.x = ReadFloatFromTextContent(); TestClosing("offsetU"); - } - else if (IsElement("offsetV")) { + } else if (IsElement("offsetV")) { out.mTransform.mTranslation.y = ReadFloatFromTextContent(); TestClosing("offsetV"); - } - else if (IsElement("rotateUV")) { + } else if (IsElement("rotateUV")) { out.mTransform.mRotation = ReadFloatFromTextContent(); TestClosing("rotateUV"); - } - else if (IsElement("blend_mode")) { + } else if (IsElement("blend_mode")) { - const char* sz = GetTextContent(); + const char *sz = GetTextContent(); // http://www.feelingsoftware.com/content/view/55/72/lang,en/ // NONE, OVER, IN, OUT, ADD, SUBTRACT, MULTIPLY, DIFFERENCE, LIGHTEN, DARKEN, SATURATE, DESATURATE and ILLUMINATE if (0 == ASSIMP_strincmp(sz, "ADD", 3)) @@ -1825,8 +1552,7 @@ void ColladaParser::ReadSamplerProperties(Sampler& out) else if (IsElement("weighting")) { out.mWeighting = ReadFloatFromTextContent(); TestClosing("weighting"); - } - else if (IsElement("mix_with_previous_layer")) { + } else if (IsElement("mix_with_previous_layer")) { out.mMixWithPrevious = ReadFloatFromTextContent(); TestClosing("mix_with_previous_layer"); } @@ -1836,8 +1562,7 @@ void ColladaParser::ReadSamplerProperties(Sampler& out) out.mWeighting = ReadFloatFromTextContent(); TestClosing("amount"); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "technique") == 0) break; } @@ -1846,37 +1571,32 @@ void ColladaParser::ReadSamplerProperties(Sampler& out) // ------------------------------------------------------------------------------------------------ // Reads an effect entry containing a color or a texture defining that color -void ColladaParser::ReadEffectColor(aiColor4D& pColor, Sampler& pSampler) -{ +void ColladaParser::ReadEffectColor(aiColor4D &pColor, Sampler &pSampler) { if (mReader->isEmptyElement()) return; // Save current element name const std::string curElem = mReader->getNodeName(); - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("color")) - { + if (IsElement("color")) { // text content contains 4 floats - const char* content = GetTextContent(); + const char *content = GetTextContent(); - content = fast_atoreal_move(content, (ai_real&)pColor.r); + content = fast_atoreal_move(content, (ai_real &)pColor.r); SkipSpacesAndLineEnd(&content); - content = fast_atoreal_move(content, (ai_real&)pColor.g); + content = fast_atoreal_move(content, (ai_real &)pColor.g); SkipSpacesAndLineEnd(&content); - content = fast_atoreal_move(content, (ai_real&)pColor.b); + content = fast_atoreal_move(content, (ai_real &)pColor.b); SkipSpacesAndLineEnd(&content); - content = fast_atoreal_move(content, (ai_real&)pColor.a); + content = fast_atoreal_move(content, (ai_real &)pColor.a); SkipSpacesAndLineEnd(&content); TestClosing("color"); - } - else if (IsElement("texture")) - { + } else if (IsElement("texture")) { // get name of source texture/sampler int attrTex = GetAttribute("texture"); pSampler.mName = mReader->getAttributeValue(attrTex); @@ -1890,28 +1610,22 @@ void ColladaParser::ReadEffectColor(aiColor4D& pColor, Sampler& pSampler) // as we've read texture, the color needs to be 1,1,1,1 pColor = aiColor4D(1.f, 1.f, 1.f, 1.f); - } - else if (IsElement("technique")) - { + } else if (IsElement("technique")) { const int _profile = GetAttribute("profile"); - const char* profile = mReader->getAttributeValue(_profile); + const char *profile = mReader->getAttributeValue(_profile); // Some extensions are quite useful ... ReadSamplerProperties processes // several extensions in MAYA, OKINO and MAX3D profiles. - if (!::strcmp(profile, "MAYA") || !::strcmp(profile, "MAX3D") || !::strcmp(profile, "OKINO")) - { + if (!::strcmp(profile, "MAYA") || !::strcmp(profile, "MAX3D") || !::strcmp(profile, "OKINO")) { // get more information on this sampler ReadSamplerProperties(pSampler); - } - else SkipElement(); - } - else if (!IsElement("extra")) - { + } else + SkipElement(); + } else if (!IsElement("extra")) { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (mReader->getNodeName() == curElem) break; } @@ -1920,27 +1634,21 @@ void ColladaParser::ReadEffectColor(aiColor4D& pColor, Sampler& pSampler) // ------------------------------------------------------------------------------------------------ // Reads an effect entry containing a float -void ColladaParser::ReadEffectFloat(ai_real& pFloat) -{ - while (mReader->read()) - { +void ColladaParser::ReadEffectFloat(ai_real &pFloat) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("float")) - { + if (IsElement("float")) { // text content contains a single floats - const char* content = GetTextContent(); + const char *content = GetTextContent(); content = fast_atoreal_move(content, pFloat); SkipSpacesAndLineEnd(&content); TestClosing("float"); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { break; } } @@ -1948,55 +1656,45 @@ void ColladaParser::ReadEffectFloat(ai_real& pFloat) // ------------------------------------------------------------------------------------------------ // Reads an effect parameter specification of any kind -void ColladaParser::ReadEffectParam(Collada::EffectParam& pParam) -{ - while (mReader->read()) - { +void ColladaParser::ReadEffectParam(Collada::EffectParam &pParam) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("surface")) - { + if (IsElement("surface")) { // image ID given inside tags TestOpening("init_from"); - const char* content = GetTextContent(); + const char *content = GetTextContent(); pParam.mType = Param_Surface; pParam.mReference = content; TestClosing("init_from"); // don't care for remaining stuff SkipElement("surface"); - } - else if (IsElement("sampler2D") && (FV_1_4_n == mFormat || FV_1_3_n == mFormat)) - { + } else if (IsElement("sampler2D") && (FV_1_4_n == mFormat || FV_1_3_n == mFormat)) { // surface ID is given inside tags TestOpening("source"); - const char* content = GetTextContent(); + const char *content = GetTextContent(); pParam.mType = Param_Sampler; pParam.mReference = content; TestClosing("source"); // don't care for remaining stuff SkipElement("sampler2D"); - } - else if (IsElement("sampler2D")) - { + } else if (IsElement("sampler2D")) { // surface ID is given inside tags TestOpening("instance_image"); int attrURL = GetAttribute("url"); - const char* url = mReader->getAttributeValue(attrURL); + const char *url = mReader->getAttributeValue(attrURL); if (url[0] != '#') ThrowException("Unsupported URL format in instance_image"); url++; pParam.mType = Param_Sampler; pParam.mReference = url; SkipElement("sampler2D"); - } - else - { + } else { // ignore unknown element SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { break; } } @@ -2004,17 +1702,13 @@ void ColladaParser::ReadEffectParam(Collada::EffectParam& pParam) // ------------------------------------------------------------------------------------------------ // Reads the geometry library contents -void ColladaParser::ReadGeometryLibrary() -{ +void ColladaParser::ReadGeometryLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("geometry")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("geometry")) { // read ID. Another entry which is "optional" by design but obligatory in reality int indexID = GetAttribute("id"); std::string id = mReader->getAttributeValue(indexID); @@ -2023,27 +1717,22 @@ void ColladaParser::ReadGeometryLibrary() // ai_assert( TestAttribute( "sid") == -1); // create a mesh and store it in the library under its ID - Mesh* mesh = new Mesh; + Mesh *mesh = new Mesh; mMeshLibrary[id] = mesh; // read the mesh name if it exists const int nameIndex = TestAttribute("name"); - if (nameIndex != -1) - { + if (nameIndex != -1) { mesh->mName = mReader->getAttributeValue(nameIndex); } // read on from there ReadGeometry(mesh); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_geometries") != 0) ThrowException("Expected end of element."); @@ -2054,28 +1743,20 @@ void ColladaParser::ReadGeometryLibrary() // ------------------------------------------------------------------------------------------------ // Reads a geometry from the geometry library. -void ColladaParser::ReadGeometry(Collada::Mesh* pMesh) -{ +void ColladaParser::ReadGeometry(Collada::Mesh *pMesh) { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("mesh")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("mesh")) { // read on from there ReadMesh(pMesh); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "geometry") != 0) ThrowException("Expected end of element."); @@ -2086,50 +1767,32 @@ void ColladaParser::ReadGeometry(Collada::Mesh* pMesh) // ------------------------------------------------------------------------------------------------ // Reads a mesh from the geometry library -void ColladaParser::ReadMesh(Mesh* pMesh) -{ +void ColladaParser::ReadMesh(Mesh *pMesh) { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("source")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("source")) { // we have professionals dealing with this ReadSource(); - } - else if (IsElement("vertices")) - { + } else if (IsElement("vertices")) { // read per-vertex mesh data ReadVertexData(pMesh); - } - else if (IsElement("triangles") || IsElement("lines") || IsElement("linestrips") - || IsElement("polygons") || IsElement("polylist") || IsElement("trifans") || IsElement("tristrips")) - { + } else if (IsElement("triangles") || IsElement("lines") || IsElement("linestrips") || IsElement("polygons") || IsElement("polylist") || IsElement("trifans") || IsElement("tristrips")) { // read per-index mesh data and faces setup ReadIndexData(pMesh); - } - else - { + } else { // ignore the restf SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if (strcmp(mReader->getNodeName(), "technique_common") == 0) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + if (strcmp(mReader->getNodeName(), "technique_common") == 0) { // end of another meaningless element - read over it - } - else if (strcmp(mReader->getNodeName(), "mesh") == 0) - { + } else if (strcmp(mReader->getNodeName(), "mesh") == 0) { // end of element - we're done here break; - } - else - { + } else { // everything else should be punished ThrowException("Expected end of element."); } @@ -2139,46 +1802,29 @@ void ColladaParser::ReadMesh(Mesh* pMesh) // ------------------------------------------------------------------------------------------------ // Reads a source element -void ColladaParser::ReadSource() -{ +void ColladaParser::ReadSource() { int indexID = GetAttribute("id"); std::string sourceID = mReader->getAttributeValue(indexID); - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("float_array") || IsElement("IDREF_array") || IsElement("Name_array")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("float_array") || IsElement("IDREF_array") || IsElement("Name_array")) { ReadDataArray(); - } - else if (IsElement("technique_common")) - { + } else if (IsElement("technique_common")) { // I don't care for your profiles - } - else if (IsElement("accessor")) - { + } else if (IsElement("accessor")) { ReadAccessor(sourceID); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if (strcmp(mReader->getNodeName(), "source") == 0) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + if (strcmp(mReader->getNodeName(), "source") == 0) { // end of - we're done break; - } - else if (strcmp(mReader->getNodeName(), "technique_common") == 0) - { + } else if (strcmp(mReader->getNodeName(), "technique_common") == 0) { // end of another meaningless element - read over it - } - else - { + } else { // everything else should be punished ThrowException("Expected end of element."); } @@ -2188,8 +1834,7 @@ void ColladaParser::ReadSource() // ------------------------------------------------------------------------------------------------ // Reads a data array holding a number of floats, and stores it in the global library -void ColladaParser::ReadDataArray() -{ +void ColladaParser::ReadDataArray() { std::string elmName = mReader->getNodeName(); bool isStringArray = (elmName == "IDREF_array" || elmName == "Name_array"); bool isEmptyElement = mReader->isEmptyElement(); @@ -2199,23 +1844,20 @@ void ColladaParser::ReadDataArray() std::string id = mReader->getAttributeValue(indexID); int indexCount = GetAttribute("count"); unsigned int count = (unsigned int)mReader->getAttributeValueAsInt(indexCount); - const char* content = TestTextContent(); + const char *content = TestTextContent(); // read values and store inside an array in the data library mDataLibrary[id] = Data(); - Data& data = mDataLibrary[id]; + Data &data = mDataLibrary[id]; data.mIsStringArray = isStringArray; // some exporters write empty data arrays, but we need to conserve them anyways because others might reference them - if (content) - { - if (isStringArray) - { + if (content) { + if (isStringArray) { data.mStrings.reserve(count); std::string s; - for (unsigned int a = 0; a < count; a++) - { + for (unsigned int a = 0; a < count; a++) { if (*content == 0) ThrowException("Expected more values while reading IDREF_array contents."); @@ -2226,13 +1868,10 @@ void ColladaParser::ReadDataArray() SkipSpacesAndLineEnd(&content); } - } - else - { + } else { data.mValues.reserve(count); - for (unsigned int a = 0; a < count; a++) - { + for (unsigned int a = 0; a < count; a++) { if (*content == 0) ThrowException("Expected more values while reading float_array contents."); @@ -2253,11 +1892,10 @@ void ColladaParser::ReadDataArray() // ------------------------------------------------------------------------------------------------ // Reads an accessor and stores it in the global library -void ColladaParser::ReadAccessor(const std::string& pID) -{ +void ColladaParser::ReadAccessor(const std::string &pID) { // read accessor attributes int attrSource = GetAttribute("source"); - const char* source = mReader->getAttributeValue(attrSource); + const char *source = mReader->getAttributeValue(attrSource); if (source[0] != '#') ThrowException(format() << "Unknown reference format in url \"" << source << "\" in source attribute of element."); int attrCount = GetAttribute("count"); @@ -2273,7 +1911,7 @@ void ColladaParser::ReadAccessor(const std::string& pID) // store in the library under the given ID mAccessorLibrary[pID] = Accessor(); - Accessor& acc = mAccessorLibrary[pID]; + Accessor &acc = mAccessorLibrary[pID]; acc.mCount = count; acc.mOffset = offset; acc.mStride = stride; @@ -2281,50 +1919,57 @@ void ColladaParser::ReadAccessor(const std::string& pID) acc.mSize = 0; // gets incremented with every param // and read the components - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("param")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("param")) { // read data param int attrName = TestAttribute("name"); std::string name; - if (attrName > -1) - { + if (attrName > -1) { name = mReader->getAttributeValue(attrName); // analyse for common type components and store it's sub-offset in the corresponding field /* Cartesian coordinates */ - if (name == "X") acc.mSubOffset[0] = acc.mParams.size(); - else if (name == "Y") acc.mSubOffset[1] = acc.mParams.size(); - else if (name == "Z") acc.mSubOffset[2] = acc.mParams.size(); + if (name == "X") + acc.mSubOffset[0] = acc.mParams.size(); + else if (name == "Y") + acc.mSubOffset[1] = acc.mParams.size(); + else if (name == "Z") + acc.mSubOffset[2] = acc.mParams.size(); /* RGBA colors */ - else if (name == "R") acc.mSubOffset[0] = acc.mParams.size(); - else if (name == "G") acc.mSubOffset[1] = acc.mParams.size(); - else if (name == "B") acc.mSubOffset[2] = acc.mParams.size(); - else if (name == "A") acc.mSubOffset[3] = acc.mParams.size(); + else if (name == "R") + acc.mSubOffset[0] = acc.mParams.size(); + else if (name == "G") + acc.mSubOffset[1] = acc.mParams.size(); + else if (name == "B") + acc.mSubOffset[2] = acc.mParams.size(); + else if (name == "A") + acc.mSubOffset[3] = acc.mParams.size(); /* UVWQ (STPQ) texture coordinates */ - else if (name == "S") acc.mSubOffset[0] = acc.mParams.size(); - else if (name == "T") acc.mSubOffset[1] = acc.mParams.size(); - else if (name == "P") acc.mSubOffset[2] = acc.mParams.size(); + else if (name == "S") + acc.mSubOffset[0] = acc.mParams.size(); + else if (name == "T") + acc.mSubOffset[1] = acc.mParams.size(); + else if (name == "P") + acc.mSubOffset[2] = acc.mParams.size(); // else if( name == "Q") acc.mSubOffset[3] = acc.mParams.size(); - /* 4D uv coordinates are not supported in Assimp */ + /* 4D uv coordinates are not supported in Assimp */ - /* Generic extra data, interpreted as UV data, too*/ - else if (name == "U") acc.mSubOffset[0] = acc.mParams.size(); - else if (name == "V") acc.mSubOffset[1] = acc.mParams.size(); + /* Generic extra data, interpreted as UV data, too*/ + else if (name == "U") + acc.mSubOffset[0] = acc.mParams.size(); + else if (name == "V") + acc.mSubOffset[1] = acc.mParams.size(); //else // DefaultLogger::get()->warn( format() << "Unknown accessor parameter \"" << name << "\". Ignoring data channel." ); } // read data type int attrType = TestAttribute("type"); - if (attrType > -1) - { + if (attrType > -1) { // for the moment we only distinguish between a 4x4 matrix and anything else. // TODO: (thom) I don't have a spec here at work. Check if there are other multi-value types // which should be tested for here. @@ -2339,14 +1984,10 @@ void ColladaParser::ReadAccessor(const std::string& pID) // skip remaining stuff of this element, if any SkipElement(); - } - else - { + } else { ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag "); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "accessor") != 0) ThrowException("Expected end of element."); break; @@ -2356,28 +1997,20 @@ void ColladaParser::ReadAccessor(const std::string& pID) // ------------------------------------------------------------------------------------------------ // Reads input declarations of per-vertex mesh data into the given mesh -void ColladaParser::ReadVertexData(Mesh* pMesh) -{ +void ColladaParser::ReadVertexData(Mesh *pMesh) { // extract the ID of the element. Not that we care, but to catch strange referencing schemes we should warn about int attrID = GetAttribute("id"); pMesh->mVertexID = mReader->getAttributeValue(attrID); // a number of elements - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("input")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("input")) { ReadInputChannel(pMesh->mPerVertexData); - } - else - { + } else { ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag "); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "vertices") != 0) ThrowException("Expected end of element."); @@ -2388,8 +2021,7 @@ void ColladaParser::ReadVertexData(Mesh* pMesh) // ------------------------------------------------------------------------------------------------ // Reads input declarations of per-index mesh data into the given mesh -void ColladaParser::ReadIndexData(Mesh* pMesh) -{ +void ColladaParser::ReadIndexData(Mesh *pMesh) { std::vector vcount; std::vector perIndexData; @@ -2427,25 +2059,18 @@ void ColladaParser::ReadIndexData(Mesh* pMesh) ai_assert(primType != Prim_Invalid); // also a number of elements, but in addition a

primitive collection and probably index counts for all primitives - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("input")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("input")) { ReadInputChannel(perIndexData); - } - else if (IsElement("vcount")) - { - if (!mReader->isEmptyElement()) - { - if (numPrimitives) // It is possible to define a mesh without any primitives + } else if (IsElement("vcount")) { + if (!mReader->isEmptyElement()) { + if (numPrimitives) // It is possible to define a mesh without any primitives { // case - specifies the number of indices for each polygon - const char* content = GetTextContent(); + const char *content = GetTextContent(); vcount.reserve(numPrimitives); - for (unsigned int a = 0; a < numPrimitives; a++) - { + for (unsigned int a = 0; a < numPrimitives; a++) { if (*content == 0) ThrowException("Expected more values while reading contents."); // read a number @@ -2457,28 +2082,19 @@ void ColladaParser::ReadIndexData(Mesh* pMesh) TestClosing("vcount"); } - } - else if (IsElement("p")) - { - if (!mReader->isEmptyElement()) - { + } else if (IsElement("p")) { + if (!mReader->isEmptyElement()) { // now here the actual fun starts - these are the indices to construct the mesh data from actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType); } - } - else if (IsElement("extra")) - { + } else if (IsElement("extra")) { SkipElement("extra"); - } - else if (IsElement("ph")) { + } else if (IsElement("ph")) { SkipElement("ph"); - } - else { + } else { ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">"); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (mReader->getNodeName() != elementName) ThrowException(format() << "Expected end of <" << elementName << "> element."); @@ -2488,7 +2104,7 @@ void ColladaParser::ReadIndexData(Mesh* pMesh) #ifdef ASSIMP_BUILD_DEBUG if (primType != Prim_TriFans && primType != Prim_TriStrips && primType != Prim_LineStrip && - primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'. + primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'. ai_assert(actualPrimitives == numPrimitives); } #endif @@ -2500,8 +2116,7 @@ void ColladaParser::ReadIndexData(Mesh* pMesh) // ------------------------------------------------------------------------------------------------ // Reads a single input channel element and stores it in the given array, if valid -void ColladaParser::ReadInputChannel(std::vector& poChannels) -{ +void ColladaParser::ReadInputChannel(std::vector &poChannels) { InputChannel channel; // read semantic @@ -2511,7 +2126,7 @@ void ColladaParser::ReadInputChannel(std::vector& poChannels) // read source int attrSource = GetAttribute("source"); - const char* source = mReader->getAttributeValue(attrSource); + const char *source = mReader->getAttributeValue(attrSource); if (source[0] != '#') ThrowException(format() << "Unknown reference format in url \"" << source << "\" in source attribute of element."); channel.mAccessor = source + 1; // skipping the leading #, hopefully the remaining text is the accessor ID only @@ -2543,15 +2158,13 @@ void ColladaParser::ReadInputChannel(std::vector& poChannels) // ------------------------------------------------------------------------------------------------ // Reads a

primitive index list and assembles the mesh data into the given mesh -size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPerIndexChannels, - size_t pNumPrimitives, const std::vector& pVCount, PrimitiveType pPrimType) -{ +size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPerIndexChannels, + size_t pNumPrimitives, const std::vector &pVCount, PrimitiveType pPrimType) { // determine number of indices coming per vertex // find the offset index for all per-vertex channels size_t numOffsets = 1; size_t perVertexOffset = SIZE_MAX; // invalid value - for (const InputChannel& channel : pPerIndexChannels) - { + for (const InputChannel &channel : pPerIndexChannels) { numOffsets = std::max(numOffsets, channel.mOffset + 1); if (channel.mType == IT_Vertex) perVertexOffset = channel.mOffset; @@ -2559,10 +2172,8 @@ size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPe // determine the expected number of indices size_t expectedPointCount = 0; - switch (pPrimType) - { - case Prim_Polylist: - { + switch (pPrimType) { + case Prim_Polylist: { for (size_t i : pVCount) expectedPointCount += i; break; @@ -2585,9 +2196,8 @@ size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPe if (pNumPrimitives > 0) // It is possible to not contain any indices { - const char* content = GetTextContent(); - while (*content != 0) - { + const char *content = GetTextContent(); + while (*content != 0) { // read a value. // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways. int value = std::max(0, strtol10(content, &content)); @@ -2603,38 +2213,33 @@ size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPe // HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines' ReportWarning("Expected different index count in

element, %zu instead of %zu.", indices.size(), expectedPointCount * numOffsets); pNumPrimitives = (indices.size() / numOffsets) / 2; - } - else + } else ThrowException("Expected different index count in

element."); - } - else if (expectedPointCount == 0 && (indices.size() % numOffsets) != 0) + } else if (expectedPointCount == 0 && (indices.size() % numOffsets) != 0) ThrowException("Expected different index count in

element."); // find the data for all sources - for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) - { - InputChannel& input = *it; + for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) { + InputChannel &input = *it; if (input.mResolved) continue; // find accessor input.mResolved = &ResolveLibraryReference(mAccessorLibrary, input.mAccessor); // resolve accessor's data pointer as well, if necessary - const Accessor* acc = input.mResolved; + const Accessor *acc = input.mResolved; if (!acc->mData) acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource); } // and the same for the per-index channels - for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) - { - InputChannel& input = *it; + for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) { + InputChannel &input = *it; if (input.mResolved) continue; // ignore vertex pointer, it doesn't refer to an accessor - if (input.mType == IT_Vertex) - { + if (input.mType == IT_Vertex) { // warn if the vertex channel does not refer to the element in the same mesh if (input.mAccessor != pMesh->mVertexID) ThrowException("Unsupported vertex referencing scheme."); @@ -2644,7 +2249,7 @@ size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPe // find accessor input.mResolved = &ResolveLibraryReference(mAccessorLibrary, input.mAccessor); // resolve accessor's data pointer as well, if necessary - const Accessor* acc = input.mResolved; + const Accessor *acc = input.mResolved; if (!acc->mData) acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource); } @@ -2667,12 +2272,10 @@ size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPe pMesh->mFacePosIndices.reserve(indices.size() / numOffsets); size_t polylistStartVertex = 0; - for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++) - { + for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++) { // determine number of points for this primitive size_t numPoints = 0; - switch (pPrimType) - { + switch (pPrimType) { case Prim_Lines: numPoints = 2; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) @@ -2722,7 +2325,7 @@ size_t ColladaParser::ReadPrimitives(Mesh* pMesh, std::vector& pPe ///@note This function willn't work correctly if both PerIndex and PerVertex channels have same channels. ///For example if TEXCOORD present in both and tags this function will create wrong uv coordinates. ///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior -void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices) { +void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh *pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices) { // calculate the base offset of the vertex whose attributes we ant to copy size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets; @@ -2740,14 +2343,13 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]); } -void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices) { +void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh *pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices) { if (currentPrimitive % 2 != 0) { //odd tristrip triangles need their indices mangled, to preserve winding direction CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); - } - else {//for non tristrips or even tristrip triangles + } else { //for non tristrips or even tristrip triangles CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); @@ -2756,18 +2358,17 @@ void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, // ------------------------------------------------------------------------------------------------ // Extracts a single object from an input channel and stores it in the appropriate mesh data array -void ColladaParser::ExtractDataObjectFromChannel(const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh) -{ +void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, size_t pLocalIndex, Mesh *pMesh) { // ignore vertex referrer - we handle them that separate if (pInput.mType == IT_Vertex) return; - const Accessor& acc = *pInput.mResolved; + const Accessor &acc = *pInput.mResolved; if (pLocalIndex >= acc.mCount) ThrowException(format() << "Invalid data index (" << pLocalIndex << "/" << acc.mCount << ") in primitive specification"); // get a pointer to the start of the data object referred to by the accessor and the local index - const ai_real* dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex * acc.mStride; + const ai_real *dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex * acc.mStride; // assemble according to the accessors component sub-offset list. We don't care, yet, // what kind of object exactly we're extracting here @@ -2776,8 +2377,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel& pInput, siz obj[c] = dataObject[acc.mSubOffset[c]]; // now we reinterpret it according to the type we're reading here - switch (pInput.mType) - { + switch (pInput.mType) { case IT_Position: // ignore all position streams except 0 - there can be only one position if (pInput.mIndex == 0) pMesh->mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2])); @@ -2819,40 +2419,33 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel& pInput, siz break; case IT_Texcoord: // up to 4 texture coord sets are fine, ignore the others - if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) - { + if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) { // pad to current vertex count if necessary if (pMesh->mTexCoords[pInput.mIndex].size() < pMesh->mPositions.size() - 1) pMesh->mTexCoords[pInput.mIndex].insert(pMesh->mTexCoords[pInput.mIndex].end(), - pMesh->mPositions.size() - pMesh->mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0)); + pMesh->mPositions.size() - pMesh->mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0)); pMesh->mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2])); if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */ pMesh->mNumUVComponents[pInput.mIndex] = 3; - } - else - { + } else { ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping."); } break; case IT_Color: // up to 4 color sets are fine, ignore the others - if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) - { + if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) { // pad to current vertex count if necessary if (pMesh->mColors[pInput.mIndex].size() < pMesh->mPositions.size() - 1) pMesh->mColors[pInput.mIndex].insert(pMesh->mColors[pInput.mIndex].end(), - pMesh->mPositions.size() - pMesh->mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1)); + pMesh->mPositions.size() - pMesh->mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1)); aiColor4D result(0, 0, 0, 1); - for (size_t i = 0; i < pInput.mResolved->mSize; ++i) - { + for (size_t i = 0; i < pInput.mResolved->mSize; ++i) { result[static_cast(i)] = obj[pInput.mResolved->mSubOffset[i]]; } pMesh->mColors[pInput.mIndex].push_back(result); - } - else - { + } else { ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping."); } @@ -2865,44 +2458,36 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel& pInput, siz // ------------------------------------------------------------------------------------------------ // Reads the library of node hierarchies and scene parts -void ColladaParser::ReadSceneLibrary() -{ +void ColladaParser::ReadSceneLibrary() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { // a visual scene - generate root node under its ID and let ReadNode() do the recursive work - if (IsElement("visual_scene")) - { + if (IsElement("visual_scene")) { // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then? int indexID = GetAttribute("id"); - const char* attrID = mReader->getAttributeValue(indexID); + const char *attrID = mReader->getAttributeValue(indexID); // read name if given. int indexName = TestAttribute("name"); - const char* attrName = "unnamed"; + const char *attrName = "unnamed"; if (indexName > -1) attrName = mReader->getAttributeValue(indexName); // create a node and store it in the library under its ID - Node* node = new Node; + Node *node = new Node; node->mID = attrID; node->mName = attrName; mNodeLibrary[node->mID] = node; ReadSceneNode(node); - } - else - { + } else { // ignore the rest SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "library_visual_scenes") == 0) //ThrowException( "Expected end of \"library_visual_scenes\" element."); @@ -2913,19 +2498,15 @@ void ColladaParser::ReadSceneLibrary() // ------------------------------------------------------------------------------------------------ // Reads a scene node's contents including children and stores it in the given node -void ColladaParser::ReadSceneNode(Node* pNode) -{ +void ColladaParser::ReadSceneNode(Node *pNode) { // quit immediately on elements if (mReader->isEmptyElement()) return; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("node")) - { - Node* child = new Node; + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("node")) { + Node *child = new Node; int attrID = TestAttribute("id"); if (attrID > -1) child->mID = mReader->getAttributeValue(attrID); @@ -2940,13 +2521,10 @@ void ColladaParser::ReadSceneNode(Node* pNode) // TODO: (thom) support SIDs // ai_assert( TestAttribute( "sid") == -1); - if (pNode) - { + if (pNode) { pNode->mChildren.push_back(child); child->mParent = pNode; - } - else - { + } else { // no parent node given, probably called from element. // create new node in node library mNodeLibrary[child->mID] = child; @@ -2972,82 +2550,65 @@ void ColladaParser::ReadSceneNode(Node* pNode) ReadNodeTransformation(pNode, TF_SKEW); else if (IsElement("translate")) ReadNodeTransformation(pNode, TF_TRANSLATE); - else if (IsElement("render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length()) - { + else if (IsElement("render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length()) { // ... scene evaluation or, in other words, postprocessing pipeline, // or, again in other words, a turing-complete description how to // render a Collada scene. The only thing that is interesting for // us is the primary camera. int attrId = TestAttribute("camera_node"); - if (-1 != attrId) - { - const char* s = mReader->getAttributeValue(attrId); + if (-1 != attrId) { + const char *s = mReader->getAttributeValue(attrId); if (s[0] != '#') ASSIMP_LOG_ERROR("Collada: Unresolved reference format of camera"); else pNode->mPrimaryCamera = s + 1; } - } - else if (IsElement("instance_node")) - { + } else if (IsElement("instance_node")) { // find the node in the library int attrID = TestAttribute("url"); - if (attrID != -1) - { - const char* s = mReader->getAttributeValue(attrID); + if (attrID != -1) { + const char *s = mReader->getAttributeValue(attrID); if (s[0] != '#') ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node"); - else - { + else { pNode->mNodeInstances.push_back(NodeInstance()); pNode->mNodeInstances.back().mNode = s + 1; } } - } - else if (IsElement("instance_geometry") || IsElement("instance_controller")) - { + } else if (IsElement("instance_geometry") || IsElement("instance_controller")) { // Reference to a mesh or controller, with possible material associations ReadNodeGeometry(pNode); - } - else if (IsElement("instance_light")) - { + } else if (IsElement("instance_light")) { // Reference to a light, name given in 'url' attribute int attrID = TestAttribute("url"); if (-1 == attrID) ASSIMP_LOG_WARN("Collada: Expected url attribute in element"); - else - { - const char* url = mReader->getAttributeValue(attrID); + else { + const char *url = mReader->getAttributeValue(attrID); if (url[0] != '#') ThrowException("Unknown reference format in element"); pNode->mLights.push_back(LightInstance()); pNode->mLights.back().mLight = url + 1; } - } - else if (IsElement("instance_camera")) - { + } else if (IsElement("instance_camera")) { // Reference to a camera, name given in 'url' attribute int attrID = TestAttribute("url"); if (-1 == attrID) ASSIMP_LOG_WARN("Collada: Expected url attribute in element"); - else - { - const char* url = mReader->getAttributeValue(attrID); + else { + const char *url = mReader->getAttributeValue(attrID); if (url[0] != '#') ThrowException("Unknown reference format in element"); pNode->mCameras.push_back(CameraInstance()); pNode->mCameras.back().mCamera = url + 1; } - } - else - { + } else { // skip everything else for the moment SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { break; } } @@ -3055,8 +2616,7 @@ void ColladaParser::ReadSceneNode(Node* pNode) // ------------------------------------------------------------------------------------------------ // Reads a node transformation entry of the given type and adds it to the given node's transformation list. -void ColladaParser::ReadNodeTransformation(Node* pNode, TransformType pType) -{ +void ColladaParser::ReadNodeTransformation(Node *pNode, TransformType pType) { if (mReader->isEmptyElement()) return; @@ -3072,11 +2632,10 @@ void ColladaParser::ReadNodeTransformation(Node* pNode, TransformType pType) // how many parameters to read per transformation type static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 }; - const char* content = GetTextContent(); + const char *content = GetTextContent(); // read as many parameters and store in the transformation - for (unsigned int a = 0; a < sNumParameters[pType]; a++) - { + for (unsigned int a = 0; a < sNumParameters[pType]; a++) { // read a number content = fast_atoreal_move(content, tf.f[a]); // skip whitespace after it @@ -3092,13 +2651,10 @@ void ColladaParser::ReadNodeTransformation(Node* pNode, TransformType pType) // ------------------------------------------------------------------------------------------------ // Processes bind_vertex_input and bind elements -void ColladaParser::ReadMaterialVertexInputBinding(Collada::SemanticMappingTable& tbl) -{ - while (mReader->read()) - { +void ColladaParser::ReadMaterialVertexInputBinding(Collada::SemanticMappingTable &tbl) { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("bind_vertex_input")) - { + if (IsElement("bind_vertex_input")) { Collada::InputSemanticMapEntry vn; // effect semantic @@ -3115,20 +2671,17 @@ void ColladaParser::ReadMaterialVertexInputBinding(Collada::SemanticMappingTable vn.mSet = mReader->getAttributeValueAsInt(n); tbl.mMap[s] = vn; - } - else if (IsElement("bind")) { + } else if (IsElement("bind")) { ASSIMP_LOG_WARN("Collada: Found unsupported element"); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { if (strcmp(mReader->getNodeName(), "instance_material") == 0) break; } } } -void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive) -{ +void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) { // Attempt to load any undefined Collada::Image in ImageLibrary for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) { Collada::Image &image = (*it).second; @@ -3149,31 +2702,26 @@ void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive) // ------------------------------------------------------------------------------------------------ // Reads a mesh reference in a node and adds it to the node's mesh list -void ColladaParser::ReadNodeGeometry(Node* pNode) -{ +void ColladaParser::ReadNodeGeometry(Node *pNode) { // referred mesh is given as an attribute of the element int attrUrl = GetAttribute("url"); - const char* url = mReader->getAttributeValue(attrUrl); + const char *url = mReader->getAttributeValue(attrUrl); if (url[0] != '#') ThrowException("Unknown reference format"); Collada::MeshInstance instance; instance.mMeshOrController = url + 1; // skipping the leading # - if (!mReader->isEmptyElement()) - { + if (!mReader->isEmptyElement()) { // read material associations. Ignore additional elements in between - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if (IsElement("instance_material")) - { + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if (IsElement("instance_material")) { // read ID of the geometry subgroup and the target material int attrGroup = GetAttribute("symbol"); std::string group = mReader->getAttributeValue(attrGroup); int attrMaterial = GetAttribute("target"); - const char* urlMat = mReader->getAttributeValue(attrMaterial); + const char *urlMat = mReader->getAttributeValue(attrMaterial); Collada::SemanticMappingTable s; if (urlMat[0] == '#') urlMat++; @@ -3187,11 +2735,8 @@ void ColladaParser::ReadNodeGeometry(Node* pNode) // store the association instance.mMaterials[group] = s; } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if (strcmp(mReader->getNodeName(), "instance_geometry") == 0 - || strcmp(mReader->getNodeName(), "instance_controller") == 0) + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + if (strcmp(mReader->getNodeName(), "instance_geometry") == 0 || strcmp(mReader->getNodeName(), "instance_controller") == 0) break; } } @@ -3203,23 +2748,20 @@ void ColladaParser::ReadNodeGeometry(Node* pNode) // ------------------------------------------------------------------------------------------------ // Reads the collada scene -void ColladaParser::ReadScene() -{ +void ColladaParser::ReadScene() { if (mReader->isEmptyElement()) return; - while (mReader->read()) - { + while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("instance_visual_scene")) - { + if (IsElement("instance_visual_scene")) { // should be the first and only occurrence if (mRootNode) ThrowException("Invalid scene containing multiple root nodes in element"); // read the url of the scene to instance. Should be of format "#some_name" int urlIndex = GetAttribute("url"); - const char* url = mReader->getAttributeValue(urlIndex); + const char *url = mReader->getAttributeValue(urlIndex); if (url[0] != '#') ThrowException("Unknown reference format in element"); @@ -3228,12 +2770,10 @@ void ColladaParser::ReadScene() if (sit == mNodeLibrary.end()) ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in element."); mRootNode = sit->second; - } - else { + } else { SkipElement(); } - } - else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { break; } } @@ -3241,11 +2781,11 @@ void ColladaParser::ReadScene() // ------------------------------------------------------------------------------------------------ // Aborts the file reading with an exception -AI_WONT_RETURN void ColladaParser::ThrowException(const std::string& pError) const { +AI_WONT_RETURN void ColladaParser::ThrowException(const std::string &pError) const { throw DeadlyImportError(format() << "Collada: " << mFileName << " - " << pError); } -void ColladaParser::ReportWarning(const char* msg, ...) { +void ColladaParser::ReportWarning(const char *msg, ...) { ai_assert(nullptr != msg); va_list args; @@ -3273,7 +2813,7 @@ void ColladaParser::SkipElement() { // ------------------------------------------------------------------------------------------------ // Skips all data until the end node of the given element -void ColladaParser::SkipElement(const char* pElement) { +void ColladaParser::SkipElement(const char *pElement) { // copy the current node's name because it'a pointer to the reader's internal buffer, // which is going to change with the upcoming parsing std::string element = pElement; @@ -3288,7 +2828,7 @@ void ColladaParser::SkipElement(const char* pElement) { // ------------------------------------------------------------------------------------------------ // Tests for an opening element of the given name, throws an exception if not found -void ColladaParser::TestOpening(const char* pName) { +void ColladaParser::TestOpening(const char *pName) { // read element start if (!mReader->read()) { ThrowException(format() << "Unexpected end of file while beginning of <" << pName << "> element."); @@ -3307,7 +2847,7 @@ void ColladaParser::TestOpening(const char* pName) { // ------------------------------------------------------------------------------------------------ // Tests for the closing tag of the given element, throws an exception if not found -void ColladaParser::TestClosing(const char* pName) { +void ColladaParser::TestClosing(const char *pName) { // check if we have an empty (self-closing) element if (mReader->isEmptyElement()) { return; @@ -3337,7 +2877,7 @@ void ColladaParser::TestClosing(const char* pName) { // ------------------------------------------------------------------------------------------------ // Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes -int ColladaParser::GetAttribute(const char* pAttr) const { +int ColladaParser::GetAttribute(const char *pAttr) const { int index = TestAttribute(pAttr); if (index == -1) { ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">."); @@ -3349,8 +2889,7 @@ int ColladaParser::GetAttribute(const char* pAttr) const { // ------------------------------------------------------------------------------------------------ // Tests the present element for the presence of one attribute, returns its index or throws an exception if not found -int ColladaParser::TestAttribute(const char* pAttr) const -{ +int ColladaParser::TestAttribute(const char *pAttr) const { for (int a = 0; a < mReader->getAttributeCount(); a++) if (strcmp(mReader->getAttributeName(a), pAttr) == 0) return a; @@ -3360,9 +2899,8 @@ int ColladaParser::TestAttribute(const char* pAttr) const // ------------------------------------------------------------------------------------------------ // Reads the text contents of an element, throws an exception if not given. Skips leading whitespace. -const char* ColladaParser::GetTextContent() -{ - const char* sz = TestTextContent(); +const char *ColladaParser::GetTextContent() { + const char *sz = TestTextContent(); if (!sz) { ThrowException("Invalid contents in element \"n\"."); } @@ -3371,8 +2909,7 @@ const char* ColladaParser::GetTextContent() // ------------------------------------------------------------------------------------------------ // Reads the text contents of an element, returns NULL if not given. Skips leading whitespace. -const char* ColladaParser::TestTextContent() -{ +const char *ColladaParser::TestTextContent() { // present node should be the beginning of an element if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement()) return NULL; @@ -3384,7 +2921,7 @@ const char* ColladaParser::TestTextContent() return NULL; // skip leading whitespace - const char* text = mReader->getNodeData(); + const char *text = mReader->getNodeData(); SkipSpacesAndLineEnd(&text); return text; @@ -3392,17 +2929,13 @@ const char* ColladaParser::TestTextContent() // ------------------------------------------------------------------------------------------------ // Calculates the resulting transformation fromm all the given transform steps -aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector& pTransforms) const -{ +aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector &pTransforms) const { aiMatrix4x4 res; - for (std::vector::const_iterator it = pTransforms.begin(); it != pTransforms.end(); ++it) - { - const Transform& tf = *it; - switch (tf.mType) - { - case TF_LOOKAT: - { + for (std::vector::const_iterator it = pTransforms.begin(); it != pTransforms.end(); ++it) { + const Transform &tf = *it; + switch (tf.mType) { + case TF_LOOKAT: { aiVector3D pos(tf.f[0], tf.f[1], tf.f[2]); aiVector3D dstPos(tf.f[3], tf.f[4], tf.f[5]); aiVector3D up = aiVector3D(tf.f[6], tf.f[7], tf.f[8]).Normalize(); @@ -3410,14 +2943,13 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector aiVector3D right = (dir ^ up).Normalize(); res *= aiMatrix4x4( - right.x, up.x, -dir.x, pos.x, - right.y, up.y, -dir.y, pos.y, - right.z, up.z, -dir.z, pos.z, - 0, 0, 0, 1); + right.x, up.x, -dir.x, pos.x, + right.y, up.y, -dir.y, pos.y, + right.z, up.z, -dir.z, pos.z, + 0, 0, 0, 1); break; } - case TF_ROTATE: - { + case TF_ROTATE: { aiMatrix4x4 rot; ai_real angle = tf.f[3] * ai_real(AI_MATH_PI) / ai_real(180.0); aiVector3D axis(tf.f[0], tf.f[1], tf.f[2]); @@ -3425,17 +2957,15 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector res *= rot; break; } - case TF_TRANSLATE: - { + case TF_TRANSLATE: { aiMatrix4x4 trans; aiMatrix4x4::Translation(aiVector3D(tf.f[0], tf.f[1], tf.f[2]), trans); res *= trans; break; } - case TF_SCALE: - { + case TF_SCALE: { aiMatrix4x4 scale(tf.f[0], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[1], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[2], 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + 0.0f, 0.0f, 0.0f, 1.0f); res *= scale; break; } @@ -3443,10 +2973,9 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector // TODO: (thom) ai_assert(false); break; - case TF_MATRIX: - { + case TF_MATRIX: { aiMatrix4x4 mat(tf.f[0], tf.f[1], tf.f[2], tf.f[3], tf.f[4], tf.f[5], tf.f[6], tf.f[7], - tf.f[8], tf.f[9], tf.f[10], tf.f[11], tf.f[12], tf.f[13], tf.f[14], tf.f[15]); + tf.f[8], tf.f[9], tf.f[10], tf.f[11], tf.f[12], tf.f[13], tf.f[14], tf.f[15]); res *= mat; break; } @@ -3461,8 +2990,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform(const std::vector // ------------------------------------------------------------------------------------------------ // Determines the input data type for the given semantic string -Collada::InputType ColladaParser::GetTypeForSemantic(const std::string& semantic) -{ +Collada::InputType ColladaParser::GetTypeForSemantic(const std::string &semantic) { if (semantic.empty()) { ASSIMP_LOG_WARN("Vertex input type is empty."); return IT_Invalid; diff --git a/code/Collada/ColladaParser.h b/code/Collada/ColladaParser.h index d1e812bd2..861a65256 100644 --- a/code/Collada/ColladaParser.h +++ b/code/Collada/ColladaParser.h @@ -47,346 +47,345 @@ #ifndef AI_COLLADAPARSER_H_INC #define AI_COLLADAPARSER_H_INC -#include #include "ColladaHelper.h" -#include #include +#include +#include -namespace Assimp -{ - class ZipArchiveIOSystem; +namespace Assimp { +class ZipArchiveIOSystem; - // ------------------------------------------------------------------------------------------ - /** Parser helper class for the Collada loader. +// ------------------------------------------------------------------------------------------ +/** Parser helper class for the Collada loader. * * Does all the XML reading and builds internal data structures from it, * but leaves the resolving of all the references to the loader. */ - class ColladaParser - { - friend class ColladaLoader; +class ColladaParser { + friend class ColladaLoader; - /** Converts a path read from a collada file to the usual representation */ - static void UriDecodePath(aiString& ss); + /** Converts a path read from a collada file to the usual representation */ + static void UriDecodePath(aiString &ss); - protected: - /** Map for generic metadata as aiString */ - typedef std::map StringMetaData; +protected: + /** Map for generic metadata as aiString */ + typedef std::map StringMetaData; - /** Constructor from XML file */ - ColladaParser(IOSystem* pIOHandler, const std::string& pFile); + /** Constructor from XML file */ + ColladaParser(IOSystem *pIOHandler, const std::string &pFile); - /** Destructor */ - ~ColladaParser(); + /** Destructor */ + ~ColladaParser(); - /** Attempts to read the ZAE manifest and returns the DAE to open */ - static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive); + /** Attempts to read the ZAE manifest and returns the DAE to open */ + static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive); - /** Reads the contents of the file */ - void ReadContents(); + /** Reads the contents of the file */ + void ReadContents(); - /** Reads the structure of the file */ - void ReadStructure(); + /** Reads the structure of the file */ + void ReadStructure(); - /** Reads asset information such as coordinate system information and legal blah */ - void ReadAssetInfo(); + /** Reads asset information such as coordinate system information and legal blah */ + void ReadAssetInfo(); - /** Reads contributor information such as author and legal blah */ - void ReadContributorInfo(); + /** Reads contributor information such as author and legal blah */ + void ReadContributorInfo(); - /** Reads generic metadata into provided map and renames keys for Assimp */ - void ReadMetaDataItem(StringMetaData &metadata); + /** Reads generic metadata into provided map and renames keys for Assimp */ + void ReadMetaDataItem(StringMetaData &metadata); - /** Reads the animation library */ - void ReadAnimationLibrary(); + /** Reads the animation library */ + void ReadAnimationLibrary(); - /** Reads the animation clip library */ - void ReadAnimationClipLibrary(); + /** Reads the animation clip library */ + void ReadAnimationClipLibrary(); - /** Unwrap controllers dependency hierarchy */ - void PostProcessControllers(); - - /** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */ - void PostProcessRootAnimations(); + /** Unwrap controllers dependency hierarchy */ + void PostProcessControllers(); - /** Reads an animation into the given parent structure */ - void ReadAnimation( Collada::Animation* pParent); + /** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */ + void PostProcessRootAnimations(); - /** Reads an animation sampler into the given anim channel */ - void ReadAnimationSampler( Collada::AnimationChannel& pChannel); + /** Reads an animation into the given parent structure */ + void ReadAnimation(Collada::Animation *pParent); - /** Reads the skeleton controller library */ - void ReadControllerLibrary(); + /** Reads an animation sampler into the given anim channel */ + void ReadAnimationSampler(Collada::AnimationChannel &pChannel); - /** Reads a controller into the given mesh structure */ - void ReadController( Collada::Controller& pController); + /** Reads the skeleton controller library */ + void ReadControllerLibrary(); - /** Reads the joint definitions for the given controller */ - void ReadControllerJoints( Collada::Controller& pController); + /** Reads a controller into the given mesh structure */ + void ReadController(Collada::Controller &pController); - /** Reads the joint weights for the given controller */ - void ReadControllerWeights( Collada::Controller& pController); + /** Reads the joint definitions for the given controller */ + void ReadControllerJoints(Collada::Controller &pController); - /** Reads the image library contents */ - void ReadImageLibrary(); + /** Reads the joint weights for the given controller */ + void ReadControllerWeights(Collada::Controller &pController); - /** Reads an image entry into the given image */ - void ReadImage( Collada::Image& pImage); + /** Reads the image library contents */ + void ReadImageLibrary(); - /** Reads the material library */ - void ReadMaterialLibrary(); + /** Reads an image entry into the given image */ + void ReadImage(Collada::Image &pImage); - /** Reads a material entry into the given material */ - void ReadMaterial( Collada::Material& pMaterial); + /** Reads the material library */ + void ReadMaterialLibrary(); - /** Reads the camera library */ - void ReadCameraLibrary(); + /** Reads a material entry into the given material */ + void ReadMaterial(Collada::Material &pMaterial); - /** Reads a camera entry into the given camera */ - void ReadCamera( Collada::Camera& pCamera); + /** Reads the camera library */ + void ReadCameraLibrary(); - /** Reads the light library */ - void ReadLightLibrary(); + /** Reads a camera entry into the given camera */ + void ReadCamera(Collada::Camera &pCamera); - /** Reads a light entry into the given light */ - void ReadLight( Collada::Light& pLight); + /** Reads the light library */ + void ReadLightLibrary(); - /** Reads the effect library */ - void ReadEffectLibrary(); + /** Reads a light entry into the given light */ + void ReadLight(Collada::Light &pLight); - /** Reads an effect entry into the given effect*/ - void ReadEffect( Collada::Effect& pEffect); + /** Reads the effect library */ + void ReadEffectLibrary(); - /** Reads an COMMON effect profile */ - void ReadEffectProfileCommon( Collada::Effect& pEffect); + /** Reads an effect entry into the given effect*/ + void ReadEffect(Collada::Effect &pEffect); - /** Read sampler properties */ - void ReadSamplerProperties( Collada::Sampler& pSampler); + /** Reads an COMMON effect profile */ + void ReadEffectProfileCommon(Collada::Effect &pEffect); - /** Reads an effect entry containing a color or a texture defining that color */ - void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); + /** Read sampler properties */ + void ReadSamplerProperties(Collada::Sampler &pSampler); - /** Reads an effect entry containing a float */ - void ReadEffectFloat( ai_real& pFloat); + /** Reads an effect entry containing a color or a texture defining that color */ + void ReadEffectColor(aiColor4D &pColor, Collada::Sampler &pSampler); - /** Reads an effect parameter specification of any kind */ - void ReadEffectParam( Collada::EffectParam& pParam); + /** Reads an effect entry containing a float */ + void ReadEffectFloat(ai_real &pFloat); - /** Reads the geometry library contents */ - void ReadGeometryLibrary(); + /** Reads an effect parameter specification of any kind */ + void ReadEffectParam(Collada::EffectParam &pParam); - /** Reads a geometry from the geometry library. */ - void ReadGeometry( Collada::Mesh* pMesh); + /** Reads the geometry library contents */ + void ReadGeometryLibrary(); - /** Reads a mesh from the geometry library */ - void ReadMesh( Collada::Mesh* pMesh); + /** Reads a geometry from the geometry library. */ + void ReadGeometry(Collada::Mesh *pMesh); - /** Reads a source element - a combination of raw data and an accessor defining + /** Reads a mesh from the geometry library */ + void ReadMesh(Collada::Mesh *pMesh); + + /** Reads a source element - a combination of raw data and an accessor defining * things that should not be redefinable. Yes, that's another rant. */ - void ReadSource(); + void ReadSource(); - /** Reads a data array holding a number of elements, and stores it in the global library. + /** Reads a data array holding a number of elements, and stores it in the global library. * Currently supported are array of floats and arrays of strings. */ - void ReadDataArray(); + void ReadDataArray(); - /** Reads an accessor and stores it in the global library under the given ID - + /** Reads an accessor and stores it in the global library under the given ID - * accessors use the ID of the parent element */ - void ReadAccessor( const std::string& pID); + void ReadAccessor(const std::string &pID); - /** Reads input declarations of per-vertex mesh data into the given mesh */ - void ReadVertexData( Collada::Mesh* pMesh); + /** Reads input declarations of per-vertex mesh data into the given mesh */ + void ReadVertexData(Collada::Mesh *pMesh); - /** Reads input declarations of per-index mesh data into the given mesh */ - void ReadIndexData( Collada::Mesh* pMesh); + /** Reads input declarations of per-index mesh data into the given mesh */ + void ReadIndexData(Collada::Mesh *pMesh); - /** Reads a single input channel element and stores it in the given array, if valid */ - void ReadInputChannel( std::vector& poChannels); + /** Reads a single input channel element and stores it in the given array, if valid */ + void ReadInputChannel(std::vector &poChannels); - /** Reads a

primitive index list and assembles the mesh data into the given mesh */ - size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, - size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); + /** Reads a

primitive index list and assembles the mesh data into the given mesh */ + size_t ReadPrimitives(Collada::Mesh *pMesh, std::vector &pPerIndexChannels, + size_t pNumPrimitives, const std::vector &pVCount, Collada::PrimitiveType pPrimType); - /** Copies the data for a single primitive into the mesh, based on the InputChannels */ - void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, - Collada::Mesh* pMesh, std::vector& pPerIndexChannels, - size_t currentPrimitive, const std::vector& indices); + /** Copies the data for a single primitive into the mesh, based on the InputChannels */ + void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, + Collada::Mesh *pMesh, std::vector &pPerIndexChannels, + size_t currentPrimitive, const std::vector &indices); - /** Reads one triangle of a tristrip into the mesh */ - void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, - std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); + /** Reads one triangle of a tristrip into the mesh */ + void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh *pMesh, + std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices); - /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ - void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); + /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ + void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh *pMesh); - /** Reads the library of node hierarchies and scene parts */ - void ReadSceneLibrary(); + /** Reads the library of node hierarchies and scene parts */ + void ReadSceneLibrary(); - /** Reads a scene node's contents including children and stores it in the given node */ - void ReadSceneNode( Collada::Node* pNode); + /** Reads a scene node's contents including children and stores it in the given node */ + void ReadSceneNode(Collada::Node *pNode); - /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ - void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); + /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ + void ReadNodeTransformation(Collada::Node *pNode, Collada::TransformType pType); - /** Reads a mesh reference in a node and adds it to the node's mesh list */ - void ReadNodeGeometry( Collada::Node* pNode); + /** Reads a mesh reference in a node and adds it to the node's mesh list */ + void ReadNodeGeometry(Collada::Node *pNode); - /** Reads the collada scene */ - void ReadScene(); + /** Reads the collada scene */ + void ReadScene(); - // Processes bind_vertex_input and bind elements - void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); + // Processes bind_vertex_input and bind elements + void ReadMaterialVertexInputBinding(Collada::SemanticMappingTable &tbl); - /** Reads embedded textures from a ZAE archive*/ - void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive); + /** Reads embedded textures from a ZAE archive*/ + void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive); - protected: - /** Aborts the file reading with an exception */ - AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX; - void ReportWarning(const char* msg,...); +protected: + /** Aborts the file reading with an exception */ + AI_WONT_RETURN void ThrowException(const std::string &pError) const AI_WONT_RETURN_SUFFIX; + void ReportWarning(const char *msg, ...); - /** Skips all data until the end node of the current element */ - void SkipElement(); + /** Skips all data until the end node of the current element */ + void SkipElement(); - /** Skips all data until the end node of the given element */ - void SkipElement( const char* pElement); + /** Skips all data until the end node of the given element */ + void SkipElement(const char *pElement); - /** Compares the current xml element name to the given string and returns true if equal */ - bool IsElement( const char* pName) const; + /** Compares the current xml element name to the given string and returns true if equal */ + bool IsElement(const char *pName) const; - /** Tests for the opening tag of the given element, throws an exception if not found */ - void TestOpening( const char* pName); + /** Tests for the opening tag of the given element, throws an exception if not found */ + void TestOpening(const char *pName); - /** Tests for the closing tag of the given element, throws an exception if not found */ - void TestClosing( const char* pName); + /** Tests for the closing tag of the given element, throws an exception if not found */ + void TestClosing(const char *pName); - /** Checks the present element for the presence of the attribute, returns its index + /** Checks the present element for the presence of the attribute, returns its index or throws an exception if not found */ - int GetAttribute( const char* pAttr) const; + int GetAttribute(const char *pAttr) const; - /** Returns the index of the named attribute or -1 if not found. Does not throw, + /** Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes */ - int TestAttribute( const char* pAttr) const; + int TestAttribute(const char *pAttr) const; - /** Reads the text contents of an element, throws an exception if not given. + /** Reads the text contents of an element, throws an exception if not given. Skips leading whitespace. */ - const char* GetTextContent(); + const char *GetTextContent(); - /** Reads the text contents of an element, returns NULL if not given. + /** Reads the text contents of an element, returns NULL if not given. Skips leading whitespace. */ - const char* TestTextContent(); + const char *TestTextContent(); - /** Reads a single bool from current text content */ - bool ReadBoolFromTextContent(); + /** Reads a single bool from current text content */ + bool ReadBoolFromTextContent(); - /** Reads a single float from current text content */ - ai_real ReadFloatFromTextContent(); + /** Reads a single float from current text content */ + ai_real ReadFloatFromTextContent(); - /** Calculates the resulting transformation from all the given transform steps */ - aiMatrix4x4 CalculateResultTransform( const std::vector& pTransforms) const; + /** Calculates the resulting transformation from all the given transform steps */ + aiMatrix4x4 CalculateResultTransform(const std::vector &pTransforms) const; - /** Determines the input data type for the given semantic string */ - Collada::InputType GetTypeForSemantic( const std::string& pSemantic); + /** Determines the input data type for the given semantic string */ + Collada::InputType GetTypeForSemantic(const std::string &pSemantic); - /** Finds the item in the given library by its reference, throws if not found */ - template const Type& ResolveLibraryReference( const std::map& pLibrary, const std::string& pURL) const; - - protected: - /** Filename, for a verbose error message */ - std::string mFileName; - - /** XML reader, member for everyday use */ - irr::io::IrrXMLReader* mReader; - - /** All data arrays found in the file by ID. Might be referred to by actually - everyone. Collada, you are a steaming pile of indirection. */ - typedef std::map DataLibrary; - DataLibrary mDataLibrary; - - /** Same for accessors which define how the data in a data array is accessed. */ - typedef std::map AccessorLibrary; - AccessorLibrary mAccessorLibrary; - - /** Mesh library: mesh by ID */ - typedef std::map MeshLibrary; - MeshLibrary mMeshLibrary; - - /** node library: root node of the hierarchy part by ID */ - typedef std::map NodeLibrary; - NodeLibrary mNodeLibrary; - - /** Image library: stores texture properties by ID */ - typedef std::map ImageLibrary; - ImageLibrary mImageLibrary; - - /** Effect library: surface attributes by ID */ - typedef std::map EffectLibrary; - EffectLibrary mEffectLibrary; - - /** Material library: surface material by ID */ - typedef std::map MaterialLibrary; - MaterialLibrary mMaterialLibrary; - - /** Light library: surface light by ID */ - typedef std::map LightLibrary; - LightLibrary mLightLibrary; - - /** Camera library: surface material by ID */ - typedef std::map CameraLibrary; - CameraLibrary mCameraLibrary; - - /** Controller library: joint controllers by ID */ - typedef std::map ControllerLibrary; - ControllerLibrary mControllerLibrary; - - /** Animation library: animation references by ID */ - typedef std::map AnimationLibrary; - AnimationLibrary mAnimationLibrary; - - /** Animation clip library: clip animation references by ID */ - typedef std::vector > > AnimationClipLibrary; - AnimationClipLibrary mAnimationClipLibrary; - - /** Pointer to the root node. Don't delete, it just points to one of - the nodes in the node library. */ - Collada::Node* mRootNode; - - /** Root animation container */ - Collada::Animation mAnims; - - /** Size unit: how large compared to a meter */ - ai_real mUnitSize; - - /** Which is the up vector */ - enum { UP_X, UP_Y, UP_Z } mUpDirection; - - /** Asset metadata (global for scene) */ - StringMetaData mAssetMetaData; - - /** Collada file format version */ - Collada::FormatVersion mFormat; - }; - - // ------------------------------------------------------------------------------------------------ - // Check for element match - inline bool ColladaParser::IsElement( const char* pName) const - { - ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); - return ::strcmp( mReader->getNodeName(), pName) == 0; - } - - // ------------------------------------------------------------------------------------------------ - // Finds the item in the given library by its reference, throws if not found + /** Finds the item in the given library by its reference, throws if not found */ template - const Type& ColladaParser::ResolveLibraryReference( const std::map& pLibrary, const std::string& pURL) const - { - typename std::map::const_iterator it = pLibrary.find( pURL); - if( it == pLibrary.end()) - ThrowException( Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"." ); - return it->second; - } + const Type &ResolveLibraryReference(const std::map &pLibrary, const std::string &pURL) const; + +protected: + /** Filename, for a verbose error message */ + std::string mFileName; + + /** XML reader, member for everyday use */ + irr::io::IrrXMLReader *mReader; + + /** All data arrays found in the file by ID. Might be referred to by actually + everyone. Collada, you are a steaming pile of indirection. */ + typedef std::map DataLibrary; + DataLibrary mDataLibrary; + + /** Same for accessors which define how the data in a data array is accessed. */ + typedef std::map AccessorLibrary; + AccessorLibrary mAccessorLibrary; + + /** Mesh library: mesh by ID */ + typedef std::map MeshLibrary; + MeshLibrary mMeshLibrary; + + /** node library: root node of the hierarchy part by ID */ + typedef std::map NodeLibrary; + NodeLibrary mNodeLibrary; + + /** Image library: stores texture properties by ID */ + typedef std::map ImageLibrary; + ImageLibrary mImageLibrary; + + /** Effect library: surface attributes by ID */ + typedef std::map EffectLibrary; + EffectLibrary mEffectLibrary; + + /** Material library: surface material by ID */ + typedef std::map MaterialLibrary; + MaterialLibrary mMaterialLibrary; + + /** Light library: surface light by ID */ + typedef std::map LightLibrary; + LightLibrary mLightLibrary; + + /** Camera library: surface material by ID */ + typedef std::map CameraLibrary; + CameraLibrary mCameraLibrary; + + /** Controller library: joint controllers by ID */ + typedef std::map ControllerLibrary; + ControllerLibrary mControllerLibrary; + + /** Animation library: animation references by ID */ + typedef std::map AnimationLibrary; + AnimationLibrary mAnimationLibrary; + + /** Animation clip library: clip animation references by ID */ + typedef std::vector>> AnimationClipLibrary; + AnimationClipLibrary mAnimationClipLibrary; + + /** Pointer to the root node. Don't delete, it just points to one of + the nodes in the node library. */ + Collada::Node *mRootNode; + + /** Root animation container */ + Collada::Animation mAnims; + + /** Size unit: how large compared to a meter */ + ai_real mUnitSize; + + /** Which is the up vector */ + enum { UP_X, + UP_Y, + UP_Z } mUpDirection; + + /** Asset metadata (global for scene) */ + StringMetaData mAssetMetaData; + + /** Collada file format version */ + Collada::FormatVersion mFormat; +}; + +// ------------------------------------------------------------------------------------------------ +// Check for element match +inline bool ColladaParser::IsElement(const char *pName) const { + ai_assert(mReader->getNodeType() == irr::io::EXN_ELEMENT); + return ::strcmp(mReader->getNodeName(), pName) == 0; +} + +// ------------------------------------------------------------------------------------------------ +// Finds the item in the given library by its reference, throws if not found +template +const Type &ColladaParser::ResolveLibraryReference(const std::map &pLibrary, const std::string &pURL) const { + typename std::map::const_iterator it = pLibrary.find(pURL); + if (it == pLibrary.end()) + ThrowException(Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"."); + return it->second; +} } // end of namespace Assimp From ff9f3b86084c3b502d9dd4fefe3d87275f4df57d Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Wed, 29 Apr 2020 17:17:46 +0100 Subject: [PATCH 042/119] Collada: Ensure has unique id Use the "id" for mesh names by default. Set option AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES to use the mesh "name" instead --- code/CMakeLists.txt | 1 + code/Collada/ColladaExporter.cpp | 104 +++++++++++++++++++++------- code/Collada/ColladaExporter.h | 12 ++-- code/Collada/ColladaHelper.h | 4 +- code/Collada/ColladaLoader.cpp | 18 ++++- code/Collada/ColladaParser.cpp | 101 ++++++++++++++------------- code/Collada/ColladaParser.h | 16 ++--- include/assimp/ColladaMetaData.h | 53 ++++++++++++++ include/assimp/config.h.in | 6 +- test/unit/utColladaImportExport.cpp | 53 +++++++++++++- 10 files changed, 274 insertions(+), 94 deletions(-) create mode 100644 include/assimp/ColladaMetaData.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 6afed40f9..f626a51e3 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -66,6 +66,7 @@ SET( PUBLIC_HEADERS ${HEADER_PATH}/color4.h ${HEADER_PATH}/color4.inl ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h + ${HEADER_PATH}/ColladaMetaData.h ${HEADER_PATH}/commonMetaData.h ${HEADER_PATH}/defs.h ${HEADER_PATH}/Defines.h diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index 0026fda26..a502e728c 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ColladaExporter.h" #include +#include #include #include #include @@ -115,7 +116,7 @@ static const std::string XMLIDEncode(const std::string &name) { if (strchr(XML_ID_CHARS, *it) != nullptr) { idEncoded << *it; } else { - // Select placeholder character based on invalid character to prevent name collisions + // Select placeholder character based on invalid character to reduce ID collisions idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; } } @@ -854,8 +855,8 @@ void ColladaExporter::WriteControllerLibrary() { // Writes a skin controller of the given mesh void ColladaExporter::WriteController(size_t pIndex) { const aiMesh *mesh = mScene->mMeshes[pIndex]; - const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); - const std::string idstrEscaped = XMLIDEncode(idstr); + const std::string idstr = GetMeshUniqueId(pIndex); + const std::string namestr = GetMeshName(pIndex); if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) return; @@ -863,11 +864,11 @@ void ColladaExporter::WriteController(size_t pIndex) { if (mesh->mNumBones == 0) return; - mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); // bind pose matrix @@ -884,10 +885,10 @@ void ColladaExporter::WriteController(size_t pIndex) { PopTag(); mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mNumBones << "\">"; + mOutput << startstr << "mNumBones << "\">"; for (size_t i = 0; i < mesh->mNumBones; ++i) mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; @@ -897,7 +898,7 @@ void ColladaExporter::WriteController(size_t pIndex) { mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mNumBones << "\" stride=\"" << 1 << "\">" << endstr; + mOutput << startstr << "mNumBones << "\" stride=\"" << 1 << "\">" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -934,8 +935,8 @@ void ColladaExporter::WriteController(size_t pIndex) { mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; @@ -943,8 +944,8 @@ void ColladaExporter::WriteController(size_t pIndex) { mOutput << startstr << "mNumVertices << "\">" << endstr; PushTag(); - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; mOutput << startstr << ""; @@ -1019,9 +1020,8 @@ void ColladaExporter::WriteGeometryLibrary() { // Writes the given mesh void ColladaExporter::WriteGeometry(size_t pIndex) { const aiMesh *mesh = mScene->mMeshes[pIndex]; - const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); - const std::string geometryName = XMLEscape(idstr); - const std::string geometryId = XMLIDEncode(idstr); + const std::string geometryName = GetMeshName(pIndex); + const std::string geometryId = GetMeshUniqueId(pIndex); if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) return; @@ -1034,15 +1034,15 @@ void ColladaExporter::WriteGeometry(size_t pIndex) { PushTag(); // Positions - WriteFloatArray(idstr + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices); + WriteFloatArray(geometryId + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices); // Normals, if any if (mesh->HasNormals()) - WriteFloatArray(idstr + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices); + WriteFloatArray(geometryId + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices); // texture coords for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { if (mesh->HasTextureCoords(static_cast(a))) { - WriteFloatArray(idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, + WriteFloatArray(geometryId + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices); } } @@ -1050,7 +1050,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) { // vertex colors for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { if (mesh->HasVertexColors(static_cast(a))) - WriteFloatArray(idstr + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices); + WriteFloatArray(geometryId + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices); } // assemble vertex structure @@ -1530,13 +1530,13 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { const std::string node_name = XMLEscape(pNode->mName.data); mOutput << startstr << "" << endstr; PushTag(); @@ -1595,14 +1595,14 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) continue; - const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); + const std::string meshId = GetMeshUniqueId(pNode->mMeshes[a]); if (mesh->mNumBones == 0) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); } else { mOutput << startstr - << "" + << "" << endstr; PushTag(); @@ -1649,5 +1649,59 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { mOutput << startstr << "" << endstr; } +/// Get or Create a unique mesh ID string for the given mesh index +std::string Assimp::ColladaExporter::GetMeshUniqueId(size_t pIndex) { + auto meshId = mMeshIdMap.find(pIndex); + if (meshId != mMeshIdMap.cend()) + return meshId->second; + + // Not seen this mesh before, create and add + return AddMeshIndexToMaps(pIndex, true); +} + +std::string Assimp::ColladaExporter::GetMeshName(size_t pIndex) { + auto meshName = mMeshNameMap.find(pIndex); + if (meshName != mMeshNameMap.cend()) + return meshName->second; + + // Not seen this mesh before, create and add + return AddMeshIndexToMaps(pIndex, false); +} + +inline bool ValueIsUnique(const std::map &map, const std::string &value) { + for (const auto &map_val : map) { + if (value == map_val.second) + return false; + } + return true; +} + +// Add the mesh index to both Id and Name maps and return either Id or Name +std::string Assimp::ColladaExporter::AddMeshIndexToMaps(size_t pIndex, bool meshId) { + const aiMesh *mesh = mScene->mMeshes[pIndex]; + std::string idStr = mesh->mName.length == 0 ? std::string("meshId_") + to_string(pIndex) : XMLIDEncode(mesh->mName.C_Str()); + // Ensure is unique. Relatively slow but will only happen once per mesh + if (!ValueIsUnique(mMeshIdMap, idStr)) { + // Select a number to append + size_t postfix = 1; + idStr.append("_"); + while (!ValueIsUnique(mMeshIdMap, idStr + to_string(postfix))) { + ++postfix; + } + idStr = idStr + to_string(postfix); + } + // Add to map + mMeshIdMap.insert(std::make_pair(pIndex, idStr)); + + // Add name to map + const std::string nameStr = mesh->mName.length == 0 ? idStr : XMLEscape(mesh->mName.C_Str()); + mMeshNameMap.insert(std::make_pair(pIndex, nameStr)); + + if (meshId) + return idStr; + else + return nameStr; +} + #endif #endif diff --git a/code/Collada/ColladaExporter.h b/code/Collada/ColladaExporter.h index fa7e6ee80..d75d2d355 100644 --- a/code/Collada/ColladaExporter.h +++ b/code/Collada/ColladaExporter.h @@ -145,10 +145,14 @@ protected: startstr.erase(startstr.length() - 2); } - /// Creates a mesh ID for the given mesh - std::string GetMeshId(size_t pIndex) const { - return std::string("meshId") + to_string(pIndex); - } + /// Get or Create a unique mesh ID string for the given mesh index + std::string GetMeshUniqueId(size_t pIndex); + std::string GetMeshName(size_t pIndex); + +private: + std::string AddMeshIndexToMaps(size_t pIndex, bool meshId); + mutable std::map mMeshIdMap; // Cache of encoded unique IDs + mutable std::map mMeshNameMap; // Cache of encoded mesh names public: /// Stringstream to write all output into diff --git a/code/Collada/ColladaHelper.h b/code/Collada/ColladaHelper.h index 3eb073cd9..f41691606 100644 --- a/code/Collada/ColladaHelper.h +++ b/code/Collada/ColladaHelper.h @@ -339,11 +339,13 @@ struct SubMesh { /** Contains data for a single mesh */ struct Mesh { - Mesh() { + Mesh(const std::string &id) : + mId(id) { for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) mNumUVComponents[i] = 2; } + const std::string mId; std::string mName; // just to check if there's some sophisticated addressing involved... diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index 44d65e40d..c76954fdf 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ColladaLoader.h" #include "ColladaParser.h" +#include #include #include #include @@ -265,6 +266,13 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad // find a name for the new node. It's more complicated than you might think node->mName.Set(FindNameForNode(pNode)); + // if we're not using the unique IDs, hold onto them for reference and export + if (useColladaName) { + if (!pNode->mID.empty()) + node->mMetaData->Add(AI_METADATA_COLLADA_ID, aiString(pNode->mID)); + if (!pNode->mSID.empty()) + node->mMetaData->Add(AI_METADATA_COLLADA_SID, aiString(pNode->mSID)); + } // calculate the transformation matrix for it node->mTransformation = pParser.CalculateResultTransform(pNode->mTransforms); @@ -603,7 +611,11 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M const Collada::Controller *pSrcController, size_t pStartVertex, size_t pStartFace) { std::unique_ptr dstMesh(new aiMesh); - dstMesh->mName = pSrcMesh->mName; + if (useColladaName) { + dstMesh->mName = pSrcMesh->mName; + } else { + dstMesh->mName = pSrcMesh->mId; + } // count the vertices addressed by its faces const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace, @@ -700,10 +712,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) { const Collada::Mesh *targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i)); - aiMesh *aimesh = findMesh(targetMesh->mName); + aiMesh *aimesh = findMesh(useColladaName ? targetMesh->mName : targetMesh->mId); if (!aimesh) { if (targetMesh->mSubMeshes.size() > 1) { - throw DeadlyImportError("Morhing target mesh must be a single"); + throw DeadlyImportError("Morphing target mesh must be a single"); } aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0); mTargetMeshes.push_back(aimesh); diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index 5080094c1..d83980929 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -1716,18 +1716,25 @@ void ColladaParser::ReadGeometryLibrary() { // TODO: (thom) support SIDs // ai_assert( TestAttribute( "sid") == -1); - // create a mesh and store it in the library under its ID - Mesh *mesh = new Mesh; - mMeshLibrary[id] = mesh; + // create a mesh and store it in the library under its (resolved) ID + // Skip and warn if ID is not unique + if (mMeshLibrary.find(id) == mMeshLibrary.cend()) { + std::unique_ptr mesh(new Mesh(id)); - // read the mesh name if it exists - const int nameIndex = TestAttribute("name"); - if (nameIndex != -1) { - mesh->mName = mReader->getAttributeValue(nameIndex); + // read the mesh name if it exists + const int nameIndex = TestAttribute("name"); + if (nameIndex != -1) { + mesh->mName = mReader->getAttributeValue(nameIndex); + } + + // read on from there + ReadGeometry(*mesh); + // Read successfully, add to library + mMeshLibrary.insert({ id, mesh.release() }); + } else { + ASSIMP_LOG_ERROR_F("Collada: Skipped duplicate geometry id: \"", id, "\""); + SkipElement(); } - - // read on from there - ReadGeometry(mesh); } else { // ignore the rest SkipElement(); @@ -1743,7 +1750,7 @@ void ColladaParser::ReadGeometryLibrary() { // ------------------------------------------------------------------------------------------------ // Reads a geometry from the geometry library. -void ColladaParser::ReadGeometry(Collada::Mesh *pMesh) { +void ColladaParser::ReadGeometry(Collada::Mesh &pMesh) { if (mReader->isEmptyElement()) return; @@ -1767,7 +1774,7 @@ void ColladaParser::ReadGeometry(Collada::Mesh *pMesh) { // ------------------------------------------------------------------------------------------------ // Reads a mesh from the geometry library -void ColladaParser::ReadMesh(Mesh *pMesh) { +void ColladaParser::ReadMesh(Mesh &pMesh) { if (mReader->isEmptyElement()) return; @@ -1997,16 +2004,16 @@ void ColladaParser::ReadAccessor(const std::string &pID) { // ------------------------------------------------------------------------------------------------ // Reads input declarations of per-vertex mesh data into the given mesh -void ColladaParser::ReadVertexData(Mesh *pMesh) { +void ColladaParser::ReadVertexData(Mesh &pMesh) { // extract the ID of the element. Not that we care, but to catch strange referencing schemes we should warn about int attrID = GetAttribute("id"); - pMesh->mVertexID = mReader->getAttributeValue(attrID); + pMesh.mVertexID = mReader->getAttributeValue(attrID); // a number of elements while (mReader->read()) { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { if (IsElement("input")) { - ReadInputChannel(pMesh->mPerVertexData); + ReadInputChannel(pMesh.mPerVertexData); } else { ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag "); } @@ -2021,7 +2028,7 @@ void ColladaParser::ReadVertexData(Mesh *pMesh) { // ------------------------------------------------------------------------------------------------ // Reads input declarations of per-index mesh data into the given mesh -void ColladaParser::ReadIndexData(Mesh *pMesh) { +void ColladaParser::ReadIndexData(Mesh &pMesh) { std::vector vcount; std::vector perIndexData; @@ -2111,7 +2118,7 @@ void ColladaParser::ReadIndexData(Mesh *pMesh) { // only when we're done reading all

tags (and thus know the final vertex count) can we commit the submesh subgroup.mNumFaces = actualPrimitives; - pMesh->mSubMeshes.push_back(subgroup); + pMesh.mSubMeshes.push_back(subgroup); } // ------------------------------------------------------------------------------------------------ @@ -2158,7 +2165,7 @@ void ColladaParser::ReadInputChannel(std::vector &poChannels) { // ------------------------------------------------------------------------------------------------ // Reads a

primitive index list and assembles the mesh data into the given mesh -size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPerIndexChannels, +size_t ColladaParser::ReadPrimitives(Mesh &pMesh, std::vector &pPerIndexChannels, size_t pNumPrimitives, const std::vector &pVCount, PrimitiveType pPrimType) { // determine number of indices coming per vertex // find the offset index for all per-vertex channels @@ -2220,7 +2227,7 @@ size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPe ThrowException("Expected different index count in

element."); // find the data for all sources - for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) { + for (std::vector::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) { InputChannel &input = *it; if (input.mResolved) continue; @@ -2241,7 +2248,7 @@ size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPe // ignore vertex pointer, it doesn't refer to an accessor if (input.mType == IT_Vertex) { // warn if the vertex channel does not refer to the element in the same mesh - if (input.mAccessor != pMesh->mVertexID) + if (input.mAccessor != pMesh.mVertexID) ThrowException("Unsupported vertex referencing scheme."); continue; } @@ -2268,8 +2275,8 @@ size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPe numPrimitives = numberOfVertices - 1; } - pMesh->mFaceSize.reserve(numPrimitives); - pMesh->mFacePosIndices.reserve(indices.size() / numOffsets); + pMesh.mFaceSize.reserve(numPrimitives); + pMesh.mFacePosIndices.reserve(indices.size() / numOffsets); size_t polylistStartVertex = 0; for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++) { @@ -2314,7 +2321,7 @@ size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPe } // store the face size to later reconstruct the face from - pMesh->mFaceSize.push_back(numPoints); + pMesh.mFaceSize.push_back(numPoints); } // if I ever get my hands on that guy who invented this steaming pile of indirection... @@ -2325,7 +2332,7 @@ size_t ColladaParser::ReadPrimitives(Mesh *pMesh, std::vector &pPe ///@note This function willn't work correctly if both PerIndex and PerVertex channels have same channels. ///For example if TEXCOORD present in both and tags this function will create wrong uv coordinates. ///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior -void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh *pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices) { +void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices) { // calculate the base offset of the vertex whose attributes we ant to copy size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets; @@ -2333,17 +2340,17 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n ai_assert((baseOffset + numOffsets - 1) < indices.size()); // extract per-vertex channels using the global per-vertex offset - for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) + for (std::vector::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh); // and extract per-index channels using there specified offset for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh); // store the vertex-data index for later assignment of bone vertex weights - pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]); + pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]); } -void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh *pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices) { +void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh &pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices) { if (currentPrimitive % 2 != 0) { //odd tristrip triangles need their indices mangled, to preserve winding direction CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); @@ -2358,7 +2365,7 @@ void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, // ------------------------------------------------------------------------------------------------ // Extracts a single object from an input channel and stores it in the appropriate mesh data array -void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, size_t pLocalIndex, Mesh *pMesh) { +void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, size_t pLocalIndex, Mesh &pMesh) { // ignore vertex referrer - we handle them that separate if (pInput.mType == IT_Vertex) return; @@ -2380,40 +2387,40 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz switch (pInput.mType) { case IT_Position: // ignore all position streams except 0 - there can be only one position if (pInput.mIndex == 0) - pMesh->mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2])); + pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2])); else ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported"); break; case IT_Normal: // pad to current vertex count if necessary - if (pMesh->mNormals.size() < pMesh->mPositions.size() - 1) - pMesh->mNormals.insert(pMesh->mNormals.end(), pMesh->mPositions.size() - pMesh->mNormals.size() - 1, aiVector3D(0, 1, 0)); + if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1) + pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0)); // ignore all normal streams except 0 - there can be only one normal if (pInput.mIndex == 0) - pMesh->mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2])); + pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2])); else ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported"); break; case IT_Tangent: // pad to current vertex count if necessary - if (pMesh->mTangents.size() < pMesh->mPositions.size() - 1) - pMesh->mTangents.insert(pMesh->mTangents.end(), pMesh->mPositions.size() - pMesh->mTangents.size() - 1, aiVector3D(1, 0, 0)); + if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1) + pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0)); // ignore all tangent streams except 0 - there can be only one tangent if (pInput.mIndex == 0) - pMesh->mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); + pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); else ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported"); break; case IT_Bitangent: // pad to current vertex count if necessary - if (pMesh->mBitangents.size() < pMesh->mPositions.size() - 1) - pMesh->mBitangents.insert(pMesh->mBitangents.end(), pMesh->mPositions.size() - pMesh->mBitangents.size() - 1, aiVector3D(0, 0, 1)); + if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) + pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1)); // ignore all bitangent streams except 0 - there can be only one bitangent if (pInput.mIndex == 0) - pMesh->mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); + pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); else ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported"); break; @@ -2421,13 +2428,13 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz // up to 4 texture coord sets are fine, ignore the others if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) { // pad to current vertex count if necessary - if (pMesh->mTexCoords[pInput.mIndex].size() < pMesh->mPositions.size() - 1) - pMesh->mTexCoords[pInput.mIndex].insert(pMesh->mTexCoords[pInput.mIndex].end(), - pMesh->mPositions.size() - pMesh->mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0)); + if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1) + pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(), + pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0)); - pMesh->mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2])); + pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2])); if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */ - pMesh->mNumUVComponents[pInput.mIndex] = 3; + pMesh.mNumUVComponents[pInput.mIndex] = 3; } else { ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping."); } @@ -2436,15 +2443,15 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz // up to 4 color sets are fine, ignore the others if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) { // pad to current vertex count if necessary - if (pMesh->mColors[pInput.mIndex].size() < pMesh->mPositions.size() - 1) - pMesh->mColors[pInput.mIndex].insert(pMesh->mColors[pInput.mIndex].end(), - pMesh->mPositions.size() - pMesh->mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1)); + if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1) + pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(), + pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1)); aiColor4D result(0, 0, 0, 1); for (size_t i = 0; i < pInput.mResolved->mSize; ++i) { result[static_cast(i)] = obj[pInput.mResolved->mSubOffset[i]]; } - pMesh->mColors[pInput.mIndex].push_back(result); + pMesh.mColors[pInput.mIndex].push_back(result); } else { ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping."); } diff --git a/code/Collada/ColladaParser.h b/code/Collada/ColladaParser.h index 861a65256..a84a59354 100644 --- a/code/Collada/ColladaParser.h +++ b/code/Collada/ColladaParser.h @@ -174,10 +174,10 @@ protected: void ReadGeometryLibrary(); /** Reads a geometry from the geometry library. */ - void ReadGeometry(Collada::Mesh *pMesh); + void ReadGeometry(Collada::Mesh &pMesh); /** Reads a mesh from the geometry library */ - void ReadMesh(Collada::Mesh *pMesh); + void ReadMesh(Collada::Mesh &pMesh); /** Reads a source element - a combination of raw data and an accessor defining * things that should not be redefinable. Yes, that's another rant. @@ -195,29 +195,29 @@ protected: void ReadAccessor(const std::string &pID); /** Reads input declarations of per-vertex mesh data into the given mesh */ - void ReadVertexData(Collada::Mesh *pMesh); + void ReadVertexData(Collada::Mesh &pMesh); /** Reads input declarations of per-index mesh data into the given mesh */ - void ReadIndexData(Collada::Mesh *pMesh); + void ReadIndexData(Collada::Mesh &pMesh); /** Reads a single input channel element and stores it in the given array, if valid */ void ReadInputChannel(std::vector &poChannels); /** Reads a

primitive index list and assembles the mesh data into the given mesh */ - size_t ReadPrimitives(Collada::Mesh *pMesh, std::vector &pPerIndexChannels, + size_t ReadPrimitives(Collada::Mesh &pMesh, std::vector &pPerIndexChannels, size_t pNumPrimitives, const std::vector &pVCount, Collada::PrimitiveType pPrimType); /** Copies the data for a single primitive into the mesh, based on the InputChannels */ void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, - Collada::Mesh *pMesh, std::vector &pPerIndexChannels, + Collada::Mesh &pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices); /** Reads one triangle of a tristrip into the mesh */ - void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh *pMesh, + void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh &pMesh, std::vector &pPerIndexChannels, size_t currentPrimitive, const std::vector &indices); /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ - void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh *pMesh); + void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh); /** Reads the library of node hierarchies and scene parts */ void ReadSceneLibrary(); diff --git a/include/assimp/ColladaMetaData.h b/include/assimp/ColladaMetaData.h new file mode 100644 index 000000000..4288692c6 --- /dev/null +++ b/include/assimp/ColladaMetaData.h @@ -0,0 +1,53 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file ColladaMetaData.h + * Declares common metadata constants used by Collada files + */ +#pragma once +#ifndef AI_COLLADAMETADATA_H_INC +#define AI_COLLADAMETADATA_H_INC + +#define AI_METADATA_COLLADA_ID "COLLADA_ID" +#define AI_METADATA_COLLADA_SID "COLLADA_SID" + +#endif diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index e2f2a3888..c26dcc77f 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -1030,10 +1030,10 @@ enum aiComponent #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION" // --------------------------------------------------------------------------- -/** @brief Specifies whether the Collada loader should use Collada names as node names. +/** @brief Specifies whether the Collada loader should use Collada names. * - * If this property is set to true, the Collada names will be used as the - * node name. The default is to use the id tag (resp. sid tag, if no id tag is present) + * If this property is set to true, the Collada names will be used as the node and + * mesh names. The default is to use the id tag (resp. sid tag, if no id tag is present) * instead. * Property type: Bool. Default value: false. */ diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index 549ff68fb..5c2f801db 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -44,13 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include using namespace Assimp; class utColladaImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { + virtual bool importerTest() final { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure); if (scene == nullptr) @@ -80,15 +81,61 @@ public: return true; } + + void ImportAndCheckIds(const char *file, size_t meshCount) { + // Import the Collada using the 'default' where mesh names are the ids + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); + ASSERT_TRUE(scene != nullptr) << "Fatal: could not re-import " << file; + EXPECT_EQ(meshCount, scene->mNumMeshes) << "in " << file; + + // Check the mesh ids are unique + std::map meshNameMap; + for (size_t idx = 0; idx < scene->mNumMeshes; ++idx) { + std::string meshName(scene->mMeshes[idx]->mName.C_Str()); + const auto result = meshNameMap.insert(std::make_pair(meshName, idx)); + EXPECT_TRUE(result.second) << "Duplicate name: " << meshName << " index " << result.first->second; + } + } }; -TEST_F(utColladaImportExport, importBlenFromFileTest) { +TEST_F(utColladaImportExport, importDaeFromFileTest) { EXPECT_TRUE(importerTest()); } +TEST_F(utColladaImportExport, exporterUniqueIdsTest) { + Assimp::Importer importer; + Assimp::Exporter exporter; + const char *outFileEmpty = "exportMeshIdTest_empty_out.dae"; + const char *outFileNamed = "exportMeshIdTest_named_out.dae"; + + // Load a sample file containing multiple meshes + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/teapots.DAE", aiProcess_ValidateDataStructure); + + ASSERT_TRUE(scene != nullptr) << "Fatal: could not import teapots.DAE!"; + ASSERT_EQ(3u, scene->mNumMeshes) << "Fatal: teapots.DAE initial load failed"; + + // Clear the mesh names + for (size_t idx = 0; idx < scene->mNumMeshes; ++idx) { + scene->mMeshes[idx]->mName.Clear(); + } + ASSERT_EQ(AI_SUCCESS, exporter.Export(scene, "collada", outFileEmpty)) << "Fatal: Could not export un-named meshes file"; + + ImportAndCheckIds(outFileEmpty, 3); + + // Force the meshes to have the same non-empty name + aiString testName("test_mesh"); + for (size_t idx = 0; idx < scene->mNumMeshes; ++idx) { + scene->mMeshes[idx]->mName = testName; + } + ASSERT_EQ(AI_SUCCESS, exporter.Export(scene, "collada", outFileNamed)) << "Fatal: Could not export named meshes file"; + + ImportAndCheckIds(outFileNamed, 3); +} + class utColladaZaeImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { + virtual bool importerTest() final { { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure); From fd555a1349a1709565f536191f1c5f077702f504 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 20:33:37 +0200 Subject: [PATCH 043/119] review findings. --- include/assimp/ai_assert.h | 2 - include/assimp/anim.h | 2 - include/assimp/cexport.h | 94 +++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index f430e4ad3..f018163bf 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/include/assimp/anim.h b/include/assimp/anim.h index 7ef5355e6..b43991b80 100644 --- a/include/assimp/anim.h +++ b/include/assimp/anim.h @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/include/assimp/cexport.h b/include/assimp/cexport.h index 959d4377e..badfd0a6f 100644 --- a/include/assimp/cexport.h +++ b/include/assimp/cexport.h @@ -47,42 +47,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_EXPORT_H_INC #ifdef __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif #ifndef ASSIMP_BUILD_NO_EXPORT -// Public ASSIMP data structures #include #ifdef __cplusplus extern "C" { #endif -struct aiScene; // aiScene.h -struct aiFileIO; // aiFileIO.h +struct aiScene; +struct aiFileIO; // -------------------------------------------------------------------------------- -/** Describes an file format which Assimp can export to. Use #aiGetExportFormatCount() to -* learn how many export formats the current Assimp build supports and #aiGetExportFormatDescription() -* to retrieve a description of an export format option. -*/ -struct aiExportFormatDesc -{ +/** + * @brief Describes an file format which Assimp can export to. + * + * Use #aiGetExportFormatCount() to learn how many export-formats are supported by + * the current Assimp-build and #aiGetExportFormatDescription() to retrieve the + * description of the export format option. + */ +struct aiExportFormatDesc { /// a short string ID to uniquely identify the export format. Use this ID string to /// specify which file format you want to export to when calling #aiExportScene(). /// Example: "dae" or "obj" - const char* id; + const char *id; /// A short description of the file format to present to users. Useful if you want /// to allow the user to select an export format. - const char* description; + const char *description; /// Recommended file extension for the exported file in lower case. - const char* fileExtension; + const char *fileExtension; }; - // -------------------------------------------------------------------------------- /** Returns the number of export file formats available in the current Assimp build. * Use aiGetExportFormatDescription() to retrieve infos of a specific export format. @@ -97,14 +97,14 @@ ASSIMP_API size_t aiGetExportFormatCount(void); * 0 to #aiGetExportFormatCount() * @return A description of that specific export format. NULL if pIndex is out of range. */ -ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex); +ASSIMP_API const C_STRUCT aiExportFormatDesc *aiGetExportFormatDescription(size_t pIndex); // -------------------------------------------------------------------------------- /** Release a description of the nth export file format. Must be returned by * aiGetExportFormatDescription * @param desc Pointer to the description */ -ASSIMP_API void aiReleaseExportFormatDescription( const C_STRUCT aiExportFormatDesc *desc ); +ASSIMP_API void aiReleaseExportFormatDescription(const C_STRUCT aiExportFormatDesc *desc); // -------------------------------------------------------------------------------- /** Create a modifiable copy of a scene. @@ -115,13 +115,12 @@ ASSIMP_API void aiReleaseExportFormatDescription( const C_STRUCT aiExportFormatD * @param pOut Receives a modifyable copy of the scene. Use aiFreeScene() to * delete it again. */ -ASSIMP_API void aiCopyScene(const C_STRUCT aiScene* pIn, - C_STRUCT aiScene** pOut); - +ASSIMP_API void aiCopyScene(const C_STRUCT aiScene *pIn, + C_STRUCT aiScene **pOut); // -------------------------------------------------------------------------------- /** Frees a scene copy created using aiCopyScene() */ -ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn); +ASSIMP_API void aiFreeScene(const C_STRUCT aiScene *pIn); // -------------------------------------------------------------------------------- /** Exports the given scene to a chosen file format and writes the result file(s) to disk. @@ -154,19 +153,18 @@ ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn); * triangulate data so they would run the step anyway. * * If assimp detects that the input scene was directly taken from the importer side of -* the library (i.e. not copied using aiCopyScene and potetially modified afterwards), -* any postprocessing steps already applied to the scene will not be applied again, unless -* they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and +* the library (i.e. not copied using aiCopyScene and potentially modified afterwards), +* any post-processing steps already applied to the scene will not be applied again, unless +* they show non-idempotent behavior (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and * #aiProcess_FlipWindingOrder). * @return a status code indicating the result of the export * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene. */ -ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene, - const char* pFormatId, - const char* pFileName, - unsigned int pPreprocessing); - +ASSIMP_API aiReturn aiExportScene(const C_STRUCT aiScene *pScene, + const char *pFormatId, + const char *pFileName, + unsigned int pPreprocessing); // -------------------------------------------------------------------------------- /** Exports the given scene to a chosen file format using custom IO logic supplied by you. @@ -183,11 +181,11 @@ ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene, * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene. */ -ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene, - const char* pFormatId, - const char* pFileName, - C_STRUCT aiFileIO* pIO, - unsigned int pPreprocessing ); +ASSIMP_API aiReturn aiExportSceneEx(const C_STRUCT aiScene *pScene, + const char *pFormatId, + const char *pFileName, + C_STRUCT aiFileIO *pIO, + unsigned int pPreprocessing); // -------------------------------------------------------------------------------- /** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an @@ -199,13 +197,12 @@ ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene, * This is used when exporters write more than one output file for a given #aiScene. See the remarks for * #aiExportDataBlob::name for more information. */ -struct aiExportDataBlob -{ +struct aiExportDataBlob { /// Size of the data in bytes size_t size; /// The data. - void* data; + void *data; /** Name of the blob. An empty string always indicates the first (and primary) blob, @@ -222,18 +219,23 @@ struct aiExportDataBlob C_STRUCT aiString name; /** Pointer to the next blob in the chain or NULL if there is none. */ - C_STRUCT aiExportDataBlob * next; + C_STRUCT aiExportDataBlob *next; #ifdef __cplusplus /// Default constructor - aiExportDataBlob() { size = 0; data = next = NULL; } + aiExportDataBlob() { + size = 0; + data = next = nullptr; + } /// Releases the data - ~aiExportDataBlob() { delete [] static_cast( data ); delete next; } + ~aiExportDataBlob() { + delete[] static_cast(data); + delete next; + } + + aiExportDataBlob(const aiExportDataBlob &) = delete; + aiExportDataBlob &operator=(const aiExportDataBlob &) = delete; -private: - // no copying - aiExportDataBlob(const aiExportDataBlob& ); - aiExportDataBlob& operator= (const aiExportDataBlob& ); #endif // __cplusplus }; @@ -247,15 +249,15 @@ private: * @param pPreprocessing Please see the documentation for #aiExportScene * @return the exported data or NULL in case of error */ -ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT aiScene* pScene, const char* pFormatId, - unsigned int pPreprocessing ); +ASSIMP_API const C_STRUCT aiExportDataBlob *aiExportSceneToBlob(const C_STRUCT aiScene *pScene, const char *pFormatId, + unsigned int pPreprocessing); // -------------------------------------------------------------------------------- /** Releases the memory associated with the given exported data. Use this function to free a data blob * returned by aiExportScene(). * @param pData the data blob returned by #aiExportSceneToBlob */ -ASSIMP_API void aiReleaseExportBlob( const C_STRUCT aiExportDataBlob* pData ); +ASSIMP_API void aiReleaseExportBlob(const C_STRUCT aiExportDataBlob *pData); #ifdef __cplusplus } From c6131ce38ada7dd1d74b693e3979cb04a83d0df2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 20:43:23 +0200 Subject: [PATCH 044/119] scenecombiner: fix leak. --- code/Common/SceneCombiner.cpp | 5 +---- include/assimp/mesh.h | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 62efe2ece..4d2a411f2 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -979,7 +979,7 @@ void GetArrayCopy(Type*& dest, ai_uint num ) { dest = new Type[num]; ::memcpy(dest, old, sizeof(Type) * num); - } +} // ------------------------------------------------------------------------------------------------ void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) { @@ -1269,9 +1269,6 @@ void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) { // get a flat copy *dest = *src; - - // and reallocate all arrays - GetArrayCopy( dest->mWeights, dest->mNumWeights ); } // ------------------------------------------------------------------------------------------------ diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index bd987bc88..4b5af97ce 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -308,7 +308,10 @@ struct aiBone { //! Copy constructor aiBone(const aiBone &other) : - mName(other.mName), mNumWeights(other.mNumWeights), mWeights(nullptr), mOffsetMatrix(other.mOffsetMatrix) { + mName(other.mName), + mNumWeights(other.mNumWeights), + mWeights(nullptr), + mOffsetMatrix(other.mOffsetMatrix) { if (other.mWeights && other.mNumWeights) { mWeights = new aiVertexWeight[mNumWeights]; ::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight)); From f808ed9fb5879f4b11d46ace3599e262a6ef50ec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 20:52:49 +0200 Subject: [PATCH 045/119] fbxconverter: fix memoryleak. --- code/FBX/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 880b5de76..c22e3a50b 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -3392,7 +3392,7 @@ void FBXConverter::ConvertGlobalSettings() { const bool hasGenerator = !doc.Creator().empty(); - mSceneOut->mMetaData = aiMetadata::Alloc(16 + (hasGenerator ? 1 : 0)); + mSceneOut->mMetaData = aiMetadata::Alloc(17 + (hasGenerator ? 1 : 0)); mSceneOut->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis()); mSceneOut->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign()); mSceneOut->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis()); From da2bf5c7a43eacc7c1b4583790e0115951bfd560 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 21:13:46 +0200 Subject: [PATCH 046/119] fix wrong size --- code/FBX/FBXConverter.cpp | 2 +- include/assimp/metadata.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index c22e3a50b..880b5de76 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -3392,7 +3392,7 @@ void FBXConverter::ConvertGlobalSettings() { const bool hasGenerator = !doc.Creator().empty(); - mSceneOut->mMetaData = aiMetadata::Alloc(17 + (hasGenerator ? 1 : 0)); + mSceneOut->mMetaData = aiMetadata::Alloc(16 + (hasGenerator ? 1 : 0)); mSceneOut->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis()); mSceneOut->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign()); mSceneOut->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis()); diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 28ddce567..cd7569ffe 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -320,7 +320,7 @@ struct aiMetadata { } template - inline bool Set( const std::string &key, const T &value ) { + inline bool Set(const std::string &key, const T &value) { if (key.empty()) { return false; } From e0bc0f7fade58376a54a1374bf1e2cd0f0e15e69 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 21:19:15 +0200 Subject: [PATCH 047/119] try to fix double memleak. --- code/FBX/FBXConverter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 880b5de76..e46e45c28 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -3401,7 +3401,8 @@ void FBXConverter::ConvertGlobalSettings() { mSceneOut->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign()); mSceneOut->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis()); mSceneOut->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign()); - mSceneOut->mMetaData->Set(8, "UnitScaleFactor", (double)doc.GlobalSettings().UnitScaleFactor()); + const double unitScaleFactor = (double)doc.GlobalSettings().UnitScaleFactor(); + mSceneOut->mMetaData->Set(8, "UnitScaleFactor", unitScaleFactor); mSceneOut->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor()); mSceneOut->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor()); mSceneOut->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode()); From 1c30b7bf8ed2a4cc02a1b33f52e46c05be815c60 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 21:31:01 +0200 Subject: [PATCH 048/119] tryout: check if leak is coupled to type double. --- code/FBX/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index e46e45c28..296d30398 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -3402,7 +3402,7 @@ void FBXConverter::ConvertGlobalSettings() { mSceneOut->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis()); mSceneOut->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign()); const double unitScaleFactor = (double)doc.GlobalSettings().UnitScaleFactor(); - mSceneOut->mMetaData->Set(8, "UnitScaleFactor", unitScaleFactor); + mSceneOut->mMetaData->Set(8, "UnitScaleFactor", doc.GlobalSettings().UnitScaleFactor()); mSceneOut->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor()); mSceneOut->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor()); mSceneOut->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode()); From 2d9d1120158197cb1e4a64d607b7aca413a1aa4f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 29 Apr 2020 21:35:42 +0200 Subject: [PATCH 049/119] fix warning --- code/FBX/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 296d30398..1bf977189 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -3401,7 +3401,7 @@ void FBXConverter::ConvertGlobalSettings() { mSceneOut->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign()); mSceneOut->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis()); mSceneOut->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign()); - const double unitScaleFactor = (double)doc.GlobalSettings().UnitScaleFactor(); + //const double unitScaleFactor = (double)doc.GlobalSettings().UnitScaleFactor(); mSceneOut->mMetaData->Set(8, "UnitScaleFactor", doc.GlobalSettings().UnitScaleFactor()); mSceneOut->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor()); mSceneOut->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor()); From a639221ededeb186c3f903b932594f8e7b44bd4c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 30 Apr 2020 09:14:42 +0200 Subject: [PATCH 050/119] Update to float - Temporary change to analyze leak. --- test/unit/utFBXImporterExporter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index 88a3e067e..2f1ea79e8 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -210,13 +210,13 @@ TEST_F(utFBXImporterExporter, importUnitScaleFactor) { EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene->mMetaData); - double factor(0.0); + float factor(0.0f); scene->mMetaData->Get("UnitScaleFactor", factor); - EXPECT_DOUBLE_EQ(500.0, factor); + EXPECT_EQ(500.0f, factor); - scene->mMetaData->Set("UnitScaleFactor", factor * 2); + scene->mMetaData->Set("UnitScaleFactor", factor * 2.0f); scene->mMetaData->Get("UnitScaleFactor", factor); - EXPECT_DOUBLE_EQ(1000.0, factor); + EXPECT_EQ(1000.0f, factor); } TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) { From 083ebdbc2ece2f4dd071e5439ab848ffade8a3c2 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Thu, 30 Apr 2020 18:28:06 +0100 Subject: [PATCH 051/119] Collada Export: More unique Ids Nodes, Materials, Animations, Lights, Cameras, Bones --- code/Collada/ColladaExporter.cpp | 405 ++++++++++++++++------------ code/Collada/ColladaExporter.h | 57 ++-- test/unit/utColladaImportExport.cpp | 107 +++++++- 3 files changed, 369 insertions(+), 200 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index a502e728c..b91e118ec 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -164,6 +164,9 @@ void ColladaExporter::WriteFile() { WriteTextures(); WriteHeader(); + // Add node names to the unique id database first so they are most likely to use their names as unique ids + CreateNodeIds(mScene->mRootNode); + WriteCamerasLibrary(); WriteLightsLibrary(); WriteMaterials(); @@ -178,7 +181,7 @@ void ColladaExporter::WriteFile() { // useless Collada fu at the end, just in case we haven't had enough indirections, yet. mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mRootNode->mName.C_Str()) + "\" />" << endstr; + mOutput << startstr << "mRootNode) + "\" />" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -391,8 +394,8 @@ void ColladaExporter::WriteCamerasLibrary() { void ColladaExporter::WriteCamera(size_t pIndex) { const aiCamera *cam = mScene->mCameras[pIndex]; - const std::string cameraName = XMLEscape(cam->mName.C_Str()); - const std::string cameraId = XMLIDEncode(cam->mName.C_Str()); + const std::string cameraId = GetObjectUniqueId(AiObjectType::Camera, pIndex); + const std::string cameraName = GetObjectName(AiObjectType::Camera, pIndex); mOutput << startstr << "" << endstr; PushTag(); @@ -444,8 +447,8 @@ void ColladaExporter::WriteLightsLibrary() { void ColladaExporter::WriteLight(size_t pIndex) { const aiLight *light = mScene->mLights[pIndex]; - const std::string lightName = XMLEscape(light->mName.C_Str()); - const std::string lightId = XMLIDEncode(light->mName.C_Str()); + const std::string lightId = GetObjectUniqueId(AiObjectType::Light, pIndex); + const std::string lightName = GetObjectName(AiObjectType::Light, pIndex); mOutput << startstr << "" << endstr; @@ -564,12 +567,11 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys -void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial *pSrcMat, - aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) { - if (pSrcMat->GetTextureCount(pTexture) > 0) { +bool ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) { + if (pSrcMat.GetTextureCount(pTexture) > 0) { aiString texfile; unsigned int uvChannel = 0; - pSrcMat->GetTexture(pTexture, 0, &texfile, NULL, &uvChannel); + pSrcMat.GetTexture(pTexture, 0, &texfile, NULL, &uvChannel); std::string index_str(texfile.C_Str()); @@ -599,8 +601,9 @@ void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial * poSurface.exist = true; } else { if (pKey) - poSurface.exist = pSrcMat->Get(pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; + poSurface.exist = pSrcMat.Get(pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; } + return poSurface.exist; } // ------------------------------------------------------------------------------------------------ @@ -611,9 +614,9 @@ static bool isalnum_C(char c) { // ------------------------------------------------------------------------------------------------ // Writes an image entry for the given surface -void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &pNameAdd) { +void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &imageId) { if (!pSurface.texture.empty()) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << ""; @@ -634,14 +637,14 @@ void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string // ------------------------------------------------------------------------------------------------ // Writes a color-or-texture entry into an effect definition -void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pImageName) { +void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId) { if (pSurface.exist) { mOutput << startstr << "<" << pTypeName << ">" << endstr; PushTag(); if (pSurface.texture.empty()) { mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; } else { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } PopTag(); mOutput << startstr << "" << endstr; @@ -650,24 +653,24 @@ void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std: // ------------------------------------------------------------------------------------------------ // Writes the two parameters necessary for referencing a texture in an effect entry -void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pMatName) { +void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId) { // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture if (!pSurface.texture.empty()) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image" << endstr; + mOutput << startstr << "" << materialId << "-" << pTypeName << "-image" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface" << endstr; + mOutput << startstr << "" << materialId << "-" << pTypeName << "-surface" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -690,80 +693,63 @@ void ColladaExporter::WriteFloatEntry(const Property &pProperty, const std::stri // ------------------------------------------------------------------------------------------------ // Writes the material setup void ColladaExporter::WriteMaterials() { + std::vector materials; materials.resize(mScene->mNumMaterials); /// collect all materials from the scene size_t numTextures = 0; for (size_t a = 0; a < mScene->mNumMaterials; ++a) { - const aiMaterial *mat = mScene->mMaterials[a]; - - aiString name; - if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) { - name = "mat"; - materials[a].name = std::string("m") + to_string(a) + name.C_Str(); - } else { - // try to use the material's name if no other material has already taken it, else append # - std::string testName = name.C_Str(); - size_t materialCountWithThisName = 0; - for (size_t i = 0; i < a; i++) { - if (materials[i].name == testName) { - materialCountWithThisName++; - } - } - if (materialCountWithThisName == 0) { - materials[a].name = name.C_Str(); - } else { - materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); - } - } + Material &material = materials[a]; + material.id = GetObjectUniqueId(AiObjectType::Material, a); + material.name = GetObjectName(AiObjectType::Material, a); + const aiMaterial &mat = *(mScene->mMaterials[a]); aiShadingMode shading = aiShadingMode_Flat; - materials[a].shading_model = "phong"; - if (mat->Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { + material.shading_model = "phong"; + if (mat.Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { if (shading == aiShadingMode_Phong) { - materials[a].shading_model = "phong"; + material.shading_model = "phong"; } else if (shading == aiShadingMode_Blinn) { - materials[a].shading_model = "blinn"; + material.shading_model = "blinn"; } else if (shading == aiShadingMode_NoShading) { - materials[a].shading_model = "constant"; + material.shading_model = "constant"; } else if (shading == aiShadingMode_Gouraud) { - materials[a].shading_model = "lambert"; + material.shading_model = "lambert"; } } - ReadMaterialSurface(materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - if (!materials[a].ambient.texture.empty()) numTextures++; - ReadMaterialSurface(materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - if (!materials[a].diffuse.texture.empty()) numTextures++; - ReadMaterialSurface(materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - if (!materials[a].specular.texture.empty()) numTextures++; - ReadMaterialSurface(materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); - if (!materials[a].emissive.texture.empty()) numTextures++; - ReadMaterialSurface(materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); - if (!materials[a].reflective.texture.empty()) numTextures++; - ReadMaterialSurface(materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); - if (!materials[a].transparent.texture.empty()) numTextures++; - ReadMaterialSurface(materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); - if (!materials[a].normal.texture.empty()) numTextures++; + if (ReadMaterialSurface(material.ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT)) + ++numTextures; + if (ReadMaterialSurface(material.diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE)) + ++numTextures; + if (ReadMaterialSurface(material.specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR)) + ++numTextures; + if (ReadMaterialSurface(material.emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE)) + ++numTextures; + if (ReadMaterialSurface(material.reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE)) + ++numTextures; + if (ReadMaterialSurface(material.transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT)) + ++numTextures; + if (ReadMaterialSurface(material.normal, mat, aiTextureType_NORMALS, nullptr, 0, 0)) + ++numTextures; - materials[a].shininess.exist = mat->Get(AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; - materials[a].transparency.exist = mat->Get(AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; - materials[a].index_refraction.exist = mat->Get(AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; + material.shininess.exist = mat.Get(AI_MATKEY_SHININESS, material.shininess.value) == aiReturn_SUCCESS; + material.transparency.exist = mat.Get(AI_MATKEY_OPACITY, material.transparency.value) == aiReturn_SUCCESS; + material.index_refraction.exist = mat.Get(AI_MATKEY_REFRACTI, material.index_refraction.value) == aiReturn_SUCCESS; } // output textures if present if (numTextures > 0) { mOutput << startstr << "" << endstr; PushTag(); - for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { - const Material &mat = *it; - WriteImageEntry(mat.ambient, mat.name + "-ambient-image"); - WriteImageEntry(mat.diffuse, mat.name + "-diffuse-image"); - WriteImageEntry(mat.specular, mat.name + "-specular-image"); - WriteImageEntry(mat.emissive, mat.name + "-emission-image"); - WriteImageEntry(mat.reflective, mat.name + "-reflective-image"); - WriteImageEntry(mat.transparent, mat.name + "-transparent-image"); - WriteImageEntry(mat.normal, mat.name + "-normal-image"); + for (const Material &mat : materials) { + WriteImageEntry(mat.ambient, mat.id + "-ambient-image"); + WriteImageEntry(mat.diffuse, mat.id + "-diffuse-image"); + WriteImageEntry(mat.specular, mat.id + "-specular-image"); + WriteImageEntry(mat.emissive, mat.id + "-emission-image"); + WriteImageEntry(mat.reflective, mat.id + "-reflective-image"); + WriteImageEntry(mat.transparent, mat.id + "-transparent-image"); + WriteImageEntry(mat.normal, mat.id + "-normal-image"); } PopTag(); mOutput << startstr << "" << endstr; @@ -773,40 +759,39 @@ void ColladaExporter::WriteMaterials() { if (!materials.empty()) { mOutput << startstr << "" << endstr; PushTag(); - for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { - const Material &mat = *it; + for (const Material &mat : materials) { // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); // write sampler- and surface params for the texture entries - WriteTextureParamEntry(mat.emissive, "emission", mat.name); - WriteTextureParamEntry(mat.ambient, "ambient", mat.name); - WriteTextureParamEntry(mat.diffuse, "diffuse", mat.name); - WriteTextureParamEntry(mat.specular, "specular", mat.name); - WriteTextureParamEntry(mat.reflective, "reflective", mat.name); - WriteTextureParamEntry(mat.transparent, "transparent", mat.name); - WriteTextureParamEntry(mat.normal, "normal", mat.name); + WriteTextureParamEntry(mat.emissive, "emission", mat.id); + WriteTextureParamEntry(mat.ambient, "ambient", mat.id); + WriteTextureParamEntry(mat.diffuse, "diffuse", mat.id); + WriteTextureParamEntry(mat.specular, "specular", mat.id); + WriteTextureParamEntry(mat.reflective, "reflective", mat.id); + WriteTextureParamEntry(mat.transparent, "transparent", mat.id); + WriteTextureParamEntry(mat.normal, "normal", mat.id); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "<" << mat.shading_model << ">" << endstr; PushTag(); - WriteTextureColorEntry(mat.emissive, "emission", mat.name + "-emission-sampler"); - WriteTextureColorEntry(mat.ambient, "ambient", mat.name + "-ambient-sampler"); - WriteTextureColorEntry(mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); - WriteTextureColorEntry(mat.specular, "specular", mat.name + "-specular-sampler"); + WriteTextureColorEntry(mat.emissive, "emission", mat.id + "-emission-sampler"); + WriteTextureColorEntry(mat.ambient, "ambient", mat.id + "-ambient-sampler"); + WriteTextureColorEntry(mat.diffuse, "diffuse", mat.id + "-diffuse-sampler"); + WriteTextureColorEntry(mat.specular, "specular", mat.id + "-specular-sampler"); WriteFloatEntry(mat.shininess, "shininess"); - WriteTextureColorEntry(mat.reflective, "reflective", mat.name + "-reflective-sampler"); - WriteTextureColorEntry(mat.transparent, "transparent", mat.name + "-transparent-sampler"); + WriteTextureColorEntry(mat.reflective, "reflective", mat.id + "-reflective-sampler"); + WriteTextureColorEntry(mat.transparent, "transparent", mat.id + "-transparent-sampler"); WriteFloatEntry(mat.transparency, "transparency"); WriteFloatEntry(mat.index_refraction, "index_of_refraction"); if (!mat.normal.texture.empty()) { - WriteTextureColorEntry(mat.normal, "bump", mat.name + "-normal-sampler"); + WriteTextureColorEntry(mat.normal, "bump", mat.id + "-normal-sampler"); } PopTag(); @@ -826,9 +811,9 @@ void ColladaExporter::WriteMaterials() { PushTag(); for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { const Material &mat = *it; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; } @@ -855,14 +840,12 @@ void ColladaExporter::WriteControllerLibrary() { // Writes a skin controller of the given mesh void ColladaExporter::WriteController(size_t pIndex) { const aiMesh *mesh = mScene->mMeshes[pIndex]; - const std::string idstr = GetMeshUniqueId(pIndex); - const std::string namestr = GetMeshName(pIndex); - - if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) + // Is there a skin controller? + if (mesh->mNumBones == 0 || mesh->mNumFaces == 0 || mesh->mNumVertices == 0) return; - if (mesh->mNumBones == 0) - return; + const std::string idstr = GetObjectUniqueId(AiObjectType::Mesh, pIndex); + const std::string namestr = GetObjectName(AiObjectType::Mesh, pIndex); mOutput << startstr << "" << endstr; @@ -891,7 +874,7 @@ void ColladaExporter::WriteController(size_t pIndex) { mOutput << startstr << "mNumBones << "\">"; for (size_t i = 0; i < mesh->mNumBones; ++i) - mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; + mOutput << GetBoneUniqueId(mesh->mBones[i]) << " "; mOutput << "" << endstr; @@ -1020,8 +1003,8 @@ void ColladaExporter::WriteGeometryLibrary() { // Writes the given mesh void ColladaExporter::WriteGeometry(size_t pIndex) { const aiMesh *mesh = mScene->mMeshes[pIndex]; - const std::string geometryName = GetMeshName(pIndex); - const std::string geometryId = GetMeshUniqueId(pIndex); + const std::string geometryId = GetObjectUniqueId(AiObjectType::Mesh, pIndex); + const std::string geometryName = GetObjectName(AiObjectType::Mesh, pIndex); if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) return; @@ -1250,8 +1233,8 @@ void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataTyp // ------------------------------------------------------------------------------------------------ // Writes the scene library void ColladaExporter::WriteSceneLibrary() { - const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str()); - const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str()); + const std::string sceneName = GetNodeUniqueId(mScene->mRootNode); + const std::string sceneId = GetNodeName(mScene->mRootNode); mOutput << startstr << "" << endstr; PushTag(); @@ -1260,7 +1243,7 @@ void ColladaExporter::WriteSceneLibrary() { // start recursive write at the root node for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a) - WriteNode(mScene, mScene->mRootNode->mChildren[a]); + WriteNode(mScene->mRootNode->mChildren[a]); PopTag(); mOutput << startstr << "" << endstr; @@ -1274,20 +1257,10 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0) return; - const std::string animation_name_escaped = XMLEscape(anim->mName.C_Str()); - std::string idstr = anim->mName.C_Str(); - std::string ending = std::string("AnimId") + to_string(pIndex); - if (idstr.length() >= ending.length()) { - if (0 != idstr.compare(idstr.length() - ending.length(), ending.length(), ending)) { - idstr = idstr + ending; - } - } else { - idstr = idstr + ending; - } + const std::string animationNameEscaped = GetObjectName(AiObjectType::Animation, pIndex); + const std::string idstrEscaped = GetObjectUniqueId(AiObjectType::Animation, pIndex); - const std::string idstrEscaped = XMLIDEncode(idstr); - - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); std::string cur_node_idstr; @@ -1503,31 +1476,25 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) { // ------------------------------------------------------------------------------------------------ // Recursively writes the given node -void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { - // the node must have a name - if (pNode->mName.length == 0) { - std::stringstream ss; - ss << "Node_" << pNode; - pNode->mName.Set(ss.str()); - } - +void ColladaExporter::WriteNode(const aiNode *pNode) { // If the node is associated with a bone, it is a joint node (JOINT) // otherwise it is a normal node (NODE) + // Assimp-specific: nodes with no name cannot be associated with bones const char *node_type; bool is_joint, is_skeleton_root = false; - if (nullptr == findBone(pScene, pNode->mName.C_Str())) { + if (pNode->mName.length == 0 && nullptr == findBone(mScene, pNode->mName.C_Str())) { node_type = "NODE"; is_joint = false; } else { node_type = "JOINT"; is_joint = true; - if (!pNode->mParent || nullptr == findBone(pScene, pNode->mParent->mName.C_Str())) { + if (!pNode->mParent || nullptr == findBone(mScene, pNode->mParent->mName.C_Str())) { is_skeleton_root = true; } } - const std::string node_id = XMLIDEncode(pNode->mName.data); - const std::string node_name = XMLEscape(pNode->mName.data); + const std::string node_id = GetNodeUniqueId(pNode); + const std::string node_name = GetNodeName(pNode); mOutput << startstr << "mNumFaces == 0 || mesh->mNumVertices == 0) continue; - const std::string meshId = GetMeshUniqueId(pNode->mMeshes[a]); + const std::string meshId = GetObjectUniqueId(AiObjectType::Mesh, pNode->mMeshes[a]); if (mesh->mNumBones == 0) { mOutput << startstr << "" << endstr; @@ -1608,9 +1575,9 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. // use the first bone to find skeleton root - const aiNode *skeletonRootBoneNode = findSkeletonRootNode(pScene, mesh); + const aiNode *skeletonRootBoneNode = findSkeletonRootNode(mScene, mesh); if (skeletonRootBoneNode) { - mFoundSkeletonRootNodeID = XMLIDEncode(skeletonRootBoneNode->mName.C_Str()); + mFoundSkeletonRootNodeID = GetNodeUniqueId(skeletonRootBoneNode); } mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; } @@ -1618,7 +1585,7 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; + mOutput << startstr << "mMaterialIndex) << "\">" << endstr; PushTag(); for (size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa) { if (mesh->HasTextureCoords(static_cast(aa))) @@ -1643,64 +1610,154 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) { // recurse into subnodes for (size_t a = 0; a < pNode->mNumChildren; ++a) - WriteNode(pScene, pNode->mChildren[a]); + WriteNode(pNode->mChildren[a]); PopTag(); mOutput << startstr << "" << endstr; } -/// Get or Create a unique mesh ID string for the given mesh index -std::string Assimp::ColladaExporter::GetMeshUniqueId(size_t pIndex) { - auto meshId = mMeshIdMap.find(pIndex); - if (meshId != mMeshIdMap.cend()) - return meshId->second; - - // Not seen this mesh before, create and add - return AddMeshIndexToMaps(pIndex, true); +inline bool IsUniqueId(const std::unordered_set &idSet, const std::string &idStr) { + return (idSet.find(idStr) == idSet.end()); } -std::string Assimp::ColladaExporter::GetMeshName(size_t pIndex) { - auto meshName = mMeshNameMap.find(pIndex); - if (meshName != mMeshNameMap.cend()) - return meshName->second; - - // Not seen this mesh before, create and add - return AddMeshIndexToMaps(pIndex, false); -} - -inline bool ValueIsUnique(const std::map &map, const std::string &value) { - for (const auto &map_val : map) { - if (value == map_val.second) - return false; - } - return true; -} - -// Add the mesh index to both Id and Name maps and return either Id or Name -std::string Assimp::ColladaExporter::AddMeshIndexToMaps(size_t pIndex, bool meshId) { - const aiMesh *mesh = mScene->mMeshes[pIndex]; - std::string idStr = mesh->mName.length == 0 ? std::string("meshId_") + to_string(pIndex) : XMLIDEncode(mesh->mName.C_Str()); - // Ensure is unique. Relatively slow but will only happen once per mesh - if (!ValueIsUnique(mMeshIdMap, idStr)) { +inline void MakeUniqueId(const std::unordered_set &idSet, std::string &idStr) { + if (!IsUniqueId(idSet, idStr)) { // Select a number to append size_t postfix = 1; idStr.append("_"); - while (!ValueIsUnique(mMeshIdMap, idStr + to_string(postfix))) { + while (!IsUniqueId(idSet, idStr + to_string(postfix))) { ++postfix; } - idStr = idStr + to_string(postfix); + idStr.append(to_string(postfix)); } - // Add to map - mMeshIdMap.insert(std::make_pair(pIndex, idStr)); +} - // Add name to map - const std::string nameStr = mesh->mName.length == 0 ? idStr : XMLEscape(mesh->mName.C_Str()); - mMeshNameMap.insert(std::make_pair(pIndex, nameStr)); +void Assimp::ColladaExporter::CreateNodeIds(const aiNode *node) { + GetNodeUniqueId(node); + for (size_t a = 0; a < node->mNumChildren; ++a) + CreateNodeIds(node->mChildren[a]); +} - if (meshId) - return idStr; +std::string Assimp::ColladaExporter::GetNodeUniqueId(const aiNode *node) { + // Use the pointer as the key. This is safe because the scene is immutable. + auto idIt = mNodeIdMap.find(node); + if (idIt != mNodeIdMap.cend()) + return idIt->second; + + // Prefer the requested Collada Id if extant + std::string idStr; + aiString origId; + if (node->mMetaData && node->mMetaData->Get(AI_METADATA_COLLADA_ID, origId)) { + idStr = origId.C_Str(); + } else { + idStr = node->mName.C_Str(); + } + // Make sure the requested id is valid + if (idStr.empty()) + idStr = "node"; else - return nameStr; + idStr = XMLIDEncode(idStr); + + // Ensure it's unique + MakeUniqueId(mUniqueIds, idStr); + mUniqueIds.insert(idStr); + mNodeIdMap.insert(std::make_pair(node, idStr)); + return idStr; +} + +std::string Assimp::ColladaExporter::GetNodeName(const aiNode *node) { + + return XMLEscape(node->mName.C_Str()); +} + +std::string Assimp::ColladaExporter::GetBoneUniqueId(const aiBone *bone) { + // Use the pointer as the key. This is safe because the scene is immutable. + auto idIt = mNodeIdMap.find(bone); + if (idIt != mNodeIdMap.cend()) + return idIt->second; + + // New, create an id + std::string idStr(bone->mName.C_Str()); + + // Make sure the requested id is valid + if (idStr.empty()) + idStr = "bone"; + else + idStr = XMLIDEncode(idStr); + + // Ensure it's unique + MakeUniqueId(mUniqueIds, idStr); + mUniqueIds.insert(idStr); + mNodeIdMap.insert(std::make_pair(bone, idStr)); + return idStr; +} + +std::string Assimp::ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) { + auto idIt = GetObjectIdMap(type).find(pIndex); + if (idIt != GetObjectIdMap(type).cend()) + return idIt->second; + + // Not seen this object before, create and add + NameIdPair result = AddObjectIndexToMaps(type, pIndex); + return result.second; +} + +std::string Assimp::ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) { + auto meshName = GetObjectNameMap(type).find(pIndex); + if (meshName != GetObjectNameMap(type).cend()) + return meshName->second; + + // Not seen this object before, create and add + NameIdPair result = AddObjectIndexToMaps(type, pIndex); + return result.first; +} + +// Determine unique id and add the name and id to the maps +// @param type object type +// @param index object index +// @param name in/out. Caller to set the original name if known. +// @param idStr in/out. Caller to set the preferred id if known. +Assimp::ColladaExporter::NameIdPair Assimp::ColladaExporter::AddObjectIndexToMaps(AiObjectType type, size_t index) { + + std::string idStr; + std::string name; + + // Get the name + switch (type) { + case AiObjectType::Mesh: name = mScene->mMeshes[index]->mName.C_Str(); break; + case AiObjectType::Material: name = mScene->mMaterials[index]->GetName().C_Str(); break; + case AiObjectType::Animation: name = mScene->mAnimations[index]->mName.C_Str(); break; + case AiObjectType::Light: name = mScene->mLights[index]->mName.C_Str(); break; + case AiObjectType::Camera: name = mScene->mCameras[index]->mName.C_Str(); break; + case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type"); + } + + if (name.empty()) { + // Default ids if empty name + switch (type) { + case AiObjectType::Mesh: idStr = std::string("meshId_"); break; + case AiObjectType::Material: idStr = std::string("materialId_"); break; // This one should never happen + case AiObjectType::Animation: idStr = std::string("animationId_"); break; + case AiObjectType::Light: idStr = std::string("lightId_"); break; + case AiObjectType::Camera: idStr = std::string("cameraId_"); break; + case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type"); + } + idStr.append(to_string(index)); + } else { + idStr = XMLIDEncode(name); + } + + if (!name.empty()) + name = XMLEscape(name); + + MakeUniqueId(mUniqueIds, idStr); + + // Add to maps + mUniqueIds.insert(idStr); + GetObjectIdMap(type).insert(std::make_pair(index, idStr)); + GetObjectNameMap(type).insert(std::make_pair(index, idStr)); + + return std::make_pair(name, idStr); } #endif diff --git a/code/Collada/ColladaExporter.h b/code/Collada/ColladaExporter.h index d75d2d355..c6801395b 100644 --- a/code/Collada/ColladaExporter.h +++ b/code/Collada/ColladaExporter.h @@ -46,17 +46,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COLLADAEXPORTER_H_INC #define AI_COLLADAEXPORTER_H_INC +#include #include #include #include #include #include + +#include #include #include +#include #include -#include - struct aiScene; struct aiNode; @@ -135,7 +137,7 @@ protected: std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call. /// Recursively writes the given node - void WriteNode(const aiScene *scene, aiNode *pNode); + void WriteNode(const aiNode *pNode); /// Enters a new xml element, which increases the indentation void PushTag() { startstr.append(" "); } @@ -145,14 +147,40 @@ protected: startstr.erase(startstr.length() - 2); } - /// Get or Create a unique mesh ID string for the given mesh index - std::string GetMeshUniqueId(size_t pIndex); - std::string GetMeshName(size_t pIndex); + void CreateNodeIds(const aiNode *node); + + /// Get or Create a unique Node ID string for the given Node + std::string GetNodeUniqueId(const aiNode *node); + std::string GetNodeName(const aiNode *node); + + std::string GetBoneUniqueId(const aiBone *bone); + + enum class AiObjectType { + Mesh, + Material, + Animation, + Light, + Camera, + Count, + }; + /// Get or Create a unique ID string for the given scene object index + std::string GetObjectUniqueId(AiObjectType type, size_t pIndex); + /// Get or Create a name string for the given scene object index + std::string GetObjectName(AiObjectType type, size_t pIndex); + + typedef std::map IndexIdMap; + typedef std::pair NameIdPair; + NameIdPair AddObjectIndexToMaps(AiObjectType type, size_t pIndex); + + // Helpers + inline IndexIdMap &GetObjectIdMap(AiObjectType type) { return mObjectIdMap[static_cast(type)]; } + inline IndexIdMap &GetObjectNameMap(AiObjectType type) { return mObjectNameMap[static_cast(type)]; } private: - std::string AddMeshIndexToMaps(size_t pIndex, bool meshId); - mutable std::map mMeshIdMap; // Cache of encoded unique IDs - mutable std::map mMeshNameMap; // Cache of encoded mesh names + std::unordered_set mUniqueIds; // Cache of used unique ids + std::map mNodeIdMap; // Cache of encoded node and bone ids + std::array(AiObjectType::Count)> mObjectIdMap; // Cache of encoded unique IDs + std::array(AiObjectType::Count)> mObjectNameMap; // Cache of encoded names public: /// Stringstream to write all output into @@ -198,6 +226,7 @@ public: // summarize a material in an convenient way. struct Material { + std::string id; std::string name; std::string shading_model; Surface ambient, diffuse, specular, emissive, reflective, transparent, normal; @@ -206,20 +235,18 @@ public: Material() {} }; - std::vector materials; - std::map textures; public: /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// Reads a single surface entry from the given material keys - void ReadMaterialSurface(Surface &poSurface, const aiMaterial *pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex); + bool ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex); /// Writes an image entry for the given surface - void WriteImageEntry(const Surface &pSurface, const std::string &pNameAdd); + void WriteImageEntry(const Surface &pSurface, const std::string &imageId); /// Writes the two parameters necessary for referencing a texture in an effect entry - void WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pMatName); + void WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId); /// Writes a color-or-texture entry into an effect definition - void WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pImageName); + void WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId); /// Writes a scalar property void WriteFloatEntry(const Property &pProperty, const std::string &pTypeName); }; diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index 5c2f801db..5b0c9f880 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -82,20 +82,75 @@ public: return true; } + typedef std::pair IdNameString; + typedef std::map IdNameMap; + + template + static inline IdNameString GetItemIdName(const T *item, size_t index) { + std::ostringstream stream; + stream << typeid(T).name() << "@" << index; + return std::make_pair(std::string(item->mName.C_Str()), stream.str()); + } + + // Specialisations + static inline IdNameString GetItemIdName(aiMaterial *item, size_t index) { + std::ostringstream stream; + stream << typeid(aiMaterial).name() << "@" << index; + return std::make_pair(std::string(item->GetName().C_Str()), stream.str()); + } + + static inline IdNameString GetItemIdName(aiTexture *item, size_t index) { + std::ostringstream stream; + stream << typeid(aiTexture).name() << "@" << index; + return std::make_pair(std::string(item->mFilename.C_Str()), stream.str()); + } + + static inline void ReportDuplicate(IdNameMap &itemIdMap, const IdNameString &namePair, const char *typeNameStr) { + const auto result = itemIdMap.insert(namePair); + EXPECT_TRUE(result.second) << "Duplicate '" << typeNameStr << "' name: '" << namePair.first << "'. " << namePair.second << " == " << result.first->second; + } + + template + static inline void CheckUniqueIds(IdNameMap &itemIdMap, unsigned int itemCount, T **itemArray) { + for (size_t idx = 0; idx < itemCount; ++idx) { + IdNameString namePair = GetItemIdName(itemArray[idx], idx); + ReportDuplicate(itemIdMap, namePair, typeid(T).name()); + } + } + + static inline void CheckUniqueIds(IdNameMap &itemIdMap, const aiNode *parent, size_t index) { + IdNameString namePair = GetItemIdName(parent, index); + ReportDuplicate(itemIdMap, namePair, typeid(aiNode).name()); + for (size_t idx = 0; idx < parent->mNumChildren; ++idx) { + CheckUniqueIds(itemIdMap, parent->mChildren[idx], idx); + } + } + + static inline void SetAllNodeNames(const aiString &newName, aiNode *node) { + node->mName = newName; + for (size_t idx = 0; idx < node->mNumChildren; ++idx) { + SetAllNodeNames(newName, node->mChildren[idx]); + } + } + void ImportAndCheckIds(const char *file, size_t meshCount) { - // Import the Collada using the 'default' where mesh names are the ids + // Import the Collada using the 'default' where aiMesh names are the Collada ids Assimp::Importer importer; const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); ASSERT_TRUE(scene != nullptr) << "Fatal: could not re-import " << file; EXPECT_EQ(meshCount, scene->mNumMeshes) << "in " << file; - // Check the mesh ids are unique - std::map meshNameMap; - for (size_t idx = 0; idx < scene->mNumMeshes; ++idx) { - std::string meshName(scene->mMeshes[idx]->mName.C_Str()); - const auto result = meshNameMap.insert(std::make_pair(meshName, idx)); - EXPECT_TRUE(result.second) << "Duplicate name: " << meshName << " index " << result.first->second; - } + // Check the ids are unique + IdNameMap itemIdMap; + // Recurse the Nodes + CheckUniqueIds(itemIdMap, scene->mRootNode, 0); + // Check the lists + CheckUniqueIds(itemIdMap, scene->mNumMeshes, scene->mMeshes); + CheckUniqueIds(itemIdMap, scene->mNumAnimations, scene->mAnimations); + CheckUniqueIds(itemIdMap, scene->mNumMaterials, scene->mMaterials); + CheckUniqueIds(itemIdMap, scene->mNumTextures, scene->mTextures); + CheckUniqueIds(itemIdMap, scene->mNumLights, scene->mLights); + CheckUniqueIds(itemIdMap, scene->mNumCameras, scene->mCameras); } }; @@ -115,19 +170,49 @@ TEST_F(utColladaImportExport, exporterUniqueIdsTest) { ASSERT_TRUE(scene != nullptr) << "Fatal: could not import teapots.DAE!"; ASSERT_EQ(3u, scene->mNumMeshes) << "Fatal: teapots.DAE initial load failed"; - // Clear the mesh names + // Clear all the names for (size_t idx = 0; idx < scene->mNumMeshes; ++idx) { scene->mMeshes[idx]->mName.Clear(); } + for (size_t idx = 0; idx < scene->mNumMaterials; ++idx) { + scene->mMaterials[idx]->RemoveProperty(AI_MATKEY_NAME); + } + for (size_t idx = 0; idx < scene->mNumAnimations; ++idx) { + scene->mAnimations[idx]->mName.Clear(); + } + // Can't clear texture names + for (size_t idx = 0; idx < scene->mNumLights; ++idx) { + scene->mLights[idx]->mName.Clear(); + } + for (size_t idx = 0; idx < scene->mNumCameras; ++idx) { + scene->mCameras[idx]->mName.Clear(); + } + + SetAllNodeNames(aiString(), scene->mRootNode); + ASSERT_EQ(AI_SUCCESS, exporter.Export(scene, "collada", outFileEmpty)) << "Fatal: Could not export un-named meshes file"; ImportAndCheckIds(outFileEmpty, 3); - // Force the meshes to have the same non-empty name - aiString testName("test_mesh"); + // Force everything to have the same non-empty name + aiString testName("test_name"); for (size_t idx = 0; idx < scene->mNumMeshes; ++idx) { scene->mMeshes[idx]->mName = testName; } + for (size_t idx = 0; idx < scene->mNumMaterials; ++idx) { + scene->mMaterials[idx]->AddProperty(&testName, AI_MATKEY_NAME); + } + for (size_t idx = 0; idx < scene->mNumAnimations; ++idx) { + scene->mAnimations[idx]->mName = testName; + } + // Can't clear texture names + for (size_t idx = 0; idx < scene->mNumLights; ++idx) { + scene->mLights[idx]->mName = testName; + } + for (size_t idx = 0; idx < scene->mNumCameras; ++idx) { + scene->mCameras[idx]->mName = testName; + } + ASSERT_EQ(AI_SUCCESS, exporter.Export(scene, "collada", outFileNamed)) << "Fatal: Could not export named meshes file"; ImportAndCheckIds(outFileNamed, 3); From ee16d2c4c95319a403f9c21ce10141b20e9df2a0 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 1 May 2020 11:13:38 +0100 Subject: [PATCH 052/119] Fix camera, light and bone unique ids Bones don't have a unit test yet --- code/Collada/ColladaExporter.cpp | 106 +++++++++++++++---------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index b91e118ec..a9137b50b 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -397,7 +397,7 @@ void ColladaExporter::WriteCamera(size_t pIndex) { const std::string cameraId = GetObjectUniqueId(AiObjectType::Camera, pIndex); const std::string cameraName = GetObjectName(AiObjectType::Camera, pIndex); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); @@ -450,7 +450,7 @@ void ColladaExporter::WriteLight(size_t pIndex) { const std::string lightId = GetObjectUniqueId(AiObjectType::Light, pIndex); const std::string lightName = GetObjectName(AiObjectType::Light, pIndex); - mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -874,7 +874,7 @@ void ColladaExporter::WriteController(size_t pIndex) { mOutput << startstr << "mNumBones << "\">"; for (size_t i = 0; i < mesh->mNumBones; ++i) - mOutput << GetBoneUniqueId(mesh->mBones[i]) << " "; + mOutput << GetBoneUniqueId(mesh->mBones[i]) << ' '; mOutput << "" << endstr; @@ -1410,12 +1410,12 @@ void ColladaExporter::WriteAnimationsLibrary() { } // ------------------------------------------------------------------------------------------------ // Helper to find a bone by name in the scene -aiBone *findBone(const aiScene *scene, const char *name) { +aiBone *findBone(const aiScene *scene, const aiString &name) { for (size_t m = 0; m < scene->mNumMeshes; m++) { aiMesh *mesh = scene->mMeshes[m]; for (size_t b = 0; b < mesh->mNumBones; b++) { aiBone *bone = mesh->mBones[b]; - if (0 == strcmp(name, bone->mName.C_Str())) { + if (name == bone->mName) { return bone; } } @@ -1424,6 +1424,7 @@ aiBone *findBone(const aiScene *scene, const char *name) { } // ------------------------------------------------------------------------------------------------ +// Helper to find the node associated with a bone in the scene const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) { if (aNode && bone && aNode->mName == bone->mName) { return aNode; @@ -1432,15 +1433,17 @@ const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) { if (aNode && bone) { for (unsigned int i = 0; i < aNode->mNumChildren; ++i) { aiNode *aChild = aNode->mChildren[i]; - const aiNode *foundFromChild = 0; + const aiNode *foundFromChild = nullptr; if (aChild) { foundFromChild = findBoneNode(aChild, bone); - if (foundFromChild) return foundFromChild; + if (foundFromChild) { + return foundFromChild; + } } } } - return NULL; + return nullptr; } const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) { @@ -1451,7 +1454,7 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) { const aiNode *node = findBoneNode(scene->mRootNode, bone); if (node) { - while (node->mParent && findBone(scene, node->mParent->mName.C_Str()) != 0) { + while (node->mParent && findBone(scene, node->mParent->mName) != nullptr) { node = node->mParent; } topParentBoneNodes.insert(node); @@ -1482,13 +1485,13 @@ void ColladaExporter::WriteNode(const aiNode *pNode) { // Assimp-specific: nodes with no name cannot be associated with bones const char *node_type; bool is_joint, is_skeleton_root = false; - if (pNode->mName.length == 0 && nullptr == findBone(mScene, pNode->mName.C_Str())) { + if (pNode->mName.length == 0 || nullptr == findBone(mScene, pNode->mName)) { node_type = "NODE"; is_joint = false; } else { node_type = "JOINT"; is_joint = true; - if (!pNode->mParent || nullptr == findBone(mScene, pNode->mParent->mName.C_Str())) { + if (!pNode->mParent || nullptr == findBone(mScene, pNode->mParent->mName)) { is_skeleton_root = true; } } @@ -1542,14 +1545,14 @@ void ColladaExporter::WriteNode(const aiNode *pNode) { //check if it is a camera node for (size_t i = 0; i < mScene->mNumCameras; i++) { if (mScene->mCameras[i]->mName == pNode->mName) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; break; } } //check if it is a light node for (size_t i = 0; i < mScene->mNumLights; i++) { if (mScene->mLights[i]->mName == pNode->mName) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; break; } } @@ -1620,16 +1623,17 @@ inline bool IsUniqueId(const std::unordered_set &idSet, const std:: return (idSet.find(idStr) == idSet.end()); } -inline void MakeUniqueId(const std::unordered_set &idSet, std::string &idStr) { - if (!IsUniqueId(idSet, idStr)) { +inline std::string MakeUniqueId(const std::unordered_set &idSet, const std::string &idPrefix, const std::string &postfix) { + std::string result(idPrefix + postfix); + if (!IsUniqueId(idSet, result)) { // Select a number to append - size_t postfix = 1; - idStr.append("_"); - while (!IsUniqueId(idSet, idStr + to_string(postfix))) { - ++postfix; - } - idStr.append(to_string(postfix)); + size_t idnum = 1; + do { + result = idPrefix + '_' + to_string(idnum) + postfix; + ++idnum; + } while (!IsUniqueId(idSet, result)); } + return result; } void Assimp::ColladaExporter::CreateNodeIds(const aiNode *node) { @@ -1659,7 +1663,7 @@ std::string Assimp::ColladaExporter::GetNodeUniqueId(const aiNode *node) { idStr = XMLIDEncode(idStr); // Ensure it's unique - MakeUniqueId(mUniqueIds, idStr); + idStr = MakeUniqueId(mUniqueIds, idStr, std::string()); mUniqueIds.insert(idStr); mNodeIdMap.insert(std::make_pair(node, idStr)); return idStr; @@ -1671,25 +1675,12 @@ std::string Assimp::ColladaExporter::GetNodeName(const aiNode *node) { } std::string Assimp::ColladaExporter::GetBoneUniqueId(const aiBone *bone) { - // Use the pointer as the key. This is safe because the scene is immutable. - auto idIt = mNodeIdMap.find(bone); - if (idIt != mNodeIdMap.cend()) - return idIt->second; + // Find the Node that is this Bone + const aiNode *boneNode = findBoneNode(mScene->mRootNode, bone); + if (boneNode == nullptr) + return std::string(); - // New, create an id - std::string idStr(bone->mName.C_Str()); - - // Make sure the requested id is valid - if (idStr.empty()) - idStr = "bone"; - else - idStr = XMLIDEncode(idStr); - - // Ensure it's unique - MakeUniqueId(mUniqueIds, idStr); - mUniqueIds.insert(idStr); - mNodeIdMap.insert(std::make_pair(bone, idStr)); - return idStr; + return GetNodeUniqueId(boneNode); } std::string Assimp::ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) { @@ -1703,9 +1694,9 @@ std::string Assimp::ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t } std::string Assimp::ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) { - auto meshName = GetObjectNameMap(type).find(pIndex); - if (meshName != GetObjectNameMap(type).cend()) - return meshName->second; + auto objectName = GetObjectNameMap(type).find(pIndex); + if (objectName != GetObjectNameMap(type).cend()) + return objectName->second; // Not seen this object before, create and add NameIdPair result = AddObjectIndexToMaps(type, pIndex); @@ -1719,27 +1710,34 @@ std::string Assimp::ColladaExporter::GetObjectName(AiObjectType type, size_t pIn // @param idStr in/out. Caller to set the preferred id if known. Assimp::ColladaExporter::NameIdPair Assimp::ColladaExporter::AddObjectIndexToMaps(AiObjectType type, size_t index) { - std::string idStr; std::string name; + std::string idStr; + std::string idPostfix; - // Get the name + // Get the name and id postfix switch (type) { case AiObjectType::Mesh: name = mScene->mMeshes[index]->mName.C_Str(); break; case AiObjectType::Material: name = mScene->mMaterials[index]->GetName().C_Str(); break; case AiObjectType::Animation: name = mScene->mAnimations[index]->mName.C_Str(); break; - case AiObjectType::Light: name = mScene->mLights[index]->mName.C_Str(); break; - case AiObjectType::Camera: name = mScene->mCameras[index]->mName.C_Str(); break; + case AiObjectType::Light: + name = mScene->mLights[index]->mName.C_Str(); + idPostfix = "-light"; + break; + case AiObjectType::Camera: + name = mScene->mCameras[index]->mName.C_Str(); + idPostfix = "-camera"; + break; case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type"); } if (name.empty()) { // Default ids if empty name switch (type) { - case AiObjectType::Mesh: idStr = std::string("meshId_"); break; - case AiObjectType::Material: idStr = std::string("materialId_"); break; // This one should never happen - case AiObjectType::Animation: idStr = std::string("animationId_"); break; - case AiObjectType::Light: idStr = std::string("lightId_"); break; - case AiObjectType::Camera: idStr = std::string("cameraId_"); break; + case AiObjectType::Mesh: idStr = std::string("mesh_"); break; + case AiObjectType::Material: idStr = std::string("material_"); break; // This one should never happen + case AiObjectType::Animation: idStr = std::string("animation_"); break; + case AiObjectType::Light: idStr = std::string("light_"); break; + case AiObjectType::Camera: idStr = std::string("camera_"); break; case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type"); } idStr.append(to_string(index)); @@ -1750,12 +1748,12 @@ Assimp::ColladaExporter::NameIdPair Assimp::ColladaExporter::AddObjectIndexToMap if (!name.empty()) name = XMLEscape(name); - MakeUniqueId(mUniqueIds, idStr); + idStr = MakeUniqueId(mUniqueIds, idStr, idPostfix); // Add to maps mUniqueIds.insert(idStr); GetObjectIdMap(type).insert(std::make_pair(index, idStr)); - GetObjectNameMap(type).insert(std::make_pair(index, idStr)); + GetObjectNameMap(type).insert(std::make_pair(index, name)); return std::make_pair(name, idStr); } From e6c4175d8dff75d0a2a62ce15c4b4299130b40f8 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 1 May 2020 11:49:15 +0100 Subject: [PATCH 053/119] Rename Collada export tests Use existing naming convention. Brings all Collada tests together in Test Explorers --- test/CMakeLists.txt | 3 +- ...adaExportLight.cpp => utColladaExport.cpp} | 51 +++++++- test/unit/utColladaExportCamera.cpp | 115 ------------------ 3 files changed, 50 insertions(+), 119 deletions(-) rename test/unit/{utColladaExportLight.cpp => utColladaExport.cpp} (78%) delete mode 100644 test/unit/utColladaExportCamera.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bf6694845..a5f8086e9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -124,8 +124,7 @@ SET( IMPORTERS unit/utBlendImportMaterials.cpp unit/utBlenderWork.cpp unit/utBVHImportExport.cpp - unit/utColladaExportCamera.cpp - unit/utColladaExportLight.cpp + unit/utColladaExport.cpp unit/utColladaImportExport.cpp unit/utCSMImportExport.cpp unit/utB3DImportExport.cpp diff --git a/test/unit/utColladaExportLight.cpp b/test/unit/utColladaExport.cpp similarity index 78% rename from test/unit/utColladaExportLight.cpp rename to test/unit/utColladaExport.cpp index 0327b296e..efb2d7f17 100644 --- a/test/unit/utColladaExportLight.cpp +++ b/test/unit/utColladaExport.cpp @@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT -class ColladaExportLight : public ::testing::Test { +class utColladaExport : public ::testing::Test { public: void SetUp() override { ex = new Assimp::Exporter(); @@ -58,7 +58,9 @@ public: void TearDown() override { delete ex; + ex = nullptr; delete im; + im = nullptr; } protected: @@ -66,8 +68,53 @@ protected: Assimp::Importer *im; }; +TEST_F(utColladaExport, testExportCamera) { + const char *file = "cameraExp.dae"; + + const aiScene *pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/cameras.dae", aiProcess_ValidateDataStructure); + ASSERT_NE(nullptr, pTest); + ASSERT_TRUE(pTest->HasCameras()); + + EXPECT_EQ(AI_SUCCESS, ex->Export(pTest, "collada", file)); + const unsigned int origNumCams(pTest->mNumCameras); + std::unique_ptr origFOV(new float[origNumCams]); + std::unique_ptr orifClipPlaneNear(new float[origNumCams]); + std::unique_ptr orifClipPlaneFar(new float[origNumCams]); + std::unique_ptr names(new aiString[origNumCams]); + std::unique_ptr pos(new aiVector3D[origNumCams]); + for (size_t i = 0; i < origNumCams; i++) { + const aiCamera *orig = pTest->mCameras[i]; + ASSERT_NE(nullptr, orig); + + origFOV[i] = orig->mHorizontalFOV; + orifClipPlaneNear[i] = orig->mClipPlaneNear; + orifClipPlaneFar[i] = orig->mClipPlaneFar; + names[i] = orig->mName; + pos[i] = orig->mPosition; + } + const aiScene *imported = im->ReadFile(file, aiProcess_ValidateDataStructure); + + ASSERT_NE(nullptr, imported); + + EXPECT_TRUE(imported->HasCameras()); + EXPECT_EQ(origNumCams, imported->mNumCameras); + + for (size_t i = 0; i < imported->mNumCameras; i++) { + const aiCamera *read = imported->mCameras[i]; + + EXPECT_TRUE(names[i] == read->mName); + EXPECT_NEAR(origFOV[i], read->mHorizontalFOV, 0.0001f); + EXPECT_FLOAT_EQ(orifClipPlaneNear[i], read->mClipPlaneNear); + EXPECT_FLOAT_EQ(orifClipPlaneFar[i], read->mClipPlaneFar); + + EXPECT_FLOAT_EQ(pos[i].x, read->mPosition.x); + EXPECT_FLOAT_EQ(pos[i].y, read->mPosition.y); + EXPECT_FLOAT_EQ(pos[i].z, read->mPosition.z); + } +} + // ------------------------------------------------------------------------------------------------ -TEST_F(ColladaExportLight, testExportLight) { +TEST_F(utColladaExport, testExportLight) { const char *file = "lightsExp.dae"; const aiScene *pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/lights.dae", aiProcess_ValidateDataStructure); diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp deleted file mode 100644 index c2c704056..000000000 --- a/test/unit/utColladaExportCamera.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2020, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(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 "UnitTestPCH.h" - -#include -#include -#include -#include -#include - -#ifndef ASSIMP_BUILD_NO_EXPORT - -class ColladaExportCamera : public ::testing::Test { -public: - void SetUp() override { - ex = new Assimp::Exporter(); - im = new Assimp::Importer(); - } - - void TearDown() override { - delete ex; - ex = nullptr; - delete im; - im = nullptr; - } - -protected: - Assimp::Exporter *ex; - Assimp::Importer *im; -}; - -TEST_F(ColladaExportCamera, testExportCamera) { - const char *file = "cameraExp.dae"; - - const aiScene *pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/cameras.dae", aiProcess_ValidateDataStructure); - ASSERT_NE(nullptr, pTest); - ASSERT_TRUE(pTest->HasCameras()); - - EXPECT_EQ(AI_SUCCESS, ex->Export(pTest, "collada", file)); - const unsigned int origNumCams(pTest->mNumCameras); - std::unique_ptr origFOV(new float[origNumCams]); - std::unique_ptr orifClipPlaneNear(new float[origNumCams]); - std::unique_ptr orifClipPlaneFar(new float[origNumCams]); - std::unique_ptr names(new aiString[origNumCams]); - std::unique_ptr pos(new aiVector3D[origNumCams]); - for (size_t i = 0; i < origNumCams; i++) { - const aiCamera *orig = pTest->mCameras[i]; - ASSERT_NE(nullptr, orig); - - origFOV[i] = orig->mHorizontalFOV; - orifClipPlaneNear[i] = orig->mClipPlaneNear; - orifClipPlaneFar[i] = orig->mClipPlaneFar; - names[i] = orig->mName; - pos[i] = orig->mPosition; - } - const aiScene *imported = im->ReadFile(file, aiProcess_ValidateDataStructure); - - ASSERT_NE(nullptr, imported); - - EXPECT_TRUE(imported->HasCameras()); - EXPECT_EQ(origNumCams, imported->mNumCameras); - - for (size_t i = 0; i < imported->mNumCameras; i++) { - const aiCamera *read = imported->mCameras[i]; - - EXPECT_TRUE(names[i] == read->mName); - EXPECT_NEAR(origFOV[i], read->mHorizontalFOV, 0.0001f); - EXPECT_FLOAT_EQ(orifClipPlaneNear[i], read->mClipPlaneNear); - EXPECT_FLOAT_EQ(orifClipPlaneFar[i], read->mClipPlaneFar); - - EXPECT_FLOAT_EQ(pos[i].x, read->mPosition.x); - EXPECT_FLOAT_EQ(pos[i].y, read->mPosition.y); - EXPECT_FLOAT_EQ(pos[i].z, read->mPosition.z); - } -} - -#endif // ASSIMP_BUILD_NO_EXPORT From 5b9f207f1fd6bda7add462c77a5ab458111cb6f0 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 1 May 2020 11:39:43 +0100 Subject: [PATCH 054/119] ColladaExporter cleanup Namespace, NULL and includes --- code/Collada/ColladaExporter.cpp | 39 ++++++++++++++------------------ code/Collada/ColladaExporter.h | 8 +++---- include/assimp/ColladaMetaData.h | 4 ++-- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index a9137b50b..5e4cdda2d 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -44,9 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER #include "ColladaExporter.h" + #include #include #include +#include #include #include #include @@ -57,15 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include - #include -#include #include -#include -#include - -using namespace Assimp; namespace Assimp { @@ -84,7 +79,7 @@ void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *p // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile(pIOSystem->Open(pFile, "wt")); - if (outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); } @@ -92,8 +87,6 @@ void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *p outfile->Write(iDoTheExportThing.mOutput.str().c_str(), static_cast(iDoTheExportThing.mOutput.tellp()), 1); } -} // end of namespace Assimp - // ------------------------------------------------------------------------------------------------ // Encodes a string into a valid XML ID using the xsd:ID schema qualifications. static const std::string XMLIDEncode(const std::string &name) { @@ -207,7 +200,7 @@ void ColladaExporter::WriteHeader() { static const unsigned int date_nb_chars = 20; char date_str[date_nb_chars]; - std::time_t date = std::time(NULL); + std::time_t date = std::time(nullptr); std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date)); aiVector3D scaling; @@ -358,7 +351,7 @@ void ColladaExporter::WriteTextures() { std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint); std::unique_ptr outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb")); - if (outfile == NULL) { + if (outfile == nullptr) { throw DeadlyExportError("could not open output texture file: " + mPath + name); } @@ -571,7 +564,7 @@ bool ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial & if (pSrcMat.GetTextureCount(pTexture) > 0) { aiString texfile; unsigned int uvChannel = 0; - pSrcMat.GetTexture(pTexture, 0, &texfile, NULL, &uvChannel); + pSrcMat.GetTexture(pTexture, 0, &texfile, nullptr, &uvChannel); std::string index_str(texfile.C_Str()); @@ -1420,7 +1413,7 @@ aiBone *findBone(const aiScene *scene, const aiString &name) { } } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1474,7 +1467,7 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) { } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1636,13 +1629,13 @@ inline std::string MakeUniqueId(const std::unordered_set &idSet, co return result; } -void Assimp::ColladaExporter::CreateNodeIds(const aiNode *node) { +void ColladaExporter::CreateNodeIds(const aiNode *node) { GetNodeUniqueId(node); for (size_t a = 0; a < node->mNumChildren; ++a) CreateNodeIds(node->mChildren[a]); } -std::string Assimp::ColladaExporter::GetNodeUniqueId(const aiNode *node) { +std::string ColladaExporter::GetNodeUniqueId(const aiNode *node) { // Use the pointer as the key. This is safe because the scene is immutable. auto idIt = mNodeIdMap.find(node); if (idIt != mNodeIdMap.cend()) @@ -1669,12 +1662,12 @@ std::string Assimp::ColladaExporter::GetNodeUniqueId(const aiNode *node) { return idStr; } -std::string Assimp::ColladaExporter::GetNodeName(const aiNode *node) { +std::string ColladaExporter::GetNodeName(const aiNode *node) { return XMLEscape(node->mName.C_Str()); } -std::string Assimp::ColladaExporter::GetBoneUniqueId(const aiBone *bone) { +std::string ColladaExporter::GetBoneUniqueId(const aiBone *bone) { // Find the Node that is this Bone const aiNode *boneNode = findBoneNode(mScene->mRootNode, bone); if (boneNode == nullptr) @@ -1683,7 +1676,7 @@ std::string Assimp::ColladaExporter::GetBoneUniqueId(const aiBone *bone) { return GetNodeUniqueId(boneNode); } -std::string Assimp::ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) { +std::string ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) { auto idIt = GetObjectIdMap(type).find(pIndex); if (idIt != GetObjectIdMap(type).cend()) return idIt->second; @@ -1693,7 +1686,7 @@ std::string Assimp::ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t return result.second; } -std::string Assimp::ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) { +std::string ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) { auto objectName = GetObjectNameMap(type).find(pIndex); if (objectName != GetObjectNameMap(type).cend()) return objectName->second; @@ -1708,7 +1701,7 @@ std::string Assimp::ColladaExporter::GetObjectName(AiObjectType type, size_t pIn // @param index object index // @param name in/out. Caller to set the original name if known. // @param idStr in/out. Caller to set the preferred id if known. -Assimp::ColladaExporter::NameIdPair Assimp::ColladaExporter::AddObjectIndexToMaps(AiObjectType type, size_t index) { +ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType type, size_t index) { std::string name; std::string idStr; @@ -1758,5 +1751,7 @@ Assimp::ColladaExporter::NameIdPair Assimp::ColladaExporter::AddObjectIndexToMap return std::make_pair(name, idStr); } +} // end of namespace Assimp + #endif #endif diff --git a/code/Collada/ColladaExporter.h b/code/Collada/ColladaExporter.h index c6801395b..bea65bafc 100644 --- a/code/Collada/ColladaExporter.h +++ b/code/Collada/ColladaExporter.h @@ -46,12 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COLLADAEXPORTER_H_INC #define AI_COLLADAEXPORTER_H_INC -#include #include -#include #include -#include -#include #include #include @@ -61,9 +57,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiScene; struct aiNode; +struct aiLight; +struct aiBone; namespace Assimp { +class IOSystem; + /// Helper class to export a given scene to a Collada file. Just for my personal /// comfort when implementing it. class ColladaExporter { diff --git a/include/assimp/ColladaMetaData.h b/include/assimp/ColladaMetaData.h index 4288692c6..82aee78d0 100644 --- a/include/assimp/ColladaMetaData.h +++ b/include/assimp/ColladaMetaData.h @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COLLADAMETADATA_H_INC #define AI_COLLADAMETADATA_H_INC -#define AI_METADATA_COLLADA_ID "COLLADA_ID" -#define AI_METADATA_COLLADA_SID "COLLADA_SID" +#define AI_METADATA_COLLADA_ID "Collada_id" +#define AI_METADATA_COLLADA_SID "Collada_sid" #endif From 1dabb1a0946168332f601bb46bfdfa7743c64d18 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 1 May 2020 14:59:09 +0100 Subject: [PATCH 055/119] Collada: Fix crash with AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES Add unit test for this --- code/Collada/ColladaLoader.cpp | 13 ++++- test/unit/utColladaImportExport.cpp | 76 +++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index c76954fdf..8ca0b130e 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -258,6 +258,15 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO } } +// Add an item of metadata to a node +// Assumes the key is not already in the list +template +inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) { + if (nullptr == node->mMetaData) + node->mMetaData = new aiMetadata(); + node->mMetaData->Add(key, value); +} + // ------------------------------------------------------------------------------------------------ // Recursively constructs a scene node for the given parser node and returns it. aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode) { @@ -269,9 +278,9 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad // if we're not using the unique IDs, hold onto them for reference and export if (useColladaName) { if (!pNode->mID.empty()) - node->mMetaData->Add(AI_METADATA_COLLADA_ID, aiString(pNode->mID)); + AddNodeMetaData(node, AI_METADATA_COLLADA_ID, aiString(pNode->mID)); if (!pNode->mSID.empty()) - node->mMetaData->Add(AI_METADATA_COLLADA_SID, aiString(pNode->mSID)); + AddNodeMetaData(node, AI_METADATA_COLLADA_SID, aiString(pNode->mSID)); } // calculate the transformation matrix for it diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index 5b0c9f880..876f60c54 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include "UnitTestPCH.h" +#include #include #include #include @@ -85,6 +86,18 @@ public: typedef std::pair IdNameString; typedef std::map IdNameMap; + template + static inline IdNameString GetColladaIdName(const T *item, size_t index) { + std::ostringstream stream; + stream << typeid(T).name() << "@" << index; + if (item->mMetaData) { + aiString aiStr; + if (item->mMetaData->Get(AI_METADATA_COLLADA_ID, aiStr)) + return std::make_pair(std::string(aiStr.C_Str()), stream.str()); + } + return std::make_pair(std::string(), stream.str()); + } + template static inline IdNameString GetItemIdName(const T *item, size_t index) { std::ostringstream stream; @@ -121,11 +134,23 @@ public: static inline void CheckUniqueIds(IdNameMap &itemIdMap, const aiNode *parent, size_t index) { IdNameString namePair = GetItemIdName(parent, index); ReportDuplicate(itemIdMap, namePair, typeid(aiNode).name()); + for (size_t idx = 0; idx < parent->mNumChildren; ++idx) { CheckUniqueIds(itemIdMap, parent->mChildren[idx], idx); } } + static inline void CheckNodeIdNames(IdNameMap &nodeIdMap, IdNameMap &nodeNameMap, const aiNode *parent, size_t index) { + IdNameString namePair = GetItemIdName(parent, index); + const auto result = nodeNameMap.insert(namePair); + IdNameString idPair = GetColladaIdName(parent, index); + ReportDuplicate(nodeIdMap, idPair, typeid(aiNode).name()); + + for (size_t idx = 0; idx < parent->mNumChildren; ++idx) { + CheckNodeIdNames(nodeIdMap, nodeNameMap, parent->mChildren[idx], idx); + } + } + static inline void SetAllNodeNames(const aiString &newName, aiNode *node) { node->mName = newName; for (size_t idx = 0; idx < node->mNumChildren; ++idx) { @@ -133,12 +158,12 @@ public: } } - void ImportAndCheckIds(const char *file, size_t meshCount) { - // Import the Collada using the 'default' where aiMesh names are the Collada ids + void ImportAndCheckIds(const char *file, const aiScene *origScene) { + // Import the Collada using the 'default' where aiNode and aiMesh names are the Collada ids Assimp::Importer importer; const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); ASSERT_TRUE(scene != nullptr) << "Fatal: could not re-import " << file; - EXPECT_EQ(meshCount, scene->mNumMeshes) << "in " << file; + EXPECT_EQ(origScene->mNumMeshes, scene->mNumMeshes) << "in " << file; // Check the ids are unique IdNameMap itemIdMap; @@ -146,11 +171,39 @@ public: CheckUniqueIds(itemIdMap, scene->mRootNode, 0); // Check the lists CheckUniqueIds(itemIdMap, scene->mNumMeshes, scene->mMeshes); - CheckUniqueIds(itemIdMap, scene->mNumAnimations, scene->mAnimations); - CheckUniqueIds(itemIdMap, scene->mNumMaterials, scene->mMaterials); - CheckUniqueIds(itemIdMap, scene->mNumTextures, scene->mTextures); - CheckUniqueIds(itemIdMap, scene->mNumLights, scene->mLights); - CheckUniqueIds(itemIdMap, scene->mNumCameras, scene->mCameras); + // The remaining will come in using the name, which may not be unique + // Check we have the right number + EXPECT_EQ(origScene->mNumAnimations, scene->mNumAnimations); + EXPECT_EQ(origScene->mNumMaterials, scene->mNumMaterials); + EXPECT_EQ(origScene->mNumTextures, scene->mNumTextures); + EXPECT_EQ(origScene->mNumLights, scene->mNumLights); + EXPECT_EQ(origScene->mNumCameras, scene->mNumCameras); + } + + void ImportAsNames(const char *file, const aiScene *origScene) { + // Import the Collada but using the user-visible names for aiNode and aiMesh + // Note that this mode may not support bones or animations + Assimp::Importer importer; + importer.SetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 1); + + const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); + ASSERT_TRUE(scene != nullptr) << "Fatal: could not re-import " << file; + EXPECT_EQ(origScene->mNumMeshes, scene->mNumMeshes) << "in " << file; + + // Check the node ids are unique but the node names are not + IdNameMap nodeIdMap; + IdNameMap nodeNameMap; + // Recurse the Nodes + CheckNodeIdNames(nodeIdMap, nodeNameMap, scene->mRootNode, 0); + + // nodeNameMap should have fewer than nodeIdMap + EXPECT_LT(nodeNameMap.size(), nodeIdMap.size()) << "Some nodes should have the same names"; + // Check the counts haven't changed + EXPECT_EQ(origScene->mNumAnimations, scene->mNumAnimations); + EXPECT_EQ(origScene->mNumMaterials, scene->mNumMaterials); + EXPECT_EQ(origScene->mNumTextures, scene->mNumTextures); + EXPECT_EQ(origScene->mNumLights, scene->mNumLights); + EXPECT_EQ(origScene->mNumCameras, scene->mNumCameras); } }; @@ -192,7 +245,7 @@ TEST_F(utColladaImportExport, exporterUniqueIdsTest) { ASSERT_EQ(AI_SUCCESS, exporter.Export(scene, "collada", outFileEmpty)) << "Fatal: Could not export un-named meshes file"; - ImportAndCheckIds(outFileEmpty, 3); + ImportAndCheckIds(outFileEmpty, scene); // Force everything to have the same non-empty name aiString testName("test_name"); @@ -213,9 +266,12 @@ TEST_F(utColladaImportExport, exporterUniqueIdsTest) { scene->mCameras[idx]->mName = testName; } + SetAllNodeNames(testName, scene->mRootNode); + ASSERT_EQ(AI_SUCCESS, exporter.Export(scene, "collada", outFileNamed)) << "Fatal: Could not export named meshes file"; - ImportAndCheckIds(outFileNamed, 3); + ImportAndCheckIds(outFileNamed, scene); + ImportAsNames(outFileNamed, scene); } class utColladaZaeImportExport : public AbstractImportExportBase { From c6f2196f60fb219c1de423c0e27e04eba05c6c90 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 16:32:25 -0400 Subject: [PATCH 056/119] vector definitions --- port/assimp_rs/src/structs/vec.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/port/assimp_rs/src/structs/vec.rs b/port/assimp_rs/src/structs/vec.rs index e69de29bb..37e1c5150 100644 --- a/port/assimp_rs/src/structs/vec.rs +++ b/port/assimp_rs/src/structs/vec.rs @@ -0,0 +1,29 @@ +struct Vector2d { + x: f32, + y: f32 +} + +struct Vector3d { + x: f32, + y: f32, + z: f32 +} + +impl Vector2d { + pub fn new(x_f32: f32, y_f32: f32) -> Vector2d { + Vector2d { + x: x_f32, + y: y_f32 + } + } +} + +impl Vector3d { + pub fn new(x_f32: f32, y_f32: f32, z_f32: f32) -> Vector3d { + Vector3d { + x: x_f32, + y: y_f32, + z: z_f32 + } + } +} From c338c5ca02e4b05d50275844f8aa89895c69a1a1 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 16:47:35 -0400 Subject: [PATCH 057/119] Populating 3d and 4d matrix struct definitions --- port/assimp_rs/src/structs/matrix.rs | 64 ++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/port/assimp_rs/src/structs/matrix.rs b/port/assimp_rs/src/structs/matrix.rs index e69de29bb..4673b2d69 100644 --- a/port/assimp_rs/src/structs/matrix.rs +++ b/port/assimp_rs/src/structs/matrix.rs @@ -0,0 +1,64 @@ +#[derive(Clone, Debug, Copy)] +struct Matrix3x3 { + a1: f32, + a2: f32, + a3: f32, + b1: f32, + b2: f32, + b3: f32, + c1: f32, + c2: f32, + c3: f32 +} + +#[derive(Clone, Debug, Copy)] +struct Matrix4x4 { + a1: f32, + a2: f32, + a3: f32, + a4: f32, + b1: f32, + b2: f32, + b3: f32, + b4: f32, + c1: f32, + c2: f32, + c3: f32, + c4: f32, + d1: f32, + d2: f32, + d3: f32, + d4: f32 +} + +impl Matrix3x3 { + pub fn new( + a1_f32: f32, a2_f32: f32, a3_f32: f32, + b1_f32: f32, b2_f32: f32, b3_f32: f32, + c1_f32: f32, c2_f32: f32, c3_f32: f32 + ) -> Matrix3x3 { + Matrix3x3 { + a1: a1_f32, a2: a2_f32, a3: a3_f32, + b1: b1_f32, b2: b2_f32, b3: b3_f32, + c1: c1_f32, c2: c2_f32, c3: c3_f32 + } + } +} + +impl Matrix4x4 { + pub fn new( + a1_f32: f32, a2_f32: f32, a3_f32: f32, a4_f32: f32, + b1_f32: f32, b2_f32: f32, b3_f32: f32, b4_f32: f32, + c1_f32: f32, c2_f32: f32, c3_f32: f32, c4_f32: f32, + d1_f32: f32, d2_f32: f32, d3_f32: f32, d4_f32: f32 + ) -> Matrix4x4 { + Matrix4x4 { + a1: a1_f32, a2: a2_f32, a3: a3_f32, a4: a4_f32, + b1: b1_f32, b2: b2_f32, b3: b3_f32, b4: b4_f32, + c1: c1_f32, c2: c2_f32, c3: c3_f32, c4: c4_f32, + d1: d1_f32, d2: d2_f32, d3: d3_f32, d4: d4_f32 + } + } +} + + From 4f8eb0f79ca0c1d88fab2bd357527e1d40137ee8 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 16:50:31 -0400 Subject: [PATCH 058/119] populating Texel struct definition for textures --- port/assimp_rs/src/structs/texel.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/port/assimp_rs/src/structs/texel.rs b/port/assimp_rs/src/structs/texel.rs index e69de29bb..b2c72f30e 100644 --- a/port/assimp_rs/src/structs/texel.rs +++ b/port/assimp_rs/src/structs/texel.rs @@ -0,0 +1,19 @@ +#[derive(Clone, Debug, Copy)] +struct Texel { + b: u32, + g: u32, + r: u32, + a: u32 +} + +impl Texel { + pub fn new(b_u32: u32, g_u32: u32, + r_u32: u32, a_u32: u32) -> Texel { + Texel { + b: b_u32, + g: g_u32, + r: r_u32, + a: a_u32 + } + } +} From ba633f95bb1af4bbca82738a95bf569cef035a35 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 16:54:56 -0400 Subject: [PATCH 059/119] populating colors --- port/assimp_rs/src/structs/color.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/port/assimp_rs/src/structs/color.rs b/port/assimp_rs/src/structs/color.rs index e69de29bb..0b5fc6413 100644 --- a/port/assimp_rs/src/structs/color.rs +++ b/port/assimp_rs/src/structs/color.rs @@ -0,0 +1,27 @@ +#[derive(Clone, Debug, Copy)] +struct Color3D { + r: f32, + g: f32, + b: f32 +} + +impl Color3D { + pub fn new(r_f32: f32, g_f32: f32, b_f32: f32) -> Color3D { + Color3D {r: r_f32, g: g_f32, b: b_f32 } + } +} + +#[derive(Clone, Debug, Copy)] +struct Color4D { + r: f32, + g: f32, + b: f32, + a: f32 +} + +impl Color4D { + pub fn new(r_f32: f32, g_f32: f32, b_f32: f32, a_f32: f32) -> Color4D { + Color4D {r: r_f32, g: g_f32, b: b_f32, a: a_f32 } + } +} + From 38b80f6c6b7dd60b0366af8eaaeca9a179128f33 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 16:58:32 -0400 Subject: [PATCH 060/119] populating plane struct --- port/assimp_rs/src/structs/plane.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/port/assimp_rs/src/structs/plane.rs b/port/assimp_rs/src/structs/plane.rs index e69de29bb..2b0b74499 100644 --- a/port/assimp_rs/src/structs/plane.rs +++ b/port/assimp_rs/src/structs/plane.rs @@ -0,0 +1,23 @@ +#[derive(Clone, Debug, Copy)] +struct Plane { + a: f32, + b: f32, + c: f32, + d: f32 +} + +impl Plane { + pub fn new( + a_f32: f32, + b_f32: f32, + c_f32: f32, + d_f32: f32 + ) -> Plane { + Plane { + a: a_f32, + b: b_f32, + c: b_f32, + d: d_f32 + } + } +} From e6837f73949d1d797f71531d0d6ba08dfee6a5fb Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 17:25:02 -0400 Subject: [PATCH 061/119] Need to consider different implementations of String kinds in Rust, and additionally how we may want to `impl Copy for Str`, i.e. `std::mem::swap` with placeholders to keep performance up. --- port/assimp_rs/src/structs/string.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/port/assimp_rs/src/structs/string.rs b/port/assimp_rs/src/structs/string.rs index e69de29bb..c99fabffb 100644 --- a/port/assimp_rs/src/structs/string.rs +++ b/port/assimp_rs/src/structs/string.rs @@ -0,0 +1,17 @@ +pub const MAXLEN: u32 = 1024; + +#[derive(Clone, Debug)] +struct Str { + length: u32, + data: Vec +} + +impl Str { + pub fn new(len_u32: u32, data_string: String) -> Str { + Str { + length: len_u32, + data: data_string.chars().collect() + } + } +} + From a286506c234068bbab212eb7de4c8ea5e853a934 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 17:32:55 -0400 Subject: [PATCH 062/119] fixed a couple of things. Adding MaterialPropertyString --- port/assimp_rs/src/structs/string.rs | 30 +++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/port/assimp_rs/src/structs/string.rs b/port/assimp_rs/src/structs/string.rs index c99fabffb..b88457df4 100644 --- a/port/assimp_rs/src/structs/string.rs +++ b/port/assimp_rs/src/structs/string.rs @@ -1,13 +1,16 @@ -pub const MAXLEN: u32 = 1024; +pub const MAXLEN: usize = 1024; +/// Want to consider replacing `Vec` +/// with a comparable definition at +/// https://doc.rust-lang.org/src/alloc/string.rs.html#415-417 #[derive(Clone, Debug)] struct Str { - length: u32, + length: usize, data: Vec } impl Str { - pub fn new(len_u32: u32, data_string: String) -> Str { + pub fn new(len_u32: usize, data_string: String) -> Str { Str { length: len_u32, data: data_string.chars().collect() @@ -15,3 +18,24 @@ impl Str { } } +/// MaterialPropertyStr +/// The size of length is truncated to 4 bytes on a 64-bit platform when used as a +/// material property (see MaterialSystem.cpp, as aiMaterial::AddProperty() ). +#[derive(Clone, Debug)] +struct MaterialPropertyStr { + length: usize, + data: Vec +} + + +impl MaterialPropertyStr { + pub fn new(len_u32: usize, data_string: String) -> MaterialPropertyStr { + MaterialPropertyStr { + length: len_u32, + data: data_string.chars().collect() + } + } +} + + + From 2d43a2447530fe2abe30f9aaeae558212734c231 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 17:41:16 -0400 Subject: [PATCH 063/119] memory info struct --- port/assimp_rs/src/structs/mem.rs | 0 port/assimp_rs/src/structs/memory.rs | 35 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) delete mode 100644 port/assimp_rs/src/structs/mem.rs create mode 100644 port/assimp_rs/src/structs/memory.rs diff --git a/port/assimp_rs/src/structs/mem.rs b/port/assimp_rs/src/structs/mem.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/port/assimp_rs/src/structs/memory.rs b/port/assimp_rs/src/structs/memory.rs new file mode 100644 index 000000000..c076f172a --- /dev/null +++ b/port/assimp_rs/src/structs/memory.rs @@ -0,0 +1,35 @@ +#[derive(Clone, Debug, Copy)] +struct MemoryInfo { + textures: u32, + materials: u32, + meshes: u32, + nodes: u32, + animations: u32, + cameras: u32, + lights: u32, + total: u32 +} + +impl MemoryInfo { + pub fn new( + textures_uint: u32, + materials_uint: u32, + meshes_uint: u32, + nodes_uint: u32, + animations_uint: u32, + cameras_uint: u32, + lights_uint: u32, + total_uint: u32) -> MemoryInfo { + + MemoryInfo { + textures: textures_uint, + materials: materials_uint, + meshes: meshes_uint, + nodes: nodes_uint, + animations: animations_uint, + cameras: cameras_uint, + lights: lights_uint, + total: total_uint + } + } +} From 778c3afbbb052bea25d6eaaccba1d663432b0b27 Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 18:11:44 -0400 Subject: [PATCH 064/119] Rust's import system dictates that we must make directories rather than use individual files to provide a clean public interface --- port/PyAssimp/pyassimp/.structs.py.swp | Bin 0 -> 16384 bytes port/assimp_rs/src/camera/mod.rs | 1 + port/assimp_rs/src/structs/.mod.rs.swp | Bin 0 -> 12288 bytes port/assimp_rs/src/structs/{ => anim}/anim.rs | 0 port/assimp_rs/src/structs/anim/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => blob}/blob.rs | 0 port/assimp_rs/src/structs/blob/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => bone}/bone.rs | 0 port/assimp_rs/src/structs/bone/mod.rs | 2 ++ .../src/structs/{ => camera}/camera.rs | 0 port/assimp_rs/src/structs/camera/mod.rs | 2 ++ .../src/structs/{ => color}/color.rs | 0 port/assimp_rs/src/structs/color/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => face}/face.rs | 0 port/assimp_rs/src/structs/face/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => key}/key.rs | 0 port/assimp_rs/src/structs/key/mod.rs | 2 ++ .../src/structs/{ => light}/light.rs | 0 port/assimp_rs/src/structs/light/mod.rs | 2 ++ .../src/structs/{ => material}/material.rs | 0 port/assimp_rs/src/structs/material/mod.rs | 2 ++ .../src/structs/{ => matrix}/matrix.rs | 0 port/assimp_rs/src/structs/matrix/mod.rs | 2 ++ .../src/structs/{ => memory}/memory.rs | 0 port/assimp_rs/src/structs/memory/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => mesh}/mesh.rs | 0 port/assimp_rs/src/structs/mesh/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => meta}/meta.rs | 0 port/assimp_rs/src/structs/meta/mod.rs | 2 ++ port/assimp_rs/src/structs/node/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => node}/node.rs | 0 port/assimp_rs/src/structs/plane/mod.rs | 2 ++ .../src/structs/{ => plane}/plane.rs | 0 port/assimp_rs/src/structs/quaternion/mod.rs | 2 ++ .../src/structs/quaternion/quaternion.rs | 7 +++++++ port/assimp_rs/src/structs/ray/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => ray}/ray.rs | 0 port/assimp_rs/src/structs/scene/mod.rs | 2 ++ .../src/structs/{ => scene}/scene.rs | 0 port/assimp_rs/src/structs/string/mod.rs | 2 ++ .../src/structs/{ => string}/string.rs | 0 port/assimp_rs/src/structs/texel/mod.rs | 2 ++ .../src/structs/{ => texel}/texel.rs | 0 port/assimp_rs/src/structs/texture/mod.rs | 2 ++ .../src/structs/{ => texture}/texture.rs | 0 port/assimp_rs/src/structs/transform/mod.rs | 2 ++ .../src/structs/{ => transform}/transform.rs | 0 port/assimp_rs/src/structs/vec/mod.rs | 2 ++ port/assimp_rs/src/structs/{ => vec}/vec.rs | 19 ++++++++++++++++++ port/assimp_rs/src/structs/vertex/mod.rs | 2 ++ .../{quaternion.rs => vertex/vertex.rs} | 0 port/assimp_rs/src/structs/vertex_weight.rs | 0 52 files changed, 75 insertions(+) create mode 100644 port/PyAssimp/pyassimp/.structs.py.swp create mode 100644 port/assimp_rs/src/structs/.mod.rs.swp rename port/assimp_rs/src/structs/{ => anim}/anim.rs (100%) create mode 100644 port/assimp_rs/src/structs/anim/mod.rs rename port/assimp_rs/src/structs/{ => blob}/blob.rs (100%) create mode 100644 port/assimp_rs/src/structs/blob/mod.rs rename port/assimp_rs/src/structs/{ => bone}/bone.rs (100%) create mode 100644 port/assimp_rs/src/structs/bone/mod.rs rename port/assimp_rs/src/structs/{ => camera}/camera.rs (100%) create mode 100644 port/assimp_rs/src/structs/camera/mod.rs rename port/assimp_rs/src/structs/{ => color}/color.rs (100%) create mode 100644 port/assimp_rs/src/structs/color/mod.rs rename port/assimp_rs/src/structs/{ => face}/face.rs (100%) create mode 100644 port/assimp_rs/src/structs/face/mod.rs rename port/assimp_rs/src/structs/{ => key}/key.rs (100%) create mode 100644 port/assimp_rs/src/structs/key/mod.rs rename port/assimp_rs/src/structs/{ => light}/light.rs (100%) create mode 100644 port/assimp_rs/src/structs/light/mod.rs rename port/assimp_rs/src/structs/{ => material}/material.rs (100%) create mode 100644 port/assimp_rs/src/structs/material/mod.rs rename port/assimp_rs/src/structs/{ => matrix}/matrix.rs (100%) create mode 100644 port/assimp_rs/src/structs/matrix/mod.rs rename port/assimp_rs/src/structs/{ => memory}/memory.rs (100%) create mode 100644 port/assimp_rs/src/structs/memory/mod.rs rename port/assimp_rs/src/structs/{ => mesh}/mesh.rs (100%) create mode 100644 port/assimp_rs/src/structs/mesh/mod.rs rename port/assimp_rs/src/structs/{ => meta}/meta.rs (100%) create mode 100644 port/assimp_rs/src/structs/meta/mod.rs create mode 100644 port/assimp_rs/src/structs/node/mod.rs rename port/assimp_rs/src/structs/{ => node}/node.rs (100%) create mode 100644 port/assimp_rs/src/structs/plane/mod.rs rename port/assimp_rs/src/structs/{ => plane}/plane.rs (100%) create mode 100644 port/assimp_rs/src/structs/quaternion/mod.rs create mode 100644 port/assimp_rs/src/structs/quaternion/quaternion.rs create mode 100644 port/assimp_rs/src/structs/ray/mod.rs rename port/assimp_rs/src/structs/{ => ray}/ray.rs (100%) create mode 100644 port/assimp_rs/src/structs/scene/mod.rs rename port/assimp_rs/src/structs/{ => scene}/scene.rs (100%) create mode 100644 port/assimp_rs/src/structs/string/mod.rs rename port/assimp_rs/src/structs/{ => string}/string.rs (100%) create mode 100644 port/assimp_rs/src/structs/texel/mod.rs rename port/assimp_rs/src/structs/{ => texel}/texel.rs (100%) create mode 100644 port/assimp_rs/src/structs/texture/mod.rs rename port/assimp_rs/src/structs/{ => texture}/texture.rs (100%) create mode 100644 port/assimp_rs/src/structs/transform/mod.rs rename port/assimp_rs/src/structs/{ => transform}/transform.rs (100%) create mode 100644 port/assimp_rs/src/structs/vec/mod.rs rename port/assimp_rs/src/structs/{ => vec}/vec.rs (60%) create mode 100644 port/assimp_rs/src/structs/vertex/mod.rs rename port/assimp_rs/src/structs/{quaternion.rs => vertex/vertex.rs} (100%) delete mode 100644 port/assimp_rs/src/structs/vertex_weight.rs diff --git a/port/PyAssimp/pyassimp/.structs.py.swp b/port/PyAssimp/pyassimp/.structs.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..1de72f0f8f12a4e35de38089723ca2b124ce4459 GIT binary patch literal 16384 zcmeI3%a0sK9mgB6iHYMl1TIK{RK^0&Mzga|k;Me0C3d7GyX&=g6Cwzi)O6R(R9xLX z>8_rgK@kuRJYvMdjs(Kt0$BV3Mu?Xp3oPIO7X$(h9EcRK5lARPfjkI&tGap~J>#7j zBo3fz`Qx7MU)8UxzV(={U(HtMA6VNUE9C_T$1RStx&HNsfAQV}PW4{L@o0;C>i(ER z(54KVV-msqQSETf4Lvs3VnHjOqjAjr=3Fz3;2<0Si4ogDqt0`3RnfK0#*U5fK|XM@PDL$Y~JL24E1@f zsnh4o`8B!ozs&Ktx&Qf`{Z(Us$lO0@9Atj}Y3wJBy`HnbV(i@5zn!zcZ0wI3`|YN{ zng5rJ{kXAzCTD-q*td=S=Q;a7jQxzUlh>smGXH-!_PVj3&Dmct_J@uA`JCNcI>gww z_N5;(|K_$mSp}>DRspMkRlq7>6|f3e1*`&A0jq#j;J=~(#RmT@JU^kqfUkisgD-&q)WF@~-Qd~{s53YVo&;^M3u@q2@XYIx2dsnpz+1rI_Cp774g3sT z0T;nn!PDR@_#jvTcY*!jS;QHB4=#c8;2iM432+>|5&Q+gi9drMfD7O&;0(AAydN9} ze?|ZJ19%Sn6kG;RgQviGa1N+G^l>oNL2y)RoCz$u|E8BZB)}5+0K@Prkzn7Sv^zIheYVA>lG6Eb!9NuS8PE5kf>* z=PpKU`e>Ce%@Y$h3@~A6Z};!qJG(;sL`bflNMiO_!UC7YcaSxCG<`pTkX?>V`>gVSaHrl`m`UZf|Qw zVUtC&Ly9qG!VS|2w>z<9e%Wm{3FX<%W5-rKZ_A`F&h*cdGpSTNN=4OlP{wG4LSmu} z(s>QiE}Lcu1M<%0*(w^iDX7Gh>&Ilb!2*)Rm;h-^%mk(9=d1+1V(mFgXUVg&rk%_7 z*8kbwsyo3XbJH{}9qFl~CPIoY=3=2fcvSaiq$wEUlf^XE za(lVdi}L38Qv9umw-BGyD=M{csWgWozH5Qn$3cu#1)WR83rP@4M069k(Q~Y%Ef)L@ zZ1I@bv{@q+vs*Jmj$Im%DocZth+?WO8*I-YYDwj6++;4VahLeUqY7W{G9mKu<0Rm6 z7Lno>i(<7cQX>7I0xyhWf*4YWh;BrDY*>h%Z&lJX?(6h-4eTMQP_VLQG3c1oMOcLf z-Qw&vxZ6PSMHti(jt$djx62UZ5&R4rQs$oSR!}BPc1|rb!}{o`wepy+GmRpO;4-ff z*5TpH{u2p)E)hMFm#B3q8INK#yOol@h#MYShf_(mF;+x_jtqwLTRnQhZio330 z!2@!BR%p(!wdQ&MbiqD6=pQVP>s~n(()k6Z5)<|H0+gA z_t%lzf9gSMi?2h%rrIZ?qNFP2hq@*)HY=oRTq+TPs3zD-*yX4Ly5W4TYN|-ReU5G= nwF)HG%|eW7Lj_&W_7Sr-&d%B}qN)3((b5kzPU^1PHqO5R$L{t! literal 0 HcmV?d00001 diff --git a/port/assimp_rs/src/camera/mod.rs b/port/assimp_rs/src/camera/mod.rs index e69de29bb..26ca1185b 100644 --- a/port/assimp_rs/src/camera/mod.rs +++ b/port/assimp_rs/src/camera/mod.rs @@ -0,0 +1 @@ +pub use self::structs::{Camera}; diff --git a/port/assimp_rs/src/structs/.mod.rs.swp b/port/assimp_rs/src/structs/.mod.rs.swp new file mode 100644 index 0000000000000000000000000000000000000000..a6b06ed631bd7b51b0450777a8e7c266e3c9b7eb GIT binary patch literal 12288 zcmeI2J!lj`6vrnP+L&mxwOBtO5HOqMt_U0iV-iKei7{SEh|Ig3(heX@lGo;^SfLz&vlmXl7!`TThI@)NcbI*c9hSRY9+a!XHvU( zMJiv(&{tZvL#_NIi^indy*6c#0Wz?Ifwo>fJvG>dqiZe1P4;q4v3hO}qQRUw1d88yO%2WPl8i0Wv@a$N(8217v^< zkO4BV2Muuiz&~@4vBn@akKg~x|Np-oV(c^c2;PC$;3aql9)k^VAKV4&K!O-t1DC-Z zI0LF+1RMjyU_aOgz7H|>1#E-&U<)qicSu_%17v^&eA{E}K&+q}Wr_7*c!yq#e5*o`_Bu~|9CX+HvmlH**%$qO04|6^L7FO zbjxF2s>BvW+;6=sLY>J4(KFo^u}2ryg=*F_nK#YY9oK}W@O1&h&e&`gXR;cZ6dP6| zn-ZF7`@&{{f$b)%LKXO3(*H*$SciunYOxj9J6Eji9=Fh{%sA%q7 Vector2d { Vector2d { @@ -27,3 +34,15 @@ impl Vector3d { } } } + +impl Vector4d { + pub fn new(x_f32: f32, y_f32: f32, z_f32: f32, w_f32: f32) -> Vector4d { + Vector4d { + x: x_f32, + y: y_f32, + z: z_f32, + w: w_f32 + } + } +} + diff --git a/port/assimp_rs/src/structs/vertex/mod.rs b/port/assimp_rs/src/structs/vertex/mod.rs new file mode 100644 index 000000000..d169246ce --- /dev/null +++ b/port/assimp_rs/src/structs/vertex/mod.rs @@ -0,0 +1,2 @@ +mod vertex; + diff --git a/port/assimp_rs/src/structs/quaternion.rs b/port/assimp_rs/src/structs/vertex/vertex.rs similarity index 100% rename from port/assimp_rs/src/structs/quaternion.rs rename to port/assimp_rs/src/structs/vertex/vertex.rs diff --git a/port/assimp_rs/src/structs/vertex_weight.rs b/port/assimp_rs/src/structs/vertex_weight.rs deleted file mode 100644 index e69de29bb..000000000 From 57e837092e6aaedf69912729b45568af30a20ffc Mon Sep 17 00:00:00 2001 From: David Golembiowski Date: Fri, 1 May 2020 18:23:14 -0400 Subject: [PATCH 065/119] populated module level files --- port/PyAssimp/pyassimp/.structs.py.swp | Bin 16384 -> 0 bytes port/assimp_rs/src/structs/.mod.rs.swp | Bin 12288 -> 0 bytes port/assimp_rs/src/structs/anim/mod.rs | 6 +++++- port/assimp_rs/src/structs/color/mod.rs | 5 ++++- port/assimp_rs/src/structs/matrix/mod.rs | 4 +++- port/assimp_rs/src/structs/memory/mod.rs | 2 +- port/assimp_rs/src/structs/mesh/mod.rs | 1 + port/assimp_rs/src/structs/quaternion/mod.rs | 1 + port/assimp_rs/src/structs/string/mod.rs | 3 ++- port/assimp_rs/src/structs/texel/mod.rs | 2 -- port/assimp_rs/src/structs/texel/texel.rs | 19 ------------------ port/assimp_rs/src/structs/texture/mod.rs | 1 + port/assimp_rs/src/structs/texture/texture.rs | 19 ++++++++++++++++++ port/assimp_rs/src/structs/vertex/mod.rs | 2 +- 14 files changed, 38 insertions(+), 27 deletions(-) delete mode 100644 port/PyAssimp/pyassimp/.structs.py.swp delete mode 100644 port/assimp_rs/src/structs/.mod.rs.swp delete mode 100644 port/assimp_rs/src/structs/texel/mod.rs delete mode 100644 port/assimp_rs/src/structs/texel/texel.rs diff --git a/port/PyAssimp/pyassimp/.structs.py.swp b/port/PyAssimp/pyassimp/.structs.py.swp deleted file mode 100644 index 1de72f0f8f12a4e35de38089723ca2b124ce4459..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI3%a0sK9mgB6iHYMl1TIK{RK^0&Mzga|k;Me0C3d7GyX&=g6Cwzi)O6R(R9xLX z>8_rgK@kuRJYvMdjs(Kt0$BV3Mu?Xp3oPIO7X$(h9EcRK5lARPfjkI&tGap~J>#7j zBo3fz`Qx7MU)8UxzV(={U(HtMA6VNUE9C_T$1RStx&HNsfAQV}PW4{L@o0;C>i(ER z(54KVV-msqQSETf4Lvs3VnHjOqjAjr=3Fz3;2<0Si4ogDqt0`3RnfK0#*U5fK|XM@PDL$Y~JL24E1@f zsnh4o`8B!ozs&Ktx&Qf`{Z(Us$lO0@9Atj}Y3wJBy`HnbV(i@5zn!zcZ0wI3`|YN{ zng5rJ{kXAzCTD-q*td=S=Q;a7jQxzUlh>smGXH-!_PVj3&Dmct_J@uA`JCNcI>gww z_N5;(|K_$mSp}>DRspMkRlq7>6|f3e1*`&A0jq#j;J=~(#RmT@JU^kqfUkisgD-&q)WF@~-Qd~{s53YVo&;^M3u@q2@XYIx2dsnpz+1rI_Cp774g3sT z0T;nn!PDR@_#jvTcY*!jS;QHB4=#c8;2iM432+>|5&Q+gi9drMfD7O&;0(AAydN9} ze?|ZJ19%Sn6kG;RgQviGa1N+G^l>oNL2y)RoCz$u|E8BZB)}5+0K@Prkzn7Sv^zIheYVA>lG6Eb!9NuS8PE5kf>* z=PpKU`e>Ce%@Y$h3@~A6Z};!qJG(;sL`bflNMiO_!UC7YcaSxCG<`pTkX?>V`>gVSaHrl`m`UZf|Qw zVUtC&Ly9qG!VS|2w>z<9e%Wm{3FX<%W5-rKZ_A`F&h*cdGpSTNN=4OlP{wG4LSmu} z(s>QiE}Lcu1M<%0*(w^iDX7Gh>&Ilb!2*)Rm;h-^%mk(9=d1+1V(mFgXUVg&rk%_7 z*8kbwsyo3XbJH{}9qFl~CPIoY=3=2fcvSaiq$wEUlf^XE za(lVdi}L38Qv9umw-BGyD=M{csWgWozH5Qn$3cu#1)WR83rP@4M069k(Q~Y%Ef)L@ zZ1I@bv{@q+vs*Jmj$Im%DocZth+?WO8*I-YYDwj6++;4VahLeUqY7W{G9mKu<0Rm6 z7Lno>i(<7cQX>7I0xyhWf*4YWh;BrDY*>h%Z&lJX?(6h-4eTMQP_VLQG3c1oMOcLf z-Qw&vxZ6PSMHti(jt$djx62UZ5&R4rQs$oSR!}BPc1|rb!}{o`wepy+GmRpO;4-ff z*5TpH{u2p)E)hMFm#B3q8INK#yOol@h#MYShf_(mF;+x_jtqwLTRnQhZio330 z!2@!BR%p(!wdQ&MbiqD6=pQVP>s~n(()k6Z5)<|H0+gA z_t%lzf9gSMi?2h%rrIZ?qNFP2hq@*)HY=oRTq+TPs3zD-*yX4Ly5W4TYN|-ReU5G= nwF)HG%|eW7Lj_&W_7Sr-&d%B}qN)3((b5kzPU^1PHqO5R$L{t! diff --git a/port/assimp_rs/src/structs/.mod.rs.swp b/port/assimp_rs/src/structs/.mod.rs.swp deleted file mode 100644 index a6b06ed631bd7b51b0450777a8e7c266e3c9b7eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2J!lj`6vrnP+L&mxwOBtO5HOqMt_U0iV-iKei7{SEh|Ig3(heX@lGo;^SfLz&vlmXl7!`TThI@)NcbI*c9hSRY9+a!XHvU( zMJiv(&{tZvL#_NIi^indy*6c#0Wz?Ifwo>fJvG>dqiZe1P4;q4v3hO}qQRUw1d88yO%2WPl8i0Wv@a$N(8217v^< zkO4BV2Muuiz&~@4vBn@akKg~x|Np-oV(c^c2;PC$;3aql9)k^VAKV4&K!O-t1DC-Z zI0LF+1RMjyU_aOgz7H|>1#E-&U<)qicSu_%17v^&eA{E}K&+q}Wr_7*c!yq#e5*o`_Bu~|9CX+HvmlH**%$qO04|6^L7FO zbjxF2s>BvW+;6=sLY>J4(KFo^u}2ryg=*F_nK#YY9oK}W@O1&h&e&`gXR;cZ6dP6| zn-ZF7`@&{{f$b)%LKXO3(*H*$SciunYOxj9J6Eji9=Fh{%sA%q7 Texel { - Texel { - b: b_u32, - g: g_u32, - r: r_u32, - a: a_u32 - } - } -} diff --git a/port/assimp_rs/src/structs/texture/mod.rs b/port/assimp_rs/src/structs/texture/mod.rs index a9d56e75b..1b5c9308d 100644 --- a/port/assimp_rs/src/structs/texture/mod.rs +++ b/port/assimp_rs/src/structs/texture/mod.rs @@ -1,2 +1,3 @@ mod texture; +pub use self::texture::Texel; diff --git a/port/assimp_rs/src/structs/texture/texture.rs b/port/assimp_rs/src/structs/texture/texture.rs index e69de29bb..b2c72f30e 100644 --- a/port/assimp_rs/src/structs/texture/texture.rs +++ b/port/assimp_rs/src/structs/texture/texture.rs @@ -0,0 +1,19 @@ +#[derive(Clone, Debug, Copy)] +struct Texel { + b: u32, + g: u32, + r: u32, + a: u32 +} + +impl Texel { + pub fn new(b_u32: u32, g_u32: u32, + r_u32: u32, a_u32: u32) -> Texel { + Texel { + b: b_u32, + g: g_u32, + r: r_u32, + a: a_u32 + } + } +} diff --git a/port/assimp_rs/src/structs/vertex/mod.rs b/port/assimp_rs/src/structs/vertex/mod.rs index d169246ce..97ae3eced 100644 --- a/port/assimp_rs/src/structs/vertex/mod.rs +++ b/port/assimp_rs/src/structs/vertex/mod.rs @@ -1,2 +1,2 @@ mod vertex; - +// pub use self::vertex:: From f8e6512a63c142ba69f654f60f05ad973664c73e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 2 May 2020 15:14:38 +0200 Subject: [PATCH 066/119] Move format importer and exporter into its won folder. --- code/AMF/AMFImporter.cpp | 705 ------- code/AMF/AMFImporter_Postprocess.cpp | 978 ---------- code/{ => AssetLib}/3DS/3DSConverter.cpp | 552 +++--- code/{ => AssetLib}/3DS/3DSExporter.cpp | 233 ++- code/{ => AssetLib}/3DS/3DSExporter.h | 0 code/{ => AssetLib}/3DS/3DSHelper.h | 0 code/{ => AssetLib}/3DS/3DSLoader.cpp | 759 ++++---- code/{ => AssetLib}/3DS/3DSLoader.h | 0 code/{ => AssetLib}/3MF/3MFXmlTags.h | 0 code/{ => AssetLib}/3MF/D3MFExporter.cpp | 252 ++- code/{ => AssetLib}/3MF/D3MFExporter.h | 0 code/{ => AssetLib}/3MF/D3MFImporter.cpp | 280 ++- code/{ => AssetLib}/3MF/D3MFImporter.h | 0 code/{ => AssetLib}/3MF/D3MFOpcPackage.cpp | 0 code/{ => AssetLib}/3MF/D3MFOpcPackage.h | 0 code/{ => AssetLib}/AC/ACLoader.cpp | 72 +- code/{ => AssetLib}/AC/ACLoader.h | 95 +- code/AssetLib/AMF/AMFImporter.cpp | 672 +++++++ code/{ => AssetLib}/AMF/AMFImporter.hpp | 0 .../AMF/AMFImporter_Geometry.cpp | 0 code/{ => AssetLib}/AMF/AMFImporter_Macro.hpp | 0 .../AMF/AMFImporter_Material.cpp | 0 code/{ => AssetLib}/AMF/AMFImporter_Node.hpp | 0 code/AssetLib/AMF/AMFImporter_Postprocess.cpp | 872 +++++++++ code/{ => AssetLib}/ASE/ASELoader.cpp | 758 ++++---- code/{ => AssetLib}/ASE/ASELoader.h | 0 code/{ => AssetLib}/ASE/ASEParser.cpp | 1382 ++++++------- code/{ => AssetLib}/ASE/ASEParser.h | 2 +- code/{ => AssetLib}/Assbin/AssbinExporter.cpp | 1 - code/{ => AssetLib}/Assbin/AssbinExporter.h | 0 .../Assbin/AssbinFileWriter.cpp | 59 +- code/{ => AssetLib}/Assbin/AssbinFileWriter.h | 13 +- code/{ => AssetLib}/Assbin/AssbinLoader.cpp | 50 +- code/{ => AssetLib}/Assbin/AssbinLoader.h | 0 code/{ => AssetLib}/Assjson/cencode.c | 0 code/{ => AssetLib}/Assjson/cencode.h | 0 code/{ => AssetLib}/Assjson/json_exporter.cpp | 0 code/{ => AssetLib}/Assjson/mesh_splitter.cpp | 0 code/{ => AssetLib}/Assjson/mesh_splitter.h | 0 code/{ => AssetLib}/Assxml/AssxmlExporter.cpp | 0 code/{ => AssetLib}/Assxml/AssxmlExporter.h | 0 code/AssetLib/Assxml/AssxmlFileWriter.cpp | 659 +++++++ code/{ => AssetLib}/Assxml/AssxmlFileWriter.h | 0 code/AssetLib/B3D/B3DImporter.cpp | 744 +++++++ code/{ => AssetLib}/B3D/B3DImporter.h | 0 code/AssetLib/BVH/BVHLoader.cpp | 543 ++++++ code/{ => AssetLib}/BVH/BVHLoader.h | 51 +- code/{ => AssetLib}/Blender/BlenderBMesh.cpp | 142 +- code/{ => AssetLib}/Blender/BlenderBMesh.h | 0 code/AssetLib/Blender/BlenderCustomData.cpp | 181 ++ .../Blender/BlenderCustomData.h | 0 code/{ => AssetLib}/Blender/BlenderDNA.cpp | 163 +- code/{ => AssetLib}/Blender/BlenderDNA.h | 371 ++-- code/{ => AssetLib}/Blender/BlenderDNA.inl | 2 +- .../Blender/BlenderIntermediate.h | 0 code/{ => AssetLib}/Blender/BlenderLoader.cpp | 0 code/{ => AssetLib}/Blender/BlenderLoader.h | 0 .../Blender/BlenderModifier.cpp | 26 +- code/{ => AssetLib}/Blender/BlenderModifier.h | 0 code/AssetLib/Blender/BlenderScene.cpp | 838 ++++++++ code/{ => AssetLib}/Blender/BlenderScene.h | 523 +++-- code/{ => AssetLib}/Blender/BlenderSceneGen.h | 0 .../Blender/BlenderTessellator.cpp | 0 .../Blender/BlenderTessellator.h | 0 code/{ => AssetLib}/C4D/C4DImporter.cpp | 0 code/{ => AssetLib}/C4D/C4DImporter.h | 0 code/{ => AssetLib}/COB/COBLoader.cpp | 843 ++++---- code/{ => AssetLib}/COB/COBLoader.h | 0 code/{ => AssetLib}/COB/COBScene.h | 0 code/{ => AssetLib}/CSM/CSMLoader.cpp | 0 code/{ => AssetLib}/CSM/CSMLoader.h | 0 code/AssetLib/Collada/ColladaExporter.cpp | 1651 ++++++++++++++++ code/{ => AssetLib}/Collada/ColladaExporter.h | 0 code/{ => AssetLib}/Collada/ColladaHelper.cpp | 0 code/{ => AssetLib}/Collada/ColladaHelper.h | 0 code/{ => AssetLib}/Collada/ColladaLoader.cpp | 0 code/{ => AssetLib}/Collada/ColladaLoader.h | 0 code/{ => AssetLib}/Collada/ColladaParser.cpp | 0 code/{ => AssetLib}/Collada/ColladaParser.h | 0 code/{ => AssetLib}/DXF/DXFHelper.h | 0 code/{ => AssetLib}/DXF/DXFLoader.cpp | 4 +- code/{ => AssetLib}/DXF/DXFLoader.h | 0 code/{ => AssetLib}/FBX/FBXAnimation.cpp | 0 .../{ => AssetLib}/FBX/FBXBinaryTokenizer.cpp | 0 code/{ => AssetLib}/FBX/FBXCommon.h | 0 code/{ => AssetLib}/FBX/FBXCompileConfig.h | 0 code/{ => AssetLib}/FBX/FBXConverter.cpp | 0 code/{ => AssetLib}/FBX/FBXConverter.h | 0 code/{ => AssetLib}/FBX/FBXDeformer.cpp | 0 code/{ => AssetLib}/FBX/FBXDocument.cpp | 0 code/{ => AssetLib}/FBX/FBXDocument.h | 0 code/{ => AssetLib}/FBX/FBXDocumentUtil.cpp | 0 code/{ => AssetLib}/FBX/FBXDocumentUtil.h | 0 code/{ => AssetLib}/FBX/FBXExportNode.cpp | 0 code/{ => AssetLib}/FBX/FBXExportNode.h | 0 code/{ => AssetLib}/FBX/FBXExportProperty.cpp | 0 code/{ => AssetLib}/FBX/FBXExportProperty.h | 0 code/{ => AssetLib}/FBX/FBXExporter.cpp | 0 code/{ => AssetLib}/FBX/FBXExporter.h | 0 code/{ => AssetLib}/FBX/FBXImportSettings.h | 0 code/{ => AssetLib}/FBX/FBXImporter.cpp | 0 code/{ => AssetLib}/FBX/FBXImporter.h | 0 code/{ => AssetLib}/FBX/FBXMaterial.cpp | 0 code/{ => AssetLib}/FBX/FBXMeshGeometry.cpp | 0 code/{ => AssetLib}/FBX/FBXMeshGeometry.h | 0 code/{ => AssetLib}/FBX/FBXModel.cpp | 0 code/{ => AssetLib}/FBX/FBXNodeAttribute.cpp | 0 code/{ => AssetLib}/FBX/FBXParser.cpp | 0 code/{ => AssetLib}/FBX/FBXParser.h | 0 code/{ => AssetLib}/FBX/FBXProperties.cpp | 0 code/{ => AssetLib}/FBX/FBXProperties.h | 0 code/{ => AssetLib}/FBX/FBXTokenizer.cpp | 0 code/{ => AssetLib}/FBX/FBXTokenizer.h | 0 code/{ => AssetLib}/FBX/FBXUtil.cpp | 0 code/{ => AssetLib}/FBX/FBXUtil.h | 0 code/{ => AssetLib}/HMP/HMPFileData.h | 0 code/{ => AssetLib}/HMP/HMPLoader.cpp | 4 +- code/{ => AssetLib}/HMP/HMPLoader.h | 4 +- code/{ => AssetLib}/HMP/HalfLifeFileData.h | 0 .../{Importer => AssetLib}/IFC/IFCBoolean.cpp | 399 ++-- code/{Importer => AssetLib}/IFC/IFCCurve.cpp | 0 .../IFC/IFCGeometry.cpp | 0 code/{Importer => AssetLib}/IFC/IFCLoader.cpp | 0 code/{Importer => AssetLib}/IFC/IFCLoader.h | 0 .../IFC/IFCMaterial.cpp | 0 .../IFC/IFCOpenings.cpp | 0 .../{Importer => AssetLib}/IFC/IFCProfile.cpp | 0 .../IFC/IFCReaderGen1_2x3.cpp | 0 .../IFC/IFCReaderGen2_2x3.cpp | 0 .../IFC/IFCReaderGen_2x3.h | 2 +- .../IFC/IFCReaderGen_4.cpp | 0 .../IFC/IFCReaderGen_4.h | 0 code/{Importer => AssetLib}/IFC/IFCUtil.cpp | 2 +- code/{Importer => AssetLib}/IFC/IFCUtil.h | 7 +- code/{ => AssetLib}/Irr/IRRLoader.cpp | 2 +- code/{ => AssetLib}/Irr/IRRLoader.h | 2 +- code/{ => AssetLib}/Irr/IRRMeshLoader.cpp | 0 code/{ => AssetLib}/Irr/IRRMeshLoader.h | 0 code/{ => AssetLib}/Irr/IRRShared.cpp | 0 code/{ => AssetLib}/Irr/IRRShared.h | 0 code/{ => AssetLib}/LWO/LWOAnimation.cpp | 429 +++-- code/{ => AssetLib}/LWO/LWOAnimation.h | 0 code/{ => AssetLib}/LWO/LWOBLoader.cpp | 0 code/AssetLib/LWO/LWOFileData.h | 638 ++++++ code/{ => AssetLib}/LWO/LWOLoader.cpp | 2 +- code/{ => AssetLib}/LWO/LWOLoader.h | 0 code/{ => AssetLib}/LWO/LWOMaterial.cpp | 0 code/{ => AssetLib}/LWS/LWSLoader.cpp | 2 +- code/{ => AssetLib}/LWS/LWSLoader.h | 2 +- code/{ => AssetLib}/M3D/M3DExporter.cpp | 0 code/{ => AssetLib}/M3D/M3DExporter.h | 0 code/{ => AssetLib}/M3D/M3DImporter.cpp | 0 code/{ => AssetLib}/M3D/M3DImporter.h | 0 code/{ => AssetLib}/M3D/M3DMaterials.h | 0 code/{ => AssetLib}/M3D/M3DWrapper.cpp | 0 code/{ => AssetLib}/M3D/M3DWrapper.h | 0 code/{ => AssetLib}/M3D/m3d.h | 0 code/{ => AssetLib}/MD2/MD2FileData.h | 0 code/{ => AssetLib}/MD2/MD2Loader.cpp | 0 code/{ => AssetLib}/MD2/MD2Loader.h | 0 code/{ => AssetLib}/MD2/MD2NormalTable.h | 0 code/{ => AssetLib}/MD3/MD3FileData.h | 0 code/{ => AssetLib}/MD3/MD3Loader.cpp | 2 +- code/{ => AssetLib}/MD3/MD3Loader.h | 0 code/{ => AssetLib}/MD4/MD4FileData.h | 0 code/{ => AssetLib}/MD5/MD5Loader.cpp | 0 code/{ => AssetLib}/MD5/MD5Loader.h | 0 code/{ => AssetLib}/MD5/MD5Parser.cpp | 2 +- code/{ => AssetLib}/MD5/MD5Parser.h | 0 code/{ => AssetLib}/MDC/MDCFileData.h | 0 code/{ => AssetLib}/MDC/MDCLoader.cpp | 6 +- code/{ => AssetLib}/MDC/MDCLoader.h | 0 code/{ => AssetLib}/MDC/MDCNormalTable.h | 0 .../{ => AssetLib}/MDL/HalfLife/HL1FileData.h | 0 .../MDL/HalfLife/HL1ImportDefinitions.h | 0 .../MDL/HalfLife/HL1ImportSettings.h | 0 .../MDL/HalfLife/HL1MDLLoader.cpp | 0 .../MDL/HalfLife/HL1MDLLoader.h | 0 .../MDL/HalfLife/HL1MeshTrivert.h | 0 .../MDL/HalfLife/HalfLifeMDLBaseHeader.h | 0 .../MDL/HalfLife/LogFunctions.h | 0 .../MDL/HalfLife/UniqueNameGenerator.cpp | 0 .../MDL/HalfLife/UniqueNameGenerator.h | 0 code/{ => AssetLib}/MDL/MDLDefaultColorMap.h | 0 code/{ => AssetLib}/MDL/MDLFileData.h | 0 code/{ => AssetLib}/MDL/MDLLoader.cpp | 8 +- code/{ => AssetLib}/MDL/MDLLoader.h | 4 +- code/{ => AssetLib}/MDL/MDLMaterialLoader.cpp | 0 code/{ => AssetLib}/MMD/MMDCpp14.h | 0 code/AssetLib/MMD/MMDImporter.cpp | 373 ++++ code/{ => AssetLib}/MMD/MMDImporter.h | 0 code/{ => AssetLib}/MMD/MMDPmdParser.h | 0 code/{ => AssetLib}/MMD/MMDPmxParser.cpp | 0 code/{ => AssetLib}/MMD/MMDPmxParser.h | 0 code/{ => AssetLib}/MMD/MMDVmdParser.h | 0 code/{ => AssetLib}/MS3D/MS3DLoader.cpp | 0 code/{ => AssetLib}/MS3D/MS3DLoader.h | 0 code/{ => AssetLib}/NDO/NDOLoader.cpp | 0 code/{ => AssetLib}/NDO/NDOLoader.h | 0 code/{ => AssetLib}/NFF/NFFLoader.cpp | 0 code/{ => AssetLib}/NFF/NFFLoader.h | 0 code/{ => AssetLib}/OFF/OFFLoader.cpp | 0 code/{ => AssetLib}/OFF/OFFLoader.h | 0 code/{ => AssetLib}/Obj/ObjExporter.cpp | 0 code/{ => AssetLib}/Obj/ObjExporter.h | 0 code/{ => AssetLib}/Obj/ObjFileData.h | 0 code/{ => AssetLib}/Obj/ObjFileImporter.cpp | 0 code/{ => AssetLib}/Obj/ObjFileImporter.h | 0 .../{ => AssetLib}/Obj/ObjFileMtlImporter.cpp | 0 code/{ => AssetLib}/Obj/ObjFileMtlImporter.h | 0 code/{ => AssetLib}/Obj/ObjFileParser.cpp | 0 code/{ => AssetLib}/Obj/ObjFileParser.h | 0 code/{ => AssetLib}/Obj/ObjTools.h | 0 .../Ogre/OgreBinarySerializer.cpp | 0 .../Ogre/OgreBinarySerializer.h | 0 code/{ => AssetLib}/Ogre/OgreImporter.cpp | 0 code/{ => AssetLib}/Ogre/OgreImporter.h | 0 code/{ => AssetLib}/Ogre/OgreMaterial.cpp | 0 code/{ => AssetLib}/Ogre/OgreParsingUtils.h | 0 code/{ => AssetLib}/Ogre/OgreStructs.cpp | 0 code/{ => AssetLib}/Ogre/OgreStructs.h | 0 .../{ => AssetLib}/Ogre/OgreXmlSerializer.cpp | 0 code/{ => AssetLib}/Ogre/OgreXmlSerializer.h | 0 .../OpenGEX/OpenGEXExporter.cpp | 0 code/{ => AssetLib}/OpenGEX/OpenGEXExporter.h | 0 .../OpenGEX/OpenGEXImporter.cpp | 2 +- code/{ => AssetLib}/OpenGEX/OpenGEXImporter.h | 0 code/{ => AssetLib}/OpenGEX/OpenGEXStructs.h | 0 code/{ => AssetLib}/Ply/PlyExporter.cpp | 0 code/{ => AssetLib}/Ply/PlyExporter.h | 0 code/{ => AssetLib}/Ply/PlyLoader.cpp | 0 code/{ => AssetLib}/Ply/PlyLoader.h | 0 code/{ => AssetLib}/Ply/PlyParser.cpp | 0 code/{ => AssetLib}/Ply/PlyParser.h | 0 code/{ => AssetLib}/Q3BSP/Q3BSPFileData.h | 0 .../Q3BSP/Q3BSPFileImporter.cpp | 0 code/{ => AssetLib}/Q3BSP/Q3BSPFileImporter.h | 0 code/{ => AssetLib}/Q3BSP/Q3BSPFileParser.cpp | 0 code/{ => AssetLib}/Q3BSP/Q3BSPFileParser.h | 0 code/{ => AssetLib}/Q3D/Q3DLoader.cpp | 0 code/{ => AssetLib}/Q3D/Q3DLoader.h | 0 code/{ => AssetLib}/Raw/RawLoader.cpp | 0 code/{ => AssetLib}/Raw/RawLoader.h | 0 code/{ => AssetLib}/SIB/SIBImporter.cpp | 0 code/{ => AssetLib}/SIB/SIBImporter.h | 0 code/{ => AssetLib}/SMD/SMDLoader.cpp | 0 code/{ => AssetLib}/SMD/SMDLoader.h | 0 .../STEPParser/STEPFileEncoding.cpp | 0 .../STEPParser/STEPFileEncoding.h | 0 .../STEPParser/STEPFileReader.cpp | 0 .../STEPParser/STEPFileReader.h | 2 +- code/{ => AssetLib}/STL/STLExporter.cpp | 0 code/{ => AssetLib}/STL/STLExporter.h | 0 code/{ => AssetLib}/STL/STLLoader.cpp | 0 code/{ => AssetLib}/STL/STLLoader.h | 0 code/{ => AssetLib}/Step/STEPFile.h | 2 +- code/{ => AssetLib}/Step/StepExporter.cpp | 2 +- code/{ => AssetLib}/Step/StepExporter.h | 0 .../StepFile/StepFileGen1.cpp | 0 .../StepFile/StepFileGen2.cpp | 0 .../StepFile/StepFileGen3.cpp | 0 .../StepFile/StepFileImporter.cpp | 0 .../StepFile/StepFileImporter.h | 0 .../StepFile/StepReaderGen.h | 0 .../Terragen/TerragenLoader.cpp | 0 code/{ => AssetLib}/Terragen/TerragenLoader.h | 0 code/{ => AssetLib}/Unreal/UnrealLoader.cpp | 2 +- code/{ => AssetLib}/Unreal/UnrealLoader.h | 0 code/{ => AssetLib}/X/XFileExporter.cpp | 2 +- code/{ => AssetLib}/X/XFileExporter.h | 0 code/{ => AssetLib}/X/XFileHelper.h | 0 code/{ => AssetLib}/X/XFileImporter.cpp | 4 +- code/{ => AssetLib}/X/XFileImporter.h | 0 code/{ => AssetLib}/X/XFileParser.cpp | 0 code/{ => AssetLib}/X/XFileParser.h | 0 code/{ => AssetLib}/X3D/FIReader.cpp | 0 code/{ => AssetLib}/X3D/FIReader.hpp | 0 code/{ => AssetLib}/X3D/X3DExporter.cpp | 0 code/{ => AssetLib}/X3D/X3DExporter.hpp | 0 code/{ => AssetLib}/X3D/X3DImporter.cpp | 0 code/{ => AssetLib}/X3D/X3DImporter.hpp | 0 .../X3D/X3DImporter_Geometry2D.cpp | 0 .../X3D/X3DImporter_Geometry3D.cpp | 0 code/{ => AssetLib}/X3D/X3DImporter_Group.cpp | 0 code/{ => AssetLib}/X3D/X3DImporter_Light.cpp | 0 code/{ => AssetLib}/X3D/X3DImporter_Macro.hpp | 0 .../X3D/X3DImporter_Metadata.cpp | 0 .../X3D/X3DImporter_Networking.cpp | 0 code/{ => AssetLib}/X3D/X3DImporter_Node.hpp | 0 .../X3D/X3DImporter_Postprocess.cpp | 0 .../X3D/X3DImporter_Rendering.cpp | 0 code/{ => AssetLib}/X3D/X3DImporter_Shape.cpp | 0 .../X3D/X3DImporter_Texturing.cpp | 0 code/{ => AssetLib}/X3D/X3DVocabulary.cpp | 0 code/{ => AssetLib}/XGL/XGLLoader.cpp | 0 code/{ => AssetLib}/XGL/XGLLoader.h | 0 code/{ => AssetLib}/glTF/glTFAsset.h | 2 +- code/{ => AssetLib}/glTF/glTFAsset.inl | 0 code/{ => AssetLib}/glTF/glTFAssetWriter.h | 0 code/{ => AssetLib}/glTF/glTFAssetWriter.inl | 0 code/{ => AssetLib}/glTF/glTFCommon.cpp | 2 +- code/{ => AssetLib}/glTF/glTFCommon.h | 0 code/{ => AssetLib}/glTF/glTFExporter.cpp | 4 +- code/{ => AssetLib}/glTF/glTFExporter.h | 0 code/{ => AssetLib}/glTF/glTFImporter.cpp | 6 +- code/{ => AssetLib}/glTF/glTFImporter.h | 0 code/{ => AssetLib}/glTF2/glTF2Asset.h | 3 +- code/{ => AssetLib}/glTF2/glTF2Asset.inl | 5 +- code/{ => AssetLib}/glTF2/glTF2AssetWriter.h | 0 .../{ => AssetLib}/glTF2/glTF2AssetWriter.inl | 0 code/{ => AssetLib}/glTF2/glTF2Exporter.cpp | 4 +- code/{ => AssetLib}/glTF2/glTF2Exporter.h | 0 code/{ => AssetLib}/glTF2/glTF2Importer.cpp | 6 +- code/{ => AssetLib}/glTF2/glTF2Importer.h | 0 code/Assxml/AssxmlFileWriter.cpp | 664 ------- code/B3D/B3DImporter.cpp | 747 ------- code/BVH/BVHLoader.cpp | 578 ------ code/Blender/BlenderCustomData.cpp | 189 -- code/Blender/BlenderScene.cpp | 875 --------- code/CMakeLists.txt | 612 +++--- code/Collada/ColladaExporter.cpp | 1708 ----------------- code/Common/ImporterRegistry.cpp | 238 ++- code/LWO/LWOFileData.h | 703 ------- code/MMD/MMDImporter.cpp | 372 ---- .../MDL/utMDLImporter_HL1_ImportSettings.cpp | 2 +- .../MDL/utMDLImporter_HL1_Materials.cpp | 2 +- .../MDL/utMDLImporter_HL1_Nodes.cpp | 2 +- test/unit/utBlenderIntermediate.cpp | 2 +- test/unit/utD3MFImportExport.cpp | 2 +- test/unit/utObjTools.cpp | 4 +- test/unit/utPMXImporter.cpp | 2 +- test/unit/utSIBImporter.cpp | 2 +- test/unit/utSMDImportExport.cpp | 2 +- tools/assimp_cmd/WriteDump.cpp | 4 +- tools/assimp_view/Background.cpp | 381 ++-- tools/assimp_view/CMakeLists.txt | 5 +- tools/assimp_view/LogWindow.cpp | 110 +- tools/assimp_view/Normals.cpp | 34 +- tools/assimp_view/SceneAnimator.cpp | 106 +- tools/assimp_view/Shaders.cpp | 1299 +++++++------ tools/assimp_view/assimp_view.h | 2 - 341 files changed, 11958 insertions(+), 13103 deletions(-) delete mode 100644 code/AMF/AMFImporter.cpp delete mode 100644 code/AMF/AMFImporter_Postprocess.cpp rename code/{ => AssetLib}/3DS/3DSConverter.cpp (59%) rename code/{ => AssetLib}/3DS/3DSExporter.cpp (75%) rename code/{ => AssetLib}/3DS/3DSExporter.h (100%) rename code/{ => AssetLib}/3DS/3DSHelper.h (100%) rename code/{ => AssetLib}/3DS/3DSLoader.cpp (69%) rename code/{ => AssetLib}/3DS/3DSLoader.h (100%) rename code/{ => AssetLib}/3MF/3MFXmlTags.h (100%) rename code/{ => AssetLib}/3MF/D3MFExporter.cpp (55%) rename code/{ => AssetLib}/3MF/D3MFExporter.h (100%) rename code/{ => AssetLib}/3MF/D3MFImporter.cpp (58%) rename code/{ => AssetLib}/3MF/D3MFImporter.h (100%) rename code/{ => AssetLib}/3MF/D3MFOpcPackage.cpp (100%) rename code/{ => AssetLib}/3MF/D3MFOpcPackage.h (100%) rename code/{ => AssetLib}/AC/ACLoader.cpp (94%) rename code/{ => AssetLib}/AC/ACLoader.h (78%) create mode 100644 code/AssetLib/AMF/AMFImporter.cpp rename code/{ => AssetLib}/AMF/AMFImporter.hpp (100%) rename code/{ => AssetLib}/AMF/AMFImporter_Geometry.cpp (100%) rename code/{ => AssetLib}/AMF/AMFImporter_Macro.hpp (100%) rename code/{ => AssetLib}/AMF/AMFImporter_Material.cpp (100%) rename code/{ => AssetLib}/AMF/AMFImporter_Node.hpp (100%) create mode 100644 code/AssetLib/AMF/AMFImporter_Postprocess.cpp rename code/{ => AssetLib}/ASE/ASELoader.cpp (64%) rename code/{ => AssetLib}/ASE/ASELoader.h (100%) rename code/{ => AssetLib}/ASE/ASEParser.cpp (59%) rename code/{ => AssetLib}/ASE/ASEParser.h (99%) rename code/{ => AssetLib}/Assbin/AssbinExporter.cpp (99%) rename code/{ => AssetLib}/Assbin/AssbinExporter.h (100%) rename code/{ => AssetLib}/Assbin/AssbinFileWriter.cpp (96%) rename code/{ => AssetLib}/Assbin/AssbinFileWriter.h (92%) rename code/{ => AssetLib}/Assbin/AssbinLoader.cpp (96%) rename code/{ => AssetLib}/Assbin/AssbinLoader.h (100%) rename code/{ => AssetLib}/Assjson/cencode.c (100%) rename code/{ => AssetLib}/Assjson/cencode.h (100%) rename code/{ => AssetLib}/Assjson/json_exporter.cpp (100%) rename code/{ => AssetLib}/Assjson/mesh_splitter.cpp (100%) rename code/{ => AssetLib}/Assjson/mesh_splitter.h (100%) rename code/{ => AssetLib}/Assxml/AssxmlExporter.cpp (100%) rename code/{ => AssetLib}/Assxml/AssxmlExporter.h (100%) create mode 100644 code/AssetLib/Assxml/AssxmlFileWriter.cpp rename code/{ => AssetLib}/Assxml/AssxmlFileWriter.h (100%) create mode 100644 code/AssetLib/B3D/B3DImporter.cpp rename code/{ => AssetLib}/B3D/B3DImporter.h (100%) create mode 100644 code/AssetLib/BVH/BVHLoader.cpp rename code/{ => AssetLib}/BVH/BVHLoader.h (82%) rename code/{ => AssetLib}/Blender/BlenderBMesh.cpp (55%) rename code/{ => AssetLib}/Blender/BlenderBMesh.h (100%) create mode 100644 code/AssetLib/Blender/BlenderCustomData.cpp rename code/{ => AssetLib}/Blender/BlenderCustomData.h (100%) rename code/{ => AssetLib}/Blender/BlenderDNA.cpp (73%) rename code/{ => AssetLib}/Blender/BlenderDNA.h (76%) rename code/{ => AssetLib}/Blender/BlenderDNA.inl (99%) rename code/{ => AssetLib}/Blender/BlenderIntermediate.h (100%) rename code/{ => AssetLib}/Blender/BlenderLoader.cpp (100%) rename code/{ => AssetLib}/Blender/BlenderLoader.h (100%) rename code/{ => AssetLib}/Blender/BlenderModifier.cpp (94%) rename code/{ => AssetLib}/Blender/BlenderModifier.h (100%) create mode 100644 code/AssetLib/Blender/BlenderScene.cpp rename code/{ => AssetLib}/Blender/BlenderScene.h (67%) rename code/{ => AssetLib}/Blender/BlenderSceneGen.h (100%) rename code/{ => AssetLib}/Blender/BlenderTessellator.cpp (100%) rename code/{ => AssetLib}/Blender/BlenderTessellator.h (100%) rename code/{ => AssetLib}/C4D/C4DImporter.cpp (100%) rename code/{ => AssetLib}/C4D/C4DImporter.h (100%) rename code/{ => AssetLib}/COB/COBLoader.cpp (53%) rename code/{ => AssetLib}/COB/COBLoader.h (100%) rename code/{ => AssetLib}/COB/COBScene.h (100%) rename code/{ => AssetLib}/CSM/CSMLoader.cpp (100%) rename code/{ => AssetLib}/CSM/CSMLoader.h (100%) create mode 100644 code/AssetLib/Collada/ColladaExporter.cpp rename code/{ => AssetLib}/Collada/ColladaExporter.h (100%) rename code/{ => AssetLib}/Collada/ColladaHelper.cpp (100%) rename code/{ => AssetLib}/Collada/ColladaHelper.h (100%) rename code/{ => AssetLib}/Collada/ColladaLoader.cpp (100%) rename code/{ => AssetLib}/Collada/ColladaLoader.h (100%) rename code/{ => AssetLib}/Collada/ColladaParser.cpp (100%) rename code/{ => AssetLib}/Collada/ColladaParser.h (100%) rename code/{ => AssetLib}/DXF/DXFHelper.h (100%) rename code/{ => AssetLib}/DXF/DXFLoader.cpp (99%) rename code/{ => AssetLib}/DXF/DXFLoader.h (100%) rename code/{ => AssetLib}/FBX/FBXAnimation.cpp (100%) rename code/{ => AssetLib}/FBX/FBXBinaryTokenizer.cpp (100%) rename code/{ => AssetLib}/FBX/FBXCommon.h (100%) rename code/{ => AssetLib}/FBX/FBXCompileConfig.h (100%) rename code/{ => AssetLib}/FBX/FBXConverter.cpp (100%) rename code/{ => AssetLib}/FBX/FBXConverter.h (100%) rename code/{ => AssetLib}/FBX/FBXDeformer.cpp (100%) rename code/{ => AssetLib}/FBX/FBXDocument.cpp (100%) rename code/{ => AssetLib}/FBX/FBXDocument.h (100%) rename code/{ => AssetLib}/FBX/FBXDocumentUtil.cpp (100%) rename code/{ => AssetLib}/FBX/FBXDocumentUtil.h (100%) rename code/{ => AssetLib}/FBX/FBXExportNode.cpp (100%) rename code/{ => AssetLib}/FBX/FBXExportNode.h (100%) rename code/{ => AssetLib}/FBX/FBXExportProperty.cpp (100%) rename code/{ => AssetLib}/FBX/FBXExportProperty.h (100%) rename code/{ => AssetLib}/FBX/FBXExporter.cpp (100%) rename code/{ => AssetLib}/FBX/FBXExporter.h (100%) rename code/{ => AssetLib}/FBX/FBXImportSettings.h (100%) rename code/{ => AssetLib}/FBX/FBXImporter.cpp (100%) rename code/{ => AssetLib}/FBX/FBXImporter.h (100%) rename code/{ => AssetLib}/FBX/FBXMaterial.cpp (100%) rename code/{ => AssetLib}/FBX/FBXMeshGeometry.cpp (100%) rename code/{ => AssetLib}/FBX/FBXMeshGeometry.h (100%) rename code/{ => AssetLib}/FBX/FBXModel.cpp (100%) rename code/{ => AssetLib}/FBX/FBXNodeAttribute.cpp (100%) rename code/{ => AssetLib}/FBX/FBXParser.cpp (100%) rename code/{ => AssetLib}/FBX/FBXParser.h (100%) rename code/{ => AssetLib}/FBX/FBXProperties.cpp (100%) rename code/{ => AssetLib}/FBX/FBXProperties.h (100%) rename code/{ => AssetLib}/FBX/FBXTokenizer.cpp (100%) rename code/{ => AssetLib}/FBX/FBXTokenizer.h (100%) rename code/{ => AssetLib}/FBX/FBXUtil.cpp (100%) rename code/{ => AssetLib}/FBX/FBXUtil.h (100%) rename code/{ => AssetLib}/HMP/HMPFileData.h (100%) rename code/{ => AssetLib}/HMP/HMPLoader.cpp (99%) rename code/{ => AssetLib}/HMP/HMPLoader.h (98%) rename code/{ => AssetLib}/HMP/HalfLifeFileData.h (100%) rename code/{Importer => AssetLib}/IFC/IFCBoolean.cpp (74%) rename code/{Importer => AssetLib}/IFC/IFCCurve.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCGeometry.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCLoader.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCLoader.h (100%) rename code/{Importer => AssetLib}/IFC/IFCMaterial.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCOpenings.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCProfile.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCReaderGen1_2x3.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCReaderGen2_2x3.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCReaderGen_2x3.h (99%) rename code/{Importer => AssetLib}/IFC/IFCReaderGen_4.cpp (100%) rename code/{Importer => AssetLib}/IFC/IFCReaderGen_4.h (100%) rename code/{Importer => AssetLib}/IFC/IFCUtil.cpp (99%) rename code/{Importer => AssetLib}/IFC/IFCUtil.h (99%) rename code/{ => AssetLib}/Irr/IRRLoader.cpp (99%) rename code/{ => AssetLib}/Irr/IRRLoader.h (99%) rename code/{ => AssetLib}/Irr/IRRMeshLoader.cpp (100%) rename code/{ => AssetLib}/Irr/IRRMeshLoader.h (100%) rename code/{ => AssetLib}/Irr/IRRShared.cpp (100%) rename code/{ => AssetLib}/Irr/IRRShared.h (100%) rename code/{ => AssetLib}/LWO/LWOAnimation.cpp (56%) rename code/{ => AssetLib}/LWO/LWOAnimation.h (100%) rename code/{ => AssetLib}/LWO/LWOBLoader.cpp (100%) create mode 100644 code/AssetLib/LWO/LWOFileData.h rename code/{ => AssetLib}/LWO/LWOLoader.cpp (99%) rename code/{ => AssetLib}/LWO/LWOLoader.h (100%) rename code/{ => AssetLib}/LWO/LWOMaterial.cpp (100%) rename code/{ => AssetLib}/LWS/LWSLoader.cpp (99%) rename code/{ => AssetLib}/LWS/LWSLoader.h (99%) rename code/{ => AssetLib}/M3D/M3DExporter.cpp (100%) rename code/{ => AssetLib}/M3D/M3DExporter.h (100%) rename code/{ => AssetLib}/M3D/M3DImporter.cpp (100%) rename code/{ => AssetLib}/M3D/M3DImporter.h (100%) rename code/{ => AssetLib}/M3D/M3DMaterials.h (100%) rename code/{ => AssetLib}/M3D/M3DWrapper.cpp (100%) rename code/{ => AssetLib}/M3D/M3DWrapper.h (100%) rename code/{ => AssetLib}/M3D/m3d.h (100%) rename code/{ => AssetLib}/MD2/MD2FileData.h (100%) rename code/{ => AssetLib}/MD2/MD2Loader.cpp (100%) rename code/{ => AssetLib}/MD2/MD2Loader.h (100%) rename code/{ => AssetLib}/MD2/MD2NormalTable.h (100%) rename code/{ => AssetLib}/MD3/MD3FileData.h (100%) rename code/{ => AssetLib}/MD3/MD3Loader.cpp (99%) rename code/{ => AssetLib}/MD3/MD3Loader.h (100%) rename code/{ => AssetLib}/MD4/MD4FileData.h (100%) rename code/{ => AssetLib}/MD5/MD5Loader.cpp (100%) rename code/{ => AssetLib}/MD5/MD5Loader.h (100%) rename code/{ => AssetLib}/MD5/MD5Parser.cpp (99%) rename code/{ => AssetLib}/MD5/MD5Parser.h (100%) rename code/{ => AssetLib}/MDC/MDCFileData.h (100%) rename code/{ => AssetLib}/MDC/MDCLoader.cpp (99%) rename code/{ => AssetLib}/MDC/MDCLoader.h (100%) rename code/{ => AssetLib}/MDC/MDCNormalTable.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/HL1FileData.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/HL1ImportDefinitions.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/HL1ImportSettings.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/HL1MDLLoader.cpp (100%) rename code/{ => AssetLib}/MDL/HalfLife/HL1MDLLoader.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/HL1MeshTrivert.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/HalfLifeMDLBaseHeader.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/LogFunctions.h (100%) rename code/{ => AssetLib}/MDL/HalfLife/UniqueNameGenerator.cpp (100%) rename code/{ => AssetLib}/MDL/HalfLife/UniqueNameGenerator.h (100%) rename code/{ => AssetLib}/MDL/MDLDefaultColorMap.h (100%) rename code/{ => AssetLib}/MDL/MDLFileData.h (100%) rename code/{ => AssetLib}/MDL/MDLLoader.cpp (99%) rename code/{ => AssetLib}/MDL/MDLLoader.h (99%) rename code/{ => AssetLib}/MDL/MDLMaterialLoader.cpp (100%) rename code/{ => AssetLib}/MMD/MMDCpp14.h (100%) create mode 100644 code/AssetLib/MMD/MMDImporter.cpp rename code/{ => AssetLib}/MMD/MMDImporter.h (100%) rename code/{ => AssetLib}/MMD/MMDPmdParser.h (100%) rename code/{ => AssetLib}/MMD/MMDPmxParser.cpp (100%) rename code/{ => AssetLib}/MMD/MMDPmxParser.h (100%) rename code/{ => AssetLib}/MMD/MMDVmdParser.h (100%) rename code/{ => AssetLib}/MS3D/MS3DLoader.cpp (100%) rename code/{ => AssetLib}/MS3D/MS3DLoader.h (100%) rename code/{ => AssetLib}/NDO/NDOLoader.cpp (100%) rename code/{ => AssetLib}/NDO/NDOLoader.h (100%) rename code/{ => AssetLib}/NFF/NFFLoader.cpp (100%) rename code/{ => AssetLib}/NFF/NFFLoader.h (100%) rename code/{ => AssetLib}/OFF/OFFLoader.cpp (100%) rename code/{ => AssetLib}/OFF/OFFLoader.h (100%) rename code/{ => AssetLib}/Obj/ObjExporter.cpp (100%) rename code/{ => AssetLib}/Obj/ObjExporter.h (100%) rename code/{ => AssetLib}/Obj/ObjFileData.h (100%) rename code/{ => AssetLib}/Obj/ObjFileImporter.cpp (100%) rename code/{ => AssetLib}/Obj/ObjFileImporter.h (100%) rename code/{ => AssetLib}/Obj/ObjFileMtlImporter.cpp (100%) rename code/{ => AssetLib}/Obj/ObjFileMtlImporter.h (100%) rename code/{ => AssetLib}/Obj/ObjFileParser.cpp (100%) rename code/{ => AssetLib}/Obj/ObjFileParser.h (100%) rename code/{ => AssetLib}/Obj/ObjTools.h (100%) rename code/{ => AssetLib}/Ogre/OgreBinarySerializer.cpp (100%) rename code/{ => AssetLib}/Ogre/OgreBinarySerializer.h (100%) rename code/{ => AssetLib}/Ogre/OgreImporter.cpp (100%) rename code/{ => AssetLib}/Ogre/OgreImporter.h (100%) rename code/{ => AssetLib}/Ogre/OgreMaterial.cpp (100%) rename code/{ => AssetLib}/Ogre/OgreParsingUtils.h (100%) rename code/{ => AssetLib}/Ogre/OgreStructs.cpp (100%) rename code/{ => AssetLib}/Ogre/OgreStructs.h (100%) rename code/{ => AssetLib}/Ogre/OgreXmlSerializer.cpp (100%) rename code/{ => AssetLib}/Ogre/OgreXmlSerializer.h (100%) rename code/{ => AssetLib}/OpenGEX/OpenGEXExporter.cpp (100%) rename code/{ => AssetLib}/OpenGEX/OpenGEXExporter.h (100%) rename code/{ => AssetLib}/OpenGEX/OpenGEXImporter.cpp (99%) rename code/{ => AssetLib}/OpenGEX/OpenGEXImporter.h (100%) rename code/{ => AssetLib}/OpenGEX/OpenGEXStructs.h (100%) rename code/{ => AssetLib}/Ply/PlyExporter.cpp (100%) rename code/{ => AssetLib}/Ply/PlyExporter.h (100%) rename code/{ => AssetLib}/Ply/PlyLoader.cpp (100%) rename code/{ => AssetLib}/Ply/PlyLoader.h (100%) rename code/{ => AssetLib}/Ply/PlyParser.cpp (100%) rename code/{ => AssetLib}/Ply/PlyParser.h (100%) rename code/{ => AssetLib}/Q3BSP/Q3BSPFileData.h (100%) rename code/{ => AssetLib}/Q3BSP/Q3BSPFileImporter.cpp (100%) rename code/{ => AssetLib}/Q3BSP/Q3BSPFileImporter.h (100%) rename code/{ => AssetLib}/Q3BSP/Q3BSPFileParser.cpp (100%) rename code/{ => AssetLib}/Q3BSP/Q3BSPFileParser.h (100%) rename code/{ => AssetLib}/Q3D/Q3DLoader.cpp (100%) rename code/{ => AssetLib}/Q3D/Q3DLoader.h (100%) rename code/{ => AssetLib}/Raw/RawLoader.cpp (100%) rename code/{ => AssetLib}/Raw/RawLoader.h (100%) rename code/{ => AssetLib}/SIB/SIBImporter.cpp (100%) rename code/{ => AssetLib}/SIB/SIBImporter.h (100%) rename code/{ => AssetLib}/SMD/SMDLoader.cpp (100%) rename code/{ => AssetLib}/SMD/SMDLoader.h (100%) rename code/{Importer => AssetLib}/STEPParser/STEPFileEncoding.cpp (100%) rename code/{Importer => AssetLib}/STEPParser/STEPFileEncoding.h (100%) rename code/{Importer => AssetLib}/STEPParser/STEPFileReader.cpp (100%) rename code/{Importer => AssetLib}/STEPParser/STEPFileReader.h (98%) rename code/{ => AssetLib}/STL/STLExporter.cpp (100%) rename code/{ => AssetLib}/STL/STLExporter.h (100%) rename code/{ => AssetLib}/STL/STLLoader.cpp (100%) rename code/{ => AssetLib}/STL/STLLoader.h (100%) rename code/{ => AssetLib}/Step/STEPFile.h (99%) rename code/{ => AssetLib}/Step/StepExporter.cpp (99%) rename code/{ => AssetLib}/Step/StepExporter.h (100%) rename code/{Importer => AssetLib}/StepFile/StepFileGen1.cpp (100%) rename code/{Importer => AssetLib}/StepFile/StepFileGen2.cpp (100%) rename code/{Importer => AssetLib}/StepFile/StepFileGen3.cpp (100%) rename code/{Importer => AssetLib}/StepFile/StepFileImporter.cpp (100%) rename code/{Importer => AssetLib}/StepFile/StepFileImporter.h (100%) rename code/{Importer => AssetLib}/StepFile/StepReaderGen.h (100%) rename code/{ => AssetLib}/Terragen/TerragenLoader.cpp (100%) rename code/{ => AssetLib}/Terragen/TerragenLoader.h (100%) rename code/{ => AssetLib}/Unreal/UnrealLoader.cpp (99%) rename code/{ => AssetLib}/Unreal/UnrealLoader.h (100%) rename code/{ => AssetLib}/X/XFileExporter.cpp (99%) rename code/{ => AssetLib}/X/XFileExporter.h (100%) rename code/{ => AssetLib}/X/XFileHelper.h (100%) rename code/{ => AssetLib}/X/XFileImporter.cpp (99%) rename code/{ => AssetLib}/X/XFileImporter.h (100%) rename code/{ => AssetLib}/X/XFileParser.cpp (100%) rename code/{ => AssetLib}/X/XFileParser.h (100%) rename code/{ => AssetLib}/X3D/FIReader.cpp (100%) rename code/{ => AssetLib}/X3D/FIReader.hpp (100%) rename code/{ => AssetLib}/X3D/X3DExporter.cpp (100%) rename code/{ => AssetLib}/X3D/X3DExporter.hpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter.hpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Geometry2D.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Geometry3D.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Group.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Light.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Macro.hpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Metadata.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Networking.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Node.hpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Postprocess.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Rendering.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Shape.cpp (100%) rename code/{ => AssetLib}/X3D/X3DImporter_Texturing.cpp (100%) rename code/{ => AssetLib}/X3D/X3DVocabulary.cpp (100%) rename code/{ => AssetLib}/XGL/XGLLoader.cpp (100%) rename code/{ => AssetLib}/XGL/XGLLoader.h (100%) rename code/{ => AssetLib}/glTF/glTFAsset.h (99%) rename code/{ => AssetLib}/glTF/glTFAsset.inl (100%) rename code/{ => AssetLib}/glTF/glTFAssetWriter.h (100%) rename code/{ => AssetLib}/glTF/glTFAssetWriter.inl (100%) rename code/{ => AssetLib}/glTF/glTFCommon.cpp (99%) rename code/{ => AssetLib}/glTF/glTFCommon.h (100%) rename code/{ => AssetLib}/glTF/glTFExporter.cpp (99%) rename code/{ => AssetLib}/glTF/glTFExporter.h (100%) rename code/{ => AssetLib}/glTF/glTFImporter.cpp (99%) rename code/{ => AssetLib}/glTF/glTFImporter.h (100%) rename code/{ => AssetLib}/glTF2/glTF2Asset.h (99%) rename code/{ => AssetLib}/glTF2/glTF2Asset.inl (99%) rename code/{ => AssetLib}/glTF2/glTF2AssetWriter.h (100%) rename code/{ => AssetLib}/glTF2/glTF2AssetWriter.inl (100%) rename code/{ => AssetLib}/glTF2/glTF2Exporter.cpp (99%) rename code/{ => AssetLib}/glTF2/glTF2Exporter.h (100%) rename code/{ => AssetLib}/glTF2/glTF2Importer.cpp (99%) rename code/{ => AssetLib}/glTF2/glTF2Importer.h (100%) delete mode 100644 code/Assxml/AssxmlFileWriter.cpp delete mode 100644 code/B3D/B3DImporter.cpp delete mode 100644 code/BVH/BVHLoader.cpp delete mode 100644 code/Blender/BlenderCustomData.cpp delete mode 100644 code/Blender/BlenderScene.cpp delete mode 100644 code/Collada/ColladaExporter.cpp delete mode 100644 code/LWO/LWOFileData.h delete mode 100644 code/MMD/MMDImporter.cpp diff --git a/code/AMF/AMFImporter.cpp b/code/AMF/AMFImporter.cpp deleted file mode 100644 index df4324d4d..000000000 --- a/code/AMF/AMFImporter.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2020, assimp team - - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/// \file AMFImporter.cpp -/// \brief AMF-format files importer for Assimp: main algorithm implementation. -/// \date 2016 -/// \author smal.root@gmail.com - -#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER - -// Header files, Assimp. -#include "AMFImporter.hpp" -#include "AMFImporter_Macro.hpp" - -#include -#include - -// Header files, stdlib. -#include - -namespace Assimp -{ - -/// \var aiImporterDesc AMFImporter::Description -/// Conastant which hold importer description -const aiImporterDesc AMFImporter::Description = { - "Additive manufacturing file format(AMF) Importer", - "smalcom", - "", - "See documentation in source code. Chapter: Limitations.", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, - 0, - 0, - 0, - 0, - "amf" -}; - -void AMFImporter::Clear() -{ - mNodeElement_Cur = nullptr; - mUnit.clear(); - mMaterial_Converted.clear(); - mTexture_Converted.clear(); - // Delete all elements - if(!mNodeElement_List.empty()) - { - for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; } - - mNodeElement_List.clear(); - } -} - -AMFImporter::~AMFImporter() -{ - if(mReader != nullptr) delete mReader; - // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. - Clear(); -} - -/*********************************************************************************************************************************************/ -/************************************************************ Functions: find set ************************************************************/ -/*********************************************************************************************************************************************/ - -bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const -{ - for(CAMFImporter_NodeElement* ne: mNodeElement_List) - { - if((ne->ID == pID) && (ne->Type == pType)) - { - if(pNodeElement != nullptr) *pNodeElement = ne; - - return true; - } - }// for(CAMFImporter_NodeElement* ne: mNodeElement_List) - - return false; -} - -bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list& pNodeList, aiNode** pNode) const -{ -aiString node_name(pID.c_str()); - - for(aiNode* node: pNodeList) - { - if(node->mName == node_name) - { - if(pNode != nullptr) *pNode = node; - - return true; - } - }// for(aiNode* node: pNodeList) - - return false; -} - -bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const -{ - for(const SPP_Material& mat: mMaterial_Converted) - { - if(mat.ID == pID) - { - if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat; - - return true; - } - }// for(const SPP_Material& mat: mMaterial_Converted) - - return false; -} - -/*********************************************************************************************************************************************/ -/************************************************************ Functions: throw set ***********************************************************/ -/*********************************************************************************************************************************************/ - -void AMFImporter::Throw_CloseNotFound(const std::string& pNode) -{ - throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); -} - -void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName) -{ - throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); -} - -void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName) -{ - throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value."); -} - -void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription) -{ - throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription); -} - -void AMFImporter::Throw_ID_NotFound(const std::string& pID) const -{ - throw DeadlyImportError("Not found node with name \"" + pID + "\"."); -} - -/*********************************************************************************************************************************************/ -/************************************************************* Functions: XML set ************************************************************/ -/*********************************************************************************************************************************************/ - -void AMFImporter::XML_CheckNode_MustHaveChildren() -{ - if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children."); -} - -void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) -{ - static const size_t Uns_Skip_Len = 3; - const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" }; - - static bool skipped_before[Uns_Skip_Len] = { false, false, false }; - - std::string nn(mReader->getNodeName()); - bool found = false; - bool close_found = false; - size_t sk_idx; - - for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) - { - if(nn != Uns_Skip[sk_idx]) continue; - - found = true; - if(mReader->isEmptyElement()) - { - close_found = true; - - goto casu_cres; - } - - while(mReader->read()) - { - if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName())) - { - close_found = true; - - goto casu_cres; - } - } - }// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) - -casu_cres: - - if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + "."); - if(!close_found) Throw_CloseNotFound(nn); - - if(!skipped_before[sk_idx]) - { - skipped_before[sk_idx] = true; - ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); - } -} - -bool AMFImporter::XML_SearchNode(const std::string& pNodeName) -{ - while(mReader->read()) - { - if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true; - } - - return false; -} - -bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) -{ - std::string val(mReader->getAttributeValue(pAttrIdx)); - - if((val == "false") || (val == "0")) - return false; - else if((val == "true") || (val == "1")) - return true; - else - throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\""); -} - -float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) -{ - std::string val; - float tvalf; - - ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); - fast_atoreal_move(val.c_str(), tvalf, false); - - return tvalf; -} - -uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) -{ - return strtoul10(mReader->getAttributeValue(pAttrIdx)); -} - -float AMFImporter::XML_ReadNode_GetVal_AsFloat() -{ - std::string val; - float tvalf; - - if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt."); - if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt."); - - ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val); - fast_atoreal_move(val.c_str(), tvalf, false); - - return tvalf; -} - -uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32() -{ - if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt."); - if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt."); - - return strtoul10(mReader->getNodeData()); -} - -void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue) -{ - if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt."); - if(mReader->getNodeType() != irr::io::EXN_TEXT) - throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt."); - - pValue = mReader->getNodeData(); -} - -/*********************************************************************************************************************************************/ -/************************************************************ Functions: parse set ***********************************************************/ -/*********************************************************************************************************************************************/ - -void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode) -{ - mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list. - mNodeElement_Cur = pNode;// switch current element to new one. -} - -void AMFImporter::ParseHelper_Node_Exit() -{ - // check if we can walk up. - if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent; -} - -void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString) -{ - size_t instr_len; - - pOutString.clear(); - instr_len = strlen(pInStr); - if(!instr_len) return; - - pOutString.reserve(instr_len * 3 / 2); - // check and correct floats in format ".x". Must be "x.y". - if(pInStr[0] == '.') pOutString.push_back('0'); - - pOutString.push_back(pInStr[0]); - for(size_t ci = 1; ci < instr_len; ci++) - { - if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) - { - pOutString.push_back('0'); - pOutString.push_back('.'); - } - else - { - pOutString.push_back(pInStr[ci]); - } - } -} - -static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) -{ - return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); -} - -void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const -{ - // With help from - // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html - const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - uint8_t tidx = 0; - uint8_t arr4[4], arr3[3]; - - // check input data - if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four."); - // prepare output place - pOutputData.clear(); - pOutputData.reserve(pInputBase64.size() / 4 * 3); - - for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--) - { - if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) - { - arr4[tidx++] = pInputBase64[in_idx++]; - if(tidx == 4) - { - for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]); - - arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); - arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); - arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; - for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]); - - tidx = 0; - }// if(tidx == 4) - }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) - else - { - in_idx++; - }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else - } - - if(tidx) - { - for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0; - for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i])); - - arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); - arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); - arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; - for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]); - } -} - -void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) -{ - irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader. - std::unique_ptr file(pIOHandler->Open(pFile, "rb")); - - // Check whether we can read from the file - if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + "."); - - // generate a XML reader for it - std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); - mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); - if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); - // - // start reading - // search for root tag - if(XML_SearchNode("amf")) - ParseNode_Root(); - else - throw DeadlyImportError("Root node \"amf\" not found."); - - delete mReader; - // restore old XMLreader - mReader = OldReader; -} - -// -// -// Root XML element. -// Multi elements - No. -void AMFImporter::ParseNode_Root() -{ - std::string unit, version; - CAMFImporter_NodeElement *ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND_WSKIP; - - // Check attributes - if(!mUnit.empty()) - { - if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit"); - } - - // create root node element. - ne = new CAMFImporter_NodeElement_Root(nullptr); - mNodeElement_Cur = ne;// set first "current" element - // and assign attribute's values - ((CAMFImporter_NodeElement_Root*)ne)->Unit = unit; - ((CAMFImporter_NodeElement_Root*)ne)->Version = version; - - // Check for child nodes - if(!mReader->isEmptyElement()) - { - MACRO_NODECHECK_LOOPBEGIN("amf"); - if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; } - if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; } - if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; } - if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; } - if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } - MACRO_NODECHECK_LOOPEND("amf"); - mNodeElement_Cur = ne;// force restore "current" element - }// if(!mReader->isEmptyElement()) - - mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph. -} - -// -// -// A collection of objects or constellations with specific relative locations. -// Multi elements - Yes. -// Parent element - . -void AMFImporter::ParseNode_Constellation() -{ - std::string id; - CAMFImporter_NodeElement* ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - - // create and if needed - define new grouping object. - ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur); - - CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience - - if(!id.empty()) als.ID = id; - // Check for child nodes - if(!mReader->isEmptyElement()) - { - ParseHelper_Node_Enter(ne); - MACRO_NODECHECK_LOOPBEGIN("constellation"); - if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; } - if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } - MACRO_NODECHECK_LOOPEND("constellation"); - ParseHelper_Node_Exit(); - }// if(!mReader->isEmptyElement()) - else - { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else - - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -// -// -// A collection of objects or constellations with specific relative locations. -// Multi elements - Yes. -// Parent element - . -void AMFImporter::ParseNode_Instance() -{ - std::string objectid; - CAMFImporter_NodeElement* ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - - // used object id must be defined, check that. - if(objectid.empty()) throw DeadlyImportError("\"objectid\" in must be defined."); - // create and define new grouping object. - ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur); - - CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience - - als.ObjectID = objectid; - // Check for child nodes - if(!mReader->isEmptyElement()) - { - bool read_flag[6] = { false, false, false, false, false, false }; - - als.Delta.Set(0, 0, 0); - als.Rotation.Set(0, 0, 0); - ParseHelper_Node_Enter(ne); - MACRO_NODECHECK_LOOPBEGIN("instance"); - MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x); - MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y); - MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z); - MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x); - MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y); - MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z); - MACRO_NODECHECK_LOOPEND("instance"); - ParseHelper_Node_Exit(); - // also convert degrees to radians. - als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f; - als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f; - als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f; - }// if(!mReader->isEmptyElement()) - else - { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else - - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -// -// -// An object definition. -// Multi elements - Yes. -// Parent element - . -void AMFImporter::ParseNode_Object() -{ - std::string id; - CAMFImporter_NodeElement* ne( nullptr ); - - // Read attributes for node . - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - - // create and if needed - define new geometry object. - ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur); - - CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience - - if(!id.empty()) als.ID = id; - // Check for child nodes - if(!mReader->isEmptyElement()) - { - bool col_read = false; - - ParseHelper_Node_Enter(ne); - MACRO_NODECHECK_LOOPBEGIN("object"); - if(XML_CheckNode_NameEqual("color")) - { - // Check if color already defined for object. - if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for ."); - // read data and set flag about it - ParseNode_Color(); - col_read = true; - - continue; - } - - if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; } - if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } - MACRO_NODECHECK_LOOPEND("object"); - ParseHelper_Node_Exit(); - }// if(!mReader->isEmptyElement()) - else - { - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else - - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -// -// -// Specify additional information about an entity. -// Multi elements - Yes. -// Parent element - , , , , . -// -// Reserved types are: -// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user. -// "Description" - A description of the content of the entity -// "URL" - A link to an external resource relating to the entity -// "Author" - Specifies the name(s) of the author(s) of the entity -// "Company" - Specifying the company generating the entity -// "CAD" - specifies the name of the originating CAD software and version -// "Revision" - specifies the revision of the entity -// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system -// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only) -void AMFImporter::ParseNode_Metadata() -{ - std::string type, value; - CAMFImporter_NodeElement* ne( nullptr ); - - // read attribute - MACRO_ATTRREAD_LOOPBEG; - MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); - MACRO_ATTRREAD_LOOPEND; - // and value of node. - value = mReader->getNodeData(); - // Create node element and assign read data. - ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur); - ((CAMFImporter_NodeElement_Metadata*)ne)->Type = type; - ((CAMFImporter_NodeElement_Metadata*)ne)->Value = value; - mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. -} - -/*********************************************************************************************************************************************/ -/******************************************************** Functions: BaseImporter set ********************************************************/ -/*********************************************************************************************************************************************/ - -bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const -{ - const std::string extension = GetExtension(pFile); - - if ( extension == "amf" ) { - return true; - } - - if(!extension.length() || pCheckSig) - { - const char* tokens[] = { "& pExtensionList) -{ - pExtensionList.insert("amf"); -} - -const aiImporterDesc* AMFImporter::GetInfo () const -{ - return &Description; -} - -void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - Clear();// delete old graph. - ParseFile(pFile, pIOHandler); - Postprocess_BuildScene(pScene); - // scene graph is ready, exit. -} - -}// namespace Assimp - -#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER diff --git a/code/AMF/AMFImporter_Postprocess.cpp b/code/AMF/AMFImporter_Postprocess.cpp deleted file mode 100644 index 273b8e0c4..000000000 --- a/code/AMF/AMFImporter_Postprocess.cpp +++ /dev/null @@ -1,978 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2020, assimp team - - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/// \file AMFImporter_Postprocess.cpp -/// \brief Convert built scenegraph and objects to Assimp scenegraph. -/// \date 2016 -/// \author smal.root@gmail.com - -#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER - -#include "AMFImporter.hpp" - -// Header files, Assimp. -#include -#include -#include - -// Header files, stdlib. -#include - -namespace Assimp -{ - -aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const -{ - aiColor4D tcol; - - // Check if stored data are supported. - if(!Composition.empty()) - { - throw DeadlyImportError("IME. GetColor for composition"); - } - else if(Color->Composed) - { - throw DeadlyImportError("IME. GetColor, composed color"); - } - else - { - tcol = Color->Color; - } - - // Check if default color must be used - if((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) - { - tcol.r = 0.5f; - tcol.g = 0.5f; - tcol.b = 0.5f; - tcol.a = 1; - } - - return tcol; -} - -void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector& pVertexCoordinateArray, - std::vector& pVertexColorArray) const -{ - CAMFImporter_NodeElement_Vertices* vn = nullptr; - size_t col_idx; - - // All data stored in "vertices", search for it. - for(CAMFImporter_NodeElement* ne_child: pNodeElement.Child) - { - if(ne_child->Type == CAMFImporter_NodeElement::ENET_Vertices) vn = (CAMFImporter_NodeElement_Vertices*)ne_child; - } - - // If "vertices" not found then no work for us. - if(vn == nullptr) return; - - pVertexCoordinateArray.reserve(vn->Child.size());// all coordinates stored as child and we need to reserve space for future push_back's. - pVertexColorArray.resize(vn->Child.size());// colors count equal vertices count. - col_idx = 0; - // Inside vertices collect all data and place to arrays - for(CAMFImporter_NodeElement* vn_child: vn->Child) - { - // vertices, colors - if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex) - { - // by default clear color for current vertex - pVertexColorArray[col_idx] = nullptr; - - for(CAMFImporter_NodeElement* vtx: vn_child->Child) - { - if(vtx->Type == CAMFImporter_NodeElement::ENET_Coordinates) - { - pVertexCoordinateArray.push_back(((CAMFImporter_NodeElement_Coordinates*)vtx)->Coordinate); - - continue; - } - - if(vtx->Type == CAMFImporter_NodeElement::ENET_Color) - { - pVertexColorArray[col_idx] = (CAMFImporter_NodeElement_Color*)vtx; - - continue; - } - }// for(CAMFImporter_NodeElement* vtx: vn_child->Child) - - col_idx++; - }// if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex) - }// for(CAMFImporter_NodeElement* vn_child: vn->Child) -} - -size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, - const std::string& pID_A) -{ - size_t TextureConverted_Index; - std::string TextureConverted_ID; - - // check input data - if(pID_R.empty() && pID_G.empty() && pID_B.empty() && pID_A.empty()) - throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. At least one texture ID must be defined."); - - // Create ID - TextureConverted_ID = pID_R + "_" + pID_G + "_" + pID_B + "_" + pID_A; - // Check if texture specified by set of IDs is converted already. - TextureConverted_Index = 0; - for(const SPP_Texture& tex_convd: mTexture_Converted) - { - if ( tex_convd.ID == TextureConverted_ID ) { - return TextureConverted_Index; - } else { - ++TextureConverted_Index; - } - } - - // - // Converted texture not found, create it. - // - CAMFImporter_NodeElement_Texture* src_texture[4]{nullptr}; - std::vector src_texture_4check; - SPP_Texture converted_texture; - - {// find all specified source textures - CAMFImporter_NodeElement* t_tex; - - // R - if(!pID_R.empty()) - { - if(!Find_NodeElement(pID_R, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_R); - - src_texture[0] = (CAMFImporter_NodeElement_Texture*)t_tex; - src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex); - } - else - { - src_texture[0] = nullptr; - } - - // G - if(!pID_G.empty()) - { - if(!Find_NodeElement(pID_G, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_G); - - src_texture[1] = (CAMFImporter_NodeElement_Texture*)t_tex; - src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex); - } - else - { - src_texture[1] = nullptr; - } - - // B - if(!pID_B.empty()) - { - if(!Find_NodeElement(pID_B, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_B); - - src_texture[2] = (CAMFImporter_NodeElement_Texture*)t_tex; - src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex); - } - else - { - src_texture[2] = nullptr; - } - - // A - if(!pID_A.empty()) - { - if(!Find_NodeElement(pID_A, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_A); - - src_texture[3] = (CAMFImporter_NodeElement_Texture*)t_tex; - src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex); - } - else - { - src_texture[3] = nullptr; - } - }// END: find all specified source textures - - // check that all textures has same size - if(src_texture_4check.size() > 1) - { - for (size_t i = 0, i_e = (src_texture_4check.size() - 1); i < i_e; i++) - { - if((src_texture_4check[i]->Width != src_texture_4check[i + 1]->Width) || (src_texture_4check[i]->Height != src_texture_4check[i + 1]->Height) || - (src_texture_4check[i]->Depth != src_texture_4check[i + 1]->Depth)) - { - throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. Source texture must has the same size."); - } - } - }// if(src_texture_4check.size() > 1) - - // set texture attributes - converted_texture.Width = src_texture_4check[0]->Width; - converted_texture.Height = src_texture_4check[0]->Height; - converted_texture.Depth = src_texture_4check[0]->Depth; - // if one of source texture is tiled then converted texture is tiled too. - converted_texture.Tiled = false; - for(uint8_t i = 0; i < src_texture_4check.size(); i++) converted_texture.Tiled |= src_texture_4check[i]->Tiled; - - // Create format hint. - strcpy(converted_texture.FormatHint, "rgba0000");// copy initial string. - if(!pID_R.empty()) converted_texture.FormatHint[4] = '8'; - if(!pID_G.empty()) converted_texture.FormatHint[5] = '8'; - if(!pID_B.empty()) converted_texture.FormatHint[6] = '8'; - if(!pID_A.empty()) converted_texture.FormatHint[7] = '8'; - - // - // Сopy data of textures. - // - size_t tex_size = 0; - size_t step = 0; - size_t off_g = 0; - size_t off_b = 0; - - // Calculate size of the target array and rule how data will be copied. - if(!pID_R.empty() && nullptr != src_texture[ 0 ] ) { - tex_size += src_texture[0]->Data.size(); step++, off_g++, off_b++; - } - if(!pID_G.empty() && nullptr != src_texture[ 1 ] ) { - tex_size += src_texture[1]->Data.size(); step++, off_b++; - } - if(!pID_B.empty() && nullptr != src_texture[ 2 ] ) { - tex_size += src_texture[2]->Data.size(); step++; - } - if(!pID_A.empty() && nullptr != src_texture[ 3 ] ) { - tex_size += src_texture[3]->Data.size(); step++; - } - - // Create target array. - converted_texture.Data = new uint8_t[tex_size]; - // And copy data - auto CopyTextureData = [&](const std::string& pID, const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void - { - if(!pID.empty()) - { - for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) { - CAMFImporter_NodeElement_Texture* tex = src_texture[pSrcTexNum]; - ai_assert(tex); - converted_texture.Data[idx_target] = tex->Data.at(idx_src); - } - } - };// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void - - CopyTextureData(pID_R, 0, step, 0); - CopyTextureData(pID_G, off_g, step, 1); - CopyTextureData(pID_B, off_b, step, 2); - CopyTextureData(pID_A, step - 1, step, 3); - - // Store new converted texture ID - converted_texture.ID = TextureConverted_ID; - // Store new converted texture - mTexture_Converted.push_back(converted_texture); - - return TextureConverted_Index; -} - -void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list& pInputList, std::list >& pOutputList_Separated) -{ - auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap* pTexMap1, const CAMFImporter_NodeElement_TexMap* pTexMap2) -> bool - { - if((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true; - if(pTexMap1 == nullptr) return false; - if(pTexMap2 == nullptr) return false; - - if(pTexMap1->TextureID_R != pTexMap2->TextureID_R) return false; - if(pTexMap1->TextureID_G != pTexMap2->TextureID_G) return false; - if(pTexMap1->TextureID_B != pTexMap2->TextureID_B) return false; - if(pTexMap1->TextureID_A != pTexMap2->TextureID_A) return false; - - return true; - }; - - pOutputList_Separated.clear(); - if(pInputList.empty()) return; - - do - { - SComplexFace face_start = pInputList.front(); - std::list face_list_cur; - - for(std::list::iterator it = pInputList.begin(), it_end = pInputList.end(); it != it_end;) - { - if(texmap_is_equal(face_start.TexMap, it->TexMap)) - { - auto it_old = it; - - ++it; - face_list_cur.push_back(*it_old); - pInputList.erase(it_old); - } - else - { - ++it; - } - } - - if(!face_list_cur.empty()) pOutputList_Separated.push_back(face_list_cur); - - } while(!pInputList.empty()); -} - -void AMFImporter::Postprocess_AddMetadata(const std::list& metadataList, aiNode& sceneNode) const -{ - if ( !metadataList.empty() ) - { - if(sceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong."); - - // copy collected metadata to output node. - sceneNode.mMetaData = aiMetadata::Alloc( static_cast(metadataList.size()) ); - size_t meta_idx( 0 ); - - for(const CAMFImporter_NodeElement_Metadata& metadata: metadataList) - { - sceneNode.mMetaData->Set(static_cast(meta_idx++), metadata.Type, aiString(metadata.Value)); - } - }// if(!metadataList.empty()) -} - -void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list& pMeshList, aiNode** pSceneNode) -{ -CAMFImporter_NodeElement_Color* object_color = nullptr; - - // create new aiNode and set name as has. - *pSceneNode = new aiNode; - (*pSceneNode)->mName = pNodeElement.ID; - // read mesh and color - for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child) - { - std::vector vertex_arr; - std::vector color_arr; - - // color for object - if(ne_child->Type == CAMFImporter_NodeElement::ENET_Color) object_color = (CAMFImporter_NodeElement_Color*)ne_child; - - if(ne_child->Type == CAMFImporter_NodeElement::ENET_Mesh) - { - // Create arrays from children of mesh: vertices. - PostprocessHelper_CreateMeshDataArray(*((CAMFImporter_NodeElement_Mesh*)ne_child), vertex_arr, color_arr); - // Use this arrays as a source when creating every aiMesh - Postprocess_BuildMeshSet(*((CAMFImporter_NodeElement_Mesh*)ne_child), vertex_arr, color_arr, object_color, pMeshList, **pSceneNode); - } - }// for(const CAMFImporter_NodeElement* ne_child: pNodeElement) -} - -void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector& pVertexCoordinateArray, - const std::vector& pVertexColorArray, - const CAMFImporter_NodeElement_Color* pObjectColor, std::list& pMeshList, aiNode& pSceneNode) -{ -std::list mesh_idx; - - // all data stored in "volume", search for it. - for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child) - { - const CAMFImporter_NodeElement_Color* ne_volume_color = nullptr; - const SPP_Material* cur_mat = nullptr; - - if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume) - { - /******************* Get faces *******************/ - const CAMFImporter_NodeElement_Volume* ne_volume = reinterpret_cast(ne_child); - - std::list complex_faces_list;// List of the faces of the volume. - std::list > complex_faces_toplist;// List of the face list for every mesh. - - // check if volume use material - if(!ne_volume->MaterialID.empty()) - { - if(!Find_ConvertedMaterial(ne_volume->MaterialID, &cur_mat)) Throw_ID_NotFound(ne_volume->MaterialID); - } - - // inside "volume" collect all data and place to arrays or create new objects - for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child) - { - // color for volume - if(ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Color) - { - ne_volume_color = reinterpret_cast(ne_volume_child); - } - else if(ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Triangle)// triangles, triangles colors - { - const CAMFImporter_NodeElement_Triangle& tri_al = *reinterpret_cast(ne_volume_child); - - SComplexFace complex_face; - - // initialize pointers - complex_face.Color = nullptr; - complex_face.TexMap = nullptr; - // get data from triangle children: color, texture coordinates. - if(tri_al.Child.size()) - { - for(const CAMFImporter_NodeElement* ne_triangle_child: tri_al.Child) - { - if(ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_Color) - complex_face.Color = reinterpret_cast(ne_triangle_child); - else if(ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_TexMap) - complex_face.TexMap = reinterpret_cast(ne_triangle_child); - } - }// if(tri_al.Child.size()) - - // create new face and store it. - complex_face.Face.mNumIndices = 3; - complex_face.Face.mIndices = new unsigned int[3]; - complex_face.Face.mIndices[0] = static_cast(tri_al.V[0]); - complex_face.Face.mIndices[1] = static_cast(tri_al.V[1]); - complex_face.Face.mIndices[2] = static_cast(tri_al.V[2]); - complex_faces_list.push_back(complex_face); - } - }// for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child) - - /**** Split faces list: one list per mesh ****/ - PostprocessHelper_SplitFacesByTextureID(complex_faces_list, complex_faces_toplist); - - /***** Create mesh for every faces list ******/ - for(std::list& face_list_cur: complex_faces_toplist) - { - auto VertexIndex_GetMinimal = [](const std::list& pFaceList, const size_t* pBiggerThan) -> size_t - { - size_t rv=0; - - if(pBiggerThan != nullptr) - { - bool found = false; - - for(const SComplexFace& face: pFaceList) - { - for(size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) - { - if(face.Face.mIndices[idx_vert] > *pBiggerThan) - { - rv = face.Face.mIndices[idx_vert]; - found = true; - - break; - } - } - - if(found) break; - } - - if(!found) return *pBiggerThan; - } - else - { - rv = pFaceList.front().Face.mIndices[0]; - }// if(pBiggerThan != nullptr) else - - for(const SComplexFace& face: pFaceList) - { - for(size_t vi = 0; vi < face.Face.mNumIndices; vi++) - { - if(face.Face.mIndices[vi] < rv) - { - if(pBiggerThan != nullptr) - { - if(face.Face.mIndices[vi] > *pBiggerThan) rv = face.Face.mIndices[vi]; - } - else - { - rv = face.Face.mIndices[vi]; - } - } - } - }// for(const SComplexFace& face: pFaceList) - - return rv; - };// auto VertexIndex_GetMinimal = [](const std::list& pFaceList, const size_t* pBiggerThan) -> size_t - - auto VertexIndex_Replace = [](std::list& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void - { - for(const SComplexFace& face: pFaceList) - { - for(size_t vi = 0; vi < face.Face.mNumIndices; vi++) - { - if(face.Face.mIndices[vi] == pIdx_From) face.Face.mIndices[vi] = static_cast(pIdx_To); - } - } - };// auto VertexIndex_Replace = [](std::list& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void - - auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D - { - // Color priorities(In descending order): - // 1. triangle color; - // 2. vertex color; - // 3. volume color; - // 4. object color; - // 5. material; - // 6. default - invisible coat. - // - // Fill vertices colors in color priority list above that's points from 1 to 6. - if((pIdx < pVertexColorArray.size()) && (pVertexColorArray[pIdx] != nullptr))// check for vertex color - { - if(pVertexColorArray[pIdx]->Composed) - throw DeadlyImportError("IME: vertex color composed"); - else - return pVertexColorArray[pIdx]->Color; - } - else if(ne_volume_color != nullptr)// check for volume color - { - if(ne_volume_color->Composed) - throw DeadlyImportError("IME: volume color composed"); - else - return ne_volume_color->Color; - } - else if(pObjectColor != nullptr)// check for object color - { - if(pObjectColor->Composed) - throw DeadlyImportError("IME: object color composed"); - else - return pObjectColor->Color; - } - else if(cur_mat != nullptr)// check for material - { - return cur_mat->GetColor(pVertexCoordinateArray.at(pIdx).x, pVertexCoordinateArray.at(pIdx).y, pVertexCoordinateArray.at(pIdx).z); - } - else// set default color. - { - return {0, 0, 0, 0}; - }// if((vi < pVertexColorArray.size()) && (pVertexColorArray[vi] != nullptr)) else - - };// auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D - - aiMesh* tmesh = new aiMesh; - - tmesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;// Only triangles is supported by AMF. - // - // set geometry and colors (vertices) - // - // copy faces/triangles - tmesh->mNumFaces = static_cast(face_list_cur.size()); - tmesh->mFaces = new aiFace[tmesh->mNumFaces]; - - // Create vertices list and optimize indices. Optimisation mean following.In AMF all volumes use one big list of vertices. And one volume - // can use only part of vertices list, for example: vertices list contain few thousands of vertices and volume use vertices 1, 3, 10. - // Do you need all this thousands of garbage? Of course no. So, optimisation step transformate sparse indices set to continuous. - size_t VertexCount_Max = tmesh->mNumFaces * 3;// 3 - triangles. - std::vector vert_arr, texcoord_arr; - std::vector col_arr; - - vert_arr.reserve(VertexCount_Max * 2);// "* 2" - see below TODO. - col_arr.reserve(VertexCount_Max * 2); - - {// fill arrays - size_t vert_idx_from, vert_idx_to; - - // first iteration. - vert_idx_to = 0; - vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr); - vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from)); - col_arr.push_back(Vertex_CalculateColor(vert_idx_from)); - if(vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to); - - // rest iterations - do - { - vert_idx_from = VertexIndex_GetMinimal(face_list_cur, &vert_idx_to); - if(vert_idx_from == vert_idx_to) break;// all indices are transferred, - - vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from)); - col_arr.push_back(Vertex_CalculateColor(vert_idx_from)); - vert_idx_to++; - if(vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to); - - } while(true); - }// fill arrays. END. - - // - // check if triangle colors are used and create additional faces if needed. - // - for(const SComplexFace& face_cur: face_list_cur) - { - if(face_cur.Color != nullptr) - { - aiColor4D face_color; - size_t vert_idx_new = vert_arr.size(); - - if(face_cur.Color->Composed) - throw DeadlyImportError("IME: face color composed"); - else - face_color = face_cur.Color->Color; - - for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++) - { - vert_arr.push_back(vert_arr.at(face_cur.Face.mIndices[idx_ind])); - col_arr.push_back(face_color); - face_cur.Face.mIndices[idx_ind] = static_cast(vert_idx_new++); - } - }// if(face_cur.Color != nullptr) - }// for(const SComplexFace& face_cur: face_list_cur) - - // - // if texture is used then copy texture coordinates too. - // - if(face_list_cur.front().TexMap != nullptr) - { - size_t idx_vert_new = vert_arr.size(); - ///TODO: clean unused vertices. "* 2": in certain cases - mesh full of triangle colors - vert_arr will contain duplicated vertices for - /// colored triangles and initial vertices (for colored vertices) which in real became unused. This part need more thinking about - /// optimisation. - bool* idx_vert_used; - - idx_vert_used = new bool[VertexCount_Max * 2]; - for(size_t i = 0, i_e = VertexCount_Max * 2; i < i_e; i++) idx_vert_used[i] = false; - - // This ID's will be used when set materials ID in scene. - tmesh->mMaterialIndex = static_cast(PostprocessHelper_GetTextureID_Or_Create(face_list_cur.front().TexMap->TextureID_R, - face_list_cur.front().TexMap->TextureID_G, - face_list_cur.front().TexMap->TextureID_B, - face_list_cur.front().TexMap->TextureID_A)); - texcoord_arr.resize(VertexCount_Max * 2); - for(const SComplexFace& face_cur: face_list_cur) - { - for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++) - { - const size_t idx_vert = face_cur.Face.mIndices[idx_ind]; - - if(!idx_vert_used[idx_vert]) - { - texcoord_arr.at(idx_vert) = face_cur.TexMap->TextureCoordinate[idx_ind]; - idx_vert_used[idx_vert] = true; - } - else if(texcoord_arr.at(idx_vert) != face_cur.TexMap->TextureCoordinate[idx_ind]) - { - // in that case one vertex is shared with many texture coordinates. We need to duplicate vertex with another texture - // coordinates. - vert_arr.push_back(vert_arr.at(idx_vert)); - col_arr.push_back(col_arr.at(idx_vert)); - texcoord_arr.at(idx_vert_new) = face_cur.TexMap->TextureCoordinate[idx_ind]; - face_cur.Face.mIndices[idx_ind] = static_cast(idx_vert_new++); - } - }// for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++) - }// for(const SComplexFace& face_cur: face_list_cur) - - delete [] idx_vert_used; - // shrink array - texcoord_arr.resize(idx_vert_new); - }// if(face_list_cur.front().TexMap != nullptr) - - // - // copy collected data to mesh - // - tmesh->mNumVertices = static_cast(vert_arr.size()); - tmesh->mVertices = new aiVector3D[tmesh->mNumVertices]; - tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices]; - - memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D)); - memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D)); - if(texcoord_arr.size() > 0) - { - tmesh->mTextureCoords[0] = new aiVector3D[tmesh->mNumVertices]; - memcpy(tmesh->mTextureCoords[0], texcoord_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D)); - tmesh->mNumUVComponents[0] = 2;// U and V stored in "x", "y" of aiVector3D. - } - - size_t idx_face = 0; - for(const SComplexFace& face_cur: face_list_cur) tmesh->mFaces[idx_face++] = face_cur.Face; - - // store new aiMesh - mesh_idx.push_back(static_cast(pMeshList.size())); - pMeshList.push_back(tmesh); - }// for(const std::list& face_list_cur: complex_faces_toplist) - }// if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume) - }// for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child) - - // if meshes was created then assign new indices with current aiNode - if(!mesh_idx.empty()) - { - std::list::const_iterator mit = mesh_idx.begin(); - - pSceneNode.mNumMeshes = static_cast(mesh_idx.size()); - pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes]; - for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *mit++; - }// if(mesh_idx.size() > 0) -} - -void AMFImporter::Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial) -{ -SPP_Material new_mat; - - new_mat.ID = pMaterial.ID; - for(const CAMFImporter_NodeElement* mat_child: pMaterial.Child) - { - if(mat_child->Type == CAMFImporter_NodeElement::ENET_Color) - { - new_mat.Color = (CAMFImporter_NodeElement_Color*)mat_child; - } - else if(mat_child->Type == CAMFImporter_NodeElement::ENET_Metadata) - { - new_mat.Metadata.push_back((CAMFImporter_NodeElement_Metadata*)mat_child); - } - }// for(const CAMFImporter_NodeElement* mat_child; pMaterial.Child) - - // place converted material to special list - mMaterial_Converted.push_back(new_mat); -} - -void AMFImporter::Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list& pNodeList) const -{ -aiNode* con_node; -std::list ch_node; - - // We will build next hierarchy: - // aiNode as parent () for set of nodes as a children - // |- aiNode for transformation ( -> , ) - aiNode for pointing to object ("objectid") - // ... - // \_ aiNode for transformation ( -> , ) - aiNode for pointing to object ("objectid") - con_node = new aiNode; - con_node->mName = pConstellation.ID; - // Walk through children and search for instances of another objects, constellations. - for(const CAMFImporter_NodeElement* ne: pConstellation.Child) - { - aiMatrix4x4 tmat; - aiNode* t_node; - aiNode* found_node; - - if(ne->Type == CAMFImporter_NodeElement::ENET_Metadata) continue; - if(ne->Type != CAMFImporter_NodeElement::ENET_Instance) throw DeadlyImportError("Only nodes can be in ."); - - // create alias for conveniance - CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne); - // find referenced object - if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID); - - // create node for applying transformation - t_node = new aiNode; - t_node->mParent = con_node; - // apply transformation - aiMatrix4x4::Translation(als.Delta, tmat), t_node->mTransformation *= tmat; - aiMatrix4x4::RotationX(als.Rotation.x, tmat), t_node->mTransformation *= tmat; - aiMatrix4x4::RotationY(als.Rotation.y, tmat), t_node->mTransformation *= tmat; - aiMatrix4x4::RotationZ(als.Rotation.z, tmat), t_node->mTransformation *= tmat; - // create array for one child node - t_node->mNumChildren = 1; - t_node->mChildren = new aiNode*[t_node->mNumChildren]; - SceneCombiner::Copy(&t_node->mChildren[0], found_node); - t_node->mChildren[0]->mParent = t_node; - ch_node.push_back(t_node); - }// for(const CAMFImporter_NodeElement* ne: pConstellation.Child) - - // copy found aiNode's as children - if(ch_node.empty()) throw DeadlyImportError(" must have at least one ."); - - size_t ch_idx = 0; - - con_node->mNumChildren = static_cast(ch_node.size()); - con_node->mChildren = new aiNode*[con_node->mNumChildren]; - for(aiNode* node: ch_node) con_node->mChildren[ch_idx++] = node; - - // and place "root" of node to node list - pNodeList.push_back(con_node); -} - -void AMFImporter::Postprocess_BuildScene(aiScene* pScene) -{ -std::list node_list; -std::list mesh_list; -std::list meta_list; - - // - // Because for AMF "material" is just complex colors mixing so aiMaterial will not be used. - // For building aiScene we are must to do few steps: - // at first creating root node for aiScene. - pScene->mRootNode = new aiNode; - pScene->mRootNode->mParent = nullptr; - pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED; - // search for root() element - CAMFImporter_NodeElement* root_el = nullptr; - - for(CAMFImporter_NodeElement* ne: mNodeElement_List) - { - if(ne->Type != CAMFImporter_NodeElement::ENET_Root) continue; - - root_el = ne; - - break; - }// for(const CAMFImporter_NodeElement* ne: mNodeElement_List) - - // Check if root element are found. - if(root_el == nullptr) throw DeadlyImportError("Root() element not found."); - - // after that walk through children of root and collect data. Five types of nodes can be placed at top level - in : , , , - // and . But at first we must read and because they will be used in . can be read - // at any moment. - // - // 1. - // 2. will be converted later when processing triangles list. \sa Postprocess_BuildMeshSet - for(const CAMFImporter_NodeElement* root_child: root_el->Child) - { - if(root_child->Type == CAMFImporter_NodeElement::ENET_Material) Postprocess_BuildMaterial(*((CAMFImporter_NodeElement_Material*)root_child)); - } - - // After "appearance" nodes we must read because it will be used in -> . - // - // 3. - for(const CAMFImporter_NodeElement* root_child: root_el->Child) - { - if(root_child->Type == CAMFImporter_NodeElement::ENET_Object) - { - aiNode* tnode = nullptr; - - // for mesh and node must be built: object ID assigned to aiNode name and will be used in future for - Postprocess_BuildNodeAndObject(*((CAMFImporter_NodeElement_Object*)root_child), mesh_list, &tnode); - if(tnode != nullptr) node_list.push_back(tnode); - - } - }// for(const CAMFImporter_NodeElement* root_child: root_el->Child) - - // And finally read rest of nodes. - // - for(const CAMFImporter_NodeElement* root_child: root_el->Child) - { - // 4. - if(root_child->Type == CAMFImporter_NodeElement::ENET_Constellation) - { - // and at top of self abstraction use aiNode. So we can use only aiNode list for creating new aiNode's. - Postprocess_BuildConstellation(*((CAMFImporter_NodeElement_Constellation*)root_child), node_list); - } - - // 5, - if(root_child->Type == CAMFImporter_NodeElement::ENET_Metadata) meta_list.push_back((CAMFImporter_NodeElement_Metadata*)root_child); - }// for(const CAMFImporter_NodeElement* root_child: root_el->Child) - - // at now we can add collected metadata to root node - Postprocess_AddMetadata(meta_list, *pScene->mRootNode); - // - // Check constellation children - // - // As said in specification: - // "When multiple objects and constellations are defined in a single file, only the top level objects and constellations are available for printing." - // What that means? For example: if some object is used in constellation then you must show only constellation but not original object. - // And at this step we are checking that relations. -nl_clean_loop: - - if(node_list.size() > 1) - { - // walk through all nodes - for(std::list::iterator nl_it = node_list.begin(); nl_it != node_list.end(); ++nl_it) - { - // and try to find them in another top nodes. - std::list::const_iterator next_it = nl_it; - - ++next_it; - for(; next_it != node_list.end(); ++next_it) - { - if((*next_it)->FindNode((*nl_it)->mName) != nullptr) - { - // if current top node(nl_it) found in another top node then erase it from node_list and restart search loop. - node_list.erase(nl_it); - - goto nl_clean_loop; - } - }// for(; next_it != node_list.end(); next_it++) - }// for(std::list::const_iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++) - } - - // - // move created objects to aiScene - // - // - // Nodes - if(!node_list.empty()) - { - std::list::const_iterator nl_it = node_list.begin(); - - pScene->mRootNode->mNumChildren = static_cast(node_list.size()); - pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; - for(size_t i = 0; i < pScene->mRootNode->mNumChildren; i++) - { - // Objects and constellation that must be showed placed at top of hierarchy in node. So all aiNode's in node_list must have - // mRootNode only as parent. - (*nl_it)->mParent = pScene->mRootNode; - pScene->mRootNode->mChildren[i] = *nl_it++; - } - }// if(node_list.size() > 0) - - // - // Meshes - if(!mesh_list.empty()) - { - std::list::const_iterator ml_it = mesh_list.begin(); - - pScene->mNumMeshes = static_cast(mesh_list.size()); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for(size_t i = 0; i < pScene->mNumMeshes; i++) pScene->mMeshes[i] = *ml_it++; - }// if(mesh_list.size() > 0) - - // - // Textures - pScene->mNumTextures = static_cast(mTexture_Converted.size()); - if(pScene->mNumTextures > 0) - { - size_t idx; - - idx = 0; - pScene->mTextures = new aiTexture*[pScene->mNumTextures]; - for(const SPP_Texture& tex_convd: mTexture_Converted) - { - pScene->mTextures[idx] = new aiTexture; - pScene->mTextures[idx]->mWidth = static_cast(tex_convd.Width); - pScene->mTextures[idx]->mHeight = static_cast(tex_convd.Height); - pScene->mTextures[idx]->pcData = (aiTexel*)tex_convd.Data; - // texture format description. - strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint); - idx++; - }// for(const SPP_Texture& tex_convd: mTexture_Converted) - - // Create materials for embedded textures. - idx = 0; - pScene->mNumMaterials = static_cast(mTexture_Converted.size()); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for(const SPP_Texture& tex_convd: mTexture_Converted) - { - const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + to_string(idx)); - const int mode = aiTextureOp_Multiply; - const int repeat = tex_convd.Tiled ? 1 : 0; - - pScene->mMaterials[idx] = new aiMaterial; - pScene->mMaterials[idx]->AddProperty(&texture_id, AI_MATKEY_TEXTURE_DIFFUSE(0)); - pScene->mMaterials[idx]->AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0)); - pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0)); - pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0)); - idx++; - } - }// if(pScene->mNumTextures > 0) -}// END: after that walk through children of root and collect data - -}// namespace Assimp - -#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER diff --git a/code/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp similarity index 59% rename from code/3DS/3DSConverter.cpp rename to code/AssetLib/3DS/3DSConverter.cpp index 8c8a8200a..1004c74a5 100644 --- a/code/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "3DSLoader.h" #include "Common/TargetAnimation.h" +#include #include #include -#include -#include #include +#include using namespace Assimp; @@ -58,75 +58,66 @@ static const unsigned int NotSet = 0xcdcdcdcd; // ------------------------------------------------------------------------------------------------ // Setup final material indices, generae a default material if necessary -void Discreet3DSImporter::ReplaceDefaultMaterial() -{ +void Discreet3DSImporter::ReplaceDefaultMaterial() { // Try to find an existing material that matches the // typical default material setting: // - no textures // - diffuse color (in grey!) // NOTE: This is here to workaround the fact that some // exporters are writing a default material, too. - unsigned int idx( NotSet ); - for (unsigned int i = 0; i < mScene->mMaterials.size();++i) - { + unsigned int idx(NotSet); + for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { std::string s = mScene->mMaterials[i].mName; - for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) { - *it = static_cast< char >( ::tolower( *it ) ); + for (std::string::iterator it = s.begin(); it != s.end(); ++it) { + *it = static_cast(::tolower(*it)); } - if (std::string::npos == s.find("default"))continue; + if (std::string::npos == s.find("default")) continue; if (mScene->mMaterials[i].mDiffuse.r != - mScene->mMaterials[i].mDiffuse.g || - mScene->mMaterials[i].mDiffuse.r != - mScene->mMaterials[i].mDiffuse.b)continue; + mScene->mMaterials[i].mDiffuse.g || + mScene->mMaterials[i].mDiffuse.r != + mScene->mMaterials[i].mDiffuse.b) continue; - if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 || - mScene->mMaterials[i].sTexBump.mMapName.length() != 0 || - mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 || - mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 || - mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 || - mScene->mMaterials[i].sTexShininess.mMapName.length() != 0 ) - { + if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 || + mScene->mMaterials[i].sTexBump.mMapName.length() != 0 || + mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 || + mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 || + mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 || + mScene->mMaterials[i].sTexShininess.mMapName.length() != 0) { continue; } idx = i; } - if ( NotSet == idx ) { - idx = ( unsigned int )mScene->mMaterials.size(); + if (NotSet == idx) { + idx = (unsigned int)mScene->mMaterials.size(); } // now iterate through all meshes and through all faces and // find all faces that are using the default material unsigned int cnt = 0; for (std::vector::iterator - i = mScene->mMeshes.begin(); - i != mScene->mMeshes.end();++i) - { + i = mScene->mMeshes.begin(); + i != mScene->mMeshes.end(); ++i) { for (std::vector::iterator - a = (*i).mFaceMaterials.begin(); - a != (*i).mFaceMaterials.end();++a) - { + a = (*i).mFaceMaterials.begin(); + a != (*i).mFaceMaterials.end(); ++a) { // NOTE: The additional check seems to be necessary, // some exporters seem to generate invalid data here - if (0xcdcdcdcd == (*a)) - { + if (0xcdcdcdcd == (*a)) { (*a) = idx; ++cnt; - } - else if ( (*a) >= mScene->mMaterials.size()) - { + } else if ((*a) >= mScene->mMaterials.size()) { (*a) = idx; ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material"); ++cnt; } } } - if (cnt && idx == mScene->mMaterials.size()) - { + if (cnt && idx == mScene->mMaterials.size()) { // We need to create our own default material D3DS::Material sMat("%%%DEFAULT"); - sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f); + sMat.mDiffuse = aiColor3D(0.3f, 0.3f, 0.3f); mScene->mMaterials.push_back(sMat); ASSIMP_LOG_INFO("3DS: Generating default material"); @@ -135,22 +126,17 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() // ------------------------------------------------------------------------------------------------ // Check whether all indices are valid. Otherwise we'd crash before the validation step is reached -void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh) -{ - for (std::vector< D3DS::Face >::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end();++i) - { +void Discreet3DSImporter::CheckIndices(D3DS::Mesh &sMesh) { + for (std::vector::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) { // check whether all indices are in range - for (unsigned int a = 0; a < 3;++a) - { - if ((*i).mIndices[a] >= sMesh.mPositions.size()) - { + for (unsigned int a = 0; a < 3; ++a) { + if ((*i).mIndices[a] >= sMesh.mPositions.size()) { ASSIMP_LOG_WARN("3DS: Vertex index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1; + (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size() - 1; } - if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) - { + if (!sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) { ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1; + (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size() - 1; } } } @@ -158,24 +144,21 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh) // ------------------------------------------------------------------------------------------------ // Generate out unique verbose format representation -void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh) -{ +void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) { // TODO: really necessary? I don't think. Just a waste of memory and time // to do it now in a separate buffer. // Allocate output storage - std::vector vNew (sMesh.mFaces.size() * 3); + std::vector vNew(sMesh.mFaces.size() * 3); std::vector vNew2; if (sMesh.mTexCoords.size()) vNew2.resize(sMesh.mFaces.size() * 3); - for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i) - { - D3DS::Face& face = sMesh.mFaces[i]; + for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size(); ++i) { + D3DS::Face &face = sMesh.mFaces[i]; // Positions - for (unsigned int a = 0; a < 3;++a,++base) - { + for (unsigned int a = 0; a < 3; ++a, ++base) { vNew[base] = sMesh.mPositions[face.mIndices[a]]; if (sMesh.mTexCoords.size()) vNew2[base] = sMesh.mTexCoords[face.mIndices[a]]; @@ -189,26 +172,24 @@ void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh) // ------------------------------------------------------------------------------------------------ // Convert a 3DS texture to texture keys in an aiMaterial -void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type) -{ +void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) { // Setup the texture name aiString tex; - tex.Set( texture.mMapName); - mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0)); + tex.Set(texture.mMapName); + mat.AddProperty(&tex, AI_MATKEY_TEXTURE(type, 0)); // Setup the texture blend factor if (is_not_qnan(texture.mTextureBlend)) - mat.AddProperty( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); + mat.AddProperty(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0)); // Setup the texture mapping mode int mapMode = static_cast(texture.mMapMode); - mat.AddProperty(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); - mat.AddProperty(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); + mat.AddProperty(&mapMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0)); + mat.AddProperty(&mapMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0)); // Mirroring - double the scaling values // FIXME: this is not really correct ... - if (texture.mMapMode == aiTextureMapMode_Mirror) - { + if (texture.mMapMode == aiTextureMapMode_Mirror) { texture.mScaleU *= 2.0; texture.mScaleV *= 2.0; texture.mOffsetU /= 2.0; @@ -216,21 +197,19 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type) } // Setup texture UV transformations - mat.AddProperty(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); + mat.AddProperty(&texture.mOffsetU, 5, AI_MATKEY_UVTRANSFORM(type, 0)); } // ------------------------------------------------------------------------------------------------ // Convert a 3DS material to an aiMaterial -void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, - aiMaterial& mat) -{ +void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, + aiMaterial &mat) { // NOTE: Pass the background image to the viewer by bypassing the // material system. This is an evil hack, never do it again! - if (0 != mBackgroundImage.length() && bHasBG) - { + if (0 != mBackgroundImage.length() && bHasBG) { aiString tex; - tex.Set( mBackgroundImage); - mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); + tex.Set(mBackgroundImage); + mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); // Be sure this is only done for the first material mBackgroundImage = std::string(""); @@ -242,143 +221,138 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, oldMat.mAmbient.b += mClrAmbient.b; aiString name; - name.Set( oldMat.mName); - mat.AddProperty( &name, AI_MATKEY_NAME); + name.Set(oldMat.mName); + mat.AddProperty(&name, AI_MATKEY_NAME); // Material colors - mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); - mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + mat.AddProperty(&oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); + mat.AddProperty(&oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat.AddProperty(&oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); + mat.AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); // Phong shininess and shininess strength if (D3DS::Discreet3DS::Phong == oldMat.mShading || - D3DS::Discreet3DS::Metal == oldMat.mShading) - { - if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) - { + D3DS::Discreet3DS::Metal == oldMat.mShading) { + if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) { oldMat.mShading = D3DS::Discreet3DS::Gouraud; - } - else - { - mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); + } else { + mat.AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); + mat.AddProperty(&oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); } } // Opacity - mat.AddProperty( &oldMat.mTransparency,1,AI_MATKEY_OPACITY); + mat.AddProperty(&oldMat.mTransparency, 1, AI_MATKEY_OPACITY); // Bump height scaling - mat.AddProperty( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING); + mat.AddProperty(&oldMat.mBumpHeight, 1, AI_MATKEY_BUMPSCALING); // Two sided rendering? - if (oldMat.mTwoSided) - { + if (oldMat.mTwoSided) { int i = 1; - mat.AddProperty(&i,1,AI_MATKEY_TWOSIDED); + mat.AddProperty(&i, 1, AI_MATKEY_TWOSIDED); } // Shading mode aiShadingMode eShading = aiShadingMode_NoShading; - switch (oldMat.mShading) - { - case D3DS::Discreet3DS::Flat: - eShading = aiShadingMode_Flat; break; + switch (oldMat.mShading) { + case D3DS::Discreet3DS::Flat: + eShading = aiShadingMode_Flat; + break; - // I don't know what "Wire" shading should be, - // assume it is simple lambertian diffuse shading - case D3DS::Discreet3DS::Wire: - { - // Set the wireframe flag - unsigned int iWire = 1; - mat.AddProperty( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); - } + // I don't know what "Wire" shading should be, + // assume it is simple lambertian diffuse shading + case D3DS::Discreet3DS::Wire: { + // Set the wireframe flag + unsigned int iWire = 1; + mat.AddProperty((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME); + } - case D3DS::Discreet3DS::Gouraud: - eShading = aiShadingMode_Gouraud; break; + case D3DS::Discreet3DS::Gouraud: + eShading = aiShadingMode_Gouraud; + break; - // assume cook-torrance shading for metals. - case D3DS::Discreet3DS::Phong : - eShading = aiShadingMode_Phong; break; + // assume cook-torrance shading for metals. + case D3DS::Discreet3DS::Phong: + eShading = aiShadingMode_Phong; + break; - case D3DS::Discreet3DS::Metal : - eShading = aiShadingMode_CookTorrance; break; + case D3DS::Discreet3DS::Metal: + eShading = aiShadingMode_CookTorrance; + break; - // FIX to workaround a warning with GCC 4 who complained - // about a missing case Blinn: here - Blinn isn't a valid - // value in the 3DS Loader, it is just needed for ASE - case D3DS::Discreet3DS::Blinn : - eShading = aiShadingMode_Blinn; break; + // FIX to workaround a warning with GCC 4 who complained + // about a missing case Blinn: here - Blinn isn't a valid + // value in the 3DS Loader, it is just needed for ASE + case D3DS::Discreet3DS::Blinn: + eShading = aiShadingMode_Blinn; + break; } int eShading_ = static_cast(eShading); mat.AddProperty(&eShading_, 1, AI_MATKEY_SHADING_MODEL); // DIFFUSE texture - if( oldMat.sTexDiffuse.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE); + if (oldMat.sTexDiffuse.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexDiffuse, aiTextureType_DIFFUSE); // SPECULAR texture - if( oldMat.sTexSpecular.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR); + if (oldMat.sTexSpecular.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexSpecular, aiTextureType_SPECULAR); // OPACITY texture - if( oldMat.sTexOpacity.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY); + if (oldMat.sTexOpacity.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexOpacity, aiTextureType_OPACITY); // EMISSIVE texture - if( oldMat.sTexEmissive.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE); + if (oldMat.sTexEmissive.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexEmissive, aiTextureType_EMISSIVE); // BUMP texture - if( oldMat.sTexBump.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT); + if (oldMat.sTexBump.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexBump, aiTextureType_HEIGHT); // SHININESS texture - if( oldMat.sTexShininess.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS); + if (oldMat.sTexShininess.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexShininess, aiTextureType_SHININESS); // REFLECTION texture - if( oldMat.sTexReflective.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION); + if (oldMat.sTexReflective.mMapName.length() > 0) + CopyTexture(mat, oldMat.sTexReflective, aiTextureType_REFLECTION); // Store the name of the material itself, too - if( oldMat.mName.length()) { + if (oldMat.mName.length()) { aiString tex; - tex.Set( oldMat.mName); - mat.AddProperty( &tex, AI_MATKEY_NAME); + tex.Set(oldMat.mName); + mat.AddProperty(&tex, AI_MATKEY_NAME); } } // ------------------------------------------------------------------------------------------------ // Split meshes by their materials and generate output aiMesh'es -void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) -{ - std::vector avOutMeshes; +void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) { + std::vector avOutMeshes; avOutMeshes.reserve(mScene->mMeshes.size() * 2); - unsigned int iFaceCnt = 0,num = 0; + unsigned int iFaceCnt = 0, num = 0; aiString name; // we need to split all meshes by their materials - for (std::vector::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) { - std::unique_ptr< std::vector[] > aiSplit(new std::vector[mScene->mMaterials.size()]); + for (std::vector::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) { + std::unique_ptr[]> aiSplit(new std::vector[mScene->mMaterials.size()]); - name.length = ASSIMP_itoa10(name.data,num++); + name.length = ASSIMP_itoa10(name.data, num++); unsigned int iNum = 0; - for (std::vector::const_iterator a = (*i).mFaceMaterials.begin(); - a != (*i).mFaceMaterials.end();++a,++iNum) - { + for (std::vector::const_iterator a = (*i).mFaceMaterials.begin(); + a != (*i).mFaceMaterials.end(); ++a, ++iNum) { aiSplit[*a].push_back(iNum); } // now generate submeshes - for (unsigned int p = 0; p < mScene->mMaterials.size();++p) - { + for (unsigned int p = 0; p < mScene->mMaterials.size(); ++p) { if (aiSplit[p].empty()) { continue; } - aiMesh* meshOut = new aiMesh(); + aiMesh *meshOut = new aiMesh(); meshOut->mName = name; meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; @@ -386,36 +360,33 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) meshOut->mMaterialIndex = p; // use the color data as temporary storage - meshOut->mColors[0] = (aiColor4D*)(&*i); + meshOut->mColors[0] = (aiColor4D *)(&*i); avOutMeshes.push_back(meshOut); // convert vertices meshOut->mNumFaces = (unsigned int)aiSplit[p].size(); - meshOut->mNumVertices = meshOut->mNumFaces*3; + meshOut->mNumVertices = meshOut->mNumFaces * 3; // allocate enough storage for faces meshOut->mFaces = new aiFace[meshOut->mNumFaces]; iFaceCnt += meshOut->mNumFaces; meshOut->mVertices = new aiVector3D[meshOut->mNumVertices]; - meshOut->mNormals = new aiVector3D[meshOut->mNumVertices]; - if ((*i).mTexCoords.size()) - { + meshOut->mNormals = new aiVector3D[meshOut->mNumVertices]; + if ((*i).mTexCoords.size()) { meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices]; } - for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q) - { + for (unsigned int q = 0, base = 0; q < aiSplit[p].size(); ++q) { unsigned int index = aiSplit[p][q]; - aiFace& face = meshOut->mFaces[q]; + aiFace &face = meshOut->mFaces[q]; face.mIndices = new unsigned int[3]; face.mNumIndices = 3; - for (unsigned int a = 0; a < 3;++a,++base) - { + for (unsigned int a = 0; a < 3; ++a, ++base) { unsigned int idx = (*i).mFaces[index].mIndices[a]; - meshOut->mVertices[base] = (*i).mPositions[idx]; - meshOut->mNormals [base] = (*i).mNormals[idx]; + meshOut->mVertices[base] = (*i).mPositions[idx]; + meshOut->mNormals[base] = (*i).mNormals[idx]; if ((*i).mTexCoords.size()) meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx]; @@ -428,8 +399,8 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) // Copy them to the output array pcOut->mNumMeshes = (unsigned int)avOutMeshes.size(); - pcOut->mMeshes = new aiMesh*[pcOut->mNumMeshes](); - for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) { + pcOut->mMeshes = new aiMesh *[pcOut->mNumMeshes](); + for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a) { pcOut->mMeshes[a] = avOutMeshes[a]; } @@ -441,47 +412,44 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) // ------------------------------------------------------------------------------------------------ // Add a node to the scenegraph and setup its final transformation -void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, - D3DS::Node* pcIn, aiMatrix4x4& /*absTrafo*/) -{ +void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, + D3DS::Node *pcIn, aiMatrix4x4 & /*absTrafo*/) { std::vector iArray; iArray.reserve(3); aiMatrix4x4 abs; // Find all meshes with the same name as the node - for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a) - { - const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0]; - ai_assert(NULL != pcMesh); + for (unsigned int a = 0; a < pcSOut->mNumMeshes; ++a) { + const D3DS::Mesh *pcMesh = (const D3DS::Mesh *)pcSOut->mMeshes[a]->mColors[0]; + ai_assert(nullptr != pcMesh); if (pcIn->mName == pcMesh->mName) iArray.push_back(a); } - if (!iArray.empty()) - { + if (!iArray.empty()) { // The matrix should be identical for all meshes with the // same name. It HAS to be identical for all meshes ..... - D3DS::Mesh* imesh = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0]); + D3DS::Mesh *imesh = ((D3DS::Mesh *)pcSOut->mMeshes[iArray[0]]->mColors[0]); // Compute the inverse of the transformation matrix to move the // vertices back to their relative and local space aiMatrix4x4 mInv = imesh->mMat, mInvTransposed = imesh->mMat; - mInv.Inverse();mInvTransposed.Transpose(); + mInv.Inverse(); + mInvTransposed.Transpose(); aiVector3D pivot = pcIn->vPivot; pcOut->mNumMeshes = (unsigned int)iArray.size(); pcOut->mMeshes = new unsigned int[iArray.size()]; - for (unsigned int i = 0;i < iArray.size();++i) { + for (unsigned int i = 0; i < iArray.size(); ++i) { const unsigned int iIndex = iArray[i]; - aiMesh* const mesh = pcSOut->mMeshes[iIndex]; + aiMesh *const mesh = pcSOut->mMeshes[iIndex]; - if (mesh->mColors[1] == NULL) - { + if (mesh->mColors[1] == nullptr) { // Transform the vertices back into their local space // fixme: consider computing normals after this, so we don't need to transform them - const aiVector3D* const pvEnd = mesh->mVertices + mesh->mNumVertices; - aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals; + const aiVector3D *const pvEnd = mesh->mVertices + mesh->mNumVertices; + aiVector3D *pvCurrent = mesh->mVertices, *t2 = mesh->mNormals; for (; pvCurrent != pvEnd; ++pvCurrent, ++t2) { *pvCurrent = mInv * (*pvCurrent); @@ -489,8 +457,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, } // Handle negative transformation matrix determinant -> invert vertex x - if (imesh->mMat.Determinant() < 0.0f) - { + if (imesh->mMat.Determinant() < 0.0f) { /* we *must* have normals */ for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) { pvCurrent->x *= -1.f; @@ -500,17 +467,15 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, } // Handle pivot point - if (pivot.x || pivot.y || pivot.z) - { - for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent) { + if (pivot.x || pivot.y || pivot.z) { + for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent) { *pvCurrent -= pivot; } } - mesh->mColors[1] = (aiColor4D*)1; - } - else - mesh->mColors[1] = (aiColor4D*)1; + mesh->mColors[1] = (aiColor4D *)1; + } else + mesh->mColors[1] = (aiColor4D *)1; // Setup the mesh index pcOut->mMeshes[i] = iIndex; @@ -519,78 +484,75 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, // Setup the name of the node // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number - if (pcIn->mInstanceNumber > 1) - { + if (pcIn->mInstanceNumber > 1) { char tmp[12]; ASSIMP_itoa10(tmp, pcIn->mInstanceNumber); std::string tempStr = pcIn->mName + "_inst_"; tempStr += tmp; pcOut->mName.Set(tempStr); - } - else + } else pcOut->mName.Set(pcIn->mName); // Now build the transformation matrix of the node // ROTATION - if (pcIn->aRotationKeys.size()){ + if (pcIn->aRotationKeys.size()) { // FIX to get to Assimp's quaternion conventions for (std::vector::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) { (*it).mValue.w *= -1.f; } - pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() ); - } - else if (pcIn->aCameraRollKeys.size()) - { - aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue), - pcOut->mTransformation); + pcOut->mTransformation = aiMatrix4x4(pcIn->aRotationKeys[0].mValue.GetMatrix()); + } else if (pcIn->aCameraRollKeys.size()) { + aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(-pcIn->aCameraRollKeys[0].mValue), + pcOut->mTransformation); } // SCALING - aiMatrix4x4& m = pcOut->mTransformation; - if (pcIn->aScalingKeys.size()) - { - const aiVector3D& v = pcIn->aScalingKeys[0].mValue; - m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x; - m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y; - m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z; + aiMatrix4x4 &m = pcOut->mTransformation; + if (pcIn->aScalingKeys.size()) { + const aiVector3D &v = pcIn->aScalingKeys[0].mValue; + m.a1 *= v.x; + m.b1 *= v.x; + m.c1 *= v.x; + m.a2 *= v.y; + m.b2 *= v.y; + m.c2 *= v.y; + m.a3 *= v.z; + m.b3 *= v.z; + m.c3 *= v.z; } // TRANSLATION - if (pcIn->aPositionKeys.size()) - { - const aiVector3D& v = pcIn->aPositionKeys[0].mValue; + if (pcIn->aPositionKeys.size()) { + const aiVector3D &v = pcIn->aPositionKeys[0].mValue; m.a4 += v.x; m.b4 += v.y; m.c4 += v.z; } // Generate animation channels for the node - if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 || - pcIn->aScalingKeys.size() > 1 || pcIn->aCameraRollKeys.size() > 1 || - pcIn->aTargetPositionKeys.size() > 1) - { - aiAnimation* anim = pcSOut->mAnimations[0]; + if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 || + pcIn->aScalingKeys.size() > 1 || pcIn->aCameraRollKeys.size() > 1 || + pcIn->aTargetPositionKeys.size() > 1) { + aiAnimation *anim = pcSOut->mAnimations[0]; ai_assert(nullptr != anim); - if (pcIn->aCameraRollKeys.size() > 1) - { + if (pcIn->aCameraRollKeys.size() > 1) { ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ..."); // Camera roll keys - in fact they're just rotations // around the camera's z axis. The angles are given // in degrees (and they're clockwise). pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size()); - for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i) - { - aiQuatKey& q = pcIn->aRotationKeys[i]; - aiFloatKey& f = pcIn->aCameraRollKeys[i]; + for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size(); ++i) { + aiQuatKey &q = pcIn->aRotationKeys[i]; + aiFloatKey &f = pcIn->aCameraRollKeys[i]; - q.mTime = f.mTime; + q.mTime = f.mTime; // FIX to get to Assimp quaternion conventions - q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD( /*-*/ f.mValue)); + q.mValue = aiQuaternion(0.f, 0.f, AI_DEG_TO_RAD(/*-*/ f.mValue)); } } #if 0 @@ -636,102 +598,93 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, // Cameras or lights define their transformation in their parent node and in the // corresponding light or camera chunks. However, we read and process the latter // to to be able to return valid cameras/lights even if no scenegraph is given. - for (unsigned int n = 0; n < pcSOut->mNumCameras;++n) { + for (unsigned int n = 0; n < pcSOut->mNumCameras; ++n) { if (pcSOut->mCameras[n]->mName == pcOut->mName) { - pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f); + pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f, 0.f, 1.f); } } - for (unsigned int n = 0; n < pcSOut->mNumLights;++n) { + for (unsigned int n = 0; n < pcSOut->mNumLights; ++n) { if (pcSOut->mLights[n]->mName == pcOut->mName) { - pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f); + pcSOut->mLights[n]->mDirection = aiVector3D(0.f, 0.f, 1.f); } } // Allocate a new node anim and setup its name - aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); + aiNodeAnim *nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); nda->mNodeName.Set(pcIn->mName); // POSITION keys - if (pcIn->aPositionKeys.size() > 0) - { + if (pcIn->aPositionKeys.size() > 0) { nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size(); nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; - ::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0], - sizeof(aiVectorKey)*nda->mNumPositionKeys); + ::memcpy(nda->mPositionKeys, &pcIn->aPositionKeys[0], + sizeof(aiVectorKey) * nda->mNumPositionKeys); } // ROTATION keys - if (pcIn->aRotationKeys.size() > 0) - { + if (pcIn->aRotationKeys.size() > 0) { nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size(); nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys]; // Rotations are quaternion offsets aiQuaternion abs1; - for (unsigned int n = 0; n < nda->mNumRotationKeys;++n) - { - const aiQuatKey& q = pcIn->aRotationKeys[n]; + for (unsigned int n = 0; n < nda->mNumRotationKeys; ++n) { + const aiQuatKey &q = pcIn->aRotationKeys[n]; abs1 = (n ? abs1 * q.mValue : q.mValue); - nda->mRotationKeys[n].mTime = q.mTime; + nda->mRotationKeys[n].mTime = q.mTime; nda->mRotationKeys[n].mValue = abs1.Normalize(); } } // SCALING keys - if (pcIn->aScalingKeys.size() > 0) - { + if (pcIn->aScalingKeys.size() > 0) { nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size(); nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys]; - ::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0], - sizeof(aiVectorKey)*nda->mNumScalingKeys); + ::memcpy(nda->mScalingKeys, &pcIn->aScalingKeys[0], + sizeof(aiVectorKey) * nda->mNumScalingKeys); } } // Allocate storage for children pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size(); - pcOut->mChildren = new aiNode*[pcIn->mChildren.size()]; + pcOut->mChildren = new aiNode *[pcIn->mChildren.size()]; // Recursively process all children const unsigned int size = static_cast(pcIn->mChildren.size()); - for (unsigned int i = 0; i < size;++i) - { + for (unsigned int i = 0; i < size; ++i) { pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i]->mParent = pcOut; - AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs); + AddNodeToGraph(pcSOut, pcOut->mChildren[i], pcIn->mChildren[i], abs); } } // ------------------------------------------------------------------------------------------------ // Find out how many node animation channels we'll have finally -void CountTracks(D3DS::Node* node, unsigned int& cnt) -{ +void CountTracks(D3DS::Node *node, unsigned int &cnt) { ////////////////////////////////////////////////////////////////////////////// // We will never generate more than one channel for a node, so // this is rather easy here. - if (node->aPositionKeys.size() > 1 || node->aRotationKeys.size() > 1 || - node->aScalingKeys.size() > 1 || node->aCameraRollKeys.size() > 1 || - node->aTargetPositionKeys.size() > 1) - { + if (node->aPositionKeys.size() > 1 || node->aRotationKeys.size() > 1 || + node->aScalingKeys.size() > 1 || node->aCameraRollKeys.size() > 1 || + node->aTargetPositionKeys.size() > 1) { ++cnt; // account for the additional channel for the camera/spotlight target position - if (node->aTargetPositionKeys.size() > 1)++cnt; + if (node->aTargetPositionKeys.size() > 1) ++cnt; } // Recursively process all children - for (unsigned int i = 0; i < node->mChildren.size();++i) - CountTracks(node->mChildren[i],cnt); + for (unsigned int i = 0; i < node->mChildren.size(); ++i) + CountTracks(node->mChildren[i], cnt); } // ------------------------------------------------------------------------------------------------ // Generate the output node graph -void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) -{ +void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) { pcOut->mRootNode = new aiNode(); - if (0 == mRootNode->mChildren.size()) - { + if (0 == mRootNode->mChildren.size()) { ////////////////////////////////////////////////////////////////////////////// // It seems the file is so messed up that it has not even a hierarchy. // generate a flat hiearachy which looks like this: @@ -745,29 +698,27 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) ASSIMP_LOG_WARN("No hierarchy information has been found in the file. "); pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes + - static_cast(mScene->mCameras.size() + mScene->mLights.size()); + static_cast(mScene->mCameras.size() + mScene->mLights.size()); - pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ]; + pcOut->mRootNode->mChildren = new aiNode *[pcOut->mRootNode->mNumChildren]; pcOut->mRootNode->mName.Set("<3DSDummyRoot>"); // Build dummy nodes for all meshes unsigned int a = 0; - for (unsigned int i = 0; i < pcOut->mNumMeshes;++i,++a) - { - aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); + for (unsigned int i = 0; i < pcOut->mNumMeshes; ++i, ++a) { + aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); pcNode->mParent = pcOut->mRootNode; pcNode->mMeshes = new unsigned int[1]; pcNode->mMeshes[0] = i; pcNode->mNumMeshes = 1; // Build a name for the node - pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u",i); + pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i); } // Build dummy nodes for all cameras - for (unsigned int i = 0; i < (unsigned int )mScene->mCameras.size();++i,++a) - { - aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); + for (unsigned int i = 0; i < (unsigned int)mScene->mCameras.size(); ++i, ++a) { + aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); pcNode->mParent = pcOut->mRootNode; // Build a name for the node @@ -775,75 +726,68 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) } // Build dummy nodes for all lights - for (unsigned int i = 0; i < (unsigned int )mScene->mLights.size();++i,++a) - { - aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); + for (unsigned int i = 0; i < (unsigned int)mScene->mLights.size(); ++i, ++a) { + aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); pcNode->mParent = pcOut->mRootNode; // Build a name for the node pcNode->mName = mScene->mLights[i]->mName; } - } - else - { + } else { // First of all: find out how many scaling, rotation and translation // animation tracks we'll have afterwards unsigned int numChannel = 0; - CountTracks(mRootNode,numChannel); + CountTracks(mRootNode, numChannel); - if (numChannel) - { + if (numChannel) { // Allocate a primary animation channel pcOut->mNumAnimations = 1; - pcOut->mAnimations = new aiAnimation*[1]; - aiAnimation* anim = pcOut->mAnimations[0] = new aiAnimation(); + pcOut->mAnimations = new aiAnimation *[1]; + aiAnimation *anim = pcOut->mAnimations[0] = new aiAnimation(); anim->mName.Set("3DSMasterAnim"); // Allocate enough storage for all node animation channels, // but don't set the mNumChannels member - we'll use it to // index into the array - anim->mChannels = new aiNodeAnim*[numChannel]; + anim->mChannels = new aiNodeAnim *[numChannel]; } aiMatrix4x4 m; - AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m); + AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode, m); } // We used the first and second vertex color set to store some temporary values so we need to cleanup here - for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a) - { - pcOut->mMeshes[a]->mColors[0] = NULL; - pcOut->mMeshes[a]->mColors[1] = NULL; + for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a) { + pcOut->mMeshes[a]->mColors[0] = nullptr; + pcOut->mMeshes[a]->mColors[1] = nullptr; } pcOut->mRootNode->mTransformation = aiMatrix4x4( - 1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f, - 0.f,-1.f,0.f,0.f, - 0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation; + 1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, -1.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 1.f) * + pcOut->mRootNode->mTransformation; // If the root node is unnamed name it "<3DSRoot>" - if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) || - (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') ) - { + if (::strstr(pcOut->mRootNode->mName.data, "UNNAMED") || + (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$')) { pcOut->mRootNode->mName.Set("<3DSRoot>"); } } // ------------------------------------------------------------------------------------------------ // Convert all meshes in the scene and generate the final output scene. -void Discreet3DSImporter::ConvertScene(aiScene* pcOut) -{ +void Discreet3DSImporter::ConvertScene(aiScene *pcOut) { // Allocate enough storage for all output materials pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size(); - pcOut->mMaterials = new aiMaterial*[pcOut->mNumMaterials]; + pcOut->mMaterials = new aiMaterial *[pcOut->mNumMaterials]; // ... and convert the 3DS materials to aiMaterial's - for (unsigned int i = 0; i < pcOut->mNumMaterials;++i) - { - aiMaterial* pcNew = new aiMaterial(); - ConvertMaterial(mScene->mMaterials[i],*pcNew); + for (unsigned int i = 0; i < pcOut->mNumMaterials; ++i) { + aiMaterial *pcNew = new aiMaterial(); + ConvertMaterial(mScene->mMaterials[i], *pcNew); pcOut->mMaterials[i] = pcNew; } @@ -852,18 +796,16 @@ void Discreet3DSImporter::ConvertScene(aiScene* pcOut) // Now copy all light sources to the output scene pcOut->mNumLights = (unsigned int)mScene->mLights.size(); - if (pcOut->mNumLights) - { - pcOut->mLights = new aiLight*[pcOut->mNumLights]; - ::memcpy(pcOut->mLights,&mScene->mLights[0],sizeof(void*)*pcOut->mNumLights); + if (pcOut->mNumLights) { + pcOut->mLights = new aiLight *[pcOut->mNumLights]; + ::memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights); } // Now copy all cameras to the output scene pcOut->mNumCameras = (unsigned int)mScene->mCameras.size(); - if (pcOut->mNumCameras) - { - pcOut->mCameras = new aiCamera*[pcOut->mNumCameras]; - ::memcpy(pcOut->mCameras,&mScene->mCameras[0],sizeof(void*)*pcOut->mNumCameras); + if (pcOut->mNumCameras) { + pcOut->mCameras = new aiCamera *[pcOut->mNumCameras]; + ::memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras); } } diff --git a/code/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp similarity index 75% rename from code/3DS/3DSExporter.cpp rename to code/AssetLib/3DS/3DSExporter.cpp index 403ca20a2..5f3d955da 100644 --- a/code/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -43,120 +43,117 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER -#include "3DS/3DSExporter.h" -#include "3DS/3DSLoader.h" -#include "3DS/3DSHelper.h" +#include "AssetLib/3DS/3DSExporter.h" +#include "AssetLib/3DS/3DSHelper.h" +#include "AssetLib/3DS/3DSLoader.h" #include "PostProcessing/SplitLargeMeshes.h" #include #include -#include #include #include +#include #include using namespace Assimp; -namespace Assimp { +namespace Assimp { using namespace D3DS; namespace { - ////////////////////////////////////////////////////////////////////////////////////// - // Scope utility to write a 3DS file chunk. - // - // Upon construction, the chunk header is written with the chunk type (flags) - // filled out, but the chunk size left empty. Upon destruction, the correct chunk - // size based on the then-position of the output stream cursor is filled in. - class ChunkWriter { - enum { - CHUNK_SIZE_NOT_SET = 0xdeadbeef - , SIZE_OFFSET = 2 - }; - public: - - ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type) - : writer(writer) - { - chunk_start_pos = writer.GetCurrentPos(); - writer.PutU2(chunk_type); - writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET); - } - - ~ChunkWriter() { - std::size_t head_pos = writer.GetCurrentPos(); - - ai_assert(head_pos > chunk_start_pos); - const std::size_t chunk_size = head_pos - chunk_start_pos; - - writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET); - writer.PutU4(static_cast(chunk_size)); - writer.SetCurrentPos(head_pos); - } - - private: - StreamWriterLE& writer; - std::size_t chunk_start_pos; +////////////////////////////////////////////////////////////////////////////////////// +// Scope utility to write a 3DS file chunk. +// +// Upon construction, the chunk header is written with the chunk type (flags) +// filled out, but the chunk size left empty. Upon destruction, the correct chunk +// size based on the then-position of the output stream cursor is filled in. +class ChunkWriter { + enum { + CHUNK_SIZE_NOT_SET = 0xdeadbeef, + SIZE_OFFSET = 2 }; - - // Return an unique name for a given |mesh| attached to |node| that - // preserves the mesh's given name if it has one. |index| is the index - // of the mesh in |aiScene::mMeshes|. - std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) { - static const std::string underscore = "_"; - char postfix[10] = {0}; - ASSIMP_itoa10(postfix, index); - - std::string result = node.mName.C_Str(); - if (mesh.mName.length > 0) { - result += underscore + mesh.mName.C_Str(); - } - return result + underscore + postfix; +public: + ChunkWriter(StreamWriterLE &writer, uint16_t chunk_type) : + writer(writer) { + chunk_start_pos = writer.GetCurrentPos(); + writer.PutU2(chunk_type); + writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET); } - // Return an unique name for a given |mat| with original position |index| - // in |aiScene::mMaterials|. The name preserves the original material - // name if possible. - std::string GetMaterialName(const aiMaterial& mat, unsigned int index) { - static const std::string underscore = "_"; - char postfix[10] = {0}; - ASSIMP_itoa10(postfix, index); + ~ChunkWriter() { + std::size_t head_pos = writer.GetCurrentPos(); - aiString mat_name; - if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) { - return mat_name.C_Str() + underscore + postfix; - } + ai_assert(head_pos > chunk_start_pos); + const std::size_t chunk_size = head_pos - chunk_start_pos; - return "Material" + underscore + postfix; + writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET); + writer.PutU4(static_cast(chunk_size)); + writer.SetCurrentPos(head_pos); } - // Collect world transformations for each node - void CollectTrafos(const aiNode* node, std::map& trafos) { - const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4(); - trafos[node] = parent * node->mTransformation; - for (unsigned int i = 0; i < node->mNumChildren; ++i) { - CollectTrafos(node->mChildren[i], trafos); - } +private: + StreamWriterLE &writer; + std::size_t chunk_start_pos; +}; + +// Return an unique name for a given |mesh| attached to |node| that +// preserves the mesh's given name if it has one. |index| is the index +// of the mesh in |aiScene::mMeshes|. +std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) { + static const std::string underscore = "_"; + char postfix[10] = { 0 }; + ASSIMP_itoa10(postfix, index); + + std::string result = node.mName.C_Str(); + if (mesh.mName.length > 0) { + result += underscore + mesh.mName.C_Str(); + } + return result + underscore + postfix; +} + +// Return an unique name for a given |mat| with original position |index| +// in |aiScene::mMaterials|. The name preserves the original material +// name if possible. +std::string GetMaterialName(const aiMaterial &mat, unsigned int index) { + static const std::string underscore = "_"; + char postfix[10] = { 0 }; + ASSIMP_itoa10(postfix, index); + + aiString mat_name; + if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) { + return mat_name.C_Str() + underscore + postfix; } - // Generate a flat list of the meshes (by index) assigned to each node - void CollectMeshes(const aiNode* node, std::multimap& meshes) { - for (unsigned int i = 0; i < node->mNumMeshes; ++i) { - meshes.insert(std::make_pair(node, node->mMeshes[i])); - } - for (unsigned int i = 0; i < node->mNumChildren; ++i) { - CollectMeshes(node->mChildren[i], meshes); - } + return "Material" + underscore + postfix; +} + +// Collect world transformations for each node +void CollectTrafos(const aiNode *node, std::map &trafos) { + const aiMatrix4x4 &parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4(); + trafos[node] = parent * node->mTransformation; + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + CollectTrafos(node->mChildren[i], trafos); } } +// Generate a flat list of the meshes (by index) assigned to each node +void CollectMeshes(const aiNode *node, std::multimap &meshes) { + for (unsigned int i = 0; i < node->mNumMeshes; ++i) { + meshes.insert(std::make_pair(node, node->mMeshes[i])); + } + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + CollectMeshes(node->mChildren[i], meshes); + } +} +} // namespace + // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp -void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) -{ - std::shared_ptr outfile (pIOSystem->Open(pFile, "wb")); - if(!outfile) { +void ExportScene3DS(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) { + std::shared_ptr outfile(pIOSystem->Open(pFile, "wb")); + if (!outfile) { throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile)); } @@ -167,8 +164,8 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen // SplitLargeMeshes can do this, but it requires the correct limit to be set // which is not possible with the current way of specifying preprocess steps // in |Exporter::ExportFormatEntry|. - aiScene* scenecopy_tmp; - SceneCombiner::CopyScene(&scenecopy_tmp,pScene); + aiScene *scenecopy_tmp; + SceneCombiner::CopyScene(&scenecopy_tmp, pScene); std::unique_ptr scenecopy(scenecopy_tmp); SplitLargeMeshesProcess_Triangle tri_splitter; @@ -186,10 +183,8 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen } // end of namespace Assimp // ------------------------------------------------------------------------------------------------ -Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr &outfile, const aiScene* scene) -: scene(scene) -, writer(outfile) -{ +Discreet3DSExporter::Discreet3DSExporter(std::shared_ptr &outfile, const aiScene *scene) : + scene(scene), writer(outfile) { CollectTrafos(scene->mRootNode, trafos); CollectMeshes(scene->mRootNode, meshes); @@ -217,10 +212,8 @@ Discreet3DSExporter::~Discreet3DSExporter() { // empty } - // ------------------------------------------------------------------------------------------------ -int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level) -{ +int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) { // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec { ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_TRACKINFO); @@ -237,7 +230,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling int16_t hierarchy_pos = static_cast(seq); if (sibling_level != -1) { - hierarchy_pos =(uint16_t) sibling_level; + hierarchy_pos = (uint16_t)sibling_level; } // Write the hierarchy position @@ -260,7 +253,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling const bool first_child = node.mNumChildren == 0 && i == 0; const unsigned int mesh_idx = node.mMeshes[i]; - const aiMesh& mesh = *scene->mMeshes[mesh_idx]; + const aiMesh &mesh = *scene->mMeshes[mesh_idx]; ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKINFO); { @@ -276,15 +269,14 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteMaterials() -{ +void Discreet3DSExporter::WriteMaterials() { for (unsigned int i = 0; i < scene->mNumMaterials; ++i) { ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL); - const aiMaterial& mat = *scene->mMaterials[i]; + const aiMaterial &mat = *scene->mMaterials[i]; { ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME); - const std::string& name = GetMaterialName(mat, i); + const std::string &name = GetMaterialName(mat, i); WriteString(name); } @@ -314,7 +306,7 @@ void Discreet3DSExporter::WriteMaterials() ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING); Discreet3DS::shadetype3ds shading_mode_out; - switch(shading_mode) { + switch (shading_mode) { case aiShadingMode_Flat: case aiShadingMode_NoShading: shading_mode_out = Discreet3DS::Flat; @@ -341,7 +333,6 @@ void Discreet3DSExporter::WriteMaterials() writer.PutU2(static_cast(shading_mode_out)); } - float f; if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) { ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS); @@ -370,8 +361,7 @@ void Discreet3DSExporter::WriteMaterials() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags) -{ +void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) { aiString path; aiTextureMapMode map_mode[2] = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap @@ -400,8 +390,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type uint16_t val = 0; // WRAP if (map_mode[0] == aiTextureMapMode_Mirror) { val = 0x2; - } - else if (map_mode[0] == aiTextureMapMode_Decal) { + } else if (map_mode[0] == aiTextureMapMode_Decal) { val = 0x10; } writer.PutU2(val); @@ -410,8 +399,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteMeshes() -{ +void Discreet3DSExporter::WriteMeshes() { // NOTE: 3DS allows for instances. However: // i) not all importers support reading them // ii) instances are not as flexible as they are in assimp, in particular, @@ -423,25 +411,24 @@ void Discreet3DSExporter::WriteMeshes() // Furthermore, the TRIMESH is transformed into world space so that it will // appear correctly if importers don't read the scene hierarchy at all. for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) { - const aiNode& node = *(*it).first; + const aiNode &node = *(*it).first; const unsigned int mesh_idx = (*it).second; - const aiMesh& mesh = *scene->mMeshes[mesh_idx]; + const aiMesh &mesh = *scene->mMeshes[mesh_idx]; // This should not happen if the SLM step is correctly executed // before the scene is handed to the exporter ai_assert(mesh.mNumVertices <= 0xffff); ai_assert(mesh.mNumFaces <= 0xffff); - const aiMatrix4x4& trafo = trafos[&node]; + const aiMatrix4x4 &trafo = trafos[&node]; ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK); // Mesh name is tied to the node it is attached to so it can later be referenced - const std::string& name = GetMeshName(mesh, mesh_idx, node); + const std::string &name = GetMeshName(mesh, mesh_idx, node); WriteString(name); - // TRIMESH chunk ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH); @@ -452,7 +439,7 @@ void Discreet3DSExporter::WriteMeshes() const uint16_t count = static_cast(mesh.mNumVertices); writer.PutU2(count); for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D& v = trafo * mesh.mVertices[i]; + const aiVector3D &v = trafo * mesh.mVertices[i]; writer.PutF4(v.x); writer.PutF4(v.y); writer.PutF4(v.z); @@ -466,7 +453,7 @@ void Discreet3DSExporter::WriteMeshes() writer.PutU2(count); for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D& v = mesh.mTextureCoords[0][i]; + const aiVector3D &v = mesh.mTextureCoords[0][i]; writer.PutF4(v.x); writer.PutF4(v.y); } @@ -481,7 +468,7 @@ void Discreet3DSExporter::WriteMeshes() // Count triangles, discard lines and points uint16_t count = 0; for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { - const aiFace& f = mesh.mFaces[i]; + const aiFace &f = mesh.mFaces[i]; if (f.mNumIndices < 3) { continue; } @@ -492,7 +479,7 @@ void Discreet3DSExporter::WriteMeshes() writer.PutU2(count); for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { - const aiFace& f = mesh.mFaces[i]; + const aiFace &f = mesh.mFaces[i]; if (f.mNumIndices < 3) { continue; } @@ -524,10 +511,9 @@ void Discreet3DSExporter::WriteMeshes() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh) -{ +void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh &mesh) { ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACEMAT); - const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex); + const std::string &name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex); WriteString(name); // Because assimp splits meshes by material, only a single @@ -542,7 +528,7 @@ void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh) } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteString(const std::string& s) { +void Discreet3DSExporter::WriteString(const std::string &s) { for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { writer.PutI1(*it); } @@ -550,7 +536,7 @@ void Discreet3DSExporter::WriteString(const std::string& s) { } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteString(const aiString& s) { +void Discreet3DSExporter::WriteString(const aiString &s) { for (std::size_t i = 0; i < s.length; ++i) { writer.PutI1(s.data[i]); } @@ -558,7 +544,7 @@ void Discreet3DSExporter::WriteString(const aiString& s) { } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteColor(const aiColor3D& color) { +void Discreet3DSExporter::WriteColor(const aiColor3D &color) { ChunkWriter curChunk(writer, Discreet3DS::CHUNK_RGBF); writer.PutF4(color.r); writer.PutF4(color.g); @@ -577,6 +563,5 @@ void Discreet3DSExporter::WritePercentChunk(double f) { writer.PutF8(f); } - #endif // ASSIMP_BUILD_NO_3DS_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/3DS/3DSExporter.h b/code/AssetLib/3DS/3DSExporter.h similarity index 100% rename from code/3DS/3DSExporter.h rename to code/AssetLib/3DS/3DSExporter.h diff --git a/code/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h similarity index 100% rename from code/3DS/3DSHelper.h rename to code/AssetLib/3DS/3DSHelper.h diff --git a/code/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp similarity index 69% rename from code/3DS/3DSLoader.cpp rename to code/AssetLib/3DS/3DSLoader.cpp index 13cef3a39..e1a6d0f89 100644 --- a/code/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -45,15 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * http://www.the-labs.com/Blender/3DS-details.html */ - #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #include "3DSLoader.h" -#include +#include +#include #include #include -#include -#include +#include using namespace Assimp; @@ -67,26 +66,25 @@ static const aiImporterDesc desc = { 0, 0, 0, - "3ds prj" + "3ds prj" }; // ------------------------------------------------------------------------------------------------ // Begins a new parsing block // - Reads the current chunk and validates it // - computes its length -#define ASSIMP_3DS_BEGIN_CHUNK() \ - while (true) { \ - if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)){ \ - return; \ - } \ - Discreet3DS::Chunk chunk; \ - ReadChunk(&chunk); \ - int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \ - if(chunkSize <= 0) \ - continue; \ - const unsigned int oldReadLimit = stream->SetReadLimit( \ - stream->GetCurrentPos() + chunkSize); \ - +#define ASSIMP_3DS_BEGIN_CHUNK() \ + while (true) { \ + if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) { \ + return; \ + } \ + Discreet3DS::Chunk chunk; \ + ReadChunk(&chunk); \ + int chunkSize = chunk.Size - sizeof(Discreet3DS::Chunk); \ + if (chunkSize <= 0) \ + continue; \ + const unsigned int oldReadLimit = stream->SetReadLimit( \ + stream->GetCurrentPos() + chunkSize); // ------------------------------------------------------------------------------------------------ // End a parsing block @@ -100,15 +98,8 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -Discreet3DSImporter::Discreet3DSImporter() -: stream() -, mLastNodeIndex() -, mCurrentNode() -, mRootNode() -, mScene() -, mMasterScale() -, bHasBG() -, bIsPrj() { +Discreet3DSImporter::Discreet3DSImporter() : + stream(), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() { // empty } @@ -120,9 +111,9 @@ Discreet3DSImporter::~Discreet3DSImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { +bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { std::string extension = GetExtension(pFile); - if(extension == "3ds" || extension == "prj") { + if (extension == "3ds" || extension == "prj") { return true; } @@ -131,29 +122,28 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle token[0] = 0x4d4d; token[1] = 0x3dc2; //token[2] = 0x3daa; - return CheckMagicToken(pIOHandler,pFile,token,2,0,2); + return CheckMagicToken(pIOHandler, pFile, token, 2, 0, 2); } return false; } // ------------------------------------------------------------------------------------------------ // Loader registry entry -const aiImporterDesc* Discreet3DSImporter::GetInfo () const { +const aiImporterDesc *Discreet3DSImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) { +void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) { // nothing to be done for the moment } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void Discreet3DSImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - StreamReaderLE theStream(pIOHandler->Open(pFile,"rb")); +void Discreet3DSImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { + StreamReaderLE theStream(pIOHandler->Open(pFile, "rb")); // We should have at least one chunk if (theStream.GetRemainingSize() < 16) { @@ -167,16 +157,16 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // Initialize members D3DS::Node _rootNode("UNNAMED"); - mLastNodeIndex = -1; - mCurrentNode = &_rootNode; - mRootNode = mCurrentNode; - mRootNode->mHierarchyPos = -1; + mLastNodeIndex = -1; + mCurrentNode = &_rootNode; + mRootNode = mCurrentNode; + mRootNode->mHierarchyPos = -1; mRootNode->mHierarchyIndex = -1; - mRootNode->mParent = NULL; - mMasterScale = 1.0f; - mBackgroundImage = ""; - bHasBG = false; - bIsPrj = false; + mRootNode->mParent = nullptr; + mMasterScale = 1.0f; + mBackgroundImage = ""; + bHasBG = false; + bIsPrj = false; // Parse the file ParseMainChunk(); @@ -187,11 +177,11 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // vectors from the smoothing groups we read from the // file. for (auto &mesh : mScene->mMeshes) { - if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { + if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile); } CheckIndices(mesh); - MakeUnique (mesh); + MakeUnique(mesh); ComputeNormalsWithSmoothingsGroups(mesh); } @@ -222,25 +212,26 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // ------------------------------------------------------------------------------------------------ // Applies a master-scaling factor to the imported scene -void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) { +void Discreet3DSImporter::ApplyMasterScale(aiScene *pScene) { // There are some 3DS files with a zero scaling factor - if (!mMasterScale)mMasterScale = 1.0f; - else mMasterScale = 1.0f / mMasterScale; + if (!mMasterScale) + mMasterScale = 1.0f; + else + mMasterScale = 1.0f / mMasterScale; // Construct an uniform scaling matrix and multiply with it pScene->mRootNode->mTransformation *= aiMatrix4x4( - mMasterScale,0.0f, 0.0f, 0.0f, - 0.0f, mMasterScale,0.0f, 0.0f, - 0.0f, 0.0f, mMasterScale,0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + mMasterScale, 0.0f, 0.0f, 0.0f, + 0.0f, mMasterScale, 0.0f, 0.0f, + 0.0f, 0.0f, mMasterScale, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); // Check whether a scaling track is assigned to the root node. } // ------------------------------------------------------------------------------------------------ // Reads a new chunk from the file -void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut) -{ +void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk *pcOut) { ai_assert(pcOut != nullptr); pcOut->Flag = stream->GetI2(); @@ -257,24 +248,21 @@ void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut) // ------------------------------------------------------------------------------------------------ // Skip a chunk -void Discreet3DSImporter::SkipChunk() -{ +void Discreet3DSImporter::SkipChunk() { Discreet3DS::Chunk psChunk; ReadChunk(&psChunk); - stream->IncPtr(psChunk.Size-sizeof(Discreet3DS::Chunk)); + stream->IncPtr(psChunk.Size - sizeof(Discreet3DS::Chunk)); return; } // ------------------------------------------------------------------------------------------------ // Process the primary chunk of the file -void Discreet3DSImporter::ParseMainChunk() -{ +void Discreet3DSImporter::ParseMainChunk() { ASSIMP_3DS_BEGIN_CHUNK(); // get chunk type - switch (chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_PRJ: bIsPrj = true; @@ -289,13 +277,11 @@ void Discreet3DSImporter::ParseMainChunk() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseEditorChunk() -{ +void Discreet3DSImporter::ParseEditorChunk() { ASSIMP_3DS_BEGIN_CHUNK(); // get chunk type - switch (chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_OBJMESH: ParseObjectChunk(); @@ -308,36 +294,31 @@ void Discreet3DSImporter::ParseEditorChunk() ParseKeyframeChunk(); break; - case Discreet3DS::CHUNK_VERSION: - { + case Discreet3DS::CHUNK_VERSION: { // print the version number char buff[10]; - ASSIMP_itoa10(buff,stream->GetI2()); + ASSIMP_itoa10(buff, stream->GetI2()); ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff); - } - break; + } break; }; ASSIMP_3DS_END_CHUNK(); } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseObjectChunk() -{ +void Discreet3DSImporter::ParseObjectChunk() { ASSIMP_3DS_BEGIN_CHUNK(); // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_OBJBLOCK: - { + switch (chunk.Flag) { + case Discreet3DS::CHUNK_OBJBLOCK: { unsigned int cnt = 0; - const char* sz = (const char*)stream->GetPtr(); + const char *sz = (const char *)stream->GetPtr(); // Get the name of the geometry object - while (stream->GetI1())++cnt; - ParseChunk(sz,cnt); - } - break; + while (stream->GetI1()) + ++cnt; + ParseChunk(sz, cnt); + } break; case Discreet3DS::CHUNK_MAT_MATERIAL: @@ -350,25 +331,23 @@ void Discreet3DSImporter::ParseObjectChunk() // This is the ambient base color of the scene. // We add it to the ambient color of all materials - ParseColorChunk(&mClrAmbient,true); - if (is_qnan(mClrAmbient.r)) - { + ParseColorChunk(&mClrAmbient, true); + if (is_qnan(mClrAmbient.r)) { // We failed to read the ambient base color. ASSIMP_LOG_ERROR("3DS: Failed to read ambient base color"); mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f; } break; - case Discreet3DS::CHUNK_BIT_MAP: - { + case Discreet3DS::CHUNK_BIT_MAP: { // Specifies the background image. The string should already be // properly 0 terminated but we need to be sure unsigned int cnt = 0; - const char* sz = (const char*)stream->GetPtr(); - while (stream->GetI1())++cnt; - mBackgroundImage = std::string(sz,cnt); - } - break; + const char *sz = (const char *)stream->GetPtr(); + while (stream->GetI1()) + ++cnt; + mBackgroundImage = std::string(sz, cnt); + } break; case Discreet3DS::CHUNK_BIT_MAP_EXISTS: bHasBG = true; @@ -383,8 +362,7 @@ void Discreet3DSImporter::ParseObjectChunk() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) -{ +void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) { ASSIMP_3DS_BEGIN_CHUNK(); // IMPLEMENTATION NOTE; @@ -393,22 +371,18 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) // to to be able to return valid cameras/lights even if no scenegraph is given. // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_TRIMESH: - { + switch (chunk.Flag) { + case Discreet3DS::CHUNK_TRIMESH: { // this starts a new triangle mesh mScene->mMeshes.push_back(D3DS::Mesh(std::string(name, num))); // Read mesh chunks ParseMeshChunk(); - } - break; + } break; - case Discreet3DS::CHUNK_LIGHT: - { + case Discreet3DS::CHUNK_LIGHT: { // This starts a new light - aiLight* light = new aiLight(); + aiLight *light = new aiLight(); mScene->mLights.push_back(light); light->mName.Set(std::string(name, num)); @@ -418,7 +392,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) light->mPosition.y = stream->GetF4(); light->mPosition.z = stream->GetF4(); - light->mColorDiffuse = aiColor3D(1.f,1.f,1.f); + light->mColorDiffuse = aiColor3D(1.f, 1.f, 1.f); // Now check for further subchunks if (!bIsPrj) /* fixme */ @@ -427,19 +401,17 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) // The specular light color is identical the the diffuse light color. The ambient light color // is equal to the ambient base color of the whole scene. light->mColorSpecular = light->mColorDiffuse; - light->mColorAmbient = mClrAmbient; + light->mColorAmbient = mClrAmbient; - if (light->mType == aiLightSource_UNDEFINED) - { + if (light->mType == aiLightSource_UNDEFINED) { // It must be a point light light->mType = aiLightSource_POINT; - }} - break; + } + } break; - case Discreet3DS::CHUNK_CAMERA: - { + case Discreet3DS::CHUNK_CAMERA: { // This starts a new camera - aiCamera* camera = new aiCamera(); + aiCamera *camera = new aiCamera(); mScene->mCameras.push_back(camera); camera->mName.Set(std::string(name, num)); @@ -457,40 +429,38 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) // There are some files with lookat == position. Don't know why or whether it's ok or not. ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector"); - camera->mLookAt = aiVector3D(0.0,1.0,0.0); + camera->mLookAt = aiVector3D(0.0, 1.0, 0.0); - } - else camera->mLookAt /= len; + } else + camera->mLookAt /= len; // And finally - the camera rotation angle, in counter clockwise direction - const ai_real angle = AI_DEG_TO_RAD( stream->GetF4() ); - aiQuaternion quat(camera->mLookAt,angle); - camera->mUp = quat.GetMatrix() * aiVector3D(0.0,1.0,0.0); + const ai_real angle = AI_DEG_TO_RAD(stream->GetF4()); + aiQuaternion quat(camera->mLookAt, angle); + camera->mUp = quat.GetMatrix() * aiVector3D(0.0, 1.0, 0.0); // Read the lense angle - camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() ); - if (camera->mHorizontalFOV < 0.001f) { + camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4()); + if (camera->mHorizontalFOV < 0.001f) { camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f); } // Now check for further subchunks if (!bIsPrj) /* fixme */ { ParseCameraChunk(); - }} - break; + } + } break; }; ASSIMP_3DS_END_CHUNK(); } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseLightChunk() -{ +void Discreet3DSImporter::ParseLightChunk() { ASSIMP_3DS_BEGIN_CHUNK(); - aiLight* light = mScene->mLights.back(); + aiLight *light = mScene->mLights.back(); // get chunk type - switch (chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_DL_SPOTLIGHT: // Now we can be sure that the light is a spot light light->mType = aiLightSource_SPOT; @@ -502,10 +472,10 @@ void Discreet3DSImporter::ParseLightChunk() light->mDirection.Normalize(); // Now the hotspot and falloff angles - in degrees - light->mAngleInnerCone = AI_DEG_TO_RAD( stream->GetF4() ); + light->mAngleInnerCone = AI_DEG_TO_RAD(stream->GetF4()); // FIX: the falloff angle is just an offset - light->mAngleOuterCone = light->mAngleInnerCone+AI_DEG_TO_RAD( stream->GetF4() ); + light->mAngleOuterCone = light->mAngleInnerCone + AI_DEG_TO_RAD(stream->GetF4()); break; // intensity multiplier @@ -531,18 +501,16 @@ void Discreet3DSImporter::ParseLightChunk() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseCameraChunk() -{ +void Discreet3DSImporter::ParseCameraChunk() { ASSIMP_3DS_BEGIN_CHUNK(); - aiCamera* camera = mScene->mCameras.back(); + aiCamera *camera = mScene->mCameras.back(); // get chunk type - switch (chunk.Flag) - { + switch (chunk.Flag) { // near and far clip plane case Discreet3DS::CHUNK_CAM_RANGES: camera->mClipPlaneNear = stream->GetF4(); - camera->mClipPlaneFar = stream->GetF4(); + camera->mClipPlaneFar = stream->GetF4(); break; } @@ -550,13 +518,11 @@ void Discreet3DSImporter::ParseCameraChunk() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseKeyframeChunk() -{ +void Discreet3DSImporter::ParseKeyframeChunk() { ASSIMP_3DS_BEGIN_CHUNK(); // get chunk type - switch (chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_TRACKCAMTGT: case Discreet3DS::CHUNK_TRACKSPOTL: case Discreet3DS::CHUNK_TRACKCAMERA: @@ -574,31 +540,30 @@ void Discreet3DSImporter::ParseKeyframeChunk() // ------------------------------------------------------------------------------------------------ // Little helper function for ParseHierarchyChunk -void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent) -{ +void Discreet3DSImporter::InverseNodeSearch(D3DS::Node *pcNode, D3DS::Node *pcCurrent) { if (!pcCurrent) { mRootNode->push_back(pcNode); return; } - if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) { - if(pcCurrent->mParent) { + if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) { + if (pcCurrent->mParent) { pcCurrent->mParent->push_back(pcNode); - } - else pcCurrent->push_back(pcNode); + } else + pcCurrent->push_back(pcNode); return; } - return InverseNodeSearch(pcNode,pcCurrent->mParent); + return InverseNodeSearch(pcNode, pcCurrent->mParent); } // ------------------------------------------------------------------------------------------------ // Find a node with a specific name in the import hierarchy -D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) { +D3DS::Node *FindNode(D3DS::Node *root, const std::string &name) { if (root->mName == name) { return root; } - for (std::vector::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) { + for (std::vector::iterator it = root->mChildren.begin(); it != root->mChildren.end(); ++it) { D3DS::Node *nd = FindNode(*it, name); if (nullptr != nd) { return nd; @@ -611,15 +576,13 @@ D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) { // ------------------------------------------------------------------------------------------------ // Binary predicate for std::unique() template -bool KeyUniqueCompare(const T& first, const T& second) -{ +bool KeyUniqueCompare(const T &first, const T &second) { return first.mTime == second.mTime; } // ------------------------------------------------------------------------------------------------ // Skip some additional import data. -void Discreet3DSImporter::SkipTCBInfo() -{ +void Discreet3DSImporter::SkipTCBInfo() { unsigned int flags = stream->GetI2(); if (!flags) { @@ -649,73 +612,68 @@ void Discreet3DSImporter::SkipTCBInfo() // ------------------------------------------------------------------------------------------------ // Read hierarchy and keyframe info -void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) -{ +void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) { ASSIMP_3DS_BEGIN_CHUNK(); // get chunk type - switch (chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_TRACKOBJNAME: // This is the name of the object to which the track applies. The chunk also // defines the position of this object in the hierarchy. { - // First of all: get the name of the object - unsigned int cnt = 0; - const char* sz = (const char*)stream->GetPtr(); + // First of all: get the name of the object + unsigned int cnt = 0; + const char *sz = (const char *)stream->GetPtr(); - while (stream->GetI1())++cnt; - std::string name = std::string(sz,cnt); + while (stream->GetI1()) + ++cnt; + std::string name = std::string(sz, cnt); - // Now find out whether we have this node already (target animation channels - // are stored with a separate object ID) - D3DS::Node* pcNode = FindNode(mRootNode,name); - int instanceNumber = 1; + // Now find out whether we have this node already (target animation channels + // are stored with a separate object ID) + D3DS::Node *pcNode = FindNode(mRootNode, name); + int instanceNumber = 1; - if ( pcNode) - { - // if the source is not a CHUNK_TRACKINFO block it won't be an object instance - if (parent != Discreet3DS::CHUNK_TRACKINFO) - { - mCurrentNode = pcNode; - break; + if (pcNode) { + // if the source is not a CHUNK_TRACKINFO block it won't be an object instance + if (parent != Discreet3DS::CHUNK_TRACKINFO) { + mCurrentNode = pcNode; + break; + } + pcNode->mInstanceCount++; + instanceNumber = pcNode->mInstanceCount; } - pcNode->mInstanceCount++; - instanceNumber = pcNode->mInstanceCount; - } - pcNode = new D3DS::Node(name); - pcNode->mInstanceNumber = instanceNumber; + pcNode = new D3DS::Node(name); + pcNode->mInstanceNumber = instanceNumber; - // There are two unknown values which we can safely ignore - stream->IncPtr(4); + // There are two unknown values which we can safely ignore + stream->IncPtr(4); - // Now read the hierarchy position of the object - uint16_t hierarchy = stream->GetI2() + 1; - pcNode->mHierarchyPos = hierarchy; - pcNode->mHierarchyIndex = mLastNodeIndex; + // Now read the hierarchy position of the object + uint16_t hierarchy = stream->GetI2() + 1; + pcNode->mHierarchyPos = hierarchy; + pcNode->mHierarchyIndex = mLastNodeIndex; - // And find a proper position in the graph for it - if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) { + // And find a proper position in the graph for it + if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) { - // add to the parent of the last touched node - mCurrentNode->mParent->push_back(pcNode); - mLastNodeIndex++; - } - else if(hierarchy >= mLastNodeIndex) { + // add to the parent of the last touched node + mCurrentNode->mParent->push_back(pcNode); + mLastNodeIndex++; + } else if (hierarchy >= mLastNodeIndex) { - // place it at the current position in the hierarchy - mCurrentNode->push_back(pcNode); - mLastNodeIndex = hierarchy; - } - else { - // need to go back to the specified position in the hierarchy. - InverseNodeSearch(pcNode,mCurrentNode); - mLastNodeIndex++; - } - // Make this node the current node - mCurrentNode = pcNode; + // place it at the current position in the hierarchy + mCurrentNode->push_back(pcNode); + mLastNodeIndex = hierarchy; + } else { + // need to go back to the specified position in the hierarchy. + InverseNodeSearch(pcNode, mCurrentNode); + mLastNodeIndex++; + } + // Make this node the current node + mCurrentNode = pcNode; } break; @@ -723,11 +681,12 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // This is the "real" name of a $$$DUMMY object { - const char* sz = (const char*) stream->GetPtr(); - while (stream->GetI1()); + const char *sz = (const char *)stream->GetPtr(); + while (stream->GetI1()) + ; // If object name is DUMMY, take this one instead - if (mCurrentNode->mName == "$$$DUMMY") { + if (mCurrentNode->mName == "$$$DUMMY") { mCurrentNode->mName = std::string(sz); break; } @@ -736,8 +695,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) case Discreet3DS::CHUNK_TRACKPIVOT: - if ( Discreet3DS::CHUNK_TRACKINFO != parent) - { + if (Discreet3DS::CHUNK_TRACKINFO != parent) { ASSIMP_LOG_WARN("3DS: Skipping pivot subchunk for non usual object"); break; } @@ -748,25 +706,23 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) mCurrentNode->vPivot.z = stream->GetF4(); break; - // //////////////////////////////////////////////////////////////////// // POSITION KEYFRAME - case Discreet3DS::CHUNK_TRACKPOS: - { + case Discreet3DS::CHUNK_TRACKPOS: { stream->IncPtr(10); const unsigned int numFrames = stream->GetI4(); bool sortKeys = false; // This could also be meant as the target position for // (targeted) lights and cameras - std::vector* l; - if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) { - l = & mCurrentNode->aTargetPositionKeys; - } - else l = & mCurrentNode->aPositionKeys; + std::vector *l; + if (Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) { + l = &mCurrentNode->aTargetPositionKeys; + } else + l = &mCurrentNode->aPositionKeys; l->reserve(numFrames); - for (unsigned int i = 0; i < numFrames;++i) { + for (unsigned int i = 0; i < numFrames; ++i) { const unsigned int fidx = stream->GetI4(); // Setup a new position key @@ -787,29 +743,29 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) } // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare), l->end() ); - }} + if (sortKeys) { + std::stable_sort(l->begin(), l->end()); + l->erase(std::unique(l->begin(), l->end(), &KeyUniqueCompare), l->end()); + } + } - break; + break; // //////////////////////////////////////////////////////////////////// // CAMERA ROLL KEYFRAME - case Discreet3DS::CHUNK_TRACKROLL: - { + case Discreet3DS::CHUNK_TRACKROLL: { // roll keys are accepted for cameras only - if (parent != Discreet3DS::CHUNK_TRACKCAMERA) { + if (parent != Discreet3DS::CHUNK_TRACKCAMERA) { ASSIMP_LOG_WARN("3DS: Ignoring roll track for non-camera object"); break; } bool sortKeys = false; - std::vector* l = &mCurrentNode->aCameraRollKeys; + std::vector *l = &mCurrentNode->aCameraRollKeys; stream->IncPtr(10); const unsigned int numFrames = stream->GetI4(); l->reserve(numFrames); - for (unsigned int i = 0; i < numFrames;++i) { + for (unsigned int i = 0; i < numFrames; ++i) { const unsigned int fidx = stream->GetI4(); // Setup a new position key @@ -829,35 +785,30 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) } // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare), l->end() ); - }} - break; - + if (sortKeys) { + std::stable_sort(l->begin(), l->end()); + l->erase(std::unique(l->begin(), l->end(), &KeyUniqueCompare), l->end()); + } + } break; // //////////////////////////////////////////////////////////////////// // CAMERA FOV KEYFRAME - case Discreet3DS::CHUNK_TRACKFOV: - { - ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. " - "This is not supported"); - } - break; - + case Discreet3DS::CHUNK_TRACKFOV: { + ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. " + "This is not supported"); + } break; // //////////////////////////////////////////////////////////////////// // ROTATION KEYFRAME - case Discreet3DS::CHUNK_TRACKROTATE: - { + case Discreet3DS::CHUNK_TRACKROTATE: { stream->IncPtr(10); const unsigned int numFrames = stream->GetI4(); bool sortKeys = false; - std::vector* l = &mCurrentNode->aRotationKeys; + std::vector *l = &mCurrentNode->aRotationKeys; l->reserve(numFrames); - for (unsigned int i = 0; i < numFrames;++i) { + for (unsigned int i = 0; i < numFrames; ++i) { const unsigned int fidx = stream->GetI4(); SkipTCBInfo(); @@ -875,7 +826,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) axis.y = 1.f; // Construct a rotation quaternion from the axis-angle pair - v.mValue = aiQuaternion(axis,rad); + v.mValue = aiQuaternion(axis, rad); // Check whether we'll need to sort the keys if (!l->empty() && v.mTime <= l->back().mTime) @@ -885,25 +836,24 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) l->push_back(v); } // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare), l->end() ); - }} - break; + if (sortKeys) { + std::stable_sort(l->begin(), l->end()); + l->erase(std::unique(l->begin(), l->end(), &KeyUniqueCompare), l->end()); + } + } break; // //////////////////////////////////////////////////////////////////// // SCALING KEYFRAME - case Discreet3DS::CHUNK_TRACKSCALE: - { + case Discreet3DS::CHUNK_TRACKSCALE: { stream->IncPtr(10); const unsigned int numFrames = stream->GetI2(); stream->IncPtr(2); bool sortKeys = false; - std::vector* l = &mCurrentNode->aScalingKeys; + std::vector *l = &mCurrentNode->aScalingKeys; l->reserve(numFrames); - for (unsigned int i = 0; i < numFrames;++i) { + for (unsigned int i = 0; i < numFrames; ++i) { const unsigned int fidx = stream->GetI4(); SkipTCBInfo(); @@ -928,11 +878,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) l->push_back(v); } // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare), l->end() ); - }} - break; + if (sortKeys) { + std::stable_sort(l->begin(), l->end()); + l->erase(std::unique(l->begin(), l->end(), &KeyUniqueCompare), l->end()); + } + } break; }; ASSIMP_3DS_END_CHUNK(); @@ -940,92 +890,85 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // ------------------------------------------------------------------------------------------------ // Read a face chunk - it contains smoothing groups and material assignments -void Discreet3DSImporter::ParseFaceChunk() -{ +void Discreet3DSImporter::ParseFaceChunk() { ASSIMP_3DS_BEGIN_CHUNK(); // Get the mesh we're currently working on - D3DS::Mesh& mMesh = mScene->mMeshes.back(); + D3DS::Mesh &mMesh = mScene->mMeshes.back(); // Get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_SMOOLIST: - { + switch (chunk.Flag) { + case Discreet3DS::CHUNK_SMOOLIST: { // This is the list of smoothing groups - a bitfield for every face. // Up to 32 smoothing groups assigned to a single face. - unsigned int num = chunkSize/4, m = 0; - if (num > mMesh.mFaces.size()) { + unsigned int num = chunkSize / 4, m = 0; + if (num > mMesh.mFaces.size()) { throw DeadlyImportError("3DS: More smoothing groups than faces"); } - for (std::vector::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) { + for (std::vector::iterator i = mMesh.mFaces.begin(); m != num; ++i, ++m) { // nth bit is set for nth smoothing group (*i).iSmoothGroup = stream->GetI4(); - }} - break; + } + } break; - case Discreet3DS::CHUNK_FACEMAT: - { + case Discreet3DS::CHUNK_FACEMAT: { // at fist an asciiz with the material name - const char* sz = (const char*)stream->GetPtr(); - while (stream->GetI1()); + const char *sz = (const char *)stream->GetPtr(); + while (stream->GetI1()) + ; // find the index of the material unsigned int idx = 0xcdcdcdcd, cnt = 0; - for (std::vector::const_iterator i = mScene->mMaterials.begin();i != mScene->mMaterials.end();++i,++cnt) { + for (std::vector::const_iterator i = mScene->mMaterials.begin(); i != mScene->mMaterials.end(); ++i, ++cnt) { // use case independent comparisons. hopefully it will work. if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) { idx = cnt; break; } } - if (0xcdcdcdcd == idx) { - ASSIMP_LOG_ERROR_F( "3DS: Unknown material: ", sz); + if (0xcdcdcdcd == idx) { + ASSIMP_LOG_ERROR_F("3DS: Unknown material: ", sz); } // Now continue and read all material indices cnt = (uint16_t)stream->GetI2(); - for (unsigned int i = 0; i < cnt;++i) { + for (unsigned int i = 0; i < cnt; ++i) { unsigned int fidx = (uint16_t)stream->GetI2(); // check range - if (fidx >= mMesh.mFaceMaterials.size()) { + if (fidx >= mMesh.mFaceMaterials.size()) { ASSIMP_LOG_ERROR("3DS: Invalid face index in face material list"); - } - else mMesh.mFaceMaterials[fidx] = idx; - }} - break; + } else + mMesh.mFaceMaterials[fidx] = idx; + } + } break; }; ASSIMP_3DS_END_CHUNK(); } // ------------------------------------------------------------------------------------------------ // Read a mesh chunk. Here's the actual mesh data -void Discreet3DSImporter::ParseMeshChunk() -{ +void Discreet3DSImporter::ParseMeshChunk() { ASSIMP_3DS_BEGIN_CHUNK(); // Get the mesh we're currently working on - D3DS::Mesh& mMesh = mScene->mMeshes.back(); + D3DS::Mesh &mMesh = mScene->mMeshes.back(); // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_VERTLIST: - { + switch (chunk.Flag) { + case Discreet3DS::CHUNK_VERTLIST: { // This is the list of all vertices in the current mesh int num = (int)(uint16_t)stream->GetI2(); mMesh.mPositions.reserve(num); - while (num-- > 0) { + while (num-- > 0) { aiVector3D v; v.x = stream->GetF4(); v.y = stream->GetF4(); v.z = stream->GetF4(); mMesh.mPositions.push_back(v); - }} - break; - case Discreet3DS::CHUNK_TRMATRIX: - { + } + } break; + case Discreet3DS::CHUNK_TRMATRIX: { // This is the RLEATIVE transformation matrix of the current mesh. Vertices are // pretransformed by this matrix wonder. mMesh.mMat.a1 = stream->GetF4(); @@ -1040,31 +983,28 @@ void Discreet3DSImporter::ParseMeshChunk() mMesh.mMat.a4 = stream->GetF4(); mMesh.mMat.b4 = stream->GetF4(); mMesh.mMat.c4 = stream->GetF4(); - } - break; + } break; - case Discreet3DS::CHUNK_MAPLIST: - { + case Discreet3DS::CHUNK_MAPLIST: { // This is the list of all UV coords in the current mesh int num = (int)(uint16_t)stream->GetI2(); mMesh.mTexCoords.reserve(num); - while (num-- > 0) { + while (num-- > 0) { aiVector3D v; v.x = stream->GetF4(); v.y = stream->GetF4(); mMesh.mTexCoords.push_back(v); - }} - break; + } + } break; - case Discreet3DS::CHUNK_FACELIST: - { + case Discreet3DS::CHUNK_FACELIST: { // This is the list of all faces in the current mesh int num = (int)(uint16_t)stream->GetI2(); mMesh.mFaces.reserve(num); - while (num-- > 0) { + while (num-- > 0) { // 3DS faces are ALWAYS triangles mMesh.mFaces.push_back(D3DS::Face()); - D3DS::Face& sFace = mMesh.mFaces.back(); + D3DS::Face &sFace = mMesh.mFaces.back(); sFace.mIndices[0] = (uint16_t)stream->GetI2(); sFace.mIndices[1] = (uint16_t)stream->GetI2(); @@ -1075,103 +1015,93 @@ void Discreet3DSImporter::ParseMeshChunk() // Resize the material array (0xcdcdcdcd marks the default material; so if a face is // not referenced by a material, $$DEFAULT will be assigned to it) - mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd); + mMesh.mFaceMaterials.resize(mMesh.mFaces.size(), 0xcdcdcdcd); // Larger 3DS files could have multiple FACE chunks here chunkSize = (int)stream->GetRemainingSizeToLimit(); - if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) ) + if (chunkSize > (int)sizeof(Discreet3DS::Chunk)) ParseFaceChunk(); - } - break; + } break; }; ASSIMP_3DS_END_CHUNK(); } // ------------------------------------------------------------------------------------------------ // Read a 3DS material chunk -void Discreet3DSImporter::ParseMaterialChunk() -{ +void Discreet3DSImporter::ParseMaterialChunk() { ASSIMP_3DS_BEGIN_CHUNK(); - switch (chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_MAT_MATNAME: - { + { // The material name string is already zero-terminated, but we need to be sure ... - const char* sz = (const char*)stream->GetPtr(); + const char *sz = (const char *)stream->GetPtr(); unsigned int cnt = 0; while (stream->GetI1()) ++cnt; - if (!cnt) { + if (!cnt) { // This may not be, we use the default name instead ASSIMP_LOG_ERROR("3DS: Empty material name"); - } - else mScene->mMaterials.back().mName = std::string(sz,cnt); - } - break; + } else + mScene->mMaterials.back().mName = std::string(sz, cnt); + } break; - case Discreet3DS::CHUNK_MAT_DIFFUSE: - { + case Discreet3DS::CHUNK_MAT_DIFFUSE: { // This is the diffuse material color - aiColor3D* pc = &mScene->mMaterials.back().mDiffuse; + aiColor3D *pc = &mScene->mMaterials.back().mDiffuse; ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it ASSIMP_LOG_ERROR("3DS: Unable to read DIFFUSE chunk"); pc->r = pc->g = pc->b = 1.0f; - }} - break; + } + } break; - case Discreet3DS::CHUNK_MAT_SPECULAR: - { + case Discreet3DS::CHUNK_MAT_SPECULAR: { // This is the specular material color - aiColor3D* pc = &mScene->mMaterials.back().mSpecular; + aiColor3D *pc = &mScene->mMaterials.back().mSpecular; ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it ASSIMP_LOG_ERROR("3DS: Unable to read SPECULAR chunk"); pc->r = pc->g = pc->b = 1.0f; - }} - break; + } + } break; - case Discreet3DS::CHUNK_MAT_AMBIENT: - { + case Discreet3DS::CHUNK_MAT_AMBIENT: { // This is the ambient material color - aiColor3D* pc = &mScene->mMaterials.back().mAmbient; + aiColor3D *pc = &mScene->mMaterials.back().mAmbient; ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it ASSIMP_LOG_ERROR("3DS: Unable to read AMBIENT chunk"); pc->r = pc->g = pc->b = 0.0f; - }} - break; + } + } break; - case Discreet3DS::CHUNK_MAT_SELF_ILLUM: - { + case Discreet3DS::CHUNK_MAT_SELF_ILLUM: { // This is the emissive material color - aiColor3D* pc = &mScene->mMaterials.back().mEmissive; + aiColor3D *pc = &mScene->mMaterials.back().mEmissive; ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it ASSIMP_LOG_ERROR("3DS: Unable to read EMISSIVE chunk"); pc->r = pc->g = pc->b = 0.0f; - }} - break; - - case Discreet3DS::CHUNK_MAT_TRANSPARENCY: - { - // This is the material's transparency - ai_real* pcf = &mScene->mMaterials.back().mTransparency; - *pcf = ParsePercentageChunk(); - - // NOTE: transparency, not opacity - if (is_qnan(*pcf)) - *pcf = ai_real( 1.0 ); - else - *pcf = ai_real( 1.0 ) - *pcf * (ai_real)0xFFFF / ai_real( 100.0 ); } - break; + } break; + + case Discreet3DS::CHUNK_MAT_TRANSPARENCY: { + // This is the material's transparency + ai_real *pcf = &mScene->mMaterials.back().mTransparency; + *pcf = ParsePercentageChunk(); + + // NOTE: transparency, not opacity + if (is_qnan(*pcf)) + *pcf = ai_real(1.0); + else + *pcf = ai_real(1.0) - *pcf * (ai_real)0xFFFF / ai_real(100.0); + } break; case Discreet3DS::CHUNK_MAT_SHADING: // This is the material shading mode @@ -1183,37 +1113,32 @@ void Discreet3DSImporter::ParseMaterialChunk() mScene->mMaterials.back().mTwoSided = true; break; - case Discreet3DS::CHUNK_MAT_SHININESS: - { // This is the shininess of the material - ai_real* pcf = &mScene->mMaterials.back().mSpecularExponent; + case Discreet3DS::CHUNK_MAT_SHININESS: { // This is the shininess of the material + ai_real *pcf = &mScene->mMaterials.back().mSpecularExponent; *pcf = ParsePercentageChunk(); if (is_qnan(*pcf)) *pcf = 0.0; - else *pcf *= (ai_real)0xFFFF; - } - break; + else + *pcf *= (ai_real)0xFFFF; + } break; - case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT: - { // This is the shininess strength of the material - ai_real* pcf = &mScene->mMaterials.back().mShininessStrength; - *pcf = ParsePercentageChunk(); - if (is_qnan(*pcf)) - *pcf = ai_real( 0.0 ); - else - *pcf *= (ai_real)0xffff / ai_real( 100.0 ); - } - break; + case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT: { // This is the shininess strength of the material + ai_real *pcf = &mScene->mMaterials.back().mShininessStrength; + *pcf = ParsePercentageChunk(); + if (is_qnan(*pcf)) + *pcf = ai_real(0.0); + else + *pcf *= (ai_real)0xffff / ai_real(100.0); + } break; - case Discreet3DS::CHUNK_MAT_SELF_ILPCT: - { // This is the self illumination strength of the material - ai_real f = ParsePercentageChunk(); - if (is_qnan(f)) - f = ai_real( 0.0 ); - else - f *= (ai_real)0xFFFF / ai_real( 100.0 ); - mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f); - } - break; + case Discreet3DS::CHUNK_MAT_SELF_ILPCT: { // This is the self illumination strength of the material + ai_real f = ParsePercentageChunk(); + if (is_qnan(f)) + f = ai_real(0.0); + else + f *= (ai_real)0xFFFF / ai_real(100.0); + mScene->mMaterials.back().mEmissive = aiColor3D(f, f, f); + } break; // Parse texture chunks case Discreet3DS::CHUNK_MAT_TEXTURE: @@ -1249,28 +1174,23 @@ void Discreet3DSImporter::ParseMaterialChunk() } // ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) -{ +void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture *pcOut) { ASSIMP_3DS_BEGIN_CHUNK(); // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_MAPFILE: - { + switch (chunk.Flag) { + case Discreet3DS::CHUNK_MAPFILE: { // The material name string is already zero-terminated, but we need to be sure ... - const char* sz = (const char*)stream->GetPtr(); + const char *sz = (const char *)stream->GetPtr(); unsigned int cnt = 0; while (stream->GetI1()) ++cnt; - pcOut->mMapName = std::string(sz,cnt); - } - break; - + pcOut->mMapName = std::string(sz, cnt); + } break; case Discreet3DS::CHUNK_PERCENTD: // Manually parse the blend factor - pcOut->mTextureBlend = ai_real( stream->GetF8() ); + pcOut->mTextureBlend = ai_real(stream->GetF8()); break; case Discreet3DS::CHUNK_PERCENTF: @@ -1280,14 +1200,13 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) case Discreet3DS::CHUNK_PERCENTW: // Manually parse the blend factor - pcOut->mTextureBlend = (ai_real)((uint16_t)stream->GetI2()) / ai_real( 100.0 ); + pcOut->mTextureBlend = (ai_real)((uint16_t)stream->GetI2()) / ai_real(100.0); break; case Discreet3DS::CHUNK_MAT_MAP_USCALE: // Texture coordinate scaling in the U direction pcOut->mScaleU = stream->GetF4(); - if (0.0f == pcOut->mScaleU) - { + if (0.0f == pcOut->mScaleU) { ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1."); pcOut->mScaleU = 1.0f; } @@ -1295,8 +1214,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) case Discreet3DS::CHUNK_MAT_MAP_VSCALE: // Texture coordinate scaling in the V direction pcOut->mScaleV = stream->GetF4(); - if (0.0f == pcOut->mScaleV) - { + if (0.0f == pcOut->mScaleV) { ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1."); pcOut->mScaleV = 1.0f; } @@ -1314,11 +1232,10 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) case Discreet3DS::CHUNK_MAT_MAP_ANG: // Texture coordinate rotation, CCW in DEGREES - pcOut->mRotation = -AI_DEG_TO_RAD( stream->GetF4() ); + pcOut->mRotation = -AI_DEG_TO_RAD(stream->GetF4()); break; - case Discreet3DS::CHUNK_MAT_MAP_TILING: - { + case Discreet3DS::CHUNK_MAT_MAP_TILING: { const uint16_t iFlags = stream->GetI2(); // Get the mapping mode (for both axes) @@ -1329,9 +1246,9 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) pcOut->mMapMode = aiTextureMapMode_Decal; // wrapping in all remaining cases - else pcOut->mMapMode = aiTextureMapMode_Wrap; - } - break; + else + pcOut->mMapMode = aiTextureMapMode_Wrap; + } break; }; ASSIMP_3DS_END_CHUNK(); @@ -1354,13 +1271,12 @@ ai_real Discreet3DSImporter::ParsePercentageChunk() { // ------------------------------------------------------------------------------------------------ // Read a color chunk. If a percentage chunk is found instead it is read as a grayscale color -void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent ) -{ - ai_assert(out != NULL); +void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) { + ai_assert(out != nullptr); // error return value const ai_real qnan = get_qnan(); - static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan); + static const aiColor3D clrError = aiColor3D(qnan, qnan, qnan); Discreet3DS::Chunk chunk; ReadChunk(&chunk); @@ -1369,13 +1285,12 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent ) bool bGamma = false; // Get the type of the chunk - switch(chunk.Flag) - { + switch (chunk.Flag) { case Discreet3DS::CHUNK_LINRGBF: bGamma = true; case Discreet3DS::CHUNK_RGBF: - if (sizeof(float) * 3 > diff) { + if (sizeof(float) * 3 > diff) { *out = clrError; return; } @@ -1386,18 +1301,16 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent ) case Discreet3DS::CHUNK_LINRGBB: bGamma = true; - case Discreet3DS::CHUNK_RGBB: - { - if ( sizeof( char ) * 3 > diff ) { - *out = clrError; - return; - } - const ai_real invVal = ai_real( 1.0 ) / ai_real( 255.0 ); - out->r = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal; - out->g = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal; - out->b = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal; + case Discreet3DS::CHUNK_RGBB: { + if (sizeof(char) * 3 > diff) { + *out = clrError; + return; } - break; + const ai_real invVal = ai_real(1.0) / ai_real(255.0); + out->r = (ai_real)(uint8_t)stream->GetI1() * invVal; + out->g = (ai_real)(uint8_t)stream->GetI1() * invVal; + out->b = (ai_real)(uint8_t)stream->GetI1() * invVal; + } break; // Percentage chunks are accepted, too. case Discreet3DS::CHUNK_PERCENTF: @@ -1410,7 +1323,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent ) case Discreet3DS::CHUNK_PERCENTW: if (acceptPercent && 1 <= diff) { - out->g = out->b = out->r = (ai_real)(uint8_t)stream->GetI1() / ai_real( 255.0 ); + out->g = out->b = out->r = (ai_real)(uint8_t)stream->GetI1() / ai_real(255.0); break; } *out = clrError; @@ -1419,7 +1332,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent ) default: stream->IncPtr(diff); // Skip unknown chunks, hope this won't cause any problems. - return ParseColorChunk(out,acceptPercent); + return ParseColorChunk(out, acceptPercent); }; (void)bGamma; } diff --git a/code/3DS/3DSLoader.h b/code/AssetLib/3DS/3DSLoader.h similarity index 100% rename from code/3DS/3DSLoader.h rename to code/AssetLib/3DS/3DSLoader.h diff --git a/code/3MF/3MFXmlTags.h b/code/AssetLib/3MF/3MFXmlTags.h similarity index 100% rename from code/3MF/3MFXmlTags.h rename to code/AssetLib/3MF/3MFXmlTags.h diff --git a/code/3MF/D3MFExporter.cpp b/code/AssetLib/3MF/D3MFExporter.cpp similarity index 55% rename from code/3MF/D3MFExporter.cpp rename to code/AssetLib/3MF/D3MFExporter.cpp index 83036b236..5b85d275b 100644 --- a/code/3MF/D3MFExporter.cpp +++ b/code/AssetLib/3MF/D3MFExporter.cpp @@ -44,81 +44,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "D3MFExporter.h" -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include "3MFXmlTags.h" #include "D3MFOpcPackage.h" #ifdef ASSIMP_USE_HUNTER -# include +#include #else -# include +#include #endif namespace Assimp { -void ExportScene3MF( const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/ ) { - if ( nullptr == pIOSystem ) { - throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) ); +void ExportScene3MF(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) { + if (nullptr == pIOSystem) { + throw DeadlyExportError("Could not export 3MP archive: " + std::string(pFile)); } - D3MF::D3MFExporter myExporter( pFile, pScene ); - if ( myExporter.validate() ) { - if ( pIOSystem->Exists( pFile ) ) { - if ( !pIOSystem->DeleteFile( pFile ) ) { - throw DeadlyExportError( "File exists, cannot override : " + std::string( pFile ) ); + D3MF::D3MFExporter myExporter(pFile, pScene); + if (myExporter.validate()) { + if (pIOSystem->Exists(pFile)) { + if (!pIOSystem->DeleteFile(pFile)) { + throw DeadlyExportError("File exists, cannot override : " + std::string(pFile)); } } bool ok = myExporter.exportArchive(pFile); - if ( !ok ) { - throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) ); + if (!ok) { + throw DeadlyExportError("Could not export 3MP archive: " + std::string(pFile)); } } } namespace D3MF { -D3MFExporter::D3MFExporter( const char* pFile, const aiScene* pScene ) -: mArchiveName( pFile ) -, m_zipArchive( nullptr ) -, mScene( pScene ) -, mModelOutput() -, mRelOutput() -, mContentOutput() -, mBuildItems() -, mRelations() { +D3MFExporter::D3MFExporter(const char *pFile, const aiScene *pScene) : + mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene), mModelOutput(), mRelOutput(), mContentOutput(), mBuildItems(), mRelations() { // empty } D3MFExporter::~D3MFExporter() { - for ( size_t i = 0; i < mRelations.size(); ++i ) { - delete mRelations[ i ]; + for (size_t i = 0; i < mRelations.size(); ++i) { + delete mRelations[i]; } mRelations.clear(); } bool D3MFExporter::validate() { - if ( mArchiveName.empty() ) { + if (mArchiveName.empty()) { return false; } - if ( nullptr == mScene ) { + if (nullptr == mScene) { return false; } return true; } -bool D3MFExporter::exportArchive( const char *file ) { - bool ok( true ); +bool D3MFExporter::exportArchive(const char *file) { + bool ok(true); - m_zipArchive = zip_open( file, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w' ); - if ( nullptr == m_zipArchive ) { + m_zipArchive = zip_open(file, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); + if (nullptr == m_zipArchive) { return false; } @@ -126,7 +119,7 @@ bool D3MFExporter::exportArchive( const char *file ) { ok |= export3DModel(); ok |= exportRelations(); - zip_close( m_zipArchive ); + zip_close(m_zipArchive); m_zipArchive = nullptr; return ok; @@ -145,7 +138,7 @@ bool D3MFExporter::exportContentTypes() { mContentOutput << std::endl; mContentOutput << ""; mContentOutput << std::endl; - exportContentTyp( XmlTag::CONTENT_TYPES_ARCHIVE ); + exportContentTyp(XmlTag::CONTENT_TYPES_ARCHIVE); return true; } @@ -157,20 +150,20 @@ bool D3MFExporter::exportRelations() { mRelOutput << std::endl; mRelOutput << ""; - for ( size_t i = 0; i < mRelations.size(); ++i ) { - if ( mRelations[ i ]->target[ 0 ] == '/' ) { - mRelOutput << "target << "\" "; + for (size_t i = 0; i < mRelations.size(); ++i) { + if (mRelations[i]->target[0] == '/') { + mRelOutput << "target << "\" "; } else { - mRelOutput << "target << "\" "; + mRelOutput << "target << "\" "; } mRelOutput << "Id=\"" << mRelations[i]->id << "\" "; - mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />"; + mRelOutput << "Type=\"" << mRelations[i]->type << "\" />"; mRelOutput << std::endl; } mRelOutput << ""; mRelOutput << std::endl; - writeRelInfoToFile( "_rels", ".rels" ); + writeRelInfoToFile("_rels", ".rels"); mRelOutput.flush(); return true; @@ -181,8 +174,8 @@ bool D3MFExporter::export3DModel() { writeHeader(); mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\"" - << " xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">" - << std::endl; + << " xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">" + << std::endl; mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; @@ -192,7 +185,6 @@ bool D3MFExporter::export3DModel() { writeObjects(); - mModelOutput << ""; mModelOutput << std::endl; writeBuild(); @@ -203,9 +195,9 @@ bool D3MFExporter::export3DModel() { info->id = "rel0"; info->target = "/3D/3DModel.model"; info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; - mRelations.push_back( info ); + mRelations.push_back(info); - writeModelToArchive( "3D", "3DModel.model" ); + writeModelToArchive("3D", "3DModel.model"); mModelOutput.flush(); return true; @@ -217,22 +209,22 @@ void D3MFExporter::writeHeader() { } void D3MFExporter::writeMetaData() { - if ( nullptr == mScene->mMetaData ) { + if (nullptr == mScene->mMetaData) { return; } - const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties ); - if ( 0 == numMetaEntries ) { + const unsigned int numMetaEntries(mScene->mMetaData->mNumProperties); + if (0 == numMetaEntries) { return; } - const aiString *key = nullptr; + const aiString *key = nullptr; const aiMetadataEntry *entry(nullptr); - for ( size_t i = 0; i < numMetaEntries; ++i ) { - mScene->mMetaData->Get( i, key, entry ); - std::string k( key->C_Str() ); + for (size_t i = 0; i < numMetaEntries; ++i) { + mScene->mMetaData->Get(i, key, entry); + std::string k(key->C_Str()); aiString value; - mScene->mMetaData->Get( k, value ); + mScene->mMetaData->Get(k, value); mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">"; mModelOutput << value.C_Str(); mModelOutput << "" << std::endl; @@ -241,115 +233,114 @@ void D3MFExporter::writeMetaData() { void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; - std::string strName, hexDiffuseColor , tmp; - for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { - aiMaterial *mat = mScene->mMaterials[ i ]; + std::string strName, hexDiffuseColor, tmp; + for (size_t i = 0; i < mScene->mNumMaterials; ++i) { + aiMaterial *mat = mScene->mMaterials[i]; aiString name; - if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) { - strName = "basemat_" + to_string( i ); + if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) { + strName = "basemat_" + to_string(i); } else { strName = name.C_Str(); } aiColor4D color; - if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { + if (mat->Get(AI_MATKEY_COLOR_DIFFUSE, color) == aiReturn_SUCCESS) { hexDiffuseColor.clear(); tmp.clear(); // rgbs % - if(color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1){ - - hexDiffuseColor = Rgba2Hex( - (int)((ai_real)color.r)*255, - (int)((ai_real)color.g)*255, - (int)((ai_real)color.b)*255, - (int)((ai_real)color.a)*255, - true - ); - - }else{ - hexDiffuseColor = "#"; - tmp = DecimalToHexa( (ai_real) color.r ); - hexDiffuseColor += tmp; - tmp = DecimalToHexa((ai_real)color.g); - hexDiffuseColor += tmp; - tmp = DecimalToHexa((ai_real)color.b); - hexDiffuseColor += tmp; - tmp = DecimalToHexa((ai_real)color.a); - hexDiffuseColor += tmp; - } + if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) { + + hexDiffuseColor = Rgba2Hex( + (int)((ai_real)color.r) * 255, + (int)((ai_real)color.g) * 255, + (int)((ai_real)color.b) * 255, + (int)((ai_real)color.a) * 255, + true); + + } else { + hexDiffuseColor = "#"; + tmp = DecimalToHexa((ai_real)color.r); + hexDiffuseColor += tmp; + tmp = DecimalToHexa((ai_real)color.g); + hexDiffuseColor += tmp; + tmp = DecimalToHexa((ai_real)color.b); + hexDiffuseColor += tmp; + tmp = DecimalToHexa((ai_real)color.a); + hexDiffuseColor += tmp; + } } else { hexDiffuseColor = "#FFFFFFFF"; } - mModelOutput << "\n"; + mModelOutput << "\n"; } mModelOutput << "\n"; } void D3MFExporter::writeObjects() { - if ( nullptr == mScene->mRootNode ) { + if (nullptr == mScene->mRootNode) { return; } aiNode *root = mScene->mRootNode; - for ( unsigned int i = 0; i < root->mNumChildren; ++i ) { - aiNode *currentNode( root->mChildren[ i ] ); - if ( nullptr == currentNode ) { + for (unsigned int i = 0; i < root->mNumChildren; ++i) { + aiNode *currentNode(root->mChildren[i]); + if (nullptr == currentNode) { continue; } mModelOutput << "<" << XmlTag::object << " id=\"" << i + 2 << "\" type=\"model\">"; mModelOutput << std::endl; - for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) { - aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ]; - if ( nullptr == currentMesh ) { + for (unsigned int j = 0; j < currentNode->mNumMeshes; ++j) { + aiMesh *currentMesh = mScene->mMeshes[currentNode->mMeshes[j]]; + if (nullptr == currentMesh) { continue; } - writeMesh( currentMesh ); + writeMesh(currentMesh); } - mBuildItems.push_back( i ); + mBuildItems.push_back(i); mModelOutput << ""; mModelOutput << std::endl; } } -void D3MFExporter::writeMesh( aiMesh *mesh ) { - if ( nullptr == mesh ) { +void D3MFExporter::writeMesh(aiMesh *mesh) { + if (nullptr == mesh) { return; } mModelOutput << "<" << XmlTag::mesh << ">" << std::endl; mModelOutput << "<" << XmlTag::vertices << ">" << std::endl; - for ( unsigned int i = 0; i < mesh->mNumVertices; ++i ) { - writeVertex( mesh->mVertices[ i ] ); + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + writeVertex(mesh->mVertices[i]); } mModelOutput << "" << std::endl; - const unsigned int matIdx( mesh->mMaterialIndex ); + const unsigned int matIdx(mesh->mMaterialIndex); - writeFaces( mesh, matIdx ); + writeFaces(mesh, matIdx); mModelOutput << "" << std::endl; } -void D3MFExporter::writeVertex( const aiVector3D &pos ) { +void D3MFExporter::writeVertex(const aiVector3D &pos) { mModelOutput << "<" << XmlTag::vertex << " x=\"" << pos.x << "\" y=\"" << pos.y << "\" z=\"" << pos.z << "\" />"; mModelOutput << std::endl; } -void D3MFExporter::writeFaces( aiMesh *mesh, unsigned int matIdx ) { - if ( nullptr == mesh ) { +void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) { + if (nullptr == mesh) { return; } - if ( !mesh->HasFaces() ) { + if (!mesh->HasFaces()) { return; } mModelOutput << "<" << XmlTag::triangles << ">" << std::endl; - for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) { - aiFace ¤tFace = mesh->mFaces[ i ]; - mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\"" - << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] - << "\" pid=\"1\" p1=\""+to_string(matIdx)+"\" />"; + for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { + aiFace ¤tFace = mesh->mFaces[i]; + mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\"" + << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2] + << "\" pid=\"1\" p1=\"" + to_string(matIdx) + "\" />"; mModelOutput << std::endl; } mModelOutput << ""; @@ -359,7 +350,7 @@ void D3MFExporter::writeFaces( aiMesh *mesh, unsigned int matIdx ) { void D3MFExporter::writeBuild() { mModelOutput << "<" << XmlTag::build << ">" << std::endl; - for ( size_t i = 0; i < mBuildItems.size(); ++i ) { + for (size_t i = 0; i < mBuildItems.size(); ++i) { mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>"; mModelOutput << std::endl; } @@ -367,46 +358,45 @@ void D3MFExporter::writeBuild() { mModelOutput << std::endl; } -void D3MFExporter::exportContentTyp( const std::string &filename ) { - if ( nullptr == m_zipArchive ) { - throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." ); +void D3MFExporter::exportContentTyp(const std::string &filename) { + if (nullptr == m_zipArchive) { + throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr."); } const std::string entry = filename; - zip_entry_open( m_zipArchive, entry.c_str() ); + zip_entry_open(m_zipArchive, entry.c_str()); - const std::string &exportTxt( mContentOutput.str() ); - zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() ); + const std::string &exportTxt(mContentOutput.str()); + zip_entry_write(m_zipArchive, exportTxt.c_str(), exportTxt.size()); - zip_entry_close( m_zipArchive ); + zip_entry_close(m_zipArchive); } -void D3MFExporter::writeModelToArchive( const std::string &folder, const std::string &modelName ) { - if ( nullptr == m_zipArchive ) { - throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." ); +void D3MFExporter::writeModelToArchive(const std::string &folder, const std::string &modelName) { + if (nullptr == m_zipArchive) { + throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr."); } const std::string entry = folder + "/" + modelName; - zip_entry_open( m_zipArchive, entry.c_str() ); + zip_entry_open(m_zipArchive, entry.c_str()); - const std::string &exportTxt( mModelOutput.str() ); - zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() ); + const std::string &exportTxt(mModelOutput.str()); + zip_entry_write(m_zipArchive, exportTxt.c_str(), exportTxt.size()); - zip_entry_close( m_zipArchive ); + zip_entry_close(m_zipArchive); } -void D3MFExporter::writeRelInfoToFile( const std::string &folder, const std::string &relName ) { - if ( nullptr == m_zipArchive ) { - throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." ); +void D3MFExporter::writeRelInfoToFile(const std::string &folder, const std::string &relName) { + if (nullptr == m_zipArchive) { + throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr."); } const std::string entry = folder + "/" + relName; - zip_entry_open( m_zipArchive, entry.c_str() ); + zip_entry_open(m_zipArchive, entry.c_str()); - const std::string &exportTxt( mRelOutput.str() ); - zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() ); + const std::string &exportTxt(mRelOutput.str()); + zip_entry_write(m_zipArchive, exportTxt.c_str(), exportTxt.size()); - zip_entry_close( m_zipArchive ); + zip_entry_close(m_zipArchive); } - } // Namespace D3MF } // Namespace Assimp diff --git a/code/3MF/D3MFExporter.h b/code/AssetLib/3MF/D3MFExporter.h similarity index 100% rename from code/3MF/D3MFExporter.h rename to code/AssetLib/3MF/D3MFExporter.h diff --git a/code/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp similarity index 58% rename from code/3MF/D3MFImporter.cpp rename to code/AssetLib/3MF/D3MFImporter.cpp index 2f30c4fc0..9fc9a653d 100644 --- a/code/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -44,24 +44,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "D3MFImporter.h" -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include "D3MFOpcPackage.h" -#include #include "3MFXmlTags.h" +#include "D3MFOpcPackage.h" #include +#include #include @@ -70,90 +70,90 @@ namespace D3MF { class XmlSerializer { public: - using MatArray = std::vector; + using MatArray = std::vector; using MatId2MatArray = std::map>; - XmlSerializer(XmlReader* xmlReader) - : mMeshes() - , mMatArray() - , mActiveMatGroup( 99999999 ) - , mMatId2MatArray() - , xmlReader(xmlReader){ - // empty + XmlSerializer(XmlReader *xmlReader) : + mMeshes(), + mMatArray(), + mActiveMatGroup(99999999), + mMatId2MatArray(), + xmlReader(xmlReader) { + // empty } ~XmlSerializer() { // empty } - void ImportXml(aiScene* scene) { - if ( nullptr == scene ) { + void ImportXml(aiScene *scene) { + if (nullptr == scene) { return; } scene->mRootNode = new aiNode(); - std::vector children; + std::vector children; std::string nodeName; - while(ReadToEndElement(D3MF::XmlTag::model)) { + while (ReadToEndElement(D3MF::XmlTag::model)) { nodeName = xmlReader->getNodeName(); - if( nodeName == D3MF::XmlTag::object) { + if (nodeName == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); - } else if( nodeName == D3MF::XmlTag::build) { - // - } else if ( nodeName == D3MF::XmlTag::basematerials ) { + } else if (nodeName == D3MF::XmlTag::build) { + // + } else if (nodeName == D3MF::XmlTag::basematerials) { ReadBaseMaterials(); - } else if ( nodeName == D3MF::XmlTag::meta ) { + } else if (nodeName == D3MF::XmlTag::meta) { ReadMetadata(); } } - if ( scene->mRootNode->mName.length == 0 ) { - scene->mRootNode->mName.Set( "3MF" ); + if (scene->mRootNode->mName.length == 0) { + scene->mRootNode->mName.Set("3MF"); } // import the metadata - if ( !mMetaData.empty() ) { - const size_t numMeta( mMetaData.size() ); - scene->mMetaData = aiMetadata::Alloc(static_cast( numMeta ) ); - for ( size_t i = 0; i < numMeta; ++i ) { - aiString val( mMetaData[ i ].value ); - scene->mMetaData->Set(static_cast( i ), mMetaData[ i ].name, val ); + if (!mMetaData.empty()) { + const size_t numMeta(mMetaData.size()); + scene->mMetaData = aiMetadata::Alloc(static_cast(numMeta)); + for (size_t i = 0; i < numMeta; ++i) { + aiString val(mMetaData[i].value); + scene->mMetaData->Set(static_cast(i), mMetaData[i].name, val); } } // import the meshes - scene->mNumMeshes = static_cast( mMeshes.size()); - scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + scene->mNumMeshes = static_cast(mMeshes.size()); + scene->mMeshes = new aiMesh *[scene->mNumMeshes](); + std::copy(mMeshes.begin(), mMeshes.end(), scene->mMeshes); // import the materials - scene->mNumMaterials = static_cast( mMatArray.size() ); - if ( 0 != scene->mNumMaterials ) { - scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; - std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); + scene->mNumMaterials = static_cast(mMatArray.size()); + if (0 != scene->mNumMaterials) { + scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; + std::copy(mMatArray.begin(), mMatArray.end(), scene->mMaterials); } // create the scenegraph scene->mRootNode->mNumChildren = static_cast(children.size()); - scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); + scene->mRootNode->mChildren = new aiNode *[scene->mRootNode->mNumChildren](); std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); } private: - aiNode* ReadObject(aiScene* scene) { + aiNode *ReadObject(aiScene *scene) { std::unique_ptr node(new aiNode()); std::vector meshIds; - const char *attrib( nullptr ); + const char *attrib(nullptr); std::string name, type; - attrib = xmlReader->getAttributeValue( D3MF::XmlTag::id.c_str() ); - if ( nullptr != attrib ) { + attrib = xmlReader->getAttributeValue(D3MF::XmlTag::id.c_str()); + if (nullptr != attrib) { name = attrib; } - attrib = xmlReader->getAttributeValue( D3MF::XmlTag::type.c_str() ); - if ( nullptr != attrib ) { + attrib = xmlReader->getAttributeValue(D3MF::XmlTag::type.c_str()); + if (nullptr != attrib) { type = attrib; } @@ -162,8 +162,8 @@ private: size_t meshIdx = mMeshes.size(); - while(ReadToEndElement(D3MF::XmlTag::object)) { - if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) { + while (ReadToEndElement(D3MF::XmlTag::object)) { + if (xmlReader->getNodeName() == D3MF::XmlTag::mesh) { auto mesh = ReadMesh(); mesh->mName.Set(name); @@ -183,11 +183,11 @@ private: } aiMesh *ReadMesh() { - aiMesh* mesh = new aiMesh(); - while(ReadToEndElement(D3MF::XmlTag::mesh)) { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) { + aiMesh *mesh = new aiMesh(); + while (ReadToEndElement(D3MF::XmlTag::mesh)) { + if (xmlReader->getNodeName() == D3MF::XmlTag::vertices) { ImportVertices(mesh); - } else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) { + } else if (xmlReader->getNodeName() == D3MF::XmlTag::triangles) { ImportTriangles(mesh); } } @@ -196,24 +196,24 @@ private: } void ReadMetadata() { - const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() ); + const std::string name = xmlReader->getAttributeValue(D3MF::XmlTag::meta_name.c_str()); xmlReader->read(); const std::string value = xmlReader->getNodeData(); - if ( name.empty() ) { + if (name.empty()) { return; } MetaEntry entry; entry.name = name; entry.value = value; - mMetaData.push_back( entry ); + mMetaData.push_back(entry); } - void ImportVertices(aiMesh* mesh) { + void ImportVertices(aiMesh *mesh) { std::vector vertices; - while(ReadToEndElement(D3MF::XmlTag::vertices)) { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) { + while (ReadToEndElement(D3MF::XmlTag::vertices)) { + if (xmlReader->getNodeName() == D3MF::XmlTag::vertex) { vertices.push_back(ReadVertex()); } } @@ -233,20 +233,20 @@ private: return vertex; } - void ImportTriangles(aiMesh* mesh) { - std::vector faces; + void ImportTriangles(aiMesh *mesh) { + std::vector faces; - while(ReadToEndElement(D3MF::XmlTag::triangles)) { - const std::string nodeName( xmlReader->getNodeName() ); - if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { - faces.push_back(ReadTriangle()); - const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) ); - if ( nullptr != pidToken ) { - int matIdx( std::atoi( pidToken ) ); - mesh->mMaterialIndex = matIdx; - } - } - } + while (ReadToEndElement(D3MF::XmlTag::triangles)) { + const std::string nodeName(xmlReader->getNodeName()); + if (xmlReader->getNodeName() == D3MF::XmlTag::triangle) { + faces.push_back(ReadTriangle()); + const char *pidToken(xmlReader->getAttributeValue(D3MF::XmlTag::p1.c_str())); + if (nullptr != pidToken) { + int matIdx(std::atoi(pidToken)); + mesh->mMaterialIndex = matIdx; + } + } + } mesh->mNumFaces = static_cast(faces.size()); mesh->mFaces = new aiFace[mesh->mNumFaces]; @@ -269,117 +269,115 @@ private: void ReadBaseMaterials() { std::vector MatIdArray; - const char *baseMaterialId( xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_id.c_str() ) ); - if ( nullptr != baseMaterialId ) { - unsigned int id = std::atoi( baseMaterialId ); - const size_t newMatIdx( mMatArray.size() ); - if ( id != mActiveMatGroup ) { + const char *baseMaterialId(xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_id.c_str())); + if (nullptr != baseMaterialId) { + unsigned int id = std::atoi(baseMaterialId); + const size_t newMatIdx(mMatArray.size()); + if (id != mActiveMatGroup) { mActiveMatGroup = id; - MatId2MatArray::const_iterator it( mMatId2MatArray.find( id ) ); - if ( mMatId2MatArray.end() == it ) { + MatId2MatArray::const_iterator it(mMatId2MatArray.find(id)); + if (mMatId2MatArray.end() == it) { MatIdArray.clear(); - mMatId2MatArray[ id ] = MatIdArray; + mMatId2MatArray[id] = MatIdArray; } else { MatIdArray = it->second; } } - MatIdArray.push_back( static_cast( newMatIdx ) ); - mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; + MatIdArray.push_back(static_cast(newMatIdx)); + mMatId2MatArray[mActiveMatGroup] = MatIdArray; } - while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { - mMatArray.push_back( readMaterialDef() ); + while (ReadToEndElement(D3MF::XmlTag::basematerials)) { + mMatArray.push_back(readMaterialDef()); } } - bool parseColor( const char *color, aiColor4D &diffuse ) { - if ( nullptr == color ) { + bool parseColor(const char *color, aiColor4D &diffuse) { + if (nullptr == color) { return false; } //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) - const size_t len( strlen( color ) ); - if ( 9 != len && 7 != len) { + const size_t len(strlen(color)); + if (9 != len && 7 != len) { return false; } - const char *buf( color ); - if ( '#' != *buf ) { + const char *buf(color); + if ('#' != *buf) { return false; } ++buf; - char comp[ 3 ] = { 0,0,'\0' }; + char comp[3] = { 0, 0, '\0' }; - comp[ 0 ] = *buf; + comp[0] = *buf; ++buf; - comp[ 1 ] = *buf; + comp[1] = *buf; ++buf; - diffuse.r = static_cast( strtol( comp, NULL, 16 ) ) / ai_real(255.0); + diffuse.r = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); + comp[0] = *buf; + ++buf; + comp[1] = *buf; + ++buf; + diffuse.g = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); - comp[ 0 ] = *buf; + comp[0] = *buf; ++buf; - comp[ 1 ] = *buf; + comp[1] = *buf; ++buf; - diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / ai_real(255.0); + diffuse.b = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); - comp[ 0 ] = *buf; - ++buf; - comp[ 1 ] = *buf; - ++buf; - diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / ai_real(255.0); - - if(7 == len) + if (7 == len) return true; - comp[ 0 ] = *buf; + comp[0] = *buf; ++buf; - comp[ 1 ] = *buf; + comp[1] = *buf; ++buf; - diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / ai_real(255.0); + diffuse.a = static_cast(strtol(comp, NULL, 16)) / ai_real(255.0); return true; } - void assignDiffuseColor( aiMaterial *mat ) { - const char *color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + void assignDiffuseColor(aiMaterial *mat) { + const char *color = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_displaycolor.c_str()); aiColor4D diffuse; - if ( parseColor( color, diffuse ) ) { - mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); + if (parseColor(color, diffuse)) { + mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); } - } aiMaterial *readMaterialDef() { - aiMaterial *mat( nullptr ); - const char *name( nullptr ); - const std::string nodeName( xmlReader->getNodeName() ); - if ( nodeName == D3MF::XmlTag::basematerials_base ) { - name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); + aiMaterial *mat(nullptr); + const char *name(nullptr); + const std::string nodeName(xmlReader->getNodeName()); + if (nodeName == D3MF::XmlTag::basematerials_base) { + name = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_name.c_str()); std::string stdMatName; aiString matName; - std::string strId( to_string( mActiveMatGroup ) ); + std::string strId(to_string(mActiveMatGroup)); stdMatName += "id"; stdMatName += strId; stdMatName += "_"; - if ( nullptr != name ) { - stdMatName += std::string( name ); + if (nullptr != name) { + stdMatName += std::string(name); } else { stdMatName += "basemat"; } - matName.Set( stdMatName ); + matName.Set(stdMatName); mat = new aiMaterial; - mat->AddProperty( &matName, AI_MATKEY_NAME ); + mat->AddProperty(&matName, AI_MATKEY_NAME); - assignDiffuseColor( mat ); + assignDiffuseColor(mat); } return mat; } private: - bool ReadToStartElement(const std::string& startTag) { - while(xmlReader->read()) { - const std::string &nodeName( xmlReader->getNodeName() ); + bool ReadToStartElement(const std::string &startTag) { + while (xmlReader->read()) { + const std::string &nodeName(xmlReader->getNodeName()); if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) { return true; } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) { @@ -390,9 +388,9 @@ private: return false; } - bool ReadToEndElement(const std::string& closeTag) { - while(xmlReader->read()) { - const std::string &nodeName( xmlReader->getNodeName() ); + bool ReadToEndElement(const std::string &closeTag) { + while (xmlReader->read()) { + const std::string &nodeName(xmlReader->getNodeName()); if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) { return true; } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) { @@ -410,11 +408,11 @@ private: std::string value; }; std::vector mMetaData; - std::vector mMeshes; + std::vector mMeshes; MatArray mMatArray; unsigned int mActiveMatGroup; MatId2MatArray mMatId2MatArray; - XmlReader* xmlReader; + XmlReader *xmlReader; }; } //namespace D3MF @@ -432,8 +430,8 @@ static const aiImporterDesc desc = { "3mf" }; -D3MFImporter::D3MFImporter() -: BaseImporter() { +D3MFImporter::D3MFImporter() : + BaseImporter() { // empty } @@ -442,17 +440,17 @@ D3MFImporter::~D3MFImporter() { } bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension( GetExtension( filename ) ); - if(extension == desc.mFileExtensions ) { + const std::string extension(GetExtension(filename)); + if (extension == desc.mFileExtensions) { return true; - } else if ( !extension.length() || checkSig ) { - if ( nullptr == pIOHandler ) { + } else if (!extension.length() || checkSig) { + if (nullptr == pIOHandler) { return false; } - if ( !ZipArchiveIOSystem::isZipArchive( pIOHandler, filename ) ) { + if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { return false; } - D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename ); + D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); return opcPackage.validate(); } @@ -467,7 +465,7 @@ const aiImporterDesc *D3MFImporter::GetInfo() const { return &desc; } -void D3MFImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) { +void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) { D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream())); diff --git a/code/3MF/D3MFImporter.h b/code/AssetLib/3MF/D3MFImporter.h similarity index 100% rename from code/3MF/D3MFImporter.h rename to code/AssetLib/3MF/D3MFImporter.h diff --git a/code/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp similarity index 100% rename from code/3MF/D3MFOpcPackage.cpp rename to code/AssetLib/3MF/D3MFOpcPackage.cpp diff --git a/code/3MF/D3MFOpcPackage.h b/code/AssetLib/3MF/D3MFOpcPackage.h similarity index 100% rename from code/3MF/D3MFOpcPackage.h rename to code/AssetLib/3MF/D3MFOpcPackage.h diff --git a/code/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp similarity index 94% rename from code/AC/ACLoader.cpp rename to code/AssetLib/AC/ACLoader.cpp index 85aee7e3a..40ff8dc86 100644 --- a/code/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -192,7 +192,7 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { objects.push_back(Object()); Object &obj = objects.back(); - aiLight *light = NULL; + aiLight *light = nullptr; if (!ASSIMP_strincmp(buffer, "light", 5)) { // This is a light source. Add it to the list mLights->push_back(light = new aiLight()); @@ -472,29 +472,29 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, } switch ((*it).flags & 0xf) { - // closed line - case 0x1: - needMat[idx].first += (unsigned int)(*it).entries.size(); - needMat[idx].second += (unsigned int)(*it).entries.size() << 1u; - break; + // closed line + case 0x1: + needMat[idx].first += (unsigned int)(*it).entries.size(); + needMat[idx].second += (unsigned int)(*it).entries.size() << 1u; + break; - // unclosed line - case 0x2: - needMat[idx].first += (unsigned int)(*it).entries.size() - 1; - needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u; - break; + // unclosed line + case 0x2: + needMat[idx].first += (unsigned int)(*it).entries.size() - 1; + needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u; + break; - // 0 == polygon, else unknown - default: - if ((*it).flags & 0xf) { - ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown"); - (*it).flags &= ~(0xf); - } + // 0 == polygon, else unknown + default: + if ((*it).flags & 0xf) { + ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown"); + (*it).flags &= ~(0xf); + } - // the number of faces increments by one, the number - // of vertices by surface.numref. - needMat[idx].first++; - needMat[idx].second += (unsigned int)(*it).entries.size(); + // the number of faces increments by one, the number + // of vertices by surface.numref. + needMat[idx].first++; + needMat[idx].second += (unsigned int)(*it).entries.size(); }; } unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes]; @@ -535,7 +535,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, // allocate UV coordinates, but only if the texture name for the // surface is not empty - aiVector3D *uv = NULL; + aiVector3D *uv = nullptr; if (object.texture.length()) { uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; mesh->mNumUVComponents[0] = 2; @@ -644,20 +644,20 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, else { // generate a name depending on the type of the node switch (object.type) { - case Object::Group: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++); - break; - case Object::Poly: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++); - break; - case Object::Light: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++); - break; + case Object::Group: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++); + break; + case Object::Poly: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++); + break; + case Object::Light: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++); + break; - // there shouldn't be more than one world, but we don't care - case Object::World: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++); - break; + // there shouldn't be more than one world, but we don't care + case Object::World: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++); + break; } } @@ -696,7 +696,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if ( file.get() == nullptr ) { + if (file.get() == nullptr) { throw DeadlyImportError("Failed to open AC3D file " + pFile + "."); } diff --git a/code/AC/ACLoader.h b/code/AssetLib/AC/ACLoader.h similarity index 78% rename from code/AC/ACLoader.h rename to code/AssetLib/AC/ACLoader.h index b32cc7ee3..e330ddf1b 100644 --- a/code/AC/ACLoader.h +++ b/code/AssetLib/AC/ACLoader.h @@ -56,27 +56,20 @@ struct aiMesh; struct aiMaterial; struct aiLight; - -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** AC3D (*.ac) importer class */ -class AC3DImporter : public BaseImporter -{ +class AC3DImporter : public BaseImporter { public: AC3DImporter(); ~AC3DImporter(); // Represents an AC3D material - struct Material - { - Material() - : rgb (0.6f,0.6f,0.6f) - , spec (1.f,1.f,1.f) - , shin (0.f) - , trans (0.f) - {} + struct Material { + Material() : + rgb(0.6f, 0.6f, 0.6f), spec(1.f, 1.f, 1.f), shin(0.f), trans(0.f) {} // base color of the material aiColor3D rgb; @@ -101,43 +94,25 @@ public: }; // Represents an AC3D surface - struct Surface - { - Surface() - : mat (0) - , flags (0) - {} + struct Surface { + Surface() : + mat(0), flags(0) {} - unsigned int mat,flags; + unsigned int mat, flags; - typedef std::pair SurfaceEntry; - std::vector< SurfaceEntry > entries; + typedef std::pair SurfaceEntry; + std::vector entries; }; // Represents an AC3D object - struct Object - { - Object() - : type (World) - , name( "" ) - , children() - , texture( "" ) - , texRepeat( 1.f, 1.f ) - , texOffset( 0.0f, 0.0f ) - , rotation() - , translation() - , vertices() - , surfaces() - , numRefs (0) - , subDiv (0) - , crease() - {} + struct Object { + Object() : + type(World), name(""), children(), texture(""), texRepeat(1.f, 1.f), texOffset(0.0f, 0.0f), rotation(), translation(), vertices(), surfaces(), numRefs(0), subDiv(0), crease() {} // Type description - enum Type - { + enum Type { World = 0x0, - Poly = 0x1, + Poly = 0x1, Group = 0x2, Light = 0x4 } type; @@ -177,37 +152,33 @@ public: float crease; }; - public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, + bool checkSig) const; protected: - // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ - const aiImporterDesc* GetInfo () const; + const aiImporterDesc *GetInfo() const; // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details*/ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); + void InternReadFile(const std::string &pFile, aiScene *pScene, + IOSystem *pIOHandler); // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration * basing on the Importer's configuration property list.*/ - void SetupProperties(const Importer* pImp); + void SetupProperties(const Importer *pImp); private: - // ------------------------------------------------------------------- /** Get the next line from the file. * @return false if the end of the file was reached*/ @@ -218,7 +189,7 @@ private: * load subobjects, the method returns after a 'kids 0' was * encountered. * @objects List of output objects*/ - void LoadObjectSection(std::vector& objects); + void LoadObjectSection(std::vector &objects); // ------------------------------------------------------------------- /** Convert all objects into meshes and nodes. @@ -227,24 +198,24 @@ private: * @param outMaterials List of output materials * @param materials Material list * @param Scenegraph node for the object */ - aiNode* ConvertObjectSection(Object& object, - std::vector& meshes, - std::vector& outMaterials, - const std::vector& materials, - aiNode* parent = NULL); + aiNode *ConvertObjectSection(Object &object, + std::vector &meshes, + std::vector &outMaterials, + const std::vector &materials, + aiNode *parent = nullptr); // ------------------------------------------------------------------- /** Convert a material * @param object Current object * @param matSrc Source material description * @param matDest Destination material to be filled */ - void ConvertMaterial(const Object& object, - const Material& matSrc, - aiMaterial& matDest); + void ConvertMaterial(const Object &object, + const Material &matSrc, + aiMaterial &matDest); private: // points to the next data line - const char* buffer; + const char *buffer; // Configuration option: if enabled, up to two meshes // are generated per material: those faces who have @@ -261,7 +232,7 @@ private: unsigned int mNumMeshes; // current list of light sources - std::vector* mLights; + std::vector *mLights; // name counters unsigned int mLightsCounter, mGroupsCounter, mPolysCounter, mWorldsCounter; diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp new file mode 100644 index 000000000..3bb18b0ab --- /dev/null +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -0,0 +1,672 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/// \file AMFImporter.cpp +/// \brief AMF-format files importer for Assimp: main algorithm implementation. +/// \date 2016 +/// \author smal.root@gmail.com + +#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER + +// Header files, Assimp. +#include "AMFImporter.hpp" +#include "AMFImporter_Macro.hpp" + +#include +#include + +// Header files, stdlib. +#include + +namespace Assimp { + +/// \var aiImporterDesc AMFImporter::Description +/// Conastant which hold importer description +const aiImporterDesc AMFImporter::Description = { + "Additive manufacturing file format(AMF) Importer", + "smalcom", + "", + "See documentation in source code. Chapter: Limitations.", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + 0, + 0, + 0, + 0, + "amf" +}; + +void AMFImporter::Clear() { + mNodeElement_Cur = nullptr; + mUnit.clear(); + mMaterial_Converted.clear(); + mTexture_Converted.clear(); + // Delete all elements + if (!mNodeElement_List.empty()) { + for (CAMFImporter_NodeElement *ne : mNodeElement_List) { + delete ne; + } + + mNodeElement_List.clear(); + } +} + +AMFImporter::~AMFImporter() { + if (mReader != nullptr) delete mReader; + // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. + Clear(); +} + +/*********************************************************************************************************************************************/ +/************************************************************ Functions: find set ************************************************************/ +/*********************************************************************************************************************************************/ + +bool AMFImporter::Find_NodeElement(const std::string &pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement **pNodeElement) const { + for (CAMFImporter_NodeElement *ne : mNodeElement_List) { + if ((ne->ID == pID) && (ne->Type == pType)) { + if (pNodeElement != nullptr) *pNodeElement = ne; + + return true; + } + } // for(CAMFImporter_NodeElement* ne: mNodeElement_List) + + return false; +} + +bool AMFImporter::Find_ConvertedNode(const std::string &pID, std::list &pNodeList, aiNode **pNode) const { + aiString node_name(pID.c_str()); + + for (aiNode *node : pNodeList) { + if (node->mName == node_name) { + if (pNode != nullptr) *pNode = node; + + return true; + } + } // for(aiNode* node: pNodeList) + + return false; +} + +bool AMFImporter::Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const { + for (const SPP_Material &mat : mMaterial_Converted) { + if (mat.ID == pID) { + if (pConvertedMaterial != nullptr) *pConvertedMaterial = &mat; + + return true; + } + } // for(const SPP_Material& mat: mMaterial_Converted) + + return false; +} + +/*********************************************************************************************************************************************/ +/************************************************************ Functions: throw set ***********************************************************/ +/*********************************************************************************************************************************************/ + +void AMFImporter::Throw_CloseNotFound(const std::string &pNode) { + throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); +} + +void AMFImporter::Throw_IncorrectAttr(const std::string &pAttrName) { + throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); +} + +void AMFImporter::Throw_IncorrectAttrValue(const std::string &pAttrName) { + throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value."); +} + +void AMFImporter::Throw_MoreThanOnceDefined(const std::string &pNodeType, const std::string &pDescription) { + throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription); +} + +void AMFImporter::Throw_ID_NotFound(const std::string &pID) const { + throw DeadlyImportError("Not found node with name \"" + pID + "\"."); +} + +/*********************************************************************************************************************************************/ +/************************************************************* Functions: XML set ************************************************************/ +/*********************************************************************************************************************************************/ + +void AMFImporter::XML_CheckNode_MustHaveChildren() { + if (mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children."); +} + +void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) { + static const size_t Uns_Skip_Len = 3; + const char *Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" }; + + static bool skipped_before[Uns_Skip_Len] = { false, false, false }; + + std::string nn(mReader->getNodeName()); + bool found = false; + bool close_found = false; + size_t sk_idx; + + for (sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) { + if (nn != Uns_Skip[sk_idx]) continue; + + found = true; + if (mReader->isEmptyElement()) { + close_found = true; + + goto casu_cres; + } + + while (mReader->read()) { + if ((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName())) { + close_found = true; + + goto casu_cres; + } + } + } // for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) + +casu_cres: + + if (!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + "."); + if (!close_found) Throw_CloseNotFound(nn); + + if (!skipped_before[sk_idx]) { + skipped_before[sk_idx] = true; + ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); + } +} + +bool AMFImporter::XML_SearchNode(const std::string &pNodeName) { + while (mReader->read()) { + if ((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true; + } + + return false; +} + +bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) { + std::string val(mReader->getAttributeValue(pAttrIdx)); + + if ((val == "false") || (val == "0")) + return false; + else if ((val == "true") || (val == "1")) + return true; + else + throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\""); +} + +float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) { + std::string val; + float tvalf; + + ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); + fast_atoreal_move(val.c_str(), tvalf, false); + + return tvalf; +} + +uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) { + return strtoul10(mReader->getAttributeValue(pAttrIdx)); +} + +float AMFImporter::XML_ReadNode_GetVal_AsFloat() { + std::string val; + float tvalf; + + if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt."); + if (mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt."); + + ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val); + fast_atoreal_move(val.c_str(), tvalf, false); + + return tvalf; +} + +uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32() { + if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt."); + if (mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt."); + + return strtoul10(mReader->getNodeData()); +} + +void AMFImporter::XML_ReadNode_GetVal_AsString(std::string &pValue) { + if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt."); + if (mReader->getNodeType() != irr::io::EXN_TEXT) + throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt."); + + pValue = mReader->getNodeData(); +} + +/*********************************************************************************************************************************************/ +/************************************************************ Functions: parse set ***********************************************************/ +/*********************************************************************************************************************************************/ + +void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement *pNode) { + mNodeElement_Cur->Child.push_back(pNode); // add new element to current element child list. + mNodeElement_Cur = pNode; // switch current element to new one. +} + +void AMFImporter::ParseHelper_Node_Exit() { + // check if we can walk up. + if (mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent; +} + +void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) { + size_t instr_len; + + pOutString.clear(); + instr_len = strlen(pInStr); + if (!instr_len) return; + + pOutString.reserve(instr_len * 3 / 2); + // check and correct floats in format ".x". Must be "x.y". + if (pInStr[0] == '.') pOutString.push_back('0'); + + pOutString.push_back(pInStr[0]); + for (size_t ci = 1; ci < instr_len; ci++) { + if ((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) { + pOutString.push_back('0'); + pOutString.push_back('.'); + } else { + pOutString.push_back(pInStr[ci]); + } + } +} + +static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { + return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); +} + +void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector &pOutputData) const { + // With help from + // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html + const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + uint8_t tidx = 0; + uint8_t arr4[4], arr3[3]; + + // check input data + if (pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four."); + // prepare output place + pOutputData.clear(); + pOutputData.reserve(pInputBase64.size() / 4 * 3); + + for (size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--) { + if (ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) { + arr4[tidx++] = pInputBase64[in_idx++]; + if (tidx == 4) { + for (tidx = 0; tidx < 4; tidx++) + arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]); + + arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); + arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); + arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; + for (tidx = 0; tidx < 3; tidx++) + pOutputData.push_back(arr3[tidx]); + + tidx = 0; + } // if(tidx == 4) + } // if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) + else { + in_idx++; + } // if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else + } + + if (tidx) { + for (uint8_t i = tidx; i < 4; i++) + arr4[i] = 0; + for (uint8_t i = 0; i < 4; i++) + arr4[i] = (uint8_t)(base64_chars.find(arr4[i])); + + arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4); + arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2); + arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3]; + for (uint8_t i = 0; i < (tidx - 1); i++) + pOutputData.push_back(arr3[i]); + } +} + +void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { + irr::io::IrrXMLReader *OldReader = mReader; // store current XMLreader. + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); + + // Check whether we can read from the file + if (file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + "."); + + // generate a XML reader for it + std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); + mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); + if (!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); + // + // start reading + // search for root tag + if (XML_SearchNode("amf")) + ParseNode_Root(); + else + throw DeadlyImportError("Root node \"amf\" not found."); + + delete mReader; + // restore old XMLreader + mReader = OldReader; +} + +// +// +// Root XML element. +// Multi elements - No. +void AMFImporter::ParseNode_Root() { + std::string unit, version; + CAMFImporter_NodeElement *ne(nullptr); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue); + MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND_WSKIP; + + // Check attributes + if (!mUnit.empty()) { + if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit"); + } + + // create root node element. + ne = new CAMFImporter_NodeElement_Root(nullptr); + mNodeElement_Cur = ne; // set first "current" element + // and assign attribute's values + ((CAMFImporter_NodeElement_Root *)ne)->Unit = unit; + ((CAMFImporter_NodeElement_Root *)ne)->Version = version; + + // Check for child nodes + if (!mReader->isEmptyElement()) { + MACRO_NODECHECK_LOOPBEGIN("amf"); + if (XML_CheckNode_NameEqual("object")) { + ParseNode_Object(); + continue; + } + if (XML_CheckNode_NameEqual("material")) { + ParseNode_Material(); + continue; + } + if (XML_CheckNode_NameEqual("texture")) { + ParseNode_Texture(); + continue; + } + if (XML_CheckNode_NameEqual("constellation")) { + ParseNode_Constellation(); + continue; + } + if (XML_CheckNode_NameEqual("metadata")) { + ParseNode_Metadata(); + continue; + } + MACRO_NODECHECK_LOOPEND("amf"); + mNodeElement_Cur = ne; // force restore "current" element + } // if(!mReader->isEmptyElement()) + + mNodeElement_List.push_back(ne); // add to node element list because its a new object in graph. +} + +// +// +// A collection of objects or constellations with specific relative locations. +// Multi elements - Yes. +// Parent element - . +void AMFImporter::ParseNode_Constellation() { + std::string id; + CAMFImporter_NodeElement *ne(nullptr); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + + // create and if needed - define new grouping object. + ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur); + + CAMFImporter_NodeElement_Constellation &als = *((CAMFImporter_NodeElement_Constellation *)ne); // alias for convenience + + if (!id.empty()) als.ID = id; + // Check for child nodes + if (!mReader->isEmptyElement()) { + ParseHelper_Node_Enter(ne); + MACRO_NODECHECK_LOOPBEGIN("constellation"); + if (XML_CheckNode_NameEqual("instance")) { + ParseNode_Instance(); + continue; + } + if (XML_CheckNode_NameEqual("metadata")) { + ParseNode_Metadata(); + continue; + } + MACRO_NODECHECK_LOOPEND("constellation"); + ParseHelper_Node_Exit(); + } // if(!mReader->isEmptyElement()) + else { + mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element + } // if(!mReader->isEmptyElement()) else + + mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. +} + +// +// +// A collection of objects or constellations with specific relative locations. +// Multi elements - Yes. +// Parent element - . +void AMFImporter::ParseNode_Instance() { + std::string objectid; + CAMFImporter_NodeElement *ne(nullptr); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + + // used object id must be defined, check that. + if (objectid.empty()) throw DeadlyImportError("\"objectid\" in must be defined."); + // create and define new grouping object. + ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur); + + CAMFImporter_NodeElement_Instance &als = *((CAMFImporter_NodeElement_Instance *)ne); // alias for convenience + + als.ObjectID = objectid; + // Check for child nodes + if (!mReader->isEmptyElement()) { + bool read_flag[6] = { false, false, false, false, false, false }; + + als.Delta.Set(0, 0, 0); + als.Rotation.Set(0, 0, 0); + ParseHelper_Node_Enter(ne); + MACRO_NODECHECK_LOOPBEGIN("instance"); + MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x); + MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y); + MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z); + MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x); + MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y); + MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z); + MACRO_NODECHECK_LOOPEND("instance"); + ParseHelper_Node_Exit(); + // also convert degrees to radians. + als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f; + als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f; + als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f; + } // if(!mReader->isEmptyElement()) + else { + mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element + } // if(!mReader->isEmptyElement()) else + + mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. +} + +// +// +// An object definition. +// Multi elements - Yes. +// Parent element - . +void AMFImporter::ParseNode_Object() { + std::string id; + CAMFImporter_NodeElement *ne(nullptr); + + // Read attributes for node . + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + + // create and if needed - define new geometry object. + ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur); + + CAMFImporter_NodeElement_Object &als = *((CAMFImporter_NodeElement_Object *)ne); // alias for convenience + + if (!id.empty()) als.ID = id; + // Check for child nodes + if (!mReader->isEmptyElement()) { + bool col_read = false; + + ParseHelper_Node_Enter(ne); + MACRO_NODECHECK_LOOPBEGIN("object"); + if (XML_CheckNode_NameEqual("color")) { + // Check if color already defined for object. + if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for ."); + // read data and set flag about it + ParseNode_Color(); + col_read = true; + + continue; + } + + if (XML_CheckNode_NameEqual("mesh")) { + ParseNode_Mesh(); + continue; + } + if (XML_CheckNode_NameEqual("metadata")) { + ParseNode_Metadata(); + continue; + } + MACRO_NODECHECK_LOOPEND("object"); + ParseHelper_Node_Exit(); + } // if(!mReader->isEmptyElement()) + else { + mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element + } // if(!mReader->isEmptyElement()) else + + mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. +} + +// +// +// Specify additional information about an entity. +// Multi elements - Yes. +// Parent element - , , , , . +// +// Reserved types are: +// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user. +// "Description" - A description of the content of the entity +// "URL" - A link to an external resource relating to the entity +// "Author" - Specifies the name(s) of the author(s) of the entity +// "Company" - Specifying the company generating the entity +// "CAD" - specifies the name of the originating CAD software and version +// "Revision" - specifies the revision of the entity +// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system +// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only) +void AMFImporter::ParseNode_Metadata() { + std::string type, value; + CAMFImporter_NodeElement *ne(nullptr); + + // read attribute + MACRO_ATTRREAD_LOOPBEG; + MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue); + MACRO_ATTRREAD_LOOPEND; + // and value of node. + value = mReader->getNodeData(); + // Create node element and assign read data. + ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur); + ((CAMFImporter_NodeElement_Metadata *)ne)->Type = type; + ((CAMFImporter_NodeElement_Metadata *)ne)->Value = value; + mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element + mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. +} + +/*********************************************************************************************************************************************/ +/******************************************************** Functions: BaseImporter set ********************************************************/ +/*********************************************************************************************************************************************/ + +bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const { + const std::string extension = GetExtension(pFile); + + if (extension == "amf") { + return true; + } + + if (!extension.length() || pCheckSig) { + const char *tokens[] = { " &pExtensionList) { + pExtensionList.insert("amf"); +} + +const aiImporterDesc *AMFImporter::GetInfo() const { + return &Description; +} + +void AMFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + Clear(); // delete old graph. + ParseFile(pFile, pIOHandler); + Postprocess_BuildScene(pScene); + // scene graph is ready, exit. +} + +} // namespace Assimp + +#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER diff --git a/code/AMF/AMFImporter.hpp b/code/AssetLib/AMF/AMFImporter.hpp similarity index 100% rename from code/AMF/AMFImporter.hpp rename to code/AssetLib/AMF/AMFImporter.hpp diff --git a/code/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp similarity index 100% rename from code/AMF/AMFImporter_Geometry.cpp rename to code/AssetLib/AMF/AMFImporter_Geometry.cpp diff --git a/code/AMF/AMFImporter_Macro.hpp b/code/AssetLib/AMF/AMFImporter_Macro.hpp similarity index 100% rename from code/AMF/AMFImporter_Macro.hpp rename to code/AssetLib/AMF/AMFImporter_Macro.hpp diff --git a/code/AMF/AMFImporter_Material.cpp b/code/AssetLib/AMF/AMFImporter_Material.cpp similarity index 100% rename from code/AMF/AMFImporter_Material.cpp rename to code/AssetLib/AMF/AMFImporter_Material.cpp diff --git a/code/AMF/AMFImporter_Node.hpp b/code/AssetLib/AMF/AMFImporter_Node.hpp similarity index 100% rename from code/AMF/AMFImporter_Node.hpp rename to code/AssetLib/AMF/AMFImporter_Node.hpp diff --git a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp new file mode 100644 index 000000000..596b0235c --- /dev/null +++ b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp @@ -0,0 +1,872 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/// \file AMFImporter_Postprocess.cpp +/// \brief Convert built scenegraph and objects to Assimp scenegraph. +/// \date 2016 +/// \author smal.root@gmail.com + +#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER + +#include "AMFImporter.hpp" + +// Header files, Assimp. +#include +#include +#include + +// Header files, stdlib. +#include + +namespace Assimp { + +aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const { + aiColor4D tcol; + + // Check if stored data are supported. + if (!Composition.empty()) { + throw DeadlyImportError("IME. GetColor for composition"); + } else if (Color->Composed) { + throw DeadlyImportError("IME. GetColor, composed color"); + } else { + tcol = Color->Color; + } + + // Check if default color must be used + if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { + tcol.r = 0.5f; + tcol.g = 0.5f; + tcol.b = 0.5f; + tcol.a = 1; + } + + return tcol; +} + +void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh &pNodeElement, std::vector &pVertexCoordinateArray, + std::vector &pVertexColorArray) const { + CAMFImporter_NodeElement_Vertices *vn = nullptr; + size_t col_idx; + + // All data stored in "vertices", search for it. + for (CAMFImporter_NodeElement *ne_child : pNodeElement.Child) { + if (ne_child->Type == CAMFImporter_NodeElement::ENET_Vertices) vn = (CAMFImporter_NodeElement_Vertices *)ne_child; + } + + // If "vertices" not found then no work for us. + if (vn == nullptr) return; + + pVertexCoordinateArray.reserve(vn->Child.size()); // all coordinates stored as child and we need to reserve space for future push_back's. + pVertexColorArray.resize(vn->Child.size()); // colors count equal vertices count. + col_idx = 0; + // Inside vertices collect all data and place to arrays + for (CAMFImporter_NodeElement *vn_child : vn->Child) { + // vertices, colors + if (vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex) { + // by default clear color for current vertex + pVertexColorArray[col_idx] = nullptr; + + for (CAMFImporter_NodeElement *vtx : vn_child->Child) { + if (vtx->Type == CAMFImporter_NodeElement::ENET_Coordinates) { + pVertexCoordinateArray.push_back(((CAMFImporter_NodeElement_Coordinates *)vtx)->Coordinate); + + continue; + } + + if (vtx->Type == CAMFImporter_NodeElement::ENET_Color) { + pVertexColorArray[col_idx] = (CAMFImporter_NodeElement_Color *)vtx; + + continue; + } + } // for(CAMFImporter_NodeElement* vtx: vn_child->Child) + + col_idx++; + } // if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex) + } // for(CAMFImporter_NodeElement* vn_child: vn->Child) +} + +size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &pID_R, const std::string &pID_G, const std::string &pID_B, + const std::string &pID_A) { + size_t TextureConverted_Index; + std::string TextureConverted_ID; + + // check input data + if (pID_R.empty() && pID_G.empty() && pID_B.empty() && pID_A.empty()) + throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. At least one texture ID must be defined."); + + // Create ID + TextureConverted_ID = pID_R + "_" + pID_G + "_" + pID_B + "_" + pID_A; + // Check if texture specified by set of IDs is converted already. + TextureConverted_Index = 0; + for (const SPP_Texture &tex_convd : mTexture_Converted) { + if (tex_convd.ID == TextureConverted_ID) { + return TextureConverted_Index; + } else { + ++TextureConverted_Index; + } + } + + // + // Converted texture not found, create it. + // + CAMFImporter_NodeElement_Texture *src_texture[4]{ nullptr }; + std::vector src_texture_4check; + SPP_Texture converted_texture; + + { // find all specified source textures + CAMFImporter_NodeElement *t_tex; + + // R + if (!pID_R.empty()) { + if (!Find_NodeElement(pID_R, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_R); + + src_texture[0] = (CAMFImporter_NodeElement_Texture *)t_tex; + src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex); + } else { + src_texture[0] = nullptr; + } + + // G + if (!pID_G.empty()) { + if (!Find_NodeElement(pID_G, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_G); + + src_texture[1] = (CAMFImporter_NodeElement_Texture *)t_tex; + src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex); + } else { + src_texture[1] = nullptr; + } + + // B + if (!pID_B.empty()) { + if (!Find_NodeElement(pID_B, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_B); + + src_texture[2] = (CAMFImporter_NodeElement_Texture *)t_tex; + src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex); + } else { + src_texture[2] = nullptr; + } + + // A + if (!pID_A.empty()) { + if (!Find_NodeElement(pID_A, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_A); + + src_texture[3] = (CAMFImporter_NodeElement_Texture *)t_tex; + src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex); + } else { + src_texture[3] = nullptr; + } + } // END: find all specified source textures + + // check that all textures has same size + if (src_texture_4check.size() > 1) { + for (size_t i = 0, i_e = (src_texture_4check.size() - 1); i < i_e; i++) { + if ((src_texture_4check[i]->Width != src_texture_4check[i + 1]->Width) || (src_texture_4check[i]->Height != src_texture_4check[i + 1]->Height) || + (src_texture_4check[i]->Depth != src_texture_4check[i + 1]->Depth)) { + throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. Source texture must has the same size."); + } + } + } // if(src_texture_4check.size() > 1) + + // set texture attributes + converted_texture.Width = src_texture_4check[0]->Width; + converted_texture.Height = src_texture_4check[0]->Height; + converted_texture.Depth = src_texture_4check[0]->Depth; + // if one of source texture is tiled then converted texture is tiled too. + converted_texture.Tiled = false; + for (uint8_t i = 0; i < src_texture_4check.size(); i++) + converted_texture.Tiled |= src_texture_4check[i]->Tiled; + + // Create format hint. + strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string. + if (!pID_R.empty()) converted_texture.FormatHint[4] = '8'; + if (!pID_G.empty()) converted_texture.FormatHint[5] = '8'; + if (!pID_B.empty()) converted_texture.FormatHint[6] = '8'; + if (!pID_A.empty()) converted_texture.FormatHint[7] = '8'; + + // + // Сopy data of textures. + // + size_t tex_size = 0; + size_t step = 0; + size_t off_g = 0; + size_t off_b = 0; + + // Calculate size of the target array and rule how data will be copied. + if (!pID_R.empty() && nullptr != src_texture[0]) { + tex_size += src_texture[0]->Data.size(); + step++, off_g++, off_b++; + } + if (!pID_G.empty() && nullptr != src_texture[1]) { + tex_size += src_texture[1]->Data.size(); + step++, off_b++; + } + if (!pID_B.empty() && nullptr != src_texture[2]) { + tex_size += src_texture[2]->Data.size(); + step++; + } + if (!pID_A.empty() && nullptr != src_texture[3]) { + tex_size += src_texture[3]->Data.size(); + step++; + } + + // Create target array. + converted_texture.Data = new uint8_t[tex_size]; + // And copy data + auto CopyTextureData = [&](const std::string &pID, const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void { + if (!pID.empty()) { + for (size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) { + CAMFImporter_NodeElement_Texture *tex = src_texture[pSrcTexNum]; + ai_assert(tex); + converted_texture.Data[idx_target] = tex->Data.at(idx_src); + } + } + }; // auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void + + CopyTextureData(pID_R, 0, step, 0); + CopyTextureData(pID_G, off_g, step, 1); + CopyTextureData(pID_B, off_b, step, 2); + CopyTextureData(pID_A, step - 1, step, 3); + + // Store new converted texture ID + converted_texture.ID = TextureConverted_ID; + // Store new converted texture + mTexture_Converted.push_back(converted_texture); + + return TextureConverted_Index; +} + +void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list &pInputList, std::list> &pOutputList_Separated) { + auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap *pTexMap1, const CAMFImporter_NodeElement_TexMap *pTexMap2) -> bool { + if ((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true; + if (pTexMap1 == nullptr) return false; + if (pTexMap2 == nullptr) return false; + + if (pTexMap1->TextureID_R != pTexMap2->TextureID_R) return false; + if (pTexMap1->TextureID_G != pTexMap2->TextureID_G) return false; + if (pTexMap1->TextureID_B != pTexMap2->TextureID_B) return false; + if (pTexMap1->TextureID_A != pTexMap2->TextureID_A) return false; + + return true; + }; + + pOutputList_Separated.clear(); + if (pInputList.empty()) return; + + do { + SComplexFace face_start = pInputList.front(); + std::list face_list_cur; + + for (std::list::iterator it = pInputList.begin(), it_end = pInputList.end(); it != it_end;) { + if (texmap_is_equal(face_start.TexMap, it->TexMap)) { + auto it_old = it; + + ++it; + face_list_cur.push_back(*it_old); + pInputList.erase(it_old); + } else { + ++it; + } + } + + if (!face_list_cur.empty()) pOutputList_Separated.push_back(face_list_cur); + + } while (!pInputList.empty()); +} + +void AMFImporter::Postprocess_AddMetadata(const std::list &metadataList, aiNode &sceneNode) const { + if (!metadataList.empty()) { + if (sceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong."); + + // copy collected metadata to output node. + sceneNode.mMetaData = aiMetadata::Alloc(static_cast(metadataList.size())); + size_t meta_idx(0); + + for (const CAMFImporter_NodeElement_Metadata &metadata : metadataList) { + sceneNode.mMetaData->Set(static_cast(meta_idx++), metadata.Type, aiString(metadata.Value)); + } + } // if(!metadataList.empty()) +} + +void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object &pNodeElement, std::list &pMeshList, aiNode **pSceneNode) { + CAMFImporter_NodeElement_Color *object_color = nullptr; + + // create new aiNode and set name as has. + *pSceneNode = new aiNode; + (*pSceneNode)->mName = pNodeElement.ID; + // read mesh and color + for (const CAMFImporter_NodeElement *ne_child : pNodeElement.Child) { + std::vector vertex_arr; + std::vector color_arr; + + // color for object + if (ne_child->Type == CAMFImporter_NodeElement::ENET_Color) object_color = (CAMFImporter_NodeElement_Color *)ne_child; + + if (ne_child->Type == CAMFImporter_NodeElement::ENET_Mesh) { + // Create arrays from children of mesh: vertices. + PostprocessHelper_CreateMeshDataArray(*((CAMFImporter_NodeElement_Mesh *)ne_child), vertex_arr, color_arr); + // Use this arrays as a source when creating every aiMesh + Postprocess_BuildMeshSet(*((CAMFImporter_NodeElement_Mesh *)ne_child), vertex_arr, color_arr, object_color, pMeshList, **pSceneNode); + } + } // for(const CAMFImporter_NodeElement* ne_child: pNodeElement) +} + +void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &pNodeElement, const std::vector &pVertexCoordinateArray, + const std::vector &pVertexColorArray, + const CAMFImporter_NodeElement_Color *pObjectColor, std::list &pMeshList, aiNode &pSceneNode) { + std::list mesh_idx; + + // all data stored in "volume", search for it. + for (const CAMFImporter_NodeElement *ne_child : pNodeElement.Child) { + const CAMFImporter_NodeElement_Color *ne_volume_color = nullptr; + const SPP_Material *cur_mat = nullptr; + + if (ne_child->Type == CAMFImporter_NodeElement::ENET_Volume) { + /******************* Get faces *******************/ + const CAMFImporter_NodeElement_Volume *ne_volume = reinterpret_cast(ne_child); + + std::list complex_faces_list; // List of the faces of the volume. + std::list> complex_faces_toplist; // List of the face list for every mesh. + + // check if volume use material + if (!ne_volume->MaterialID.empty()) { + if (!Find_ConvertedMaterial(ne_volume->MaterialID, &cur_mat)) Throw_ID_NotFound(ne_volume->MaterialID); + } + + // inside "volume" collect all data and place to arrays or create new objects + for (const CAMFImporter_NodeElement *ne_volume_child : ne_volume->Child) { + // color for volume + if (ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Color) { + ne_volume_color = reinterpret_cast(ne_volume_child); + } else if (ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Triangle) // triangles, triangles colors + { + const CAMFImporter_NodeElement_Triangle &tri_al = *reinterpret_cast(ne_volume_child); + + SComplexFace complex_face; + + // initialize pointers + complex_face.Color = nullptr; + complex_face.TexMap = nullptr; + // get data from triangle children: color, texture coordinates. + if (tri_al.Child.size()) { + for (const CAMFImporter_NodeElement *ne_triangle_child : tri_al.Child) { + if (ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_Color) + complex_face.Color = reinterpret_cast(ne_triangle_child); + else if (ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_TexMap) + complex_face.TexMap = reinterpret_cast(ne_triangle_child); + } + } // if(tri_al.Child.size()) + + // create new face and store it. + complex_face.Face.mNumIndices = 3; + complex_face.Face.mIndices = new unsigned int[3]; + complex_face.Face.mIndices[0] = static_cast(tri_al.V[0]); + complex_face.Face.mIndices[1] = static_cast(tri_al.V[1]); + complex_face.Face.mIndices[2] = static_cast(tri_al.V[2]); + complex_faces_list.push_back(complex_face); + } + } // for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child) + + /**** Split faces list: one list per mesh ****/ + PostprocessHelper_SplitFacesByTextureID(complex_faces_list, complex_faces_toplist); + + /***** Create mesh for every faces list ******/ + for (std::list &face_list_cur : complex_faces_toplist) { + auto VertexIndex_GetMinimal = [](const std::list &pFaceList, const size_t *pBiggerThan) -> size_t { + size_t rv = 0; + + if (pBiggerThan != nullptr) { + bool found = false; + + for (const SComplexFace &face : pFaceList) { + for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) { + if (face.Face.mIndices[idx_vert] > *pBiggerThan) { + rv = face.Face.mIndices[idx_vert]; + found = true; + + break; + } + } + + if (found) break; + } + + if (!found) return *pBiggerThan; + } else { + rv = pFaceList.front().Face.mIndices[0]; + } // if(pBiggerThan != nullptr) else + + for (const SComplexFace &face : pFaceList) { + for (size_t vi = 0; vi < face.Face.mNumIndices; vi++) { + if (face.Face.mIndices[vi] < rv) { + if (pBiggerThan != nullptr) { + if (face.Face.mIndices[vi] > *pBiggerThan) rv = face.Face.mIndices[vi]; + } else { + rv = face.Face.mIndices[vi]; + } + } + } + } // for(const SComplexFace& face: pFaceList) + + return rv; + }; // auto VertexIndex_GetMinimal = [](const std::list& pFaceList, const size_t* pBiggerThan) -> size_t + + auto VertexIndex_Replace = [](std::list &pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void { + for (const SComplexFace &face : pFaceList) { + for (size_t vi = 0; vi < face.Face.mNumIndices; vi++) { + if (face.Face.mIndices[vi] == pIdx_From) face.Face.mIndices[vi] = static_cast(pIdx_To); + } + } + }; // auto VertexIndex_Replace = [](std::list& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void + + auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D { + // Color priorities(In descending order): + // 1. triangle color; + // 2. vertex color; + // 3. volume color; + // 4. object color; + // 5. material; + // 6. default - invisible coat. + // + // Fill vertices colors in color priority list above that's points from 1 to 6. + if ((pIdx < pVertexColorArray.size()) && (pVertexColorArray[pIdx] != nullptr)) // check for vertex color + { + if (pVertexColorArray[pIdx]->Composed) + throw DeadlyImportError("IME: vertex color composed"); + else + return pVertexColorArray[pIdx]->Color; + } else if (ne_volume_color != nullptr) // check for volume color + { + if (ne_volume_color->Composed) + throw DeadlyImportError("IME: volume color composed"); + else + return ne_volume_color->Color; + } else if (pObjectColor != nullptr) // check for object color + { + if (pObjectColor->Composed) + throw DeadlyImportError("IME: object color composed"); + else + return pObjectColor->Color; + } else if (cur_mat != nullptr) // check for material + { + return cur_mat->GetColor(pVertexCoordinateArray.at(pIdx).x, pVertexCoordinateArray.at(pIdx).y, pVertexCoordinateArray.at(pIdx).z); + } else // set default color. + { + return { 0, 0, 0, 0 }; + } // if((vi < pVertexColorArray.size()) && (pVertexColorArray[vi] != nullptr)) else + }; // auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D + + aiMesh *tmesh = new aiMesh; + + tmesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // Only triangles is supported by AMF. + // + // set geometry and colors (vertices) + // + // copy faces/triangles + tmesh->mNumFaces = static_cast(face_list_cur.size()); + tmesh->mFaces = new aiFace[tmesh->mNumFaces]; + + // Create vertices list and optimize indices. Optimisation mean following.In AMF all volumes use one big list of vertices. And one volume + // can use only part of vertices list, for example: vertices list contain few thousands of vertices and volume use vertices 1, 3, 10. + // Do you need all this thousands of garbage? Of course no. So, optimisation step transformate sparse indices set to continuous. + size_t VertexCount_Max = tmesh->mNumFaces * 3; // 3 - triangles. + std::vector vert_arr, texcoord_arr; + std::vector col_arr; + + vert_arr.reserve(VertexCount_Max * 2); // "* 2" - see below TODO. + col_arr.reserve(VertexCount_Max * 2); + + { // fill arrays + size_t vert_idx_from, vert_idx_to; + + // first iteration. + vert_idx_to = 0; + vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr); + vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from)); + col_arr.push_back(Vertex_CalculateColor(vert_idx_from)); + if (vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to); + + // rest iterations + do { + vert_idx_from = VertexIndex_GetMinimal(face_list_cur, &vert_idx_to); + if (vert_idx_from == vert_idx_to) break; // all indices are transferred, + + vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from)); + col_arr.push_back(Vertex_CalculateColor(vert_idx_from)); + vert_idx_to++; + if (vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to); + + } while (true); + } // fill arrays. END. + + // + // check if triangle colors are used and create additional faces if needed. + // + for (const SComplexFace &face_cur : face_list_cur) { + if (face_cur.Color != nullptr) { + aiColor4D face_color; + size_t vert_idx_new = vert_arr.size(); + + if (face_cur.Color->Composed) + throw DeadlyImportError("IME: face color composed"); + else + face_color = face_cur.Color->Color; + + for (size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++) { + vert_arr.push_back(vert_arr.at(face_cur.Face.mIndices[idx_ind])); + col_arr.push_back(face_color); + face_cur.Face.mIndices[idx_ind] = static_cast(vert_idx_new++); + } + } // if(face_cur.Color != nullptr) + } // for(const SComplexFace& face_cur: face_list_cur) + + // + // if texture is used then copy texture coordinates too. + // + if (face_list_cur.front().TexMap != nullptr) { + size_t idx_vert_new = vert_arr.size(); + ///TODO: clean unused vertices. "* 2": in certain cases - mesh full of triangle colors - vert_arr will contain duplicated vertices for + /// colored triangles and initial vertices (for colored vertices) which in real became unused. This part need more thinking about + /// optimisation. + bool *idx_vert_used; + + idx_vert_used = new bool[VertexCount_Max * 2]; + for (size_t i = 0, i_e = VertexCount_Max * 2; i < i_e; i++) + idx_vert_used[i] = false; + + // This ID's will be used when set materials ID in scene. + tmesh->mMaterialIndex = static_cast(PostprocessHelper_GetTextureID_Or_Create(face_list_cur.front().TexMap->TextureID_R, + face_list_cur.front().TexMap->TextureID_G, + face_list_cur.front().TexMap->TextureID_B, + face_list_cur.front().TexMap->TextureID_A)); + texcoord_arr.resize(VertexCount_Max * 2); + for (const SComplexFace &face_cur : face_list_cur) { + for (size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++) { + const size_t idx_vert = face_cur.Face.mIndices[idx_ind]; + + if (!idx_vert_used[idx_vert]) { + texcoord_arr.at(idx_vert) = face_cur.TexMap->TextureCoordinate[idx_ind]; + idx_vert_used[idx_vert] = true; + } else if (texcoord_arr.at(idx_vert) != face_cur.TexMap->TextureCoordinate[idx_ind]) { + // in that case one vertex is shared with many texture coordinates. We need to duplicate vertex with another texture + // coordinates. + vert_arr.push_back(vert_arr.at(idx_vert)); + col_arr.push_back(col_arr.at(idx_vert)); + texcoord_arr.at(idx_vert_new) = face_cur.TexMap->TextureCoordinate[idx_ind]; + face_cur.Face.mIndices[idx_ind] = static_cast(idx_vert_new++); + } + } // for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++) + } // for(const SComplexFace& face_cur: face_list_cur) + + delete[] idx_vert_used; + // shrink array + texcoord_arr.resize(idx_vert_new); + } // if(face_list_cur.front().TexMap != nullptr) + + // + // copy collected data to mesh + // + tmesh->mNumVertices = static_cast(vert_arr.size()); + tmesh->mVertices = new aiVector3D[tmesh->mNumVertices]; + tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices]; + + memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D)); + memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D)); + if (texcoord_arr.size() > 0) { + tmesh->mTextureCoords[0] = new aiVector3D[tmesh->mNumVertices]; + memcpy(tmesh->mTextureCoords[0], texcoord_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D)); + tmesh->mNumUVComponents[0] = 2; // U and V stored in "x", "y" of aiVector3D. + } + + size_t idx_face = 0; + for (const SComplexFace &face_cur : face_list_cur) + tmesh->mFaces[idx_face++] = face_cur.Face; + + // store new aiMesh + mesh_idx.push_back(static_cast(pMeshList.size())); + pMeshList.push_back(tmesh); + } // for(const std::list& face_list_cur: complex_faces_toplist) + } // if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume) + } // for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child) + + // if meshes was created then assign new indices with current aiNode + if (!mesh_idx.empty()) { + std::list::const_iterator mit = mesh_idx.begin(); + + pSceneNode.mNumMeshes = static_cast(mesh_idx.size()); + pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes]; + for (size_t i = 0; i < pSceneNode.mNumMeshes; i++) + pSceneNode.mMeshes[i] = *mit++; + } // if(mesh_idx.size() > 0) +} + +void AMFImporter::Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material &pMaterial) { + SPP_Material new_mat; + + new_mat.ID = pMaterial.ID; + for (const CAMFImporter_NodeElement *mat_child : pMaterial.Child) { + if (mat_child->Type == CAMFImporter_NodeElement::ENET_Color) { + new_mat.Color = (CAMFImporter_NodeElement_Color *)mat_child; + } else if (mat_child->Type == CAMFImporter_NodeElement::ENET_Metadata) { + new_mat.Metadata.push_back((CAMFImporter_NodeElement_Metadata *)mat_child); + } + } // for(const CAMFImporter_NodeElement* mat_child; pMaterial.Child) + + // place converted material to special list + mMaterial_Converted.push_back(new_mat); +} + +void AMFImporter::Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation &pConstellation, std::list &pNodeList) const { + aiNode *con_node; + std::list ch_node; + + // We will build next hierarchy: + // aiNode as parent () for set of nodes as a children + // |- aiNode for transformation ( -> , ) - aiNode for pointing to object ("objectid") + // ... + // \_ aiNode for transformation ( -> , ) - aiNode for pointing to object ("objectid") + con_node = new aiNode; + con_node->mName = pConstellation.ID; + // Walk through children and search for instances of another objects, constellations. + for (const CAMFImporter_NodeElement *ne : pConstellation.Child) { + aiMatrix4x4 tmat; + aiNode *t_node; + aiNode *found_node; + + if (ne->Type == CAMFImporter_NodeElement::ENET_Metadata) continue; + if (ne->Type != CAMFImporter_NodeElement::ENET_Instance) throw DeadlyImportError("Only nodes can be in ."); + + // create alias for conveniance + CAMFImporter_NodeElement_Instance &als = *((CAMFImporter_NodeElement_Instance *)ne); + // find referenced object + if (!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID); + + // create node for applying transformation + t_node = new aiNode; + t_node->mParent = con_node; + // apply transformation + aiMatrix4x4::Translation(als.Delta, tmat), t_node->mTransformation *= tmat; + aiMatrix4x4::RotationX(als.Rotation.x, tmat), t_node->mTransformation *= tmat; + aiMatrix4x4::RotationY(als.Rotation.y, tmat), t_node->mTransformation *= tmat; + aiMatrix4x4::RotationZ(als.Rotation.z, tmat), t_node->mTransformation *= tmat; + // create array for one child node + t_node->mNumChildren = 1; + t_node->mChildren = new aiNode *[t_node->mNumChildren]; + SceneCombiner::Copy(&t_node->mChildren[0], found_node); + t_node->mChildren[0]->mParent = t_node; + ch_node.push_back(t_node); + } // for(const CAMFImporter_NodeElement* ne: pConstellation.Child) + + // copy found aiNode's as children + if (ch_node.empty()) throw DeadlyImportError(" must have at least one ."); + + size_t ch_idx = 0; + + con_node->mNumChildren = static_cast(ch_node.size()); + con_node->mChildren = new aiNode *[con_node->mNumChildren]; + for (aiNode *node : ch_node) + con_node->mChildren[ch_idx++] = node; + + // and place "root" of node to node list + pNodeList.push_back(con_node); +} + +void AMFImporter::Postprocess_BuildScene(aiScene *pScene) { + std::list node_list; + std::list mesh_list; + std::list meta_list; + + // + // Because for AMF "material" is just complex colors mixing so aiMaterial will not be used. + // For building aiScene we are must to do few steps: + // at first creating root node for aiScene. + pScene->mRootNode = new aiNode; + pScene->mRootNode->mParent = nullptr; + pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED; + // search for root() element + CAMFImporter_NodeElement *root_el = nullptr; + + for (CAMFImporter_NodeElement *ne : mNodeElement_List) { + if (ne->Type != CAMFImporter_NodeElement::ENET_Root) continue; + + root_el = ne; + + break; + } // for(const CAMFImporter_NodeElement* ne: mNodeElement_List) + + // Check if root element are found. + if (root_el == nullptr) throw DeadlyImportError("Root() element not found."); + + // after that walk through children of root and collect data. Five types of nodes can be placed at top level - in : , , , + // and . But at first we must read and because they will be used in . can be read + // at any moment. + // + // 1. + // 2. will be converted later when processing triangles list. \sa Postprocess_BuildMeshSet + for (const CAMFImporter_NodeElement *root_child : root_el->Child) { + if (root_child->Type == CAMFImporter_NodeElement::ENET_Material) Postprocess_BuildMaterial(*((CAMFImporter_NodeElement_Material *)root_child)); + } + + // After "appearance" nodes we must read because it will be used in -> . + // + // 3. + for (const CAMFImporter_NodeElement *root_child : root_el->Child) { + if (root_child->Type == CAMFImporter_NodeElement::ENET_Object) { + aiNode *tnode = nullptr; + + // for mesh and node must be built: object ID assigned to aiNode name and will be used in future for + Postprocess_BuildNodeAndObject(*((CAMFImporter_NodeElement_Object *)root_child), mesh_list, &tnode); + if (tnode != nullptr) node_list.push_back(tnode); + } + } // for(const CAMFImporter_NodeElement* root_child: root_el->Child) + + // And finally read rest of nodes. + // + for (const CAMFImporter_NodeElement *root_child : root_el->Child) { + // 4. + if (root_child->Type == CAMFImporter_NodeElement::ENET_Constellation) { + // and at top of self abstraction use aiNode. So we can use only aiNode list for creating new aiNode's. + Postprocess_BuildConstellation(*((CAMFImporter_NodeElement_Constellation *)root_child), node_list); + } + + // 5, + if (root_child->Type == CAMFImporter_NodeElement::ENET_Metadata) meta_list.push_back((CAMFImporter_NodeElement_Metadata *)root_child); + } // for(const CAMFImporter_NodeElement* root_child: root_el->Child) + + // at now we can add collected metadata to root node + Postprocess_AddMetadata(meta_list, *pScene->mRootNode); + // + // Check constellation children + // + // As said in specification: + // "When multiple objects and constellations are defined in a single file, only the top level objects and constellations are available for printing." + // What that means? For example: if some object is used in constellation then you must show only constellation but not original object. + // And at this step we are checking that relations. +nl_clean_loop: + + if (node_list.size() > 1) { + // walk through all nodes + for (std::list::iterator nl_it = node_list.begin(); nl_it != node_list.end(); ++nl_it) { + // and try to find them in another top nodes. + std::list::const_iterator next_it = nl_it; + + ++next_it; + for (; next_it != node_list.end(); ++next_it) { + if ((*next_it)->FindNode((*nl_it)->mName) != nullptr) { + // if current top node(nl_it) found in another top node then erase it from node_list and restart search loop. + node_list.erase(nl_it); + + goto nl_clean_loop; + } + } // for(; next_it != node_list.end(); next_it++) + } // for(std::list::const_iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++) + } + + // + // move created objects to aiScene + // + // + // Nodes + if (!node_list.empty()) { + std::list::const_iterator nl_it = node_list.begin(); + + pScene->mRootNode->mNumChildren = static_cast(node_list.size()); + pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren]; + for (size_t i = 0; i < pScene->mRootNode->mNumChildren; i++) { + // Objects and constellation that must be showed placed at top of hierarchy in node. So all aiNode's in node_list must have + // mRootNode only as parent. + (*nl_it)->mParent = pScene->mRootNode; + pScene->mRootNode->mChildren[i] = *nl_it++; + } + } // if(node_list.size() > 0) + + // + // Meshes + if (!mesh_list.empty()) { + std::list::const_iterator ml_it = mesh_list.begin(); + + pScene->mNumMeshes = static_cast(mesh_list.size()); + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + for (size_t i = 0; i < pScene->mNumMeshes; i++) + pScene->mMeshes[i] = *ml_it++; + } // if(mesh_list.size() > 0) + + // + // Textures + pScene->mNumTextures = static_cast(mTexture_Converted.size()); + if (pScene->mNumTextures > 0) { + size_t idx; + + idx = 0; + pScene->mTextures = new aiTexture *[pScene->mNumTextures]; + for (const SPP_Texture &tex_convd : mTexture_Converted) { + pScene->mTextures[idx] = new aiTexture; + pScene->mTextures[idx]->mWidth = static_cast(tex_convd.Width); + pScene->mTextures[idx]->mHeight = static_cast(tex_convd.Height); + pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data; + // texture format description. + strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint); + idx++; + } // for(const SPP_Texture& tex_convd: mTexture_Converted) + + // Create materials for embedded textures. + idx = 0; + pScene->mNumMaterials = static_cast(mTexture_Converted.size()); + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; + for (const SPP_Texture &tex_convd : mTexture_Converted) { + const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + to_string(idx)); + const int mode = aiTextureOp_Multiply; + const int repeat = tex_convd.Tiled ? 1 : 0; + + pScene->mMaterials[idx] = new aiMaterial; + pScene->mMaterials[idx]->AddProperty(&texture_id, AI_MATKEY_TEXTURE_DIFFUSE(0)); + pScene->mMaterials[idx]->AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0)); + pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0)); + pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0)); + idx++; + } + } // if(pScene->mNumTextures > 0) +} // END: after that walk through children of root and collect data + +} // namespace Assimp + +#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER diff --git a/code/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp similarity index 64% rename from code/ASE/ASELoader.cpp rename to code/AssetLib/ASE/ASELoader.cpp index b2155d5e5..47b357248 100644 --- a/code/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -51,15 +51,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "ASELoader.h" -#include -#include #include "Common/TargetAnimation.h" +#include +#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include @@ -84,12 +84,8 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -ASEImporter::ASEImporter() -: mParser() -, mBuffer() -, pcScene() -, configRecomputeNormals() -, noSkeletonMesh() { +ASEImporter::ASEImporter() : + mParser(), mBuffer(), pcScene(), configRecomputeNormals(), noSkeletonMesh() { // empty } @@ -101,7 +97,7 @@ ASEImporter::~ASEImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const { +bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const { // check file extension const std::string extension = GetExtension(pFile); @@ -110,41 +106,43 @@ bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool } if ((!extension.length() || cs) && pIOHandler) { - const char* tokens[] = {"*3dsmax_asciiexport"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); + const char *tokens[] = { "*3dsmax_asciiexport" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } return false; } // ------------------------------------------------------------------------------------------------ // Loader meta information -const aiImporterDesc* ASEImporter::GetInfo () const { +const aiImporterDesc *ASEImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration options -void ASEImporter::SetupProperties(const Importer* pImp) { +void ASEImporter::SetupProperties(const Importer *pImp) { configRecomputeNormals = (pImp->GetPropertyInteger( - AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false); + AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS, 1) ? + true : + false); - noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; + noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void ASEImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) { - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); +void ASEImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( file.get() == nullptr) { - throw DeadlyImportError( "Failed to open ASE file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open ASE file " + pFile + "."); } // Allocate storage and copy the contents of the file to a memory buffer std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); + TextFileToBuffer(file.get(), mBuffer2); this->mBuffer = &mBuffer2[0]; this->pcScene = pScene; @@ -155,8 +153,8 @@ void ASEImporter::InternReadFile( const std::string& pFile, // ASE is the actual version 200 (that is currently written by max) // ------------------------------------------------------------------ unsigned int defaultFormat; - std::string::size_type s = pFile.length()-1; - switch (pFile.c_str()[s]) { + std::string::size_type s = pFile.length() - 1; + switch (pFile.c_str()[s]) { case 'C': case 'c': @@ -167,7 +165,7 @@ void ASEImporter::InternReadFile( const std::string& pFile, }; // Construct an ASE parser and parse the file - ASE::Parser parser(mBuffer,defaultFormat); + ASE::Parser parser(mBuffer, defaultFormat); mParser = &parser; mParser->Parse(); @@ -175,7 +173,7 @@ void ASEImporter::InternReadFile( const std::string& pFile, // Check whether we god at least one mesh. If we did - generate // materials and copy meshes. // ------------------------------------------------------------------ - if ( !mParser->m_vMeshes.empty()) { + if (!mParser->m_vMeshes.empty()) { // If absolutely no material has been loaded from the file // we need to generate a default material @@ -183,32 +181,32 @@ void ASEImporter::InternReadFile( const std::string& pFile, // process all meshes bool tookNormals = false; - std::vector avOutMeshes; - avOutMeshes.reserve(mParser->m_vMeshes.size()*2); - for (std::vector::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) { + std::vector avOutMeshes; + avOutMeshes.reserve(mParser->m_vMeshes.size() * 2); + for (std::vector::iterator i = mParser->m_vMeshes.begin(); i != mParser->m_vMeshes.end(); ++i) { if ((*i).bSkip) { continue; } BuildUniqueRepresentation(*i); // Need to generate proper vertex normals if necessary - if(GenerateNormals(*i)) { + if (GenerateNormals(*i)) { tookNormals = true; } // Convert all meshes to aiMesh objects - ConvertMeshes(*i,avOutMeshes); + ConvertMeshes(*i, avOutMeshes); } - if (tookNormals) { + if (tookNormals) { ASSIMP_LOG_DEBUG("ASE: Taking normals from the file. Use " - "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you " - "experience problems"); + "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you " + "experience problems"); } // Now build the output mesh list. Remove dummies pScene->mNumMeshes = (unsigned int)avOutMeshes.size(); - aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (std::vector::const_iterator i = avOutMeshes.begin();i != avOutMeshes.end();++i) { + aiMesh **pp = pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + for (std::vector::const_iterator i = avOutMeshes.begin(); i != avOutMeshes.end(); ++i) { if (!(*i)->mNumFaces) { continue; } @@ -225,18 +223,21 @@ void ASEImporter::InternReadFile( const std::string& pFile, // Copy all scene graph nodes - lights, cameras, dummies and meshes // into one huge list. //------------------------------------------------------------------ - std::vector nodes; - nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size() - + mParser->m_vCameras.size() + mParser->m_vDummies.size()); + std::vector nodes; + nodes.reserve(mParser->m_vMeshes.size() + mParser->m_vLights.size() + mParser->m_vCameras.size() + mParser->m_vDummies.size()); // Lights - for (auto &light : mParser->m_vLights)nodes.push_back(&light); + for (auto &light : mParser->m_vLights) + nodes.push_back(&light); // Cameras - for (auto &camera : mParser->m_vCameras)nodes.push_back(&camera); + for (auto &camera : mParser->m_vCameras) + nodes.push_back(&camera); // Meshes - for (auto &mesh : mParser->m_vMeshes)nodes.push_back(&mesh); + for (auto &mesh : mParser->m_vMeshes) + nodes.push_back(&mesh); // Dummies - for (auto &dummy : mParser->m_vDummies)nodes.push_back(&dummy); + for (auto &dummy : mParser->m_vDummies) + nodes.push_back(&dummy); // build the final node graph BuildNodes(nodes); @@ -255,7 +256,7 @@ void ASEImporter::InternReadFile( const std::string& pFile, // to build a mesh for the animation skeleton // FIXME: very strange results // ------------------------------------------------------------------ - if (!pScene->mNumMeshes) { + if (!pScene->mNumMeshes) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; if (!noSkeletonMesh) { SkeletonMeshBuilder skeleton(pScene); @@ -263,82 +264,80 @@ void ASEImporter::InternReadFile( const std::string& pFile, } } // ------------------------------------------------------------------------------------------------ -void ASEImporter::GenerateDefaultMaterial() -{ - ai_assert(NULL != mParser); +void ASEImporter::GenerateDefaultMaterial() { + ai_assert(nullptr != mParser); bool bHas = false; - for (std::vector::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) { - if ((*i).bSkip)continue; + for (std::vector::iterator i = mParser->m_vMeshes.begin(); i != mParser->m_vMeshes.end(); ++i) { + if ((*i).bSkip) continue; if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex) { (*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size(); bHas = true; } } - if (bHas || mParser->m_vMaterials.empty()) { + if (bHas || mParser->m_vMaterials.empty()) { // add a simple material without submaterials to the parser's list - mParser->m_vMaterials.push_back ( ASE::Material(AI_DEFAULT_MATERIAL_NAME) ); - ASE::Material& mat = mParser->m_vMaterials.back(); + mParser->m_vMaterials.push_back(ASE::Material(AI_DEFAULT_MATERIAL_NAME)); + ASE::Material &mat = mParser->m_vMaterials.back(); - mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f); - mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f); - mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f); - mat.mShading = Discreet3DS::Gouraud; + mat.mDiffuse = aiColor3D(0.6f, 0.6f, 0.6f); + mat.mSpecular = aiColor3D(1.0f, 1.0f, 1.0f); + mat.mAmbient = aiColor3D(0.05f, 0.05f, 0.05f); + mat.mShading = Discreet3DS::Gouraud; } } // ------------------------------------------------------------------------------------------------ -void ASEImporter::BuildAnimations(const std::vector& nodes) -{ +void ASEImporter::BuildAnimations(const std::vector &nodes) { // check whether we have at least one mesh which has animations - std::vector::const_iterator i = nodes.begin(); + std::vector::const_iterator i = nodes.begin(); unsigned int iNum = 0; - for (;i != nodes.end();++i) { + for (; i != nodes.end(); ++i) { // TODO: Implement Bezier & TCB support if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) { ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. " - "This is not supported."); + "This is not supported."); } if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) { ASSIMP_LOG_WARN("ASE: Rotation controller uses Bezier/TCB keys. " - "This is not supported."); + "This is not supported."); } - if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) { + if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) { ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. " - "This is not supported."); + "This is not supported."); } // We compare against 1 here - firstly one key is not // really an animation and secondly MAX writes dummies // that represent the node transformation. - if ((*i)->mAnim.akeyPositions.size()>1 || (*i)->mAnim.akeyRotations.size()>1 || (*i)->mAnim.akeyScaling.size()>1){ + if ((*i)->mAnim.akeyPositions.size() > 1 || (*i)->mAnim.akeyRotations.size() > 1 || (*i)->mAnim.akeyScaling.size() > 1) { ++iNum; } - if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( (*i)->mTargetPosition.x )) { + if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan((*i)->mTargetPosition.x)) { ++iNum; } } - if (iNum) { + if (iNum) { // Generate a new animation channel and setup everything for it pcScene->mNumAnimations = 1; - pcScene->mAnimations = new aiAnimation*[1]; - aiAnimation* pcAnim = pcScene->mAnimations[0] = new aiAnimation(); - pcAnim->mNumChannels = iNum; - pcAnim->mChannels = new aiNodeAnim*[iNum]; + pcScene->mAnimations = new aiAnimation *[1]; + aiAnimation *pcAnim = pcScene->mAnimations[0] = new aiAnimation(); + pcAnim->mNumChannels = iNum; + pcAnim->mChannels = new aiNodeAnim *[iNum]; pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame; iNum = 0; // Now iterate through all meshes and collect all data we can find - for (i = nodes.begin();i != nodes.end();++i) { + for (i = nodes.begin(); i != nodes.end(); ++i) { - ASE::BaseNode* me = *i; - if ( me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( me->mTargetPosition.x )) { + ASE::BaseNode *me = *i; + if (me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan(me->mTargetPosition.x)) { // Generate an extra channel for the camera/light target. // BuildNodes() does also generate an extra node, named // .Target. - aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); + aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); nd->mNodeName.Set(me->mName + ".Target"); // If there is no input position channel we will need @@ -357,32 +356,31 @@ void ASEImporter::BuildAnimations(const std::vector& nodes) helper.Process(&me->mTargetAnim.akeyPositions);*/ // Allocate the key array and fill it - nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size(); + nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size(); nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - ::memcpy(nd->mPositionKeys,&me->mTargetAnim.akeyPositions[0], - nd->mNumPositionKeys * sizeof(aiVectorKey)); + ::memcpy(nd->mPositionKeys, &me->mTargetAnim.akeyPositions[0], + nd->mNumPositionKeys * sizeof(aiVectorKey)); } - if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1) { + if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1) { // Begin a new node animation channel for this node - aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); + aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); nd->mNodeName.Set(me->mName); // copy position keys - if (me->mAnim.akeyPositions.size() > 1 ) - { + if (me->mAnim.akeyPositions.size() > 1) { // Allocate the key array and fill it - nd->mNumPositionKeys = (unsigned int) me->mAnim.akeyPositions.size(); + nd->mNumPositionKeys = (unsigned int)me->mAnim.akeyPositions.size(); nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - ::memcpy(nd->mPositionKeys,&me->mAnim.akeyPositions[0], - nd->mNumPositionKeys * sizeof(aiVectorKey)); + ::memcpy(nd->mPositionKeys, &me->mAnim.akeyPositions[0], + nd->mNumPositionKeys * sizeof(aiVectorKey)); } // copy rotation keys - if (me->mAnim.akeyRotations.size() > 1 ) { + if (me->mAnim.akeyRotations.size() > 1) { // Allocate the key array and fill it - nd->mNumRotationKeys = (unsigned int) me->mAnim.akeyRotations.size(); + nd->mNumRotationKeys = (unsigned int)me->mAnim.akeyRotations.size(); nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; // -------------------------------------------------------------------- @@ -395,11 +393,11 @@ void ASEImporter::BuildAnimations(const std::vector& nodes) // -------------------------------------------------------------------- aiQuaternion cur; - for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { + for (unsigned int a = 0; a < nd->mNumRotationKeys; ++a) { aiQuatKey q = me->mAnim.akeyRotations[a]; if (mParser->iFileFormat > 110) { - cur = (a ? cur*q.mValue : q.mValue); + cur = (a ? cur * q.mValue : q.mValue); q.mValue = cur.Normalize(); } nd->mRotationKeys[a] = q; @@ -409,13 +407,13 @@ void ASEImporter::BuildAnimations(const std::vector& nodes) } } // copy scaling keys - if (me->mAnim.akeyScaling.size() > 1 ) { + if (me->mAnim.akeyScaling.size() > 1) { // Allocate the key array and fill it - nd->mNumScalingKeys = (unsigned int) me->mAnim.akeyScaling.size(); + nd->mNumScalingKeys = (unsigned int)me->mAnim.akeyScaling.size(); nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys]; - ::memcpy(nd->mScalingKeys,&me->mAnim.akeyScaling[0], - nd->mNumScalingKeys * sizeof(aiVectorKey)); + ::memcpy(nd->mScalingKeys, &me->mAnim.akeyScaling[0], + nd->mNumScalingKeys * sizeof(aiVectorKey)); } } } @@ -424,18 +422,17 @@ void ASEImporter::BuildAnimations(const std::vector& nodes) // ------------------------------------------------------------------------------------------------ // Build output cameras -void ASEImporter::BuildCameras() -{ - if (!mParser->m_vCameras.empty()) { +void ASEImporter::BuildCameras() { + if (!mParser->m_vCameras.empty()) { pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size(); - pcScene->mCameras = new aiCamera*[pcScene->mNumCameras]; + pcScene->mCameras = new aiCamera *[pcScene->mNumCameras]; - for (unsigned int i = 0; i < pcScene->mNumCameras;++i) { - aiCamera* out = pcScene->mCameras[i] = new aiCamera(); - ASE::Camera& in = mParser->m_vCameras[i]; + for (unsigned int i = 0; i < pcScene->mNumCameras; ++i) { + aiCamera *out = pcScene->mCameras[i] = new aiCamera(); + ASE::Camera &in = mParser->m_vCameras[i]; // copy members - out->mClipPlaneFar = in.mFar; + out->mClipPlaneFar = in.mFar; out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f); out->mHorizontalFOV = in.mFOV; @@ -446,24 +443,22 @@ void ASEImporter::BuildCameras() // ------------------------------------------------------------------------------------------------ // Build output lights -void ASEImporter::BuildLights() -{ - if (!mParser->m_vLights.empty()) { +void ASEImporter::BuildLights() { + if (!mParser->m_vLights.empty()) { pcScene->mNumLights = (unsigned int)mParser->m_vLights.size(); - pcScene->mLights = new aiLight*[pcScene->mNumLights]; + pcScene->mLights = new aiLight *[pcScene->mNumLights]; - for (unsigned int i = 0; i < pcScene->mNumLights;++i) { - aiLight* out = pcScene->mLights[i] = new aiLight(); - ASE::Light& in = mParser->m_vLights[i]; + for (unsigned int i = 0; i < pcScene->mNumLights; ++i) { + aiLight *out = pcScene->mLights[i] = new aiLight(); + ASE::Light &in = mParser->m_vLights[i]; // The direction is encoded in the transformation matrix of the node. // In 3DS MAX the light source points into negative Z direction if // the node transformation is the identity. - out->mDirection = aiVector3D(0.f,0.f,-1.f); + out->mDirection = aiVector3D(0.f, 0.f, -1.f); out->mName.Set(in.mName); - switch (in.mLightType) - { + switch (in.mLightType) { case ASE::Light::TARGET: out->mType = aiLightSource_SPOT; out->mAngleInnerCone = AI_DEG_TO_RAD(in.mAngle); @@ -475,7 +470,7 @@ void ASEImporter::BuildLights() break; default: - //case ASE::Light::OMNI: + //case ASE::Light::OMNI: out->mType = aiLightSource_POINT; break; }; @@ -485,57 +480,55 @@ void ASEImporter::BuildLights() } // ------------------------------------------------------------------------------------------------ -void ASEImporter::AddNodes(const std::vector& nodes, - aiNode* pcParent,const char* szName) -{ +void ASEImporter::AddNodes(const std::vector &nodes, + aiNode *pcParent, const char *szName) { aiMatrix4x4 m; - AddNodes(nodes,pcParent,szName,m); + AddNodes(nodes, pcParent, szName, m); } // ------------------------------------------------------------------------------------------------ // Add meshes to a given node -void ASEImporter::AddMeshes(const ASE::BaseNode* snode,aiNode* node) -{ - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) { +void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) { + for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) { // Get the name of the mesh (the mesh instance has been temporarily stored in the third vertex color) - const aiMesh* pcMesh = pcScene->mMeshes[i]; - const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2]; + const aiMesh *pcMesh = pcScene->mMeshes[i]; + const ASE::Mesh *mesh = (const ASE::Mesh *)pcMesh->mColors[2]; if (mesh == snode) { ++node->mNumMeshes; } } - if(node->mNumMeshes) { + if (node->mNumMeshes) { node->mMeshes = new unsigned int[node->mNumMeshes]; - for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i) { + for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes; ++i) { - const aiMesh* pcMesh = pcScene->mMeshes[i]; - const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2]; - if (mesh == snode) { + const aiMesh *pcMesh = pcScene->mMeshes[i]; + const ASE::Mesh *mesh = (const ASE::Mesh *)pcMesh->mColors[2]; + if (mesh == snode) { node->mMeshes[p++] = i; // Transform all vertices of the mesh back into their local space -> // at the moment they are pretransformed - aiMatrix4x4 m = mesh->mTransform; + aiMatrix4x4 m = mesh->mTransform; m.Inverse(); - aiVector3D* pvCurPtr = pcMesh->mVertices; - const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices; - while (pvCurPtr != pvEndPtr) { + aiVector3D *pvCurPtr = pcMesh->mVertices; + const aiVector3D *pvEndPtr = pvCurPtr + pcMesh->mNumVertices; + while (pvCurPtr != pvEndPtr) { *pvCurPtr = m * (*pvCurPtr); pvCurPtr++; } // Do the same for the normal vectors, if we have them. // As always, inverse transpose. - if (pcMesh->mNormals) { - aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform ); + if (pcMesh->mNormals) { + aiMatrix3x3 m3 = aiMatrix3x3(mesh->mTransform); m3.Transpose(); pvCurPtr = pcMesh->mNormals; pvEndPtr = pvCurPtr + pcMesh->mNumVertices; - while (pvCurPtr != pvEndPtr) { + while (pvCurPtr != pvEndPtr) { *pvCurPtr = m3 * (*pvCurPtr); pvCurPtr++; } @@ -547,68 +540,65 @@ void ASEImporter::AddMeshes(const ASE::BaseNode* snode,aiNode* node) // ------------------------------------------------------------------------------------------------ // Add child nodes to a given parent node -void ASEImporter::AddNodes (const std::vector& nodes, - aiNode* pcParent, const char* szName, - const aiMatrix4x4& mat) -{ +void ASEImporter::AddNodes(const std::vector &nodes, + aiNode *pcParent, const char *szName, + const aiMatrix4x4 &mat) { const size_t len = szName ? ::strlen(szName) : 0; ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS); // Receives child nodes for the pcParent node - std::vector apcNodes; + std::vector apcNodes; // Now iterate through all nodes in the scene and search for one // which has *us* as parent. - for (std::vector::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { - const BaseNode* snode = *it; + for (std::vector::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { + const BaseNode *snode = *it; if (szName) { - if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str())) + if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str())) continue; - } - else if (snode->mParent.length()) + } else if (snode->mParent.length()) continue; (*it)->mProcessed = true; // Allocate a new node and add it to the output data structure apcNodes.push_back(new aiNode()); - aiNode* node = apcNodes.back(); + aiNode *node = apcNodes.back(); node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node")); node->mParent = pcParent; // Setup the transformation matrix of the node - aiMatrix4x4 mParentAdjust = mat; + aiMatrix4x4 mParentAdjust = mat; mParentAdjust.Inverse(); - node->mTransformation = mParentAdjust*snode->mTransform; + node->mTransformation = mParentAdjust * snode->mTransform; // Add sub nodes - prevent stack overflow due to recursive parenting - if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName ) { - AddNodes(nodes,node,node->mName.data,snode->mTransform); + if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) { + AddNodes(nodes, node, node->mName.data, snode->mTransform); } // Further processing depends on the type of the node - if (snode->mType == ASE::BaseNode::Mesh) { + if (snode->mType == ASE::BaseNode::Mesh) { // If the type of this node is "Mesh" we need to search // the list of output meshes in the data structure for // all those that belonged to this node once. This is // slightly inconvinient here and a better solution should // be used when this code is refactored next. - AddMeshes(snode,node); - } - else if (is_not_qnan( snode->mTargetPosition.x )) { + AddMeshes(snode, node); + } else if (is_not_qnan(snode->mTargetPosition.x)) { // If this is a target camera or light we generate a small // child node which marks the position of the camera // target (the direction information is contained in *this* // node's animation track but the exact target position // would be lost otherwise) - if (!node->mNumChildren) { - node->mChildren = new aiNode*[1]; + if (!node->mNumChildren) { + node->mChildren = new aiNode *[1]; } - aiNode* nd = new aiNode(); + aiNode *nd = new aiNode(); - nd->mName.Set ( snode->mName + ".Target" ); + nd->mName.Set(snode->mName + ".Target"); nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4; nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4; @@ -617,14 +607,14 @@ void ASEImporter::AddNodes (const std::vector& nodes, nd->mParent = node; // The .Target node is always the first child node - for (unsigned int m = 0; m < node->mNumChildren;++m) - node->mChildren[m+1] = node->mChildren[m]; + for (unsigned int m = 0; m < node->mNumChildren; ++m) + node->mChildren[m + 1] = node->mChildren[m]; node->mChildren[0] = nd; node->mNumChildren++; // What we did is so great, it is at least worth a debug message - ASSIMP_LOG_DEBUG("ASE: Generating separate target node ("+snode->mName+")"); + ASSIMP_LOG_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); } } @@ -632,10 +622,10 @@ void ASEImporter::AddNodes (const std::vector& nodes, // We allocate one slot more in case this is a target camera/light pcParent->mNumChildren = (unsigned int)apcNodes.size(); if (pcParent->mNumChildren) { - pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */]; + pcParent->mChildren = new aiNode *[apcNodes.size() + 1 /* PLUS ONE !!! */]; // now build all nodes for our nice new children - for (unsigned int p = 0; p < apcNodes.size();++p) + for (unsigned int p = 0; p < apcNodes.size(); ++p) pcParent->mChildren[p] = apcNodes[p]; } return; @@ -643,32 +633,32 @@ void ASEImporter::AddNodes (const std::vector& nodes, // ------------------------------------------------------------------------------------------------ // Build the output node graph -void ASEImporter::BuildNodes(std::vector& nodes) { - ai_assert(NULL != pcScene); +void ASEImporter::BuildNodes(std::vector &nodes) { + ai_assert(nullptr != pcScene); // allocate the one and only root node - aiNode* root = pcScene->mRootNode = new aiNode(); + aiNode *root = pcScene->mRootNode = new aiNode(); root->mName.Set(""); // Setup the coordinate system transformation pcScene->mRootNode->mNumChildren = 1; - pcScene->mRootNode->mChildren = new aiNode*[1]; - aiNode* ch = pcScene->mRootNode->mChildren[0] = new aiNode(); + pcScene->mRootNode->mChildren = new aiNode *[1]; + aiNode *ch = pcScene->mRootNode->mChildren[0] = new aiNode(); ch->mParent = root; // Change the transformation matrix of all nodes for (BaseNode *node : nodes) { - aiMatrix4x4& m = node->mTransform; + aiMatrix4x4 &m = node->mTransform; m.Transpose(); // row-order vs column-order } // add all nodes - AddNodes(nodes,ch,NULL); + AddNodes(nodes, ch, nullptr); // now iterate through al nodes and find those that have not yet // been added to the nodegraph (= their parent could not be recognized) - std::vector aiList; - for (std::vector::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) { + std::vector aiList; + for (std::vector::iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { if ((*it)->mProcessed) { continue; } @@ -678,54 +668,54 @@ void ASEImporter::BuildNodes(std::vector& nodes) { // search the list another time, starting *here* and try to find out whether // there is a node that references *us* as a parent - for (std::vector::const_iterator it2 = nodes.begin();it2 != end; ++it2) { + for (std::vector::const_iterator it2 = nodes.begin(); it2 != end; ++it2) { if (it2 == it) { continue; } - if ((*it2)->mName == (*it)->mParent) { + if ((*it2)->mName == (*it)->mParent) { bKnowParent = true; break; } } - if (!bKnowParent) { + if (!bKnowParent) { aiList.push_back(*it); } } // Are there ane orphaned nodes? - if (!aiList.empty()) { - std::vector apcNodes; + if (!aiList.empty()) { + std::vector apcNodes; apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren); - for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren;++i) + for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren; ++i) apcNodes.push_back(pcScene->mRootNode->mChildren[i]); delete[] pcScene->mRootNode->mChildren; - for (std::vector::/*const_*/iterator i = aiList.begin();i != aiList.end();++i) { - const ASE::BaseNode* src = *i; + for (std::vector::/*const_*/ iterator i = aiList.begin(); i != aiList.end(); ++i) { + const ASE::BaseNode *src = *i; // The parent is not known, so we can assume that we must add // this node to the root node of the whole scene - aiNode* pcNode = new aiNode(); + aiNode *pcNode = new aiNode(); pcNode->mParent = pcScene->mRootNode; pcNode->mName.Set(src->mName); - AddMeshes(src,pcNode); - AddNodes(nodes,pcNode,pcNode->mName.data); + AddMeshes(src, pcNode); + AddNodes(nodes, pcNode, pcNode->mName.data); apcNodes.push_back(pcNode); } // Regenerate our output array - pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()]; - for (unsigned int i = 0; i < apcNodes.size();++i) + pcScene->mRootNode->mChildren = new aiNode *[apcNodes.size()]; + for (unsigned int i = 0; i < apcNodes.size(); ++i) pcScene->mRootNode->mChildren[i] = apcNodes[i]; pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size(); } - // Reset the third color set to NULL - we used this field to store a temporary pointer - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - pcScene->mMeshes[i]->mColors[2] = NULL; + // Reset the third color set to nullptr - we used this field to store a temporary pointer + for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) + pcScene->mMeshes[i]->mColors[2] = nullptr; // The root node should not have at least one child or the file is valid if (!pcScene->mRootNode->mNumChildren) { @@ -733,17 +723,17 @@ void ASEImporter::BuildNodes(std::vector& nodes) { } // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); + pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); } // ------------------------------------------------------------------------------------------------ // Convert the imported data to the internal verbose representation -void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) { +void ASEImporter::BuildUniqueRepresentation(ASE::Mesh &mesh) { // allocate output storage std::vector mPositions; std::vector amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - std::vector mVertexColors; + std::vector mVertexColors; std::vector mNormals; std::vector mBoneVertices; @@ -751,13 +741,13 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) { mPositions.resize(iSize); // optional texture coordinates - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) { - if (!mesh.amTexCoords[i].empty()) { + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (!mesh.amTexCoords[i].empty()) { amTexCoords[i].resize(iSize); } } // optional vertex colors - if (!mesh.mVertexColors.empty()) { + if (!mesh.mVertexColors.empty()) { mVertexColors.resize(iSize); } @@ -766,38 +756,37 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) { mNormals.resize(iSize); } // bone vertices. There is no need to change the bone list - if (!mesh.mBoneVertices.empty()) { + if (!mesh.mBoneVertices.empty()) { mBoneVertices.resize(iSize); } // iterate through all faces in the mesh unsigned int iCurrent = 0, fi = 0; - for (std::vector::iterator i = mesh.mFaces.begin();i != mesh.mFaces.end();++i,++fi) { - for (unsigned int n = 0; n < 3;++n,++iCurrent) - { + for (std::vector::iterator i = mesh.mFaces.begin(); i != mesh.mFaces.end(); ++i, ++fi) { + for (unsigned int n = 0; n < 3; ++n, ++iCurrent) { mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]]; // add texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { - if (mesh.amTexCoords[c].empty())break; + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { + if (mesh.amTexCoords[c].empty()) break; amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]]; } // add vertex colors - if (!mesh.mVertexColors.empty()) { + if (!mesh.mVertexColors.empty()) { mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]]; } // add normal vectors if (!mesh.mNormals.empty()) { - mNormals[iCurrent] = mesh.mNormals[fi*3+n]; + mNormals[iCurrent] = mesh.mNormals[fi * 3 + n]; mNormals[iCurrent].Normalize(); } // handle bone vertices - if ((*i).mIndices[n] < mesh.mBoneVertices.size()) { + if ((*i).mIndices[n] < mesh.mBoneVertices.size()) { // (sometimes this will cause bone verts to be duplicated // however, I' quite sure Schrompf' JoinVerticesStep // will fix that again ...) - mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]]; + mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]]; } (*i).mIndices[n] = iCurrent; } @@ -808,31 +797,29 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) { mesh.mPositions = mPositions; mesh.mVertexColors = mVertexColors; - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) mesh.amTexCoords[c] = amTexCoords[c]; } // ------------------------------------------------------------------------------------------------ // Copy a texture from the ASE structs to the output material -void CopyASETexture(aiMaterial& mat, ASE::Texture& texture, aiTextureType type) -{ +void CopyASETexture(aiMaterial &mat, ASE::Texture &texture, aiTextureType type) { // Setup the texture name aiString tex; - tex.Set( texture.mMapName); - mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0)); + tex.Set(texture.mMapName); + mat.AddProperty(&tex, AI_MATKEY_TEXTURE(type, 0)); // Setup the texture blend factor if (is_not_qnan(texture.mTextureBlend)) - mat.AddProperty( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); + mat.AddProperty(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0)); // Setup texture UV transformations - mat.AddProperty(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); + mat.AddProperty(&texture.mOffsetU, 5, AI_MATKEY_UVTRANSFORM(type, 0)); } // ------------------------------------------------------------------------------------------------ // Convert from ASE material to output material -void ASEImporter::ConvertMaterial(ASE::Material& mat) -{ +void ASEImporter::ConvertMaterial(ASE::Material &mat) { // LARGE TODO: Much code her is copied from 3DS ... join them maybe? // Allocate the output material @@ -845,135 +832,134 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat) mat.mAmbient.b += mParser->m_clrAmbient.b; aiString name; - name.Set( mat.mName); - mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME); + name.Set(mat.mName); + mat.pcInstance->AddProperty(&name, AI_MATKEY_NAME); // material colors - mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); - mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + mat.pcInstance->AddProperty(&mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); + mat.pcInstance->AddProperty(&mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat.pcInstance->AddProperty(&mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); + mat.pcInstance->AddProperty(&mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); // shininess - if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength) - { - mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); + if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength) { + mat.pcInstance->AddProperty(&mat.mSpecularExponent, 1, AI_MATKEY_SHININESS); + mat.pcInstance->AddProperty(&mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); } // If there is no shininess, we can disable phong lighting else if (D3DS::Discreet3DS::Metal == mat.mShading || - D3DS::Discreet3DS::Phong == mat.mShading || - D3DS::Discreet3DS::Blinn == mat.mShading) - { + D3DS::Discreet3DS::Phong == mat.mShading || + D3DS::Discreet3DS::Blinn == mat.mShading) { mat.mShading = D3DS::Discreet3DS::Gouraud; } // opacity - mat.pcInstance->AddProperty( &mat.mTransparency,1,AI_MATKEY_OPACITY); + mat.pcInstance->AddProperty(&mat.mTransparency, 1, AI_MATKEY_OPACITY); // Two sided rendering? - if (mat.mTwoSided) - { + if (mat.mTwoSided) { int i = 1; - mat.pcInstance->AddProperty(&i,1,AI_MATKEY_TWOSIDED); + mat.pcInstance->AddProperty(&i, 1, AI_MATKEY_TWOSIDED); } // shading mode aiShadingMode eShading = aiShadingMode_NoShading; - switch (mat.mShading) - { - case D3DS::Discreet3DS::Flat: - eShading = aiShadingMode_Flat; break; - case D3DS::Discreet3DS::Phong : - eShading = aiShadingMode_Phong; break; - case D3DS::Discreet3DS::Blinn : - eShading = aiShadingMode_Blinn; break; + switch (mat.mShading) { + case D3DS::Discreet3DS::Flat: + eShading = aiShadingMode_Flat; + break; + case D3DS::Discreet3DS::Phong: + eShading = aiShadingMode_Phong; + break; + case D3DS::Discreet3DS::Blinn: + eShading = aiShadingMode_Blinn; + break; - // I don't know what "Wire" shading should be, - // assume it is simple lambertian diffuse (L dot N) shading - case D3DS::Discreet3DS::Wire: - { - // set the wireframe flag - unsigned int iWire = 1; - mat.pcInstance->AddProperty( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); - } - case D3DS::Discreet3DS::Gouraud: - eShading = aiShadingMode_Gouraud; break; - case D3DS::Discreet3DS::Metal : - eShading = aiShadingMode_CookTorrance; break; + // I don't know what "Wire" shading should be, + // assume it is simple lambertian diffuse (L dot N) shading + case D3DS::Discreet3DS::Wire: { + // set the wireframe flag + unsigned int iWire = 1; + mat.pcInstance->AddProperty((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME); } - mat.pcInstance->AddProperty( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); + case D3DS::Discreet3DS::Gouraud: + eShading = aiShadingMode_Gouraud; + break; + case D3DS::Discreet3DS::Metal: + eShading = aiShadingMode_CookTorrance; + break; + } + mat.pcInstance->AddProperty((int *)&eShading, 1, AI_MATKEY_SHADING_MODEL); // DIFFUSE texture - if( mat.sTexDiffuse.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE); + if (mat.sTexDiffuse.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexDiffuse, aiTextureType_DIFFUSE); // SPECULAR texture - if( mat.sTexSpecular.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR); + if (mat.sTexSpecular.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexSpecular, aiTextureType_SPECULAR); // AMBIENT texture - if( mat.sTexAmbient.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT); + if (mat.sTexAmbient.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexAmbient, aiTextureType_AMBIENT); // OPACITY texture - if( mat.sTexOpacity.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY); + if (mat.sTexOpacity.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexOpacity, aiTextureType_OPACITY); // EMISSIVE texture - if( mat.sTexEmissive.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE); + if (mat.sTexEmissive.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexEmissive, aiTextureType_EMISSIVE); // BUMP texture - if( mat.sTexBump.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT); + if (mat.sTexBump.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexBump, aiTextureType_HEIGHT); // SHININESS texture - if( mat.sTexShininess.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS); + if (mat.sTexShininess.mMapName.length() > 0) + CopyASETexture(*mat.pcInstance, mat.sTexShininess, aiTextureType_SHININESS); // store the name of the material itself, too - if( mat.mName.length() > 0) { - aiString tex;tex.Set( mat.mName); - mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME); + if (mat.mName.length() > 0) { + aiString tex; + tex.Set(mat.mName); + mat.pcInstance->AddProperty(&tex, AI_MATKEY_NAME); } return; } // ------------------------------------------------------------------------------------------------ // Build output meshes -void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMeshes) -{ +void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector &avOutMeshes) { // validate the material index of the mesh - if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) { - mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1; + if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) { + mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size() - 1; ASSIMP_LOG_WARN("Material index is out of range"); } // If the material the mesh is assigned to is consisting of submeshes, split it if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) { - std::vector vSubMaterials = mParser-> - m_vMaterials[mesh.iMaterialIndex].avSubMaterials; + std::vector vSubMaterials = mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials; - std::vector* aiSplit = new std::vector[vSubMaterials.size()]; + std::vector *aiSplit = new std::vector[vSubMaterials.size()]; // build a list of all faces per sub-material - for (unsigned int i = 0; i < mesh.mFaces.size();++i) { + for (unsigned int i = 0; i < mesh.mFaces.size(); ++i) { // check range if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) { ASSIMP_LOG_WARN("Submaterial index is out of range"); // use the last material instead - aiSplit[vSubMaterials.size()-1].push_back(i); - } - else aiSplit[mesh.mFaces[i].iMaterial].push_back(i); + aiSplit[vSubMaterials.size() - 1].push_back(i); + } else + aiSplit[mesh.mFaces[i].iMaterial].push_back(i); } // now generate submeshes - for (unsigned int p = 0; p < vSubMaterials.size();++p) { - if (!aiSplit[p].empty()) { + for (unsigned int p = 0; p < vSubMaterials.size(); ++p) { + if (!aiSplit[p].empty()) { - aiMesh* p_pcOut = new aiMesh(); + aiMesh *p_pcOut = new aiMesh(); p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // let the sub material index @@ -983,55 +969,55 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true; // store the real index here ... color channel 3 - p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex; + p_pcOut->mColors[3] = (aiColor4D *)(uintptr_t)mesh.iMaterialIndex; // store a pointer to the mesh in color channel 2 - p_pcOut->mColors[2] = (aiColor4D*) &mesh; + p_pcOut->mColors[2] = (aiColor4D *)&mesh; avOutMeshes.push_back(p_pcOut); // convert vertices - p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3; + p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size() * 3; p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size(); // receive output vertex weights - std::vector > *avOutputBones = NULL; - if (!mesh.mBones.empty()) { - avOutputBones = new std::vector >[mesh.mBones.size()]; + std::vector> *avOutputBones = nullptr; + if (!mesh.mBones.empty()) { + avOutputBones = new std::vector>[mesh.mBones.size()]; } // allocate enough storage for faces p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; - unsigned int iBase = 0,iIndex; - if (p_pcOut->mNumVertices) { + unsigned int iBase = 0, iIndex; + if (p_pcOut->mNumVertices) { p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices]; - p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices]; - for (unsigned int q = 0; q < aiSplit[p].size();++q) { + p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices]; + for (unsigned int q = 0; q < aiSplit[p].size(); ++q) { iIndex = aiSplit[p][q]; p_pcOut->mFaces[q].mIndices = new unsigned int[3]; p_pcOut->mFaces[q].mNumIndices = 3; - for (unsigned int t = 0; t < 3;++t, ++iBase) { + for (unsigned int t = 0; t < 3; ++t, ++iBase) { const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t]; - p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2]; - p_pcOut->mNormals [iBase] = mesh.mNormals [iIndex2]; + p_pcOut->mVertices[iBase] = mesh.mPositions[iIndex2]; + p_pcOut->mNormals[iBase] = mesh.mNormals[iIndex2]; // convert bones, if existing if (!mesh.mBones.empty()) { ai_assert(avOutputBones); // check whether there is a vertex weight for this vertex index - if (iIndex2 < mesh.mBoneVertices.size()) { + if (iIndex2 < mesh.mBoneVertices.size()) { - for (std::vector >::const_iterator - blubb = mesh.mBoneVertices[iIndex2].mBoneWeights.begin(); - blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb) { + for (std::vector>::const_iterator + blubb = mesh.mBoneVertices[iIndex2].mBoneWeights.begin(); + blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end(); ++blubb) { // NOTE: illegal cases have already been filtered out avOutputBones[(*blubb).first].push_back(std::pair( - iBase,(*blubb).second)); + iBase, (*blubb).second)); } } } @@ -1040,14 +1026,13 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh } } // convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported) - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { - if (!mesh.amTexCoords[c].empty()) - { + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { + if (!mesh.amTexCoords[c].empty()) { p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices]; iBase = 0; - for (unsigned int q = 0; q < aiSplit[p].size();++q) { + for (unsigned int q = 0; q < aiSplit[p].size(); ++q) { iIndex = aiSplit[p][q]; - for (unsigned int t = 0; t < 3;++t) { + for (unsigned int t = 0; t < 3; ++t) { p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]]; } } @@ -1057,38 +1042,36 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh } // Convert vertex colors (only one set supported) - if (!mesh.mVertexColors.empty()){ + if (!mesh.mVertexColors.empty()) { p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices]; iBase = 0; - for (unsigned int q = 0; q < aiSplit[p].size();++q) { + for (unsigned int q = 0; q < aiSplit[p].size(); ++q) { iIndex = aiSplit[p][q]; - for (unsigned int t = 0; t < 3;++t) { + for (unsigned int t = 0; t < 3; ++t) { p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]]; } } } // Copy bones - if (!mesh.mBones.empty()) { + if (!mesh.mBones.empty()) { p_pcOut->mNumBones = 0; - for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock) - if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++; + for (unsigned int mrspock = 0; mrspock < mesh.mBones.size(); ++mrspock) + if (!avOutputBones[mrspock].empty()) p_pcOut->mNumBones++; - p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ]; - aiBone** pcBone = p_pcOut->mBones; - for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock) - { - if (!avOutputBones[mrspock].empty()) { + p_pcOut->mBones = new aiBone *[p_pcOut->mNumBones]; + aiBone **pcBone = p_pcOut->mBones; + for (unsigned int mrspock = 0; mrspock < mesh.mBones.size(); ++mrspock) { + if (!avOutputBones[mrspock].empty()) { // we will need this bone. add it to the output mesh and // add all per-vertex weights - aiBone* pc = *pcBone = new aiBone(); + aiBone *pc = *pcBone = new aiBone(); pc->mName.Set(mesh.mBones[mrspock].mName); pc->mNumWeights = (unsigned int)avOutputBones[mrspock].size(); pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk) - { - const std::pair& ref = avOutputBones[mrspock][captainkirk]; + for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights; ++captainkirk) { + const std::pair &ref = avOutputBones[mrspock][captainkirk]; pc->mWeights[captainkirk].mVertexId = ref.first; pc->mWeights[captainkirk].mWeight = ref.second; } @@ -1102,15 +1085,13 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh } // delete storage delete[] aiSplit; - } - else - { + } else { // Otherwise we can simply copy the data to one output mesh // This codepath needs less memory and uses fast memcpy()s // to do the actual copying. So I think it is worth the // effort here. - aiMesh* p_pcOut = new aiMesh(); + aiMesh *p_pcOut = new aiMesh(); p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // set an empty sub material index @@ -1118,10 +1099,10 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true; // store the real index here ... in color channel 3 - p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex; + p_pcOut->mColors[3] = (aiColor4D *)(uintptr_t)mesh.iMaterialIndex; // store a pointer to the mesh in color channel 2 - p_pcOut->mColors[2] = (aiColor4D*) &mesh; + p_pcOut->mColors[2] = (aiColor4D *)&mesh; avOutMeshes.push_back(p_pcOut); // If the mesh hasn't faces or vertices, there are two cases @@ -1140,20 +1121,20 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // copy vertices p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()]; - memcpy(p_pcOut->mVertices,&mesh.mPositions[0], - mesh.mPositions.size() * sizeof(aiVector3D)); + memcpy(p_pcOut->mVertices, &mesh.mPositions[0], + mesh.mPositions.size() * sizeof(aiVector3D)); // copy normals p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()]; - memcpy(p_pcOut->mNormals,&mesh.mNormals[0], - mesh.mNormals.size() * sizeof(aiVector3D)); + memcpy(p_pcOut->mNormals, &mesh.mNormals[0], + mesh.mNormals.size() * sizeof(aiVector3D)); // copy texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { - if (!mesh.amTexCoords[c].empty()) { + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { + if (!mesh.amTexCoords[c].empty()) { p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()]; - memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0], - mesh.amTexCoords[c].size() * sizeof(aiVector3D)); + memcpy(p_pcOut->mTextureCoords[c], &mesh.amTexCoords[c][0], + mesh.amTexCoords[c].size() * sizeof(aiVector3D)); // setup the number of valid vertex components p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c]; @@ -1161,14 +1142,14 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh } // copy vertex colors - if (!mesh.mVertexColors.empty()) { + if (!mesh.mVertexColors.empty()) { p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()]; - memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0], - mesh.mVertexColors.size() * sizeof(aiColor4D)); + memcpy(p_pcOut->mColors[0], &mesh.mVertexColors[0], + mesh.mVertexColors.size() * sizeof(aiColor4D)); } // copy faces - for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace) { + for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces; ++iFace) { p_pcOut->mFaces[iFace].mNumIndices = 3; p_pcOut->mFaces[iFace].mIndices = new unsigned int[3]; @@ -1179,18 +1160,17 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh } // copy vertex bones - if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty()) { - std::vector > avBonesOut( mesh.mBones.size() ); + if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty()) { + std::vector> avBonesOut(mesh.mBones.size()); // find all vertex weights for this bone unsigned int quak = 0; - for (std::vector::const_iterator harrypotter = mesh.mBoneVertices.begin(); - harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak) { + for (std::vector::const_iterator harrypotter = mesh.mBoneVertices.begin(); + harrypotter != mesh.mBoneVertices.end(); ++harrypotter, ++quak) { - for (std::vector >::const_iterator - ronaldweasley = (*harrypotter).mBoneWeights.begin(); - ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley) - { + for (std::vector>::const_iterator + ronaldweasley = (*harrypotter).mBoneWeights.begin(); + ronaldweasley != (*harrypotter).mBoneWeights.end(); ++ronaldweasley) { aiVertexWeight weight; weight.mVertexId = quak; weight.mWeight = (*ronaldweasley).second; @@ -1200,19 +1180,19 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // now build a final bone list p_pcOut->mNumBones = 0; - for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy) - if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++; + for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size(); ++jfkennedy) + if (!avBonesOut[jfkennedy].empty()) p_pcOut->mNumBones++; - p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones]; - aiBone** pcBone = p_pcOut->mBones; - for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy) { + p_pcOut->mBones = new aiBone *[p_pcOut->mNumBones]; + aiBone **pcBone = p_pcOut->mBones; + for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size(); ++jfkennedy) { if (!avBonesOut[jfkennedy].empty()) { - aiBone* pc = *pcBone = new aiBone(); + aiBone *pc = *pcBone = new aiBone(); pc->mName.Set(mesh.mBones[jfkennedy].mName); pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size(); pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - ::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0], - sizeof(aiVertexWeight) * pc->mNumWeights); + ::memcpy(pc->mWeights, &avBonesOut[jfkennedy][0], + sizeof(aiVertexWeight) * pc->mNumWeights); ++pcBone; } } @@ -1222,23 +1202,20 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // ------------------------------------------------------------------------------------------------ // Setup proper material indices and build output materials -void ASEImporter::BuildMaterialIndices() -{ - ai_assert(NULL != pcScene); +void ASEImporter::BuildMaterialIndices() { + ai_assert(nullptr != pcScene); // iterate through all materials and check whether we need them - for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) - { - ASE::Material& mat = mParser->m_vMaterials[iMat]; - if (mat.bNeed) { + for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size(); ++iMat) { + ASE::Material &mat = mParser->m_vMaterials[iMat]; + if (mat.bNeed) { // Convert it to the aiMaterial layout ConvertMaterial(mat); ++pcScene->mNumMaterials; } - for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat) - { - ASE::Material& submat = mat.avSubMaterials[iSubMat]; - if (submat.bNeed) { + for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size(); ++iSubMat) { + ASE::Material &submat = mat.avSubMaterials[iSubMat]; + if (submat.bNeed) { // Convert it to the aiMaterial layout ConvertMaterial(submat); ++pcScene->mNumMaterials; @@ -1247,15 +1224,14 @@ void ASEImporter::BuildMaterialIndices() } // allocate the output material array - pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials]; - D3DS::Material** pcIntMaterials = new D3DS::Material*[pcScene->mNumMaterials]; + pcScene->mMaterials = new aiMaterial *[pcScene->mNumMaterials]; + D3DS::Material **pcIntMaterials = new D3DS::Material *[pcScene->mNumMaterials]; unsigned int iNum = 0; - for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) { - ASE::Material& mat = mParser->m_vMaterials[iMat]; - if (mat.bNeed) - { - ai_assert(NULL != mat.pcInstance); + for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size(); ++iMat) { + ASE::Material &mat = mParser->m_vMaterials[iMat]; + if (mat.bNeed) { + ai_assert(nullptr != mat.pcInstance); pcScene->mMaterials[iNum] = mat.pcInstance; // Store the internal material, too @@ -1263,22 +1239,20 @@ void ASEImporter::BuildMaterialIndices() // Iterate through all meshes and search for one which is using // this top-level material index - for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) - { - aiMesh* mesh = pcScene->mMeshes[iMesh]; + for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes; ++iMesh) { + aiMesh *mesh = pcScene->mMeshes[iMesh]; if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex && - iMat == (uintptr_t)mesh->mColors[3]) - { + iMat == (uintptr_t)mesh->mColors[3]) { mesh->mMaterialIndex = iNum; - mesh->mColors[3] = NULL; + mesh->mColors[3] = nullptr; } } iNum++; } - for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat) { - ASE::Material& submat = mat.avSubMaterials[iSubMat]; - if (submat.bNeed) { - ai_assert(NULL != submat.pcInstance); + for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size(); ++iSubMat) { + ASE::Material &submat = mat.avSubMaterials[iSubMat]; + if (submat.bNeed) { + ai_assert(nullptr != submat.pcInstance); pcScene->mMaterials[iNum] = submat.pcInstance; // Store the internal material, too @@ -1286,12 +1260,12 @@ void ASEImporter::BuildMaterialIndices() // Iterate through all meshes and search for one which is using // this sub-level material index - for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) { - aiMesh* mesh = pcScene->mMeshes[iMesh]; + for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes; ++iMesh) { + aiMesh *mesh = pcScene->mMeshes[iMesh]; if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3]) { mesh->mMaterialIndex = iNum; - mesh->mColors[3] = NULL; + mesh->mColors[3] = nullptr; } } iNum++; @@ -1305,15 +1279,13 @@ void ASEImporter::BuildMaterialIndices() // ------------------------------------------------------------------------------------------------ // Generate normal vectors basing on smoothing groups -bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) { +bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) { - if (!mesh.mNormals.empty() && !configRecomputeNormals) - { + if (!mesh.mNormals.empty() && !configRecomputeNormals) { // Check whether there are only uninitialized normals. If there are // some, skip all normals from the file and compute them on our own - for (std::vector::const_iterator qq = mesh.mNormals.begin();qq != mesh.mNormals.end();++qq) { - if ((*qq).x || (*qq).y || (*qq).z) - { + for (std::vector::const_iterator qq = mesh.mNormals.begin(); qq != mesh.mNormals.end(); ++qq) { + if ((*qq).x || (*qq).y || (*qq).z) { return true; } } diff --git a/code/ASE/ASELoader.h b/code/AssetLib/ASE/ASELoader.h similarity index 100% rename from code/ASE/ASELoader.h rename to code/AssetLib/ASE/ASELoader.h diff --git a/code/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp similarity index 59% rename from code/ASE/ASEParser.cpp rename to code/AssetLib/ASE/ASEParser.cpp index 72e8b3373..09ad2ab1d 100644 --- a/code/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -49,8 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER // internal headers -#include "PostProcessing/TextureTransform.h" #include "ASELoader.h" +#include "PostProcessing/TextureTransform.h" #include #include @@ -67,26 +67,23 @@ using namespace Assimp::ASE; // ------------------------------------------------------------------------------------------------ // Handle a "top-level" section in the file. EOF is no error in this case. -#define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \ - else if ('{' == *filePtr)iDepth++; \ - else if ('}' == *filePtr) \ - { \ - if (0 == --iDepth) \ - { \ - ++filePtr; \ - SkipToNextToken(); \ - return; \ - } \ - } \ - else if ('\0' == *filePtr) \ - { \ - return; \ - } \ - if(IsLineEnd(*filePtr) && !bLastWasEndLine) \ - { \ - ++iLineNumber; \ - bLastWasEndLine = true; \ - } else bLastWasEndLine = false; \ +#define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \ + else if ('{' == *filePtr) iDepth++; \ + else if ('}' == *filePtr) { \ + if (0 == --iDepth) { \ + ++filePtr; \ + SkipToNextToken(); \ + return; \ + } \ + } \ + else if ('\0' == *filePtr) { \ + return; \ + } \ + if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \ + ++iLineNumber; \ + bLastWasEndLine = true; \ + } else \ + bLastWasEndLine = false; \ ++filePtr; // ------------------------------------------------------------------------------------------------ @@ -94,59 +91,54 @@ using namespace Assimp::ASE; // @param level "Depth" of the section // @param msg Full name of the section (including the asterisk) -#define AI_ASE_HANDLE_SECTION(level, msg) \ - if ('{' == *filePtr)iDepth++; \ - else if ('}' == *filePtr) \ - { \ - if (0 == --iDepth) \ - { \ - ++filePtr; \ - SkipToNextToken(); \ - return; \ - } \ - } \ - else if ('\0' == *filePtr) \ - { \ +#define AI_ASE_HANDLE_SECTION(level, msg) \ + if ('{' == *filePtr) \ + iDepth++; \ + else if ('}' == *filePtr) { \ + if (0 == --iDepth) { \ + ++filePtr; \ + SkipToNextToken(); \ + return; \ + } \ + } else if ('\0' == *filePtr) { \ LogError("Encountered unexpected EOL while parsing a " msg \ - " chunk (Level " level ")"); \ - } \ - if(IsLineEnd(*filePtr) && !bLastWasEndLine) \ - { \ - ++iLineNumber; \ - bLastWasEndLine = true; \ - } else bLastWasEndLine = false; \ + " chunk (Level " level ")"); \ + } \ + if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \ + ++iLineNumber; \ + bLastWasEndLine = true; \ + } else \ + bLastWasEndLine = false; \ ++filePtr; // ------------------------------------------------------------------------------------------------ -Parser::Parser (const char* szFile, unsigned int fileFormatDefault) -{ - ai_assert(NULL != szFile); +Parser::Parser(const char *szFile, unsigned int fileFormatDefault) { + ai_assert(nullptr != szFile); filePtr = szFile; iFileFormat = fileFormatDefault; // make sure that the color values are invalid m_clrBackground.r = get_qnan(); - m_clrAmbient.r = get_qnan(); + m_clrAmbient.r = get_qnan(); // setup some default values iLineNumber = 0; iFirstFrame = 0; iLastFrame = 0; - iFrameSpeed = 30; // use 30 as default value for this property - iTicksPerFrame = 1; // use 1 as default value for this property + iFrameSpeed = 30; // use 30 as default value for this property + iTicksPerFrame = 1; // use 1 as default value for this property bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping } // ------------------------------------------------------------------------------------------------ -void Parser::LogWarning(const char* szWarn) -{ - ai_assert(NULL != szWarn); +void Parser::LogWarning(const char *szWarn) { + ai_assert(nullptr != szWarn); char szTemp[2048]; #if _MSC_VER >= 1400 - sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn); + sprintf_s(szTemp, "Line %u: %s", iLineNumber, szWarn); #else - ai_snprintf(szTemp,sizeof(szTemp),"Line %u: %s",iLineNumber,szWarn); + ai_snprintf(szTemp, sizeof(szTemp), "Line %u: %s", iLineNumber, szWarn); #endif // output the warning to the logger ... @@ -154,15 +146,14 @@ void Parser::LogWarning(const char* szWarn) } // ------------------------------------------------------------------------------------------------ -void Parser::LogInfo(const char* szWarn) -{ - ai_assert(NULL != szWarn); +void Parser::LogInfo(const char *szWarn) { + ai_assert(nullptr != szWarn); char szTemp[1024]; #if _MSC_VER >= 1400 - sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn); + sprintf_s(szTemp, "Line %u: %s", iLineNumber, szWarn); #else - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn); + ai_snprintf(szTemp, 1024, "Line %u: %s", iLineNumber, szWarn); #endif // output the information to the logger ... @@ -170,15 +161,14 @@ void Parser::LogInfo(const char* szWarn) } // ------------------------------------------------------------------------------------------------ -AI_WONT_RETURN void Parser::LogError(const char* szWarn) -{ - ai_assert(NULL != szWarn); +AI_WONT_RETURN void Parser::LogError(const char *szWarn) { + ai_assert(nullptr != szWarn); char szTemp[1024]; #if _MSC_VER >= 1400 - sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn); + sprintf_s(szTemp, "Line %u: %s", iLineNumber, szWarn); #else - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn); + ai_snprintf(szTemp, 1024, "Line %u: %s", iLineNumber, szWarn); #endif // throw an exception @@ -186,76 +176,60 @@ AI_WONT_RETURN void Parser::LogError(const char* szWarn) } // ------------------------------------------------------------------------------------------------ -bool Parser::SkipToNextToken() -{ - while (true) - { +bool Parser::SkipToNextToken() { + while (true) { char me = *filePtr; // increase the line number counter if necessary - if (IsLineEnd(me) && !bLastWasEndLine) - { + if (IsLineEnd(me) && !bLastWasEndLine) { ++iLineNumber; bLastWasEndLine = true; - } - else bLastWasEndLine = false; - if ('*' == me || '}' == me || '{' == me)return true; - if ('\0' == me)return false; + } else + bLastWasEndLine = false; + if ('*' == me || '}' == me || '{' == me) return true; + if ('\0' == me) return false; ++filePtr; } } // ------------------------------------------------------------------------------------------------ -bool Parser::SkipSection() -{ +bool Parser::SkipSection() { // must handle subsections ... int iCnt = 0; - while (true) - { - if ('}' == *filePtr) - { + while (true) { + if ('}' == *filePtr) { --iCnt; - if (0 == iCnt) - { + if (0 == iCnt) { // go to the next valid token ... ++filePtr; SkipToNextToken(); return true; } - } - else if ('{' == *filePtr) - { + } else if ('{' == *filePtr) { ++iCnt; - } - else if ('\0' == *filePtr) - { + } else if ('\0' == *filePtr) { LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]"); return false; - } - else if(IsLineEnd(*filePtr))++iLineNumber; + } else if (IsLineEnd(*filePtr)) + ++iLineNumber; ++filePtr; } } // ------------------------------------------------------------------------------------------------ -void Parser::Parse() -{ +void Parser::Parse() { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Version should be 200. Validate this ... - if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18)) - { + if (TokenMatch(filePtr, "3DSMAX_ASCIIEXPORT", 18)) { unsigned int fmt; ParseLV4MeshLong(fmt); - if (fmt > 200) - { + if (fmt > 200) { LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \ be <= 200"); } @@ -266,32 +240,29 @@ void Parser::Parse() // at the file extension (ASE, ASK, ASC) // ************************************************************* - if ( fmt ) { + if (fmt) { iFileFormat = fmt; } continue; } // main scene information - if (TokenMatch(filePtr,"SCENE",5)) - { + if (TokenMatch(filePtr, "SCENE", 5)) { ParseLV1SceneBlock(); continue; } // "group" - no implementation yet, in facte // we're just ignoring them for the moment - if (TokenMatch(filePtr,"GROUP",5)) - { + if (TokenMatch(filePtr, "GROUP", 5)) { Parse(); continue; } // material list - if (TokenMatch(filePtr,"MATERIAL_LIST",13)) - { + if (TokenMatch(filePtr, "MATERIAL_LIST", 13)) { ParseLV1MaterialListBlock(); continue; } // geometric object (mesh) - if (TokenMatch(filePtr,"GEOMOBJECT",10)) + if (TokenMatch(filePtr, "GEOMOBJECT", 10)) { m_vMeshes.push_back(Mesh("UNNAMED")); @@ -299,7 +270,7 @@ void Parser::Parse() continue; } // helper object = dummy in the hierarchy - if (TokenMatch(filePtr,"HELPEROBJECT",12)) + if (TokenMatch(filePtr, "HELPEROBJECT", 12)) { m_vDummies.push_back(Dummy()); @@ -307,7 +278,7 @@ void Parser::Parse() continue; } // light object - if (TokenMatch(filePtr,"LIGHTOBJECT",11)) + if (TokenMatch(filePtr, "LIGHTOBJECT", 11)) { m_vLights.push_back(Light("UNNAMED")); @@ -315,23 +286,20 @@ void Parser::Parse() continue; } // camera object - if (TokenMatch(filePtr,"CAMERAOBJECT",12)) - { + if (TokenMatch(filePtr, "CAMERAOBJECT", 12)) { m_vCameras.push_back(Camera("UNNAMED")); ParseLV1ObjectBlock(m_vCameras.back()); continue; } // comment - print it on the console - if (TokenMatch(filePtr,"COMMENT",7)) - { + if (TokenMatch(filePtr, "COMMENT", 7)) { std::string out = ""; - ParseString(out,"*COMMENT"); + ParseString(out, "*COMMENT"); LogInfo(("Comment: " + out).c_str()); continue; } // ASC bone weights - if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18)) - { + if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr, "MESH_SOFTSKINVERTS", 18)) { ParseLV1SoftSkinBlock(); } } @@ -341,8 +309,7 @@ void Parser::Parse() } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1SoftSkinBlock() -{ +void Parser::ParseLV1SoftSkinBlock() { // TODO: fix line counting here // ************************************************************** @@ -364,80 +331,77 @@ void Parser::ParseLV1SoftSkinBlock() FORMAT END */ // ************************************************************** - while (true) - { - if (*filePtr == '}' ) {++filePtr;return;} - else if (*filePtr == '\0') return; - else if (*filePtr == '{' ) ++filePtr; + while (true) { + if (*filePtr == '}') { + ++filePtr; + return; + } else if (*filePtr == '\0') + return; + else if (*filePtr == '{') + ++filePtr; else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr)) { - ASE::Mesh* curMesh = NULL; - unsigned int numVerts = 0; + ASE::Mesh *curMesh = nullptr; + unsigned int numVerts = 0; - const char* sz = filePtr; - while (!IsSpaceOrNewLine(*filePtr))++filePtr; + const char *sz = filePtr; + while (!IsSpaceOrNewLine(*filePtr)) + ++filePtr; - const unsigned int diff = (unsigned int)(filePtr-sz); - if (diff) - { - std::string name = std::string(sz,diff); + const unsigned int diff = (unsigned int)(filePtr - sz); + if (diff) { + std::string name = std::string(sz, diff); for (std::vector::iterator it = m_vMeshes.begin(); - it != m_vMeshes.end(); ++it) - { - if ((*it).mName == name) - { - curMesh = & (*it); + it != m_vMeshes.end(); ++it) { + if ((*it).mName == name) { + curMesh = &(*it); break; } } - if (!curMesh) - { + if (!curMesh) { LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section"); // Skip the mesh data - until we find a new mesh // or the end of the *MESH_SOFTSKINVERTS section - while (true) - { + while (true) { SkipSpacesAndLineEnd(&filePtr); - if (*filePtr == '}') - {++filePtr;return;} - else if (!IsNumeric(*filePtr)) + if (*filePtr == '}') { + ++filePtr; + return; + } else if (!IsNumeric(*filePtr)) break; SkipLine(&filePtr); } - } - else - { + } else { SkipSpacesAndLineEnd(&filePtr); ParseLV4MeshLong(numVerts); // Reserve enough storage curMesh->mBoneVertices.reserve(numVerts); - for (unsigned int i = 0; i < numVerts;++i) - { + for (unsigned int i = 0; i < numVerts; ++i) { SkipSpacesAndLineEnd(&filePtr); unsigned int numWeights; ParseLV4MeshLong(numWeights); curMesh->mBoneVertices.push_back(ASE::BoneVertex()); - ASE::BoneVertex& vert = curMesh->mBoneVertices.back(); + ASE::BoneVertex &vert = curMesh->mBoneVertices.back(); // Reserve enough storage vert.mBoneWeights.reserve(numWeights); std::string bone; - for (unsigned int w = 0; w < numWeights;++w) { + for (unsigned int w = 0; w < numWeights; ++w) { bone.clear(); - ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); + ParseString(bone, "*MESH_SOFTSKINVERTS.Bone"); // Find the bone in the mesh's list - std::pair me; + std::pair me; me.first = -1; - for (unsigned int n = 0; n < curMesh->mBones.size();++n) { + for (unsigned int n = 0; n < curMesh->mBones.size(); ++n) { if (curMesh->mBones[n].mName == bone) { me.first = n; break; @@ -445,10 +409,10 @@ void Parser::ParseLV1SoftSkinBlock() } if (-1 == me.first) { // We don't have this bone yet, so add it to the list - me.first = static_cast( curMesh->mBones.size() ); - curMesh->mBones.push_back( ASE::Bone( bone ) ); + me.first = static_cast(curMesh->mBones.size()); + curMesh->mBones.push_back(ASE::Bone(bone)); } - ParseLV4MeshFloat( me.second ); + ParseLV4MeshFloat(me.second); // Add the new bone weight to list vert.mBoneWeights.push_back(me); @@ -463,45 +427,38 @@ void Parser::ParseLV1SoftSkinBlock() } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1SceneBlock() -{ +void Parser::ParseLV1SceneBlock() { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23)) + if (TokenMatch(filePtr, "SCENE_BACKGROUND_STATIC", 23)) { // parse a color triple and assume it is really the bg color - ParseLV4MeshFloatTriple( &m_clrBackground.r ); + ParseLV4MeshFloatTriple(&m_clrBackground.r); continue; } - if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20)) + if (TokenMatch(filePtr, "SCENE_AMBIENT_STATIC", 20)) { // parse a color triple and assume it is really the bg color - ParseLV4MeshFloatTriple( &m_clrAmbient.r ); + ParseLV4MeshFloatTriple(&m_clrAmbient.r); continue; } - if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16)) - { + if (TokenMatch(filePtr, "SCENE_FIRSTFRAME", 16)) { ParseLV4MeshLong(iFirstFrame); continue; } - if (TokenMatch(filePtr,"SCENE_LASTFRAME",15)) - { + if (TokenMatch(filePtr, "SCENE_LASTFRAME", 15)) { ParseLV4MeshLong(iLastFrame); continue; } - if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16)) - { + if (TokenMatch(filePtr, "SCENE_FRAMESPEED", 16)) { ParseLV4MeshLong(iFrameSpeed); continue; } - if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19)) - { + if (TokenMatch(filePtr, "SCENE_TICKSPERFRAME", 19)) { ParseLV4MeshLong(iTicksPerFrame); continue; } @@ -511,38 +468,32 @@ void Parser::ParseLV1SceneBlock() } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1MaterialListBlock() -{ +void Parser::ParseLV1MaterialListBlock() { AI_ASE_PARSER_INIT(); unsigned int iMaterialCount = 0; unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (TokenMatch(filePtr,"MATERIAL_COUNT",14)) - { + if (TokenMatch(filePtr, "MATERIAL_COUNT", 14)) { ParseLV4MeshLong(iMaterialCount); // now allocate enough storage to hold all materials - m_vMaterials.resize(iOldMaterialCount+iMaterialCount, Material("INVALID")); + m_vMaterials.resize(iOldMaterialCount + iMaterialCount, Material("INVALID")); continue; } - if (TokenMatch(filePtr,"MATERIAL",8)) - { + if (TokenMatch(filePtr, "MATERIAL", 8)) { unsigned int iIndex = 0; ParseLV4MeshLong(iIndex); - if (iIndex >= iMaterialCount) - { + if (iIndex >= iMaterialCount) { LogWarning("Out of range: material index is too large"); - iIndex = iMaterialCount-1; + iIndex = iMaterialCount - 1; } // get a reference to the material - Material& sMat = m_vMaterials[iIndex+iOldMaterialCount]; + Material &sMat = m_vMaterials[iIndex + iOldMaterialCount]; // parse the material block ParseLV2MaterialBlock(sMat); continue; @@ -553,61 +504,44 @@ void Parser::ParseLV1MaterialListBlock() } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2MaterialBlock(ASE::Material& mat) -{ +void Parser::ParseLV2MaterialBlock(ASE::Material &mat) { AI_ASE_PARSER_INIT(); unsigned int iNumSubMaterials = 0; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (TokenMatch(filePtr,"MATERIAL_NAME",13)) - { - if (!ParseString(mat.mName,"*MATERIAL_NAME")) + if (TokenMatch(filePtr, "MATERIAL_NAME", 13)) { + if (!ParseString(mat.mName, "*MATERIAL_NAME")) SkipToNextToken(); continue; } // ambient material color - if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16)) - { + if (TokenMatch(filePtr, "MATERIAL_AMBIENT", 16)) { ParseLV4MeshFloatTriple(&mat.mAmbient.r); continue; } // diffuse material color - if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) ) - { + if (TokenMatch(filePtr, "MATERIAL_DIFFUSE", 16)) { ParseLV4MeshFloatTriple(&mat.mDiffuse.r); continue; } // specular material color - if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17)) - { + if (TokenMatch(filePtr, "MATERIAL_SPECULAR", 17)) { ParseLV4MeshFloatTriple(&mat.mSpecular.r); continue; } // material shading type - if (TokenMatch(filePtr,"MATERIAL_SHADING",16)) - { - if (TokenMatch(filePtr,"Blinn",5)) - { + if (TokenMatch(filePtr, "MATERIAL_SHADING", 16)) { + if (TokenMatch(filePtr, "Blinn", 5)) { mat.mShading = Discreet3DS::Blinn; - } - else if (TokenMatch(filePtr,"Phong",5)) - { + } else if (TokenMatch(filePtr, "Phong", 5)) { mat.mShading = Discreet3DS::Phong; - } - else if (TokenMatch(filePtr,"Flat",4)) - { + } else if (TokenMatch(filePtr, "Flat", 4)) { mat.mShading = Discreet3DS::Flat; - } - else if (TokenMatch(filePtr,"Wire",4)) - { + } else if (TokenMatch(filePtr, "Wire", 4)) { mat.mShading = Discreet3DS::Wire; - } - else - { + } else { // assume gouraud shading mat.mShading = Discreet3DS::Gouraud; SkipToNextToken(); @@ -615,15 +549,13 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat) continue; } // material transparency - if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21)) - { + if (TokenMatch(filePtr, "MATERIAL_TRANSPARENCY", 21)) { ParseLV4MeshFloat(mat.mTransparency); - mat.mTransparency = ai_real( 1.0 ) - mat.mTransparency; + mat.mTransparency = ai_real(1.0) - mat.mTransparency; continue; } // material self illumination - if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18)) - { + if (TokenMatch(filePtr, "MATERIAL_SELFILLUM", 18)) { ai_real f = 0.0; ParseLV4MeshFloat(f); @@ -633,108 +565,94 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat) continue; } // material shininess - if (TokenMatch(filePtr,"MATERIAL_SHINE",14) ) - { + if (TokenMatch(filePtr, "MATERIAL_SHINE", 14)) { ParseLV4MeshFloat(mat.mSpecularExponent); mat.mSpecularExponent *= 15; continue; } // two-sided material - if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) ) - { + if (TokenMatch(filePtr, "MATERIAL_TWOSIDED", 17)) { mat.mTwoSided = true; continue; } // material shininess strength - if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22)) - { + if (TokenMatch(filePtr, "MATERIAL_SHINESTRENGTH", 22)) { ParseLV4MeshFloat(mat.mShininessStrength); continue; } // diffuse color map - if (TokenMatch(filePtr,"MAP_DIFFUSE",11)) - { + if (TokenMatch(filePtr, "MAP_DIFFUSE", 11)) { // parse the texture block ParseLV3MapBlock(mat.sTexDiffuse); continue; } // ambient color map - if (TokenMatch(filePtr,"MAP_AMBIENT",11)) - { + if (TokenMatch(filePtr, "MAP_AMBIENT", 11)) { // parse the texture block ParseLV3MapBlock(mat.sTexAmbient); continue; } // specular color map - if (TokenMatch(filePtr,"MAP_SPECULAR",12)) - { + if (TokenMatch(filePtr, "MAP_SPECULAR", 12)) { // parse the texture block ParseLV3MapBlock(mat.sTexSpecular); continue; } // opacity map - if (TokenMatch(filePtr,"MAP_OPACITY",11)) - { + if (TokenMatch(filePtr, "MAP_OPACITY", 11)) { // parse the texture block ParseLV3MapBlock(mat.sTexOpacity); continue; } // emissive map - if (TokenMatch(filePtr,"MAP_SELFILLUM",13)) - { + if (TokenMatch(filePtr, "MAP_SELFILLUM", 13)) { // parse the texture block ParseLV3MapBlock(mat.sTexEmissive); continue; } // bump map - if (TokenMatch(filePtr,"MAP_BUMP",8)) - { + if (TokenMatch(filePtr, "MAP_BUMP", 8)) { // parse the texture block ParseLV3MapBlock(mat.sTexBump); } // specular/shininess map - if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17)) - { + if (TokenMatch(filePtr, "MAP_SHINESTRENGTH", 17)) { // parse the texture block ParseLV3MapBlock(mat.sTexShininess); continue; } // number of submaterials - if (TokenMatch(filePtr,"NUMSUBMTLS",10)) - { + if (TokenMatch(filePtr, "NUMSUBMTLS", 10)) { ParseLV4MeshLong(iNumSubMaterials); // allocate enough storage mat.avSubMaterials.resize(iNumSubMaterials, Material("INVALID SUBMATERIAL")); } // submaterial chunks - if (TokenMatch(filePtr,"SUBMATERIAL",11)) - { + if (TokenMatch(filePtr, "SUBMATERIAL", 11)) { unsigned int iIndex = 0; ParseLV4MeshLong(iIndex); - if (iIndex >= iNumSubMaterials) - { + if (iIndex >= iNumSubMaterials) { LogWarning("Out of range: submaterial index is too large"); - iIndex = iNumSubMaterials-1; + iIndex = iNumSubMaterials - 1; } // get a reference to the material - Material& sMat = mat.avSubMaterials[iIndex]; + Material &sMat = mat.avSubMaterials[iIndex]; // parse the material block ParseLV2MaterialBlock(sMat); continue; } } - AI_ASE_HANDLE_SECTION("2","*MATERIAL"); + AI_ASE_HANDLE_SECTION("2", "*MATERIAL"); } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MapBlock(Texture& map) -{ +void Parser::ParseLV3MapBlock(Texture &map) { AI_ASE_PARSER_INIT(); // *********************************************************** @@ -744,32 +662,26 @@ void Parser::ParseLV3MapBlock(Texture& map) // *********************************************************** bool parsePath = true; std::string temp; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // type of map - if (TokenMatch(filePtr,"MAP_CLASS" ,9)) - { + if (TokenMatch(filePtr, "MAP_CLASS", 9)) { temp.clear(); - if(!ParseString(temp,"*MAP_CLASS")) + if (!ParseString(temp, "*MAP_CLASS")) SkipToNextToken(); - if (temp != "Bitmap" && temp != "Normal Bump") - { + if (temp != "Bitmap" && temp != "Normal Bump") { ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp); parsePath = false; } continue; } // path to the texture - if (parsePath && TokenMatch(filePtr,"BITMAP" ,6)) - { - if(!ParseString(map.mMapName,"*BITMAP")) + if (parsePath && TokenMatch(filePtr, "BITMAP", 6)) { + if (!ParseString(map.mMapName, "*BITMAP")) SkipToNextToken(); - if (map.mMapName == "None") - { + if (map.mMapName == "None") { // Files with 'None' as map name are produced by // an Maja to ASE exporter which name I forgot .. ASSIMP_LOG_WARN("ASE: Skipping invalid map entry"); @@ -779,198 +691,157 @@ void Parser::ParseLV3MapBlock(Texture& map) continue; } // offset on the u axis - if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12)) - { + if (TokenMatch(filePtr, "UVW_U_OFFSET", 12)) { ParseLV4MeshFloat(map.mOffsetU); continue; } // offset on the v axis - if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12)) - { + if (TokenMatch(filePtr, "UVW_V_OFFSET", 12)) { ParseLV4MeshFloat(map.mOffsetV); continue; } // tiling on the u axis - if (TokenMatch(filePtr,"UVW_U_TILING" ,12)) - { + if (TokenMatch(filePtr, "UVW_U_TILING", 12)) { ParseLV4MeshFloat(map.mScaleU); continue; } // tiling on the v axis - if (TokenMatch(filePtr,"UVW_V_TILING" ,12)) - { + if (TokenMatch(filePtr, "UVW_V_TILING", 12)) { ParseLV4MeshFloat(map.mScaleV); continue; } // rotation around the z-axis - if (TokenMatch(filePtr,"UVW_ANGLE" ,9)) - { + if (TokenMatch(filePtr, "UVW_ANGLE", 9)) { ParseLV4MeshFloat(map.mRotation); continue; } // map blending factor - if (TokenMatch(filePtr,"MAP_AMOUNT" ,10)) - { + if (TokenMatch(filePtr, "MAP_AMOUNT", 10)) { ParseLV4MeshFloat(map.mTextureBlend); continue; } } - AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX"); + AI_ASE_HANDLE_SECTION("3", "*MAP_XXXXXX"); } return; } // ------------------------------------------------------------------------------------------------ -bool Parser::ParseString(std::string& out,const char* szName) -{ +bool Parser::ParseString(std::string &out, const char *szName) { char szBuffer[1024]; - if (!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { - ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Unexpected EOL",szName); + ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Unexpected EOL", szName); LogWarning(szBuffer); return false; } // there must be '"' - if ('\"' != *filePtr) - { + if ('\"' != *filePtr) { ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected " - "to be enclosed in double quotation marks",szName); + "to be enclosed in double quotation marks", + szName); LogWarning(szBuffer); return false; } ++filePtr; - const char* sz = filePtr; - while (true) - { - if ('\"' == *sz)break; - else if ('\0' == *sz) - { + const char *sz = filePtr; + while (true) { + if ('\"' == *sz) + break; + else if ('\0' == *sz) { ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected to " - "be enclosed in double quotation marks but EOF was reached before " - "a closing quotation mark was encountered",szName); + "be enclosed in double quotation marks but EOF was reached before " + "a closing quotation mark was encountered", + szName); LogWarning(szBuffer); return false; } sz++; } - out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr); - filePtr = sz+1; + out = std::string(filePtr, (uintptr_t)sz - (uintptr_t)filePtr); + filePtr = sz + 1; return true; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node) -{ +void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // first process common tokens such as node name and transform // name of the mesh/node - if (TokenMatch(filePtr,"NODE_NAME" ,9)) - { - if(!ParseString(node.mName,"*NODE_NAME")) + if (TokenMatch(filePtr, "NODE_NAME", 9)) { + if (!ParseString(node.mName, "*NODE_NAME")) SkipToNextToken(); continue; } // name of the parent of the node - if (TokenMatch(filePtr,"NODE_PARENT" ,11) ) - { - if(!ParseString(node.mParent,"*NODE_PARENT")) + if (TokenMatch(filePtr, "NODE_PARENT", 11)) { + if (!ParseString(node.mParent, "*NODE_PARENT")) SkipToNextToken(); continue; } // transformation matrix of the node - if (TokenMatch(filePtr,"NODE_TM" ,7)) - { + if (TokenMatch(filePtr, "NODE_TM", 7)) { ParseLV2NodeTransformBlock(node); continue; } // animation data of the node - if (TokenMatch(filePtr,"TM_ANIMATION" ,12)) - { + if (TokenMatch(filePtr, "TM_ANIMATION", 12)) { ParseLV2AnimationBlock(node); continue; } - if (node.mType == BaseNode::Light) - { + if (node.mType == BaseNode::Light) { // light settings - if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14)) - { - ParseLV2LightSettingsBlock((ASE::Light&)node); + if (TokenMatch(filePtr, "LIGHT_SETTINGS", 14)) { + ParseLV2LightSettingsBlock((ASE::Light &)node); continue; } // type of the light source - if (TokenMatch(filePtr,"LIGHT_TYPE" ,10)) - { - if (!ASSIMP_strincmp("omni",filePtr,4)) - { - ((ASE::Light&)node).mLightType = ASE::Light::OMNI; - } - else if (!ASSIMP_strincmp("target",filePtr,6)) - { - ((ASE::Light&)node).mLightType = ASE::Light::TARGET; - } - else if (!ASSIMP_strincmp("free",filePtr,4)) - { - ((ASE::Light&)node).mLightType = ASE::Light::FREE; - } - else if (!ASSIMP_strincmp("directional",filePtr,11)) - { - ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL; - } - else - { + if (TokenMatch(filePtr, "LIGHT_TYPE", 10)) { + if (!ASSIMP_strincmp("omni", filePtr, 4)) { + ((ASE::Light &)node).mLightType = ASE::Light::OMNI; + } else if (!ASSIMP_strincmp("target", filePtr, 6)) { + ((ASE::Light &)node).mLightType = ASE::Light::TARGET; + } else if (!ASSIMP_strincmp("free", filePtr, 4)) { + ((ASE::Light &)node).mLightType = ASE::Light::FREE; + } else if (!ASSIMP_strincmp("directional", filePtr, 11)) { + ((ASE::Light &)node).mLightType = ASE::Light::DIRECTIONAL; + } else { LogWarning("Unknown kind of light source"); } continue; } - } - else if (node.mType == BaseNode::Camera) - { + } else if (node.mType == BaseNode::Camera) { // Camera settings - if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15)) - { - ParseLV2CameraSettingsBlock((ASE::Camera&)node); + if (TokenMatch(filePtr, "CAMERA_SETTINGS", 15)) { + ParseLV2CameraSettingsBlock((ASE::Camera &)node); continue; - } - else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11)) - { - if (!ASSIMP_strincmp("target",filePtr,6)) - { - ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET; - } - else if (!ASSIMP_strincmp("free",filePtr,4)) - { - ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE; - } - else - { + } else if (TokenMatch(filePtr, "CAMERA_TYPE", 11)) { + if (!ASSIMP_strincmp("target", filePtr, 6)) { + ((ASE::Camera &)node).mCameraType = ASE::Camera::TARGET; + } else if (!ASSIMP_strincmp("free", filePtr, 4)) { + ((ASE::Camera &)node).mCameraType = ASE::Camera::FREE; + } else { LogWarning("Unknown kind of camera"); } continue; } - } - else if (node.mType == BaseNode::Mesh) - { + } else if (node.mType == BaseNode::Mesh) { // mesh data // FIX: Older files use MESH_SOFTSKIN - if (TokenMatch(filePtr,"MESH" ,4) || - TokenMatch(filePtr,"MESH_SOFTSKIN",13)) - { - ParseLV2MeshBlock((ASE::Mesh&)node); + if (TokenMatch(filePtr, "MESH", 4) || + TokenMatch(filePtr, "MESH_SOFTSKIN", 13)) { + ParseLV2MeshBlock((ASE::Mesh &)node); continue; } // mesh material index - if (TokenMatch(filePtr,"MATERIAL_REF" ,12)) - { - ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex); + if (TokenMatch(filePtr, "MATERIAL_REF", 12)) { + ParseLV4MeshLong(((ASE::Mesh &)node).iMaterialIndex); continue; } } @@ -981,156 +852,131 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node) } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera) -{ +void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (TokenMatch(filePtr,"CAMERA_NEAR" ,11)) - { + if (TokenMatch(filePtr, "CAMERA_NEAR", 11)) { ParseLV4MeshFloat(camera.mNear); continue; } - if (TokenMatch(filePtr,"CAMERA_FAR" ,10)) - { + if (TokenMatch(filePtr, "CAMERA_FAR", 10)) { ParseLV4MeshFloat(camera.mFar); continue; } - if (TokenMatch(filePtr,"CAMERA_FOV" ,10)) - { + if (TokenMatch(filePtr, "CAMERA_FOV", 10)) { ParseLV4MeshFloat(camera.mFOV); continue; } } - AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS"); + AI_ASE_HANDLE_SECTION("2", "CAMERA_SETTINGS"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2LightSettingsBlock(ASE::Light& light) -{ +void Parser::ParseLV2LightSettingsBlock(ASE::Light &light) { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (TokenMatch(filePtr,"LIGHT_COLOR" ,11)) - { + if (TokenMatch(filePtr, "LIGHT_COLOR", 11)) { ParseLV4MeshFloatTriple(&light.mColor.r); continue; } - if (TokenMatch(filePtr,"LIGHT_INTENS" ,12)) - { + if (TokenMatch(filePtr, "LIGHT_INTENS", 12)) { ParseLV4MeshFloat(light.mIntensity); continue; } - if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13)) - { + if (TokenMatch(filePtr, "LIGHT_HOTSPOT", 13)) { ParseLV4MeshFloat(light.mAngle); continue; } - if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13)) - { + if (TokenMatch(filePtr, "LIGHT_FALLOFF", 13)) { ParseLV4MeshFloat(light.mFalloff); continue; } } - AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS"); + AI_ASE_HANDLE_SECTION("2", "LIGHT_SETTINGS"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) -{ +void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) { AI_ASE_PARSER_INIT(); - ASE::Animation* anim = &mesh.mAnim; - while (true) - { - if ('*' == *filePtr) - { + ASE::Animation *anim = &mesh.mAnim; + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (TokenMatch(filePtr,"NODE_NAME" ,9)) - { + if (TokenMatch(filePtr, "NODE_NAME", 9)) { std::string temp; - if(!ParseString(temp,"*NODE_NAME")) + if (!ParseString(temp, "*NODE_NAME")) SkipToNextToken(); // If the name of the node contains .target it // represents an animated camera or spot light // target. - if (std::string::npos != temp.find(".Target")) - { - if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) && - ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET)) - { + if (std::string::npos != temp.find(".Target")) { + if ((mesh.mType != BaseNode::Camera || ((ASE::Camera &)mesh).mCameraType != ASE::Camera::TARGET) && + (mesh.mType != BaseNode::Light || ((ASE::Light &)mesh).mLightType != ASE::Light::TARGET)) { ASSIMP_LOG_ERROR("ASE: Found target animation channel " - "but the node is neither a camera nor a spot light"); + "but the node is neither a camera nor a spot light"); anim = NULL; - } - else anim = &mesh.mTargetAnim; + } else + anim = &mesh.mTargetAnim; } continue; } // position keyframes - if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) || - TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) || - TokenMatch(filePtr,"CONTROL_POS_TCB" ,15)) - { - if (!anim)SkipSection(); - else ParseLV3PosAnimationBlock(*anim); + if (TokenMatch(filePtr, "CONTROL_POS_TRACK", 17) || + TokenMatch(filePtr, "CONTROL_POS_BEZIER", 18) || + TokenMatch(filePtr, "CONTROL_POS_TCB", 15)) { + if (!anim) + SkipSection(); + else + ParseLV3PosAnimationBlock(*anim); continue; } // scaling keyframes - if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) || - TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) || - TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17)) - { - if (!anim || anim == &mesh.mTargetAnim) - { + if (TokenMatch(filePtr, "CONTROL_SCALE_TRACK", 19) || + TokenMatch(filePtr, "CONTROL_SCALE_BEZIER", 20) || + TokenMatch(filePtr, "CONTROL_SCALE_TCB", 17)) { + if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation"); SkipSection(); - } - else ParseLV3ScaleAnimationBlock(*anim); + } else + ParseLV3ScaleAnimationBlock(*anim); continue; } // rotation keyframes - if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) || - TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) || - TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15)) - { - if (!anim || anim == &mesh.mTargetAnim) - { + if (TokenMatch(filePtr, "CONTROL_ROT_TRACK", 17) || + TokenMatch(filePtr, "CONTROL_ROT_BEZIER", 18) || + TokenMatch(filePtr, "CONTROL_ROT_TCB", 15)) { + if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation"); SkipSection(); - } - else ParseLV3RotAnimationBlock(*anim); + } else + ParseLV3RotAnimationBlock(*anim); continue; } } - AI_ASE_HANDLE_SECTION("2","TM_ANIMATION"); + AI_ASE_HANDLE_SECTION("2", "TM_ANIMATION"); } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim) -{ +void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation &anim) { AI_ASE_PARSER_INIT(); unsigned int iIndex; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; bool b = false; @@ -1139,44 +985,37 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim) // we ignore the additional information for bezier's and TCBs // simple scaling keyframe - if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20)) - { + if (TokenMatch(filePtr, "CONTROL_SCALE_SAMPLE", 20)) { b = true; anim.mScalingType = ASE::Animation::TRACK; } // Bezier scaling keyframe - if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24)) - { + if (TokenMatch(filePtr, "CONTROL_BEZIER_SCALE_KEY", 24)) { b = true; anim.mScalingType = ASE::Animation::BEZIER; } // TCB scaling keyframe - if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21)) - { + if (TokenMatch(filePtr, "CONTROL_TCB_SCALE_KEY", 21)) { b = true; anim.mScalingType = ASE::Animation::TCB; } - if (b) - { + if (b) { anim.akeyScaling.push_back(aiVectorKey()); - aiVectorKey& key = anim.akeyScaling.back(); - ParseLV4MeshFloatTriple(&key.mValue.x,iIndex); + aiVectorKey &key = anim.akeyScaling.back(); + ParseLV4MeshFloatTriple(&key.mValue.x, iIndex); key.mTime = (double)iIndex; } } - AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK"); + AI_ASE_HANDLE_SECTION("3", "*CONTROL_POS_TRACK"); } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim) -{ +void Parser::ParseLV3PosAnimationBlock(ASE::Animation &anim) { AI_ASE_PARSER_INIT(); unsigned int iIndex; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; bool b = false; @@ -1185,44 +1024,37 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim) // we ignore the additional information for bezier's and TCBs // simple scaling keyframe - if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18)) - { + if (TokenMatch(filePtr, "CONTROL_POS_SAMPLE", 18)) { b = true; anim.mPositionType = ASE::Animation::TRACK; } // Bezier scaling keyframe - if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22)) - { + if (TokenMatch(filePtr, "CONTROL_BEZIER_POS_KEY", 22)) { b = true; anim.mPositionType = ASE::Animation::BEZIER; } // TCB scaling keyframe - if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19)) - { + if (TokenMatch(filePtr, "CONTROL_TCB_POS_KEY", 19)) { b = true; anim.mPositionType = ASE::Animation::TCB; } - if (b) - { + if (b) { anim.akeyPositions.push_back(aiVectorKey()); - aiVectorKey& key = anim.akeyPositions.back(); - ParseLV4MeshFloatTriple(&key.mValue.x,iIndex); + aiVectorKey &key = anim.akeyPositions.back(); + ParseLV4MeshFloatTriple(&key.mValue.x, iIndex); key.mTime = (double)iIndex; } } - AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK"); + AI_ASE_HANDLE_SECTION("3", "*CONTROL_POS_TRACK"); } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim) -{ +void Parser::ParseLV3RotAnimationBlock(ASE::Animation &anim) { AI_ASE_PARSER_INIT(); unsigned int iIndex; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; bool b = false; @@ -1231,150 +1063,126 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim) // we ignore the additional information for bezier's and TCBs // simple scaling keyframe - if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18)) - { + if (TokenMatch(filePtr, "CONTROL_ROT_SAMPLE", 18)) { b = true; anim.mRotationType = ASE::Animation::TRACK; } // Bezier scaling keyframe - if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22)) - { + if (TokenMatch(filePtr, "CONTROL_BEZIER_ROT_KEY", 22)) { b = true; anim.mRotationType = ASE::Animation::BEZIER; } // TCB scaling keyframe - if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19)) - { + if (TokenMatch(filePtr, "CONTROL_TCB_ROT_KEY", 19)) { b = true; anim.mRotationType = ASE::Animation::TCB; } - if (b) - { + if (b) { anim.akeyRotations.push_back(aiQuatKey()); - aiQuatKey& key = anim.akeyRotations.back(); - aiVector3D v;ai_real f; - ParseLV4MeshFloatTriple(&v.x,iIndex); + aiQuatKey &key = anim.akeyRotations.back(); + aiVector3D v; + ai_real f; + ParseLV4MeshFloatTriple(&v.x, iIndex); ParseLV4MeshFloat(f); key.mTime = (double)iIndex; - key.mValue = aiQuaternion(v,f); + key.mValue = aiQuaternion(v, f); } } - AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK"); + AI_ASE_HANDLE_SECTION("3", "*CONTROL_ROT_TRACK"); } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh) -{ +void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { AI_ASE_PARSER_INIT(); - int mode = 0; - while (true) - { - if ('*' == *filePtr) - { + int mode = 0; + while (true) { + if ('*' == *filePtr) { ++filePtr; // name of the node - if (TokenMatch(filePtr,"NODE_NAME" ,9)) - { + if (TokenMatch(filePtr, "NODE_NAME", 9)) { std::string temp; - if(!ParseString(temp,"*NODE_NAME")) + if (!ParseString(temp, "*NODE_NAME")) SkipToNextToken(); std::string::size_type s; - if (temp == mesh.mName) - { + if (temp == mesh.mName) { mode = 1; - } - else if (std::string::npos != (s = temp.find(".Target")) && - mesh.mName == temp.substr(0,s)) - { + } else if (std::string::npos != (s = temp.find(".Target")) && + mesh.mName == temp.substr(0, s)) { // This should be either a target light or a target camera - if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) || - (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET)) - { + if ((mesh.mType == BaseNode::Light && ((ASE::Light &)mesh).mLightType == ASE::Light::TARGET) || + (mesh.mType == BaseNode::Camera && ((ASE::Camera &)mesh).mCameraType == ASE::Camera::TARGET)) { mode = 2; - } - else { + } else { ASSIMP_LOG_ERROR("ASE: Ignoring target transform, " - "this is no spot light or target camera"); + "this is no spot light or target camera"); } - } - else - { + } else { ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp); // mode = 0 } continue; } - if (mode) - { + if (mode) { // fourth row of the transformation matrix - and also the // only information here that is interesting for targets - if (TokenMatch(filePtr,"TM_ROW3" ,7)) - { + if (TokenMatch(filePtr, "TM_ROW3", 7)) { ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x)); continue; } - if (mode == 1) - { + if (mode == 1) { // first row of the transformation matrix - if (TokenMatch(filePtr,"TM_ROW0" ,7)) - { + if (TokenMatch(filePtr, "TM_ROW0", 7)) { ParseLV4MeshFloatTriple(mesh.mTransform[0]); continue; } // second row of the transformation matrix - if (TokenMatch(filePtr,"TM_ROW1" ,7)) - { + if (TokenMatch(filePtr, "TM_ROW1", 7)) { ParseLV4MeshFloatTriple(mesh.mTransform[1]); continue; } // third row of the transformation matrix - if (TokenMatch(filePtr,"TM_ROW2" ,7)) - { + if (TokenMatch(filePtr, "TM_ROW2", 7)) { ParseLV4MeshFloatTriple(mesh.mTransform[2]); continue; } // inherited position axes - if (TokenMatch(filePtr,"INHERIT_POS" ,11)) - { + if (TokenMatch(filePtr, "INHERIT_POS", 11)) { unsigned int aiVal[3]; ParseLV4MeshLongTriple(aiVal); - for (unsigned int i = 0; i < 3;++i) + for (unsigned int i = 0; i < 3; ++i) mesh.inherit.abInheritPosition[i] = aiVal[i] != 0; continue; } // inherited rotation axes - if (TokenMatch(filePtr,"INHERIT_ROT" ,11)) - { + if (TokenMatch(filePtr, "INHERIT_ROT", 11)) { unsigned int aiVal[3]; ParseLV4MeshLongTriple(aiVal); - for (unsigned int i = 0; i < 3;++i) + for (unsigned int i = 0; i < 3; ++i) mesh.inherit.abInheritRotation[i] = aiVal[i] != 0; continue; } // inherited scaling axes - if (TokenMatch(filePtr,"INHERIT_SCL" ,11)) - { + if (TokenMatch(filePtr, "INHERIT_SCL", 11)) { unsigned int aiVal[3]; ParseLV4MeshLongTriple(aiVal); - for (unsigned int i = 0; i < 3;++i) + for (unsigned int i = 0; i < 3; ++i) mesh.inherit.abInheritScaling[i] = aiVal[i] != 0; continue; } } } } - AI_ASE_HANDLE_SECTION("2","*NODE_TM"); + AI_ASE_HANDLE_SECTION("2", "*NODE_TM"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh) -{ +void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); unsigned int iNumVertices = 0; @@ -1383,386 +1191,327 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh) unsigned int iNumTFaces = 0; unsigned int iNumCVertices = 0; unsigned int iNumCFaces = 0; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Number of vertices in the mesh - if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14)) - { + if (TokenMatch(filePtr, "MESH_NUMVERTEX", 14)) { ParseLV4MeshLong(iNumVertices); continue; } // Number of texture coordinates in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15)) - { + if (TokenMatch(filePtr, "MESH_NUMTVERTEX", 15)) { ParseLV4MeshLong(iNumTVertices); continue; } // Number of vertex colors in the mesh - if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15)) - { + if (TokenMatch(filePtr, "MESH_NUMCVERTEX", 15)) { ParseLV4MeshLong(iNumCVertices); continue; } // Number of regular faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMFACES" ,13)) - { + if (TokenMatch(filePtr, "MESH_NUMFACES", 13)) { ParseLV4MeshLong(iNumFaces); continue; } // Number of UVWed faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15)) - { + if (TokenMatch(filePtr, "MESH_NUMTVFACES", 15)) { ParseLV4MeshLong(iNumTFaces); continue; } // Number of colored faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15)) - { + if (TokenMatch(filePtr, "MESH_NUMCVFACES", 15)) { ParseLV4MeshLong(iNumCFaces); continue; } // mesh vertex list block - if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16)) - { - ParseLV3MeshVertexListBlock(iNumVertices,mesh); + if (TokenMatch(filePtr, "MESH_VERTEX_LIST", 16)) { + ParseLV3MeshVertexListBlock(iNumVertices, mesh); continue; } // mesh face list block - if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14)) - { - ParseLV3MeshFaceListBlock(iNumFaces,mesh); + if (TokenMatch(filePtr, "MESH_FACE_LIST", 14)) { + ParseLV3MeshFaceListBlock(iNumFaces, mesh); continue; } // mesh texture vertex list block - if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14)) - { - ParseLV3MeshTListBlock(iNumTVertices,mesh); + if (TokenMatch(filePtr, "MESH_TVERTLIST", 14)) { + ParseLV3MeshTListBlock(iNumTVertices, mesh); continue; } // mesh texture face block - if (TokenMatch(filePtr,"MESH_TFACELIST" ,14)) - { - ParseLV3MeshTFaceListBlock(iNumTFaces,mesh); + if (TokenMatch(filePtr, "MESH_TFACELIST", 14)) { + ParseLV3MeshTFaceListBlock(iNumTFaces, mesh); continue; } // mesh color vertex list block - if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14)) - { - ParseLV3MeshCListBlock(iNumCVertices,mesh); + if (TokenMatch(filePtr, "MESH_CVERTLIST", 14)) { + ParseLV3MeshCListBlock(iNumCVertices, mesh); continue; } // mesh color face block - if (TokenMatch(filePtr,"MESH_CFACELIST" ,14)) - { - ParseLV3MeshCFaceListBlock(iNumCFaces,mesh); + if (TokenMatch(filePtr, "MESH_CFACELIST", 14)) { + ParseLV3MeshCFaceListBlock(iNumCFaces, mesh); continue; } // mesh normals - if (TokenMatch(filePtr,"MESH_NORMALS" ,12)) - { + if (TokenMatch(filePtr, "MESH_NORMALS", 12)) { ParseLV3MeshNormalListBlock(mesh); continue; } // another mesh UV channel ... - if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) { - unsigned int iIndex( 0 ); + if (TokenMatch(filePtr, "MESH_MAPPINGCHANNEL", 19)) { + unsigned int iIndex(0); ParseLV4MeshLong(iIndex); - if ( 0 == iIndex ) { - LogWarning( "Mapping channel has an invalid index. Skipping UV channel" ); + if (0 == iIndex) { + LogWarning("Mapping channel has an invalid index. Skipping UV channel"); // skip it ... SkipSection(); } else { - if ( iIndex < 2 ) { - LogWarning( "Mapping channel has an invalid index. Skipping UV channel" ); + if (iIndex < 2) { + LogWarning("Mapping channel has an invalid index. Skipping UV channel"); // skip it ... SkipSection(); } - if ( iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS ) { - LogWarning( "Too many UV channels specified. Skipping channel .." ); + if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) { + LogWarning("Too many UV channels specified. Skipping channel .."); // skip it ... SkipSection(); } else { // parse the mapping channel - ParseLV3MappingChannel( iIndex - 1, mesh ); + ParseLV3MappingChannel(iIndex - 1, mesh); } continue; } } // mesh animation keyframe. Not supported - if (TokenMatch(filePtr,"MESH_ANIMATION" ,14)) - { + if (TokenMatch(filePtr, "MESH_ANIMATION", 14)) { LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. " - "Keyframe animation is not supported by Assimp, this element " - "will be ignored"); + "Keyframe animation is not supported by Assimp, this element " + "will be ignored"); //SkipSection(); continue; } - if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12)) - { - ParseLV3MeshWeightsBlock(mesh);continue; + if (TokenMatch(filePtr, "MESH_WEIGHTS", 12)) { + ParseLV3MeshWeightsBlock(mesh); + continue; } } - AI_ASE_HANDLE_SECTION("2","*MESH"); + AI_ASE_HANDLE_SECTION("2", "*MESH"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh) -{ +void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); unsigned int iNumVertices = 0, iNumBones = 0; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Number of bone vertices ... - if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14)) - { + if (TokenMatch(filePtr, "MESH_NUMVERTEX", 14)) { ParseLV4MeshLong(iNumVertices); continue; } // Number of bones - if (TokenMatch(filePtr,"MESH_NUMBONE" ,12)) - { + if (TokenMatch(filePtr, "MESH_NUMBONE", 12)) { ParseLV4MeshLong(iNumBones); continue; } // parse the list of bones - if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14)) - { - ParseLV4MeshBones(iNumBones,mesh); + if (TokenMatch(filePtr, "MESH_BONE_LIST", 14)) { + ParseLV4MeshBones(iNumBones, mesh); continue; } // parse the list of bones vertices - if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) ) - { - ParseLV4MeshBonesVertices(iNumVertices,mesh); + if (TokenMatch(filePtr, "MESH_BONE_VERTEX_LIST", 21)) { + ParseLV4MeshBonesVertices(iNumVertices, mesh); continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS"); + AI_ASE_HANDLE_SECTION("3", "*MESH_WEIGHTS"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh) -{ +void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); mesh.mBones.resize(iNumBones, Bone("UNNAMED")); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Mesh bone with name ... - if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14)) - { + if (TokenMatch(filePtr, "MESH_BONE_NAME", 14)) { // parse an index ... - if(SkipSpaces(&filePtr)) - { - unsigned int iIndex = strtoul10(filePtr,&filePtr); - if (iIndex >= iNumBones) - { + if (SkipSpaces(&filePtr)) { + unsigned int iIndex = strtoul10(filePtr, &filePtr); + if (iIndex >= iNumBones) { LogWarning("Bone index is out of bounds"); continue; } - if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME")) + if (!ParseString(mesh.mBones[iIndex].mName, "*MESH_BONE_NAME")) SkipToNextToken(); continue; } } } - AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_BONE_LIST"); } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh) -{ +void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); mesh.mBoneVertices.resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Mesh bone vertex - if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16)) - { + if (TokenMatch(filePtr, "MESH_BONE_VERTEX", 16)) { // read the vertex index - unsigned int iIndex = strtoul10(filePtr,&filePtr); - if (iIndex >= mesh.mPositions.size()) - { - iIndex = (unsigned int)mesh.mPositions.size()-1; + unsigned int iIndex = strtoul10(filePtr, &filePtr); + if (iIndex >= mesh.mPositions.size()) { + iIndex = (unsigned int)mesh.mPositions.size() - 1; LogWarning("Bone vertex index is out of bounds. Using the largest valid " - "bone vertex index instead"); + "bone vertex index instead"); } // --- ignored ai_real afVert[3]; ParseLV4MeshFloatTriple(afVert); - std::pair pairOut; - while (true) - { + std::pair pairOut; + while (true) { // first parse the bone index ... - if (!SkipSpaces(&filePtr))break; - pairOut.first = strtoul10(filePtr,&filePtr); + if (!SkipSpaces(&filePtr)) break; + pairOut.first = strtoul10(filePtr, &filePtr); // then parse the vertex weight - if (!SkipSpaces(&filePtr))break; - filePtr = fast_atoreal_move(filePtr,pairOut.second); + if (!SkipSpaces(&filePtr)) break; + filePtr = fast_atoreal_move(filePtr, pairOut.second); // -1 marks unused entries - if (-1 != pairOut.first) - { + if (-1 != pairOut.first) { mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut); } } continue; } } - AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX"); + AI_ASE_HANDLE_SECTION("4", "*MESH_BONE_VERTEX"); } return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshVertexListBlock( - unsigned int iNumVertices, ASE::Mesh& mesh) -{ + unsigned int iNumVertices, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); // allocate enough storage in the array mesh.mPositions.resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Vertex entry - if (TokenMatch(filePtr,"MESH_VERTEX" ,11)) - { + if (TokenMatch(filePtr, "MESH_VERTEX", 11)) { aiVector3D vTemp; unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.x,iIndex); + ParseLV4MeshFloatTriple(&vTemp.x, iIndex); - if (iIndex >= iNumVertices) - { + if (iIndex >= iNumVertices) { LogWarning("Invalid vertex index. It will be ignored"); - } - else mesh.mPositions[iIndex] = vTemp; + } else + mesh.mPositions[iIndex] = vTemp; continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_VERTEX_LIST"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) -{ +void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); // allocate enough storage in the face array mesh.mFaces.resize(iNumFaces); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Face entry - if (TokenMatch(filePtr,"MESH_FACE" ,9)) - { + if (TokenMatch(filePtr, "MESH_FACE", 9)) { ASE::Face mFace; ParseLV4MeshFace(mFace); - if (mFace.iFace >= iNumFaces) - { + if (mFace.iFace >= iNumFaces) { LogWarning("Face has an invalid index. It will be ignored"); - } - else mesh.mFaces[mFace.iFace] = mFace; + } else + mesh.mFaces[mFace.iFace] = mFace; continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_FACE_LIST"); } return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, - ASE::Mesh& mesh, unsigned int iChannel) -{ + ASE::Mesh &mesh, unsigned int iChannel) { AI_ASE_PARSER_INIT(); // allocate enough storage in the array mesh.amTexCoords[iChannel].resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Vertex entry - if (TokenMatch(filePtr,"MESH_TVERT" ,10)) - { + if (TokenMatch(filePtr, "MESH_TVERT", 10)) { aiVector3D vTemp; unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.x,iIndex); + ParseLV4MeshFloatTriple(&vTemp.x, iIndex); - if (iIndex >= iNumVertices) - { + if (iIndex >= iNumVertices) { LogWarning("Tvertex has an invalid index. It will be ignored"); - } - else mesh.amTexCoords[iChannel][iIndex] = vTemp; + } else + mesh.amTexCoords[iChannel][iIndex] = vTemp; - if (0.0f != vTemp.z) - { + if (0.0f != vTemp.z) { // we need 3 coordinate channels mesh.mNumUVComponents[iChannel] = 3; } continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_TVERT_LIST"); } return; } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, - ASE::Mesh& mesh, unsigned int iChannel) -{ + ASE::Mesh &mesh, unsigned int iChannel) { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Face entry - if (TokenMatch(filePtr,"MESH_TFACE" ,10)) - { + if (TokenMatch(filePtr, "MESH_TFACE", 10)) { unsigned int aiValues[3]; unsigned int iIndex = 0; - ParseLV4MeshLongTriple(aiValues,iIndex); - if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) - { + ParseLV4MeshLongTriple(aiValues, iIndex); + if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) { LogWarning("UV-Face has an invalid index. It will be ignored"); - } - else - { + } else { // copy UV indices mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0]; mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1]; @@ -1771,108 +1520,89 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_TFACE_LIST"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh) -{ +void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); unsigned int iNumTVertices = 0; unsigned int iNumTFaces = 0; - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Number of texture coordinates in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15)) - { + if (TokenMatch(filePtr, "MESH_NUMTVERTEX", 15)) { ParseLV4MeshLong(iNumTVertices); continue; } // Number of UVWed faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15)) - { + if (TokenMatch(filePtr, "MESH_NUMTVFACES", 15)) { ParseLV4MeshLong(iNumTFaces); continue; } // mesh texture vertex list block - if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14)) - { - ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel); + if (TokenMatch(filePtr, "MESH_TVERTLIST", 14)) { + ParseLV3MeshTListBlock(iNumTVertices, mesh, iChannel); continue; } // mesh texture face block - if (TokenMatch(filePtr,"MESH_TFACELIST" ,14)) - { - ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel); + if (TokenMatch(filePtr, "MESH_TFACELIST", 14)) { + ParseLV3MeshTFaceListBlock(iNumTFaces, mesh, iChannel); continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL"); + AI_ASE_HANDLE_SECTION("3", "*MESH_MAPPING_CHANNEL"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh) -{ +void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); // allocate enough storage in the array mesh.mVertexColors.resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Vertex entry - if (TokenMatch(filePtr,"MESH_VERTCOL" ,12)) - { + if (TokenMatch(filePtr, "MESH_VERTCOL", 12)) { aiColor4D vTemp; vTemp.a = 1.0f; unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.r,iIndex); + ParseLV4MeshFloatTriple(&vTemp.r, iIndex); - if (iIndex >= iNumVertices) - { + if (iIndex >= iNumVertices) { LogWarning("Vertex color has an invalid index. It will be ignored"); - } - else mesh.mVertexColors[iIndex] = vTemp; + } else + mesh.mVertexColors[iIndex] = vTemp; continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_CVERTEX_LIST"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) -{ +void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { + while (true) { + if ('*' == *filePtr) { ++filePtr; // Face entry - if (TokenMatch(filePtr,"MESH_CFACE" ,10)) - { + if (TokenMatch(filePtr, "MESH_CFACE", 10)) { unsigned int aiValues[3]; unsigned int iIndex = 0; - ParseLV4MeshLongTriple(aiValues,iIndex); - if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) - { + ParseLV4MeshLongTriple(aiValues, iIndex); + if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) { LogWarning("UV-Face has an invalid index. It will be ignored"); - } - else - { + } else { // copy color indices mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0]; mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1]; @@ -1881,17 +1611,16 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST"); + AI_ASE_HANDLE_SECTION("3", "*MESH_CFACE_LIST"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) -{ +void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { AI_ASE_PARSER_INIT(); // Allocate enough storage for the normals - sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f )); + sMesh.mNormals.resize(sMesh.mFaces.size() * 3, aiVector3D(0.f, 0.f, 0.f)); unsigned int index, faceIdx = UINT_MAX; // FIXME: rewrite this and find out how to interpret the normals @@ -1899,34 +1628,34 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) // Smooth the vertex and face normals together. The result // will be edgy then, but otherwise everything would be soft ... - while (true) { - if ('*' == *filePtr) { + while (true) { + if ('*' == *filePtr) { ++filePtr; - if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) { + if (faceIdx != UINT_MAX && TokenMatch(filePtr, "MESH_VERTEXNORMAL", 17)) { aiVector3D vNormal; - ParseLV4MeshFloatTriple(&vNormal.x,index); - if (faceIdx >= sMesh.mFaces.size()) + ParseLV4MeshFloatTriple(&vNormal.x, index); + if (faceIdx >= sMesh.mFaces.size()) continue; // Make sure we assign it to the correct face - const ASE::Face& face = sMesh.mFaces[faceIdx]; + const ASE::Face &face = sMesh.mFaces[faceIdx]; if (index == face.mIndices[0]) index = 0; else if (index == face.mIndices[1]) index = 1; else if (index == face.mIndices[2]) index = 2; - else { + else { ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); continue; } // We'll renormalize later - sMesh.mNormals[faceIdx*3+index] += vNormal; + sMesh.mNormals[faceIdx * 3 + index] += vNormal; continue; } - if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) { + if (TokenMatch(filePtr, "MESH_FACENORMAL", 15)) { aiVector3D vNormal; - ParseLV4MeshFloatTriple(&vNormal.x,faceIdx); + ParseLV4MeshFloatTriple(&vNormal.x, faceIdx); if (faceIdx >= sMesh.mFaces.size()) { ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section"); @@ -1934,53 +1663,47 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) } // We'll renormalize later - sMesh.mNormals[faceIdx*3] += vNormal; - sMesh.mNormals[faceIdx*3+1] += vNormal; - sMesh.mNormals[faceIdx*3+2] += vNormal; + sMesh.mNormals[faceIdx * 3] += vNormal; + sMesh.mNormals[faceIdx * 3 + 1] += vNormal; + sMesh.mNormals[faceIdx * 3 + 2] += vNormal; continue; } } - AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS"); + AI_ASE_HANDLE_SECTION("3", "*MESH_NORMALS"); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFace(ASE::Face& out) -{ +void Parser::ParseLV4MeshFace(ASE::Face &out) { // skip spaces and tabs - if(!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]"); SkipToNextToken(); return; } // parse the face index - out.iFace = strtoul10(filePtr,&filePtr); + out.iFace = strtoul10(filePtr, &filePtr); // next character should be ':' - if(!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { // FIX: there are some ASE files which haven't got : here .... LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]"); SkipToNextToken(); return; } // FIX: There are some ASE files which haven't got ':' here - if(':' == *filePtr)++filePtr; + if (':' == *filePtr) ++filePtr; // Parse all mesh indices - for (unsigned int i = 0; i < 3;++i) - { + for (unsigned int i = 0; i < 3; ++i) { unsigned int iIndex = 0; - if(!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL"); SkipToNextToken(); return; } - switch (*filePtr) - { + switch (*filePtr) { case 'A': case 'a': break; @@ -1994,38 +1717,34 @@ void Parser::ParseLV4MeshFace(ASE::Face& out) break; default: LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " - "A,B or C expected [#3]"); + "A,B or C expected [#3]"); SkipToNextToken(); return; }; ++filePtr; // next character should be ':' - if(!SkipSpaces(&filePtr) || ':' != *filePtr) - { + if (!SkipSpaces(&filePtr) || ':' != *filePtr) { LogWarning("Unable to parse *MESH_FACE Element: " - "Unexpected EOL. \':\' expected [#2]"); + "Unexpected EOL. \':\' expected [#2]"); SkipToNextToken(); return; } ++filePtr; - if(!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " - "Vertex index ecpected [#4]"); + "Vertex index ecpected [#4]"); SkipToNextToken(); return; } - out.mIndices[iIndex] = strtoul10(filePtr,&filePtr); + out.mIndices[iIndex] = strtoul10(filePtr, &filePtr); } // now we need to skip the AB, BC, CA blocks. - while (true) - { - if ('*' == *filePtr)break; - if (IsLineEnd(*filePtr)) - { + while (true) { + if ('*' == *filePtr) break; + if (IsLineEnd(*filePtr)) { //iLineNumber++; return; } @@ -2033,27 +1752,22 @@ void Parser::ParseLV4MeshFace(ASE::Face& out) } // parse the smoothing group of the face - if (TokenMatch(filePtr,"*MESH_SMOOTHING",15)) - { - if(!SkipSpaces(&filePtr)) - { + if (TokenMatch(filePtr, "*MESH_SMOOTHING", 15)) { + if (!SkipSpaces(&filePtr)) { LogWarning("Unable to parse *MESH_SMOOTHING Element: " - "Unexpected EOL. Smoothing group(s) expected [#5]"); + "Unexpected EOL. Smoothing group(s) expected [#5]"); SkipToNextToken(); return; } // Parse smoothing groups until we don't anymore see commas // FIX: There needn't always be a value, sad but true - while (true) - { - if (*filePtr < '9' && *filePtr >= '0') - { - out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr)); + while (true) { + if (*filePtr < '9' && *filePtr >= '0') { + out.iSmoothGroup |= (1 << strtoul10(filePtr, &filePtr)); } SkipSpaces(&filePtr); - if (',' != *filePtr) - { + if (',' != *filePtr) { break; } ++filePtr; @@ -2062,40 +1776,34 @@ void Parser::ParseLV4MeshFace(ASE::Face& out) } // *MESH_MTLID is optional, too - while (true) - { - if ('*' == *filePtr)break; - if (IsLineEnd(*filePtr)) - { + while (true) { + if ('*' == *filePtr) break; + if (IsLineEnd(*filePtr)) { return; } filePtr++; } - if (TokenMatch(filePtr,"*MESH_MTLID",11)) - { - if(!SkipSpaces(&filePtr)) - { + if (TokenMatch(filePtr, "*MESH_MTLID", 11)) { + if (!SkipSpaces(&filePtr)) { LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. " - "Material index expected [#6]"); + "Material index expected [#6]"); SkipToNextToken(); return; } - out.iMaterial = strtoul10(filePtr,&filePtr); + out.iMaterial = strtoul10(filePtr, &filePtr); } return; } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshLongTriple(unsigned int* apOut) -{ +void Parser::ParseLV4MeshLongTriple(unsigned int *apOut) { ai_assert(NULL != apOut); - for (unsigned int i = 0; i < 3;++i) + for (unsigned int i = 0; i < 3; ++i) ParseLV4MeshLong(apOut[i]); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut) -{ +void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut) { ai_assert(NULL != apOut); // parse the index @@ -2105,8 +1813,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut ParseLV4MeshLongTriple(apOut); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut) -{ +void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) { ai_assert(NULL != apOut); // parse the index @@ -2116,19 +1823,16 @@ void Parser::ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut) ParseLV4MeshFloatTriple(apOut); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloatTriple(ai_real* apOut) -{ +void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) { ai_assert(NULL != apOut); - for (unsigned int i = 0; i < 3;++i) + for (unsigned int i = 0; i < 3; ++i) ParseLV4MeshFloat(apOut[i]); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloat(ai_real& fOut) -{ +void Parser::ParseLV4MeshFloat(ai_real &fOut) { // skip spaces and tabs - if(!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { // LOG LogWarning("Unable to parse float: unexpected EOL [#1]"); fOut = 0.0; @@ -2136,14 +1840,12 @@ void Parser::ParseLV4MeshFloat(ai_real& fOut) return; } // parse the first float - filePtr = fast_atoreal_move(filePtr,fOut); + filePtr = fast_atoreal_move(filePtr, fOut); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshLong(unsigned int& iOut) -{ +void Parser::ParseLV4MeshLong(unsigned int &iOut) { // Skip spaces and tabs - if(!SkipSpaces(&filePtr)) - { + if (!SkipSpaces(&filePtr)) { // LOG LogWarning("Unable to parse long: unexpected EOL [#1]"); iOut = 0; @@ -2151,7 +1853,7 @@ void Parser::ParseLV4MeshLong(unsigned int& iOut) return; } // parse the value - iOut = strtoul10(filePtr,&filePtr); + iOut = strtoul10(filePtr, &filePtr); } #endif // ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/code/ASE/ASEParser.h b/code/AssetLib/ASE/ASEParser.h similarity index 99% rename from code/ASE/ASEParser.h rename to code/AssetLib/ASE/ASEParser.h index aba37d38f..c94c8e3aa 100644 --- a/code/ASE/ASEParser.h +++ b/code/AssetLib/ASE/ASEParser.h @@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // ASE is quite similar to 3ds. We can reuse some structures -#include "3DS/3DSLoader.h" +#include "AssetLib/3DS/3DSLoader.h" namespace Assimp { namespace ASE { diff --git a/code/Assbin/AssbinExporter.cpp b/code/AssetLib/Assbin/AssbinExporter.cpp similarity index 99% rename from code/Assbin/AssbinExporter.cpp rename to code/AssetLib/Assbin/AssbinExporter.cpp index 0b99afbda..e86a6526d 100644 --- a/code/Assbin/AssbinExporter.cpp +++ b/code/AssetLib/Assbin/AssbinExporter.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Assbin/AssbinExporter.h b/code/AssetLib/Assbin/AssbinExporter.h similarity index 100% rename from code/Assbin/AssbinExporter.h rename to code/AssetLib/Assbin/AssbinExporter.h diff --git a/code/Assbin/AssbinFileWriter.cpp b/code/AssetLib/Assbin/AssbinFileWriter.cpp similarity index 96% rename from code/Assbin/AssbinFileWriter.cpp rename to code/AssetLib/Assbin/AssbinFileWriter.cpp index 7fceaa1ad..431be4d3a 100644 --- a/code/Assbin/AssbinFileWriter.cpp +++ b/code/AssetLib/Assbin/AssbinFileWriter.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -54,16 +53,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include +#include #else -# include "../contrib/zlib/zlib.h" +#include "../contrib/zlib/zlib.h" #endif #include #ifdef _WIN32 -# pragma warning(push) -# pragma warning(disable : 4706) +#pragma warning(push) +#pragma warning(disable : 4706) #endif // _WIN32 namespace Assimp { @@ -269,7 +268,7 @@ private: public: AssbinChunkWriter(IOStream *container, uint32_t magic, size_t initial = 4096) : - buffer(NULL), + buffer(nullptr), magic(magic), container(container), cur_size(0), @@ -362,32 +361,32 @@ protected: Write(&chunk, (uint16_t)type); switch (type) { - case AI_BOOL: - Write(&chunk, *((bool *)value)); - break; - case AI_INT32: - Write(&chunk, *((int32_t *)value)); - break; - case AI_UINT64: - Write(&chunk, *((uint64_t *)value)); - break; - case AI_FLOAT: - Write(&chunk, *((float *)value)); - break; - case AI_DOUBLE: - Write(&chunk, *((double *)value)); - break; - case AI_AISTRING: - Write(&chunk, *((aiString *)value)); - break; - case AI_AIVECTOR3D: - Write(&chunk, *((aiVector3D *)value)); - break; + case AI_BOOL: + Write(&chunk, *((bool *)value)); + break; + case AI_INT32: + Write(&chunk, *((int32_t *)value)); + break; + case AI_UINT64: + Write(&chunk, *((uint64_t *)value)); + break; + case AI_FLOAT: + Write(&chunk, *((float *)value)); + break; + case AI_DOUBLE: + Write(&chunk, *((double *)value)); + break; + case AI_AISTRING: + Write(&chunk, *((aiString *)value)); + break; + case AI_AIVECTOR3D: + Write(&chunk, *((aiVector3D *)value)); + break; #ifdef SWIG case FORCE_32BIT: #endif // SWIG - default: - break; + default: + break; } } } @@ -827,7 +826,7 @@ void DumpSceneToAssbin( fileWriter.WriteBinaryDump(pFile, cmd, pIOSystem, pScene); } #ifdef _WIN32 -# pragma warning(pop) +#pragma warning(pop) #endif // _WIN32 } // end of namespace Assimp diff --git a/code/Assbin/AssbinFileWriter.h b/code/AssetLib/Assbin/AssbinFileWriter.h similarity index 92% rename from code/Assbin/AssbinFileWriter.h rename to code/AssetLib/Assbin/AssbinFileWriter.h index 25db6db2d..25cbc8106 100644 --- a/code/Assbin/AssbinFileWriter.h +++ b/code/AssetLib/Assbin/AssbinFileWriter.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -54,12 +53,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { void ASSIMP_API DumpSceneToAssbin( - const char* pFile, - const char* cmd, - IOSystem* pIOSystem, - const aiScene* pScene, - bool shortened, - bool compressed); + const char *pFile, + const char *cmd, + IOSystem *pIOSystem, + const aiScene *pScene, + bool shortened, + bool compressed); } diff --git a/code/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp similarity index 96% rename from code/Assbin/AssbinLoader.cpp rename to code/AssetLib/Assbin/AssbinLoader.cpp index 4293cae29..5ee87e952 100644 --- a/code/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER // internal headers -#include "Assbin/AssbinLoader.h" +#include "AssetLib/Assbin/AssbinLoader.h" #include "Common/assbin_chunks.h" #include #include @@ -253,32 +253,32 @@ void AssbinImporter::ReadBinaryNode(IOStream *stream, aiNode **onode, aiNode *pa void *data = nullptr; switch (node->mMetaData->mValues[i].mType) { - case AI_BOOL: - data = new bool(Read(stream)); - break; - case AI_INT32: - data = new int32_t(Read(stream)); - break; - case AI_UINT64: - data = new uint64_t(Read(stream)); - break; - case AI_FLOAT: - data = new ai_real(Read(stream)); - break; - case AI_DOUBLE: - data = new double(Read(stream)); - break; - case AI_AISTRING: - data = new aiString(Read(stream)); - break; - case AI_AIVECTOR3D: - data = new aiVector3D(Read(stream)); - break; + case AI_BOOL: + data = new bool(Read(stream)); + break; + case AI_INT32: + data = new int32_t(Read(stream)); + break; + case AI_UINT64: + data = new uint64_t(Read(stream)); + break; + case AI_FLOAT: + data = new ai_real(Read(stream)); + break; + case AI_DOUBLE: + data = new double(Read(stream)); + break; + case AI_AISTRING: + data = new aiString(Read(stream)); + break; + case AI_AIVECTOR3D: + data = new aiVector3D(Read(stream)); + break; #ifndef SWIG - case FORCE_32BIT: + case FORCE_32BIT: #endif // SWIG - default: - break; + default: + break; } node->mMetaData->mValues[i].mData = data; diff --git a/code/Assbin/AssbinLoader.h b/code/AssetLib/Assbin/AssbinLoader.h similarity index 100% rename from code/Assbin/AssbinLoader.h rename to code/AssetLib/Assbin/AssbinLoader.h diff --git a/code/Assjson/cencode.c b/code/AssetLib/Assjson/cencode.c similarity index 100% rename from code/Assjson/cencode.c rename to code/AssetLib/Assjson/cencode.c diff --git a/code/Assjson/cencode.h b/code/AssetLib/Assjson/cencode.h similarity index 100% rename from code/Assjson/cencode.h rename to code/AssetLib/Assjson/cencode.h diff --git a/code/Assjson/json_exporter.cpp b/code/AssetLib/Assjson/json_exporter.cpp similarity index 100% rename from code/Assjson/json_exporter.cpp rename to code/AssetLib/Assjson/json_exporter.cpp diff --git a/code/Assjson/mesh_splitter.cpp b/code/AssetLib/Assjson/mesh_splitter.cpp similarity index 100% rename from code/Assjson/mesh_splitter.cpp rename to code/AssetLib/Assjson/mesh_splitter.cpp diff --git a/code/Assjson/mesh_splitter.h b/code/AssetLib/Assjson/mesh_splitter.h similarity index 100% rename from code/Assjson/mesh_splitter.h rename to code/AssetLib/Assjson/mesh_splitter.h diff --git a/code/Assxml/AssxmlExporter.cpp b/code/AssetLib/Assxml/AssxmlExporter.cpp similarity index 100% rename from code/Assxml/AssxmlExporter.cpp rename to code/AssetLib/Assxml/AssxmlExporter.cpp diff --git a/code/Assxml/AssxmlExporter.h b/code/AssetLib/Assxml/AssxmlExporter.h similarity index 100% rename from code/Assxml/AssxmlExporter.h rename to code/AssetLib/Assxml/AssxmlExporter.h diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.cpp b/code/AssetLib/Assxml/AssxmlFileWriter.cpp new file mode 100644 index 000000000..b175265b5 --- /dev/null +++ b/code/AssetLib/Assxml/AssxmlFileWriter.cpp @@ -0,0 +1,659 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file AssxmlFileWriter.cpp + * @brief Implementation of Assxml file writer. + */ + +#include "AssxmlFileWriter.h" + +#include "PostProcessing/ProcessHelper.h" + +#include +#include +#include +#include + +#include + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include +#else +#include +#endif + +#include +#include +#include + +using namespace Assimp; + +namespace Assimp { + +namespace AssxmlFileWriter { + +// ----------------------------------------------------------------------------------- +static int ioprintf(IOStream *io, const char *format, ...) { + using namespace std; + if (nullptr == io) { + return -1; + } + + static const int Size = 4096; + char sz[Size]; + ::memset(sz, '\0', Size); + va_list va; + va_start(va, format); + const unsigned int nSize = vsnprintf(sz, Size - 1, format, va); + ai_assert(nSize < Size); + va_end(va); + + io->Write(sz, sizeof(char), nSize); + + return nSize; +} + +// ----------------------------------------------------------------------------------- +// Convert a name to standard XML format +static void ConvertName(aiString &out, const aiString &in) { + out.length = 0; + for (unsigned int i = 0; i < in.length; ++i) { + switch (in.data[i]) { + case '<': + out.Append("<"); + break; + case '>': + out.Append(">"); + break; + case '&': + out.Append("&"); + break; + case '\"': + out.Append("""); + break; + case '\'': + out.Append("'"); + break; + default: + out.data[out.length++] = in.data[i]; + } + } + out.data[out.length] = 0; +} + +// ----------------------------------------------------------------------------------- +// Write a single node as text dump +static void WriteNode(const aiNode *node, IOStream *io, unsigned int depth) { + char prefix[512]; + for (unsigned int i = 0; i < depth; ++i) + prefix[i] = '\t'; + prefix[depth] = '\0'; + + const aiMatrix4x4 &m = node->mTransformation; + + aiString name; + ConvertName(name, node->mName); + ioprintf(io, "%s \n" + "%s\t \n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t \n", + prefix, name.data, prefix, + prefix, m.a1, m.a2, m.a3, m.a4, + prefix, m.b1, m.b2, m.b3, m.b4, + prefix, m.c1, m.c2, m.c3, m.c4, + prefix, m.d1, m.d2, m.d3, m.d4, prefix); + + if (node->mNumMeshes) { + ioprintf(io, "%s\t\n%s\t", + prefix, node->mNumMeshes, prefix); + + for (unsigned int i = 0; i < node->mNumMeshes; ++i) { + ioprintf(io, "%u ", node->mMeshes[i]); + } + ioprintf(io, "\n%s\t\n", prefix); + } + + if (node->mNumChildren) { + ioprintf(io, "%s\t\n", + prefix, node->mNumChildren); + + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + WriteNode(node->mChildren[i], io, depth + 2); + } + ioprintf(io, "%s\t\n", prefix); + } + ioprintf(io, "%s\n", prefix); +} + +// ----------------------------------------------------------------------------------- +// Some chuncks of text will need to be encoded for XML +// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 +static std::string encodeXML(const std::string &data) { + std::string buffer; + buffer.reserve(data.size()); + for (size_t pos = 0; pos != data.size(); ++pos) { + switch (data[pos]) { + case '&': buffer.append("&"); break; + case '\"': buffer.append("""); break; + case '\'': buffer.append("'"); break; + case '<': buffer.append("<"); break; + case '>': buffer.append(">"); break; + default: buffer.append(&data[pos], 1); break; + } + } + return buffer; +} + +// ----------------------------------------------------------------------------------- +// Write a text model dump +static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, IOStream *io, bool shortened) { + time_t tt = ::time(NULL); +#if _WIN32 + tm *p = gmtime(&tt); +#else + struct tm now; + tm *p = gmtime_r(&tt, &now); +#endif + ai_assert(nullptr != p); + + std::string c = cmd; + std::string::size_type s; + + // https://sourceforge.net/tracker/?func=detail&aid=3167364&group_id=226462&atid=1067632 + // -- not allowed in XML comments + while ((s = c.find("--")) != std::string::npos) { + c[s] = '?'; + } + + // write header + std::string header( + "\n" + "\n\n" + "" + " \n\n" + "\n"); + + const unsigned int majorVersion(aiGetVersionMajor()); + const unsigned int minorVersion(aiGetVersionMinor()); + const unsigned int rev(aiGetVersionRevision()); + const char *curtime(asctime(p)); + ioprintf(io, header.c_str(), majorVersion, minorVersion, rev, pFile, c.c_str(), curtime, scene->mFlags, 0u); + + // write the node graph + WriteNode(scene->mRootNode, io, 0); + +#if 0 + // write cameras + for (unsigned int i = 0; i < scene->mNumCameras;++i) { + aiCamera* cam = scene->mCameras[i]; + ConvertName(name,cam->mName); + + // camera header + ioprintf(io,"\t\n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\n", + name.data, + cam->mUp.x,cam->mUp.y,cam->mUp.z, + cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, + cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, + cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); + } + + // write lights + for (unsigned int i = 0; i < scene->mNumLights;++i) { + aiLight* l = scene->mLights[i]; + ConvertName(name,l->mName); + + // light header + ioprintf(io,"\t type=\"%s\"\n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n", + name.data, + (l->mType == aiLightSource_DIRECTIONAL ? "directional" : + (l->mType == aiLightSource_POINT ? "point" : "spot" )), + l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, + l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, + l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); + + if (l->mType != aiLightSource_DIRECTIONAL) { + ioprintf(io, + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\t %f \n", + l->mPosition.x,l->mPosition.y,l->mPosition.z, + l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); + } + + if (l->mType != aiLightSource_POINT) { + ioprintf(io, + "\t\t %0 8f %0 8f %0 8f \n", + l->mDirection.x,l->mDirection.y,l->mDirection.z); + } + + if (l->mType == aiLightSource_SPOT) { + ioprintf(io, + "\t\t %f \n" + "\t\t %f \n", + l->mAngleOuterCone,l->mAngleInnerCone); + } + ioprintf(io,"\t\n"); + } +#endif + aiString name; + + // write textures + if (scene->mNumTextures) { + ioprintf(io, "\n", scene->mNumTextures); + for (unsigned int i = 0; i < scene->mNumTextures; ++i) { + aiTexture *tex = scene->mTextures[i]; + bool compressed = (tex->mHeight == 0); + + // mesh header + ioprintf(io, "\t \n", + (compressed ? -1 : tex->mWidth), (compressed ? -1 : tex->mHeight), + (compressed ? "true" : "false")); + + if (compressed) { + ioprintf(io, "\t\t \n", tex->mWidth); + + if (!shortened) { + for (unsigned int n = 0; n < tex->mWidth; ++n) { + ioprintf(io, "\t\t\t%2x", reinterpret_cast(tex->pcData)[n]); + if (n && !(n % 50)) { + ioprintf(io, "\n"); + } + } + } + } else if (!shortened) { + ioprintf(io, "\t\t \n", tex->mWidth * tex->mHeight * 4); + + // const unsigned int width = (unsigned int)std::log10((double)std::max(tex->mHeight,tex->mWidth))+1; + for (unsigned int y = 0; y < tex->mHeight; ++y) { + for (unsigned int x = 0; x < tex->mWidth; ++x) { + aiTexel *tx = tex->pcData + y * tex->mWidth + x; + unsigned int r = tx->r, g = tx->g, b = tx->b, a = tx->a; + ioprintf(io, "\t\t\t%2x %2x %2x %2x", r, g, b, a); + + // group by four for readability + if (0 == (x + y * tex->mWidth) % 4) { + ioprintf(io, "\n"); + } + } + } + } + ioprintf(io, "\t\t\n\t\n"); + } + ioprintf(io, "\n"); + } + + // write materials + if (scene->mNumMaterials) { + ioprintf(io, "\n", scene->mNumMaterials); + for (unsigned int i = 0; i < scene->mNumMaterials; ++i) { + const aiMaterial *mat = scene->mMaterials[i]; + + ioprintf(io, "\t\n"); + ioprintf(io, "\t\t\n", mat->mNumProperties); + for (unsigned int n = 0; n < mat->mNumProperties; ++n) { + + const aiMaterialProperty *prop = mat->mProperties[n]; + const char *sz = ""; + if (prop->mType == aiPTI_Float) { + sz = "float"; + } else if (prop->mType == aiPTI_Integer) { + sz = "integer"; + } else if (prop->mType == aiPTI_String) { + sz = "string"; + } else if (prop->mType == aiPTI_Buffer) { + sz = "binary_buffer"; + } + + ioprintf(io, "\t\t\tmKey.data, sz, + ::TextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex); + + if (prop->mType == aiPTI_Float) { + ioprintf(io, " size=\"%i\">\n\t\t\t\t", + static_cast(prop->mDataLength / sizeof(float))); + + for (unsigned int pp = 0; pp < prop->mDataLength / sizeof(float); ++pp) { + ioprintf(io, "%f ", *((float *)(prop->mData + pp * sizeof(float)))); + } + } else if (prop->mType == aiPTI_Integer) { + ioprintf(io, " size=\"%i\">\n\t\t\t\t", + static_cast(prop->mDataLength / sizeof(int))); + + for (unsigned int pp = 0; pp < prop->mDataLength / sizeof(int); ++pp) { + ioprintf(io, "%i ", *((int *)(prop->mData + pp * sizeof(int)))); + } + } else if (prop->mType == aiPTI_Buffer) { + ioprintf(io, " size=\"%i\">\n\t\t\t\t", + static_cast(prop->mDataLength)); + + for (unsigned int pp = 0; pp < prop->mDataLength; ++pp) { + ioprintf(io, "%2x ", prop->mData[pp]); + if (pp && 0 == pp % 30) { + ioprintf(io, "\n\t\t\t\t"); + } + } + } else if (prop->mType == aiPTI_String) { + ioprintf(io, ">\n\t\t\t\t\"%s\"", encodeXML(prop->mData + 4).c_str() /* skip length */); + } + ioprintf(io, "\n\t\t\t\n"); + } + ioprintf(io, "\t\t\n"); + ioprintf(io, "\t\n"); + } + ioprintf(io, "\n"); + } + + // write animations + if (scene->mNumAnimations) { + ioprintf(io, "\n", scene->mNumAnimations); + for (unsigned int i = 0; i < scene->mNumAnimations; ++i) { + aiAnimation *anim = scene->mAnimations[i]; + + // anim header + ConvertName(name, anim->mName); + ioprintf(io, "\t\n", + name.data, anim->mDuration, anim->mTicksPerSecond); + + // write bone animation channels + if (anim->mNumChannels) { + ioprintf(io, "\t\t\n", anim->mNumChannels); + for (unsigned int n = 0; n < anim->mNumChannels; ++n) { + aiNodeAnim *nd = anim->mChannels[n]; + + // node anim header + ConvertName(name, nd->mNodeName); + ioprintf(io, "\t\t\t\n", name.data); + + if (!shortened) { + // write position keys + if (nd->mNumPositionKeys) { + ioprintf(io, "\t\t\t\t\n", nd->mNumPositionKeys); + for (unsigned int a = 0; a < nd->mNumPositionKeys; ++a) { + aiVectorKey *vc = nd->mPositionKeys + a; + ioprintf(io, "\t\t\t\t\t\n" + "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", + vc->mTime, vc->mValue.x, vc->mValue.y, vc->mValue.z); + } + ioprintf(io, "\t\t\t\t\n"); + } + + // write scaling keys + if (nd->mNumScalingKeys) { + ioprintf(io, "\t\t\t\t\n", nd->mNumScalingKeys); + for (unsigned int a = 0; a < nd->mNumScalingKeys; ++a) { + aiVectorKey *vc = nd->mScalingKeys + a; + ioprintf(io, "\t\t\t\t\t\n" + "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", + vc->mTime, vc->mValue.x, vc->mValue.y, vc->mValue.z); + } + ioprintf(io, "\t\t\t\t\n"); + } + + // write rotation keys + if (nd->mNumRotationKeys) { + ioprintf(io, "\t\t\t\t\n", nd->mNumRotationKeys); + for (unsigned int a = 0; a < nd->mNumRotationKeys; ++a) { + aiQuatKey *vc = nd->mRotationKeys + a; + ioprintf(io, "\t\t\t\t\t\n" + "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t\n", + vc->mTime, vc->mValue.x, vc->mValue.y, vc->mValue.z, vc->mValue.w); + } + ioprintf(io, "\t\t\t\t\n"); + } + } + ioprintf(io, "\t\t\t\n"); + } + ioprintf(io, "\t\t\n"); + } + ioprintf(io, "\t\n"); + } + ioprintf(io, "\n"); + } + + // write meshes + if (scene->mNumMeshes) { + ioprintf(io, "\n", scene->mNumMeshes); + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) { + aiMesh *mesh = scene->mMeshes[i]; + // const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1; + + // mesh header + ioprintf(io, "\t\n", + (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), + (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), + (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), + (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), + mesh->mMaterialIndex); + + // bones + if (mesh->mNumBones) { + ioprintf(io, "\t\t\n", mesh->mNumBones); + + for (unsigned int n = 0; n < mesh->mNumBones; ++n) { + aiBone *bone = mesh->mBones[n]; + + ConvertName(name, bone->mName); + // bone header + ioprintf(io, "\t\t\t\n" + "\t\t\t\t \n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t \n", + name.data, + bone->mOffsetMatrix.a1, bone->mOffsetMatrix.a2, bone->mOffsetMatrix.a3, bone->mOffsetMatrix.a4, + bone->mOffsetMatrix.b1, bone->mOffsetMatrix.b2, bone->mOffsetMatrix.b3, bone->mOffsetMatrix.b4, + bone->mOffsetMatrix.c1, bone->mOffsetMatrix.c2, bone->mOffsetMatrix.c3, bone->mOffsetMatrix.c4, + bone->mOffsetMatrix.d1, bone->mOffsetMatrix.d2, bone->mOffsetMatrix.d3, bone->mOffsetMatrix.d4); + + if (!shortened && bone->mNumWeights) { + ioprintf(io, "\t\t\t\t\n", bone->mNumWeights); + + // bone weights + for (unsigned int a = 0; a < bone->mNumWeights; ++a) { + aiVertexWeight *wght = bone->mWeights + a; + + ioprintf(io, "\t\t\t\t\t\n\t\t\t\t\t\t%f\n\t\t\t\t\t\n", + wght->mVertexId, wght->mWeight); + } + ioprintf(io, "\t\t\t\t\n"); + } + ioprintf(io, "\t\t\t\n"); + } + ioprintf(io, "\t\t\n"); + } + + // faces + if (!shortened && mesh->mNumFaces) { + ioprintf(io, "\t\t\n", mesh->mNumFaces); + for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { + aiFace &f = mesh->mFaces[n]; + ioprintf(io, "\t\t\t\n" + "\t\t\t\t", + f.mNumIndices); + + for (unsigned int j = 0; j < f.mNumIndices; ++j) + ioprintf(io, "%u ", f.mIndices[j]); + + ioprintf(io, "\n\t\t\t\n"); + } + ioprintf(io, "\t\t\n"); + } + + // vertex positions + if (mesh->HasPositions()) { + ioprintf(io, "\t\t \n", mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f %0 8f\n", + mesh->mVertices[n].x, + mesh->mVertices[n].y, + mesh->mVertices[n].z); + } + } + ioprintf(io, "\t\t\n"); + } + + // vertex normals + if (mesh->HasNormals()) { + ioprintf(io, "\t\t \n", mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f %0 8f\n", + mesh->mNormals[n].x, + mesh->mNormals[n].y, + mesh->mNormals[n].z); + } + } + ioprintf(io, "\t\t\n"); + } + + // vertex tangents and bitangents + if (mesh->HasTangentsAndBitangents()) { + ioprintf(io, "\t\t \n", mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f %0 8f\n", + mesh->mTangents[n].x, + mesh->mTangents[n].y, + mesh->mTangents[n].z); + } + } + ioprintf(io, "\t\t\n"); + + ioprintf(io, "\t\t \n", mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f %0 8f\n", + mesh->mBitangents[n].x, + mesh->mBitangents[n].y, + mesh->mBitangents[n].z); + } + } + ioprintf(io, "\t\t\n"); + } + + // texture coordinates + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (!mesh->mTextureCoords[a]) + break; + + ioprintf(io, "\t\t \n", mesh->mNumVertices, + a, mesh->mNumUVComponents[a]); + + if (!shortened) { + if (mesh->mNumUVComponents[a] == 3) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f %0 8f\n", + mesh->mTextureCoords[a][n].x, + mesh->mTextureCoords[a][n].y, + mesh->mTextureCoords[a][n].z); + } + } else { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f\n", + mesh->mTextureCoords[a][n].x, + mesh->mTextureCoords[a][n].y); + } + } + } + ioprintf(io, "\t\t\n"); + } + + // vertex colors + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { + if (!mesh->mColors[a]) + break; + ioprintf(io, "\t\t \n", mesh->mNumVertices, a); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io, "\t\t%0 8f %0 8f %0 8f %0 8f\n", + mesh->mColors[a][n].r, + mesh->mColors[a][n].g, + mesh->mColors[a][n].b, + mesh->mColors[a][n].a); + } + } + ioprintf(io, "\t\t\n"); + } + ioprintf(io, "\t\n"); + } + ioprintf(io, "\n"); + } + ioprintf(io, "\n"); +} + +} // end of namespace AssxmlFileWriter + +void DumpSceneToAssxml( + const char *pFile, const char *cmd, IOSystem *pIOSystem, + const aiScene *pScene, bool shortened) { + std::unique_ptr file(pIOSystem->Open(pFile, "wt")); + if (!file.get()) { + throw std::runtime_error("Unable to open output file " + std::string(pFile) + '\n'); + } + + AssxmlFileWriter::WriteDump(pFile, cmd, pScene, file.get(), shortened); +} + +} // end of namespace Assimp diff --git a/code/Assxml/AssxmlFileWriter.h b/code/AssetLib/Assxml/AssxmlFileWriter.h similarity index 100% rename from code/Assxml/AssxmlFileWriter.h rename to code/AssetLib/Assxml/AssxmlFileWriter.h diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp new file mode 100644 index 000000000..ff595aaf1 --- /dev/null +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -0,0 +1,744 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file B3DImporter.cpp + * @brief Implementation of the b3d importer class + */ + +#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER + +// internal headers +#include "AssetLib/B3D/B3DImporter.h" +#include "PostProcessing/ConvertToLHProcess.h" +#include "PostProcessing/TextureTransform.h" + +#include +#include +#include +#include +#include +#include + +#include + +using namespace Assimp; +using namespace std; + +static const aiImporterDesc desc = { + "BlitzBasic 3D Importer", + "", + "", + "http://www.blitzbasic.com/", + aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "b3d" +}; + +#ifdef _MSC_VER +#pragma warning(disable : 4018) +#endif + +//#define DEBUG_B3D + +template +void DeleteAllBarePointers(std::vector &x) { + for (auto p : x) { + delete p; + } +} + +B3DImporter::~B3DImporter() { +} + +// ------------------------------------------------------------------------------------------------ +bool B3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + + size_t pos = pFile.find_last_of('.'); + if (pos == string::npos) { + return false; + } + + string ext = pFile.substr(pos + 1); + if (ext.size() != 3) { + return false; + } + + return (ext[0] == 'b' || ext[0] == 'B') && (ext[1] == '3') && (ext[2] == 'd' || ext[2] == 'D'); +} + +// ------------------------------------------------------------------------------------------------ +// Loader meta information +const aiImporterDesc *B3DImporter::GetInfo() const { + return &desc; +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile)); + + // Check whether we can read from the file + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open B3D file " + pFile + "."); + } + + // check whether the .b3d file is large enough to contain + // at least one chunk. + size_t fileSize = file->FileSize(); + if (fileSize < 8) { + throw DeadlyImportError("B3D File is too small."); + } + + _pos = 0; + _buf.resize(fileSize); + file->Read(&_buf[0], 1, fileSize); + _stack.clear(); + + ReadBB3D(pScene); +} + +// ------------------------------------------------------------------------------------------------ +AI_WONT_RETURN void B3DImporter::Oops() { + throw DeadlyImportError("B3D Importer - INTERNAL ERROR"); +} + +// ------------------------------------------------------------------------------------------------ +AI_WONT_RETURN void B3DImporter::Fail(string str) { +#ifdef DEBUG_B3D + ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str); +#endif + throw DeadlyImportError("B3D Importer - error in B3D file data: " + str); +} + +// ------------------------------------------------------------------------------------------------ +int B3DImporter::ReadByte() { + if (_pos > _buf.size()) { + Fail("EOF"); + } + + return _buf[_pos++]; +} + +// ------------------------------------------------------------------------------------------------ +int B3DImporter::ReadInt() { + if (_pos + 4 > _buf.size()) { + Fail("EOF"); + } + + int n; + memcpy(&n, &_buf[_pos], 4); + _pos += 4; + + return n; +} + +// ------------------------------------------------------------------------------------------------ +float B3DImporter::ReadFloat() { + if (_pos + 4 > _buf.size()) { + Fail("EOF"); + } + + float n; + memcpy(&n, &_buf[_pos], 4); + _pos += 4; + + return n; +} + +// ------------------------------------------------------------------------------------------------ +aiVector2D B3DImporter::ReadVec2() { + float x = ReadFloat(); + float y = ReadFloat(); + return aiVector2D(x, y); +} + +// ------------------------------------------------------------------------------------------------ +aiVector3D B3DImporter::ReadVec3() { + float x = ReadFloat(); + float y = ReadFloat(); + float z = ReadFloat(); + return aiVector3D(x, y, z); +} + +// ------------------------------------------------------------------------------------------------ +aiQuaternion B3DImporter::ReadQuat() { + // (aramis_acg) Fix to adapt the loader to changed quat orientation + float w = -ReadFloat(); + float x = ReadFloat(); + float y = ReadFloat(); + float z = ReadFloat(); + return aiQuaternion(w, x, y, z); +} + +// ------------------------------------------------------------------------------------------------ +string B3DImporter::ReadString() { + if (_pos > _buf.size()) { + Fail("EOF"); + } + string str; + while (_pos < _buf.size()) { + char c = (char)ReadByte(); + if (!c) { + return str; + } + str += c; + } + return string(); +} + +// ------------------------------------------------------------------------------------------------ +string B3DImporter::ReadChunk() { + string tag; + for (int i = 0; i < 4; ++i) { + tag += char(ReadByte()); + } +#ifdef DEBUG_B3D + ASSIMP_LOG_DEBUG_F("ReadChunk: ", tag); +#endif + unsigned sz = (unsigned)ReadInt(); + _stack.push_back(_pos + sz); + return tag; +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ExitChunk() { + _pos = _stack.back(); + _stack.pop_back(); +} + +// ------------------------------------------------------------------------------------------------ +size_t B3DImporter::ChunkSize() { + return _stack.back() - _pos; +} +// ------------------------------------------------------------------------------------------------ + +template +T *B3DImporter::to_array(const vector &v) { + if (v.empty()) { + return 0; + } + T *p = new T[v.size()]; + for (size_t i = 0; i < v.size(); ++i) { + p[i] = v[i]; + } + return p; +} + +// ------------------------------------------------------------------------------------------------ +template +T **unique_to_array(vector> &v) { + if (v.empty()) { + return 0; + } + T **p = new T *[v.size()]; + for (size_t i = 0; i < v.size(); ++i) { + p[i] = v[i].release(); + } + return p; +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadTEXS() { + while (ChunkSize()) { + string name = ReadString(); + /*int flags=*/ReadInt(); + /*int blend=*/ReadInt(); + /*aiVector2D pos=*/ReadVec2(); + /*aiVector2D scale=*/ReadVec2(); + /*float rot=*/ReadFloat(); + + _textures.push_back(name); + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadBRUS() { + int n_texs = ReadInt(); + if (n_texs < 0 || n_texs > 8) { + Fail("Bad texture count"); + } + while (ChunkSize()) { + string name = ReadString(); + aiVector3D color = ReadVec3(); + float alpha = ReadFloat(); + float shiny = ReadFloat(); + /*int blend=**/ ReadInt(); + int fx = ReadInt(); + + std::unique_ptr mat(new aiMaterial); + + // Name + aiString ainame(name); + mat->AddProperty(&ainame, AI_MATKEY_NAME); + + // Diffuse color + mat->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE); + + // Opacity + mat->AddProperty(&alpha, 1, AI_MATKEY_OPACITY); + + // Specular color + aiColor3D speccolor(shiny, shiny, shiny); + mat->AddProperty(&speccolor, 1, AI_MATKEY_COLOR_SPECULAR); + + // Specular power + float specpow = shiny * 128; + mat->AddProperty(&specpow, 1, AI_MATKEY_SHININESS); + + // Double sided + if (fx & 0x10) { + int i = 1; + mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED); + } + + //Textures + for (int i = 0; i < n_texs; ++i) { + int texid = ReadInt(); + if (texid < -1 || (texid >= 0 && texid >= static_cast(_textures.size()))) { + Fail("Bad texture id"); + } + if (i == 0 && texid >= 0) { + aiString texname(_textures[texid]); + mat->AddProperty(&texname, AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + } + _materials.emplace_back(std::move(mat)); + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadVRTS() { + _vflags = ReadInt(); + _tcsets = ReadInt(); + _tcsize = ReadInt(); + if (_tcsets < 0 || _tcsets > 4 || _tcsize < 0 || _tcsize > 4) { + Fail("Bad texcoord data"); + } + + int sz = 12 + (_vflags & 1 ? 12 : 0) + (_vflags & 2 ? 16 : 0) + (_tcsets * _tcsize * 4); + size_t n_verts = ChunkSize() / sz; + + int v0 = static_cast(_vertices.size()); + _vertices.resize(v0 + n_verts); + + for (unsigned int i = 0; i < n_verts; ++i) { + Vertex &v = _vertices[v0 + i]; + + memset(v.bones, 0, sizeof(v.bones)); + memset(v.weights, 0, sizeof(v.weights)); + + v.vertex = ReadVec3(); + + if (_vflags & 1) { + v.normal = ReadVec3(); + } + + if (_vflags & 2) { + ReadQuat(); //skip v 4bytes... + } + + for (int j = 0; j < _tcsets; ++j) { + float t[4] = { 0, 0, 0, 0 }; + for (int k = 0; k < _tcsize; ++k) { + t[k] = ReadFloat(); + } + t[1] = 1 - t[1]; + if (!j) { + v.texcoords = aiVector3D(t[0], t[1], t[2]); + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadTRIS(int v0) { + int matid = ReadInt(); + if (matid == -1) { + matid = 0; + } else if (matid < 0 || matid >= (int)_materials.size()) { +#ifdef DEBUG_B3D + ASSIMP_LOG_ERROR_F("material id=", matid); +#endif + Fail("Bad material id"); + } + + std::unique_ptr mesh(new aiMesh); + + mesh->mMaterialIndex = matid; + mesh->mNumFaces = 0; + mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + size_t n_tris = ChunkSize() / 12; + aiFace *face = mesh->mFaces = new aiFace[n_tris]; + + for (unsigned int i = 0; i < n_tris; ++i) { + int i0 = ReadInt() + v0; + int i1 = ReadInt() + v0; + int i2 = ReadInt() + v0; + if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { +#ifdef DEBUG_B3D + ASSIMP_LOG_ERROR_F("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2); +#endif + Fail("Bad triangle index"); + continue; + } + face->mNumIndices = 3; + face->mIndices = new unsigned[3]; + face->mIndices[0] = i0; + face->mIndices[1] = i1; + face->mIndices[2] = i2; + ++mesh->mNumFaces; + ++face; + } + + _meshes.emplace_back(std::move(mesh)); +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadMESH() { + /*int matid=*/ReadInt(); + + int v0 = static_cast(_vertices.size()); + + while (ChunkSize()) { + string t = ReadChunk(); + if (t == "VRTS") { + ReadVRTS(); + } else if (t == "TRIS") { + ReadTRIS(v0); + } + ExitChunk(); + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadBONE(int id) { + while (ChunkSize()) { + int vertex = ReadInt(); + float weight = ReadFloat(); + if (vertex < 0 || vertex >= (int)_vertices.size()) { + Fail("Bad vertex index"); + } + + Vertex &v = _vertices[vertex]; + for (int i = 0; i < 4; ++i) { + if (!v.weights[i]) { + v.bones[i] = static_cast(id); + v.weights[i] = weight; + break; + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadKEYS(aiNodeAnim *nodeAnim) { + vector trans, scale; + vector rot; + int flags = ReadInt(); + while (ChunkSize()) { + int frame = ReadInt(); + if (flags & 1) { + trans.push_back(aiVectorKey(frame, ReadVec3())); + } + if (flags & 2) { + scale.push_back(aiVectorKey(frame, ReadVec3())); + } + if (flags & 4) { + rot.push_back(aiQuatKey(frame, ReadQuat())); + } + } + + if (flags & 1) { + nodeAnim->mNumPositionKeys = static_cast(trans.size()); + nodeAnim->mPositionKeys = to_array(trans); + } + + if (flags & 2) { + nodeAnim->mNumScalingKeys = static_cast(scale.size()); + nodeAnim->mScalingKeys = to_array(scale); + } + + if (flags & 4) { + nodeAnim->mNumRotationKeys = static_cast(rot.size()); + nodeAnim->mRotationKeys = to_array(rot); + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadANIM() { + /*int flags=*/ReadInt(); + int frames = ReadInt(); + float fps = ReadFloat(); + + std::unique_ptr anim(new aiAnimation); + + anim->mDuration = frames; + anim->mTicksPerSecond = fps; + _animations.emplace_back(std::move(anim)); +} + +// ------------------------------------------------------------------------------------------------ +aiNode *B3DImporter::ReadNODE(aiNode *parent) { + + string name = ReadString(); + aiVector3D t = ReadVec3(); + aiVector3D s = ReadVec3(); + aiQuaternion r = ReadQuat(); + + aiMatrix4x4 trans, scale, rot; + + aiMatrix4x4::Translation(t, trans); + aiMatrix4x4::Scaling(s, scale); + rot = aiMatrix4x4(r.GetMatrix()); + + aiMatrix4x4 tform = trans * rot * scale; + + int nodeid = static_cast(_nodes.size()); + + aiNode *node = new aiNode(name); + _nodes.push_back(node); + + node->mParent = parent; + node->mTransformation = tform; + + std::unique_ptr nodeAnim; + vector meshes; + vector children; + + while (ChunkSize()) { + const string chunk = ReadChunk(); + if (chunk == "MESH") { + unsigned int n = static_cast(_meshes.size()); + ReadMESH(); + for (unsigned int i = n; i < static_cast(_meshes.size()); ++i) { + meshes.push_back(i); + } + } else if (chunk == "BONE") { + ReadBONE(nodeid); + } else if (chunk == "ANIM") { + ReadANIM(); + } else if (chunk == "KEYS") { + if (!nodeAnim) { + nodeAnim.reset(new aiNodeAnim); + nodeAnim->mNodeName = node->mName; + } + ReadKEYS(nodeAnim.get()); + } else if (chunk == "NODE") { + aiNode *child = ReadNODE(node); + children.push_back(child); + } + ExitChunk(); + } + + if (nodeAnim) { + _nodeAnims.emplace_back(std::move(nodeAnim)); + } + + node->mNumMeshes = static_cast(meshes.size()); + node->mMeshes = to_array(meshes); + + node->mNumChildren = static_cast(children.size()); + node->mChildren = to_array(children); + + return node; +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadBB3D(aiScene *scene) { + + _textures.clear(); + + _materials.clear(); + + _vertices.clear(); + + _meshes.clear(); + + DeleteAllBarePointers(_nodes); + _nodes.clear(); + + _nodeAnims.clear(); + + _animations.clear(); + + string t = ReadChunk(); + if (t == "BB3D") { + int version = ReadInt(); + + if (!DefaultLogger::isNullLogger()) { + char dmp[128]; + ai_snprintf(dmp, 128, "B3D file format version: %i", version); + ASSIMP_LOG_INFO(dmp); + } + + while (ChunkSize()) { + const string chunk = ReadChunk(); + if (chunk == "TEXS") { + ReadTEXS(); + } else if (chunk == "BRUS") { + ReadBRUS(); + } else if (chunk == "NODE") { + ReadNODE(0); + } + ExitChunk(); + } + } + ExitChunk(); + + if (!_nodes.size()) { + Fail("No nodes"); + } + + if (!_meshes.size()) { + Fail("No meshes"); + } + + // Fix nodes/meshes/bones + for (size_t i = 0; i < _nodes.size(); ++i) { + aiNode *node = _nodes[i]; + + for (size_t j = 0; j < node->mNumMeshes; ++j) { + aiMesh *mesh = _meshes[node->mMeshes[j]].get(); + + int n_tris = mesh->mNumFaces; + int n_verts = mesh->mNumVertices = n_tris * 3; + + aiVector3D *mv = mesh->mVertices = new aiVector3D[n_verts], *mn = 0, *mc = 0; + if (_vflags & 1) { + mn = mesh->mNormals = new aiVector3D[n_verts]; + } + if (_tcsets) { + mc = mesh->mTextureCoords[0] = new aiVector3D[n_verts]; + } + + aiFace *face = mesh->mFaces; + + vector> vweights(_nodes.size()); + + for (int vertIdx = 0; vertIdx < n_verts; vertIdx += 3) { + for (int faceIndex = 0; faceIndex < 3; ++faceIndex) { + Vertex &v = _vertices[face->mIndices[faceIndex]]; + + *mv++ = v.vertex; + if (mn) *mn++ = v.normal; + if (mc) *mc++ = v.texcoords; + + face->mIndices[faceIndex] = vertIdx + faceIndex; + + for (int k = 0; k < 4; ++k) { + if (!v.weights[k]) + break; + + int bone = v.bones[k]; + float weight = v.weights[k]; + + vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight)); + } + } + ++face; + } + + vector bones; + for (size_t weightIndx = 0; weightIndx < vweights.size(); ++weightIndx) { + vector &weights = vweights[weightIndx]; + if (!weights.size()) { + continue; + } + + aiBone *bone = new aiBone; + bones.push_back(bone); + + aiNode *bnode = _nodes[weightIndx]; + + bone->mName = bnode->mName; + bone->mNumWeights = static_cast(weights.size()); + bone->mWeights = to_array(weights); + + aiMatrix4x4 mat = bnode->mTransformation; + while (bnode->mParent) { + bnode = bnode->mParent; + mat = bnode->mTransformation * mat; + } + bone->mOffsetMatrix = mat.Inverse(); + } + mesh->mNumBones = static_cast(bones.size()); + mesh->mBones = to_array(bones); + } + } + + //nodes + scene->mRootNode = _nodes[0]; + _nodes.clear(); // node ownership now belongs to scene + + //material + if (!_materials.size()) { + _materials.emplace_back(std::unique_ptr(new aiMaterial)); + } + scene->mNumMaterials = static_cast(_materials.size()); + scene->mMaterials = unique_to_array(_materials); + + //meshes + scene->mNumMeshes = static_cast(_meshes.size()); + scene->mMeshes = unique_to_array(_meshes); + + //animations + if (_animations.size() == 1 && _nodeAnims.size()) { + + aiAnimation *anim = _animations.back().get(); + anim->mNumChannels = static_cast(_nodeAnims.size()); + anim->mChannels = unique_to_array(_nodeAnims); + + scene->mNumAnimations = static_cast(_animations.size()); + scene->mAnimations = unique_to_array(_animations); + } + + // convert to RH + MakeLeftHandedProcess makeleft; + makeleft.Execute(scene); + + FlipWindingOrderProcess flip; + flip.Execute(scene); +} + +#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER diff --git a/code/B3D/B3DImporter.h b/code/AssetLib/B3D/B3DImporter.h similarity index 100% rename from code/B3D/B3DImporter.h rename to code/AssetLib/B3D/B3DImporter.h diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp new file mode 100644 index 000000000..9c22879d2 --- /dev/null +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -0,0 +1,543 @@ +/** Implementation of the BVH loader */ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(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_BVH_IMPORTER + +#include "BVHLoader.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Assimp; +using namespace Assimp::Formatter; + +static const aiImporterDesc desc = { + "BVH Importer (MoCap)", + "", + "", + "", + aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "bvh" +}; + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +BVHLoader::BVHLoader() : + mLine(), + mAnimTickDuration(), + mAnimNumFrames(), + noSkeletonMesh() {} + +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +BVHLoader::~BVHLoader() {} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const { + // check file extension + const std::string extension = GetExtension(pFile); + + if (extension == "bvh") + return true; + + if ((!extension.length() || cs) && pIOHandler) { + const char *tokens[] = { "HIERARCHY" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +void BVHLoader::SetupProperties(const Importer *pImp) { + noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0; +} + +// ------------------------------------------------------------------------------------------------ +// Loader meta information +const aiImporterDesc *BVHLoader::GetInfo() const { + return &desc; +} + +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void BVHLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + mFileName = pFile; + + // read file into memory + std::unique_ptr file(pIOHandler->Open(pFile)); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open file " + pFile + "."); + } + + size_t fileSize = file->FileSize(); + if (fileSize == 0) { + throw DeadlyImportError("File is too small."); + } + + mBuffer.resize(fileSize); + file->Read(&mBuffer.front(), 1, fileSize); + + // start reading + mReader = mBuffer.begin(); + mLine = 1; + ReadStructure(pScene); + + if (!noSkeletonMesh) { + // build a dummy mesh for the skeleton so that we see something at least + SkeletonMeshBuilder meshBuilder(pScene); + } + + // construct an animation from all the motion data we read + CreateAnimation(pScene); +} + +// ------------------------------------------------------------------------------------------------ +// Reads the file +void BVHLoader::ReadStructure(aiScene *pScene) { + // first comes hierarchy + std::string header = GetNextToken(); + if (header != "HIERARCHY") + ThrowException("Expected header string \"HIERARCHY\"."); + ReadHierarchy(pScene); + + // then comes the motion data + std::string motion = GetNextToken(); + if (motion != "MOTION") + ThrowException("Expected beginning of motion data \"MOTION\"."); + ReadMotion(pScene); +} + +// ------------------------------------------------------------------------------------------------ +// Reads the hierarchy +void BVHLoader::ReadHierarchy(aiScene *pScene) { + std::string root = GetNextToken(); + if (root != "ROOT") + ThrowException("Expected root node \"ROOT\"."); + + // Go read the hierarchy from here + pScene->mRootNode = ReadNode(); +} + +// ------------------------------------------------------------------------------------------------ +// Reads a node and recursively its childs and returns the created node; +aiNode *BVHLoader::ReadNode() { + // first token is name + std::string nodeName = GetNextToken(); + if (nodeName.empty() || nodeName == "{") + ThrowException(format() << "Expected node name, but found \"" << nodeName << "\"."); + + // then an opening brace should follow + std::string openBrace = GetNextToken(); + if (openBrace != "{") + ThrowException(format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"."); + + // Create a node + aiNode *node = new aiNode(nodeName); + std::vector childNodes; + + // and create an bone entry for it + mNodes.push_back(Node(node)); + Node &internNode = mNodes.back(); + + // now read the node's contents + std::string siteToken; + while (1) { + std::string token = GetNextToken(); + + // node offset to parent node + if (token == "OFFSET") + ReadNodeOffset(node); + else if (token == "CHANNELS") + ReadNodeChannels(internNode); + else if (token == "JOINT") { + // child node follows + aiNode *child = ReadNode(); + child->mParent = node; + childNodes.push_back(child); + } else if (token == "End") { + // The real symbol is "End Site". Second part comes in a separate token + siteToken.clear(); + siteToken = GetNextToken(); + if (siteToken != "Site") + ThrowException(format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"."); + + aiNode *child = ReadEndSite(nodeName); + child->mParent = node; + childNodes.push_back(child); + } else if (token == "}") { + // we're done with that part of the hierarchy + break; + } else { + // everything else is a parse error + ThrowException(format() << "Unknown keyword \"" << token << "\"."); + } + } + + // add the child nodes if there are any + if (childNodes.size() > 0) { + node->mNumChildren = static_cast(childNodes.size()); + node->mChildren = new aiNode *[node->mNumChildren]; + std::copy(childNodes.begin(), childNodes.end(), node->mChildren); + } + + // and return the sub-hierarchy we built here + return node; +} + +// ------------------------------------------------------------------------------------------------ +// Reads an end node and returns the created node. +aiNode *BVHLoader::ReadEndSite(const std::string &pParentName) { + // check opening brace + std::string openBrace = GetNextToken(); + if (openBrace != "{") + ThrowException(format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"."); + + // Create a node + aiNode *node = new aiNode("EndSite_" + pParentName); + + // now read the node's contents. Only possible entry is "OFFSET" + std::string token; + while (1) { + token.clear(); + token = GetNextToken(); + + // end node's offset + if (token == "OFFSET") { + ReadNodeOffset(node); + } else if (token == "}") { + // we're done with the end node + break; + } else { + // everything else is a parse error + ThrowException(format() << "Unknown keyword \"" << token << "\"."); + } + } + + // and return the sub-hierarchy we built here + return node; +} +// ------------------------------------------------------------------------------------------------ +// Reads a node offset for the given node +void BVHLoader::ReadNodeOffset(aiNode *pNode) { + // Offset consists of three floats to read + aiVector3D offset; + offset.x = GetNextTokenAsFloat(); + offset.y = GetNextTokenAsFloat(); + offset.z = GetNextTokenAsFloat(); + + // build a transformation matrix from it + pNode->mTransformation = aiMatrix4x4(1.0f, 0.0f, 0.0f, offset.x, + 0.0f, 1.0f, 0.0f, offset.y, + 0.0f, 0.0f, 1.0f, offset.z, + 0.0f, 0.0f, 0.0f, 1.0f); +} + +// ------------------------------------------------------------------------------------------------ +// Reads the animation channels for the given node +void BVHLoader::ReadNodeChannels(BVHLoader::Node &pNode) { + // number of channels. Use the float reader because we're lazy + float numChannelsFloat = GetNextTokenAsFloat(); + unsigned int numChannels = (unsigned int)numChannelsFloat; + + for (unsigned int a = 0; a < numChannels; a++) { + std::string channelToken = GetNextToken(); + + if (channelToken == "Xposition") + pNode.mChannels.push_back(Channel_PositionX); + else if (channelToken == "Yposition") + pNode.mChannels.push_back(Channel_PositionY); + else if (channelToken == "Zposition") + pNode.mChannels.push_back(Channel_PositionZ); + else if (channelToken == "Xrotation") + pNode.mChannels.push_back(Channel_RotationX); + else if (channelToken == "Yrotation") + pNode.mChannels.push_back(Channel_RotationY); + else if (channelToken == "Zrotation") + pNode.mChannels.push_back(Channel_RotationZ); + else + ThrowException(format() << "Invalid channel specifier \"" << channelToken << "\"."); + } +} + +// ------------------------------------------------------------------------------------------------ +// Reads the motion data +void BVHLoader::ReadMotion(aiScene * /*pScene*/) { + // Read number of frames + std::string tokenFrames = GetNextToken(); + if (tokenFrames != "Frames:") + ThrowException(format() << "Expected frame count \"Frames:\", but found \"" << tokenFrames << "\"."); + + float numFramesFloat = GetNextTokenAsFloat(); + mAnimNumFrames = (unsigned int)numFramesFloat; + + // Read frame duration + std::string tokenDuration1 = GetNextToken(); + std::string tokenDuration2 = GetNextToken(); + if (tokenDuration1 != "Frame" || tokenDuration2 != "Time:") + ThrowException(format() << "Expected frame duration \"Frame Time:\", but found \"" << tokenDuration1 << " " << tokenDuration2 << "\"."); + + mAnimTickDuration = GetNextTokenAsFloat(); + + // resize value vectors for each node + for (std::vector::iterator it = mNodes.begin(); it != mNodes.end(); ++it) + it->mChannelValues.reserve(it->mChannels.size() * mAnimNumFrames); + + // now read all the data and store it in the corresponding node's value vector + for (unsigned int frame = 0; frame < mAnimNumFrames; ++frame) { + // on each line read the values for all nodes + for (std::vector::iterator it = mNodes.begin(); it != mNodes.end(); ++it) { + // get as many values as the node has channels + for (unsigned int c = 0; c < it->mChannels.size(); ++c) + it->mChannelValues.push_back(GetNextTokenAsFloat()); + } + + // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it + } +} + +// ------------------------------------------------------------------------------------------------ +// Retrieves the next token +std::string BVHLoader::GetNextToken() { + // skip any preceding whitespace + while (mReader != mBuffer.end()) { + if (!isspace(*mReader)) + break; + + // count lines + if (*mReader == '\n') + mLine++; + + ++mReader; + } + + // collect all chars till the next whitespace. BVH is easy in respect to that. + std::string token; + while (mReader != mBuffer.end()) { + if (isspace(*mReader)) + break; + + token.push_back(*mReader); + ++mReader; + + // little extra logic to make sure braces are counted correctly + if (token == "{" || token == "}") + break; + } + + // empty token means end of file, which is just fine + return token; +} + +// ------------------------------------------------------------------------------------------------ +// Reads the next token as a float +float BVHLoader::GetNextTokenAsFloat() { + std::string token = GetNextToken(); + if (token.empty()) + ThrowException("Unexpected end of file while trying to read a float"); + + // check if the float is valid by testing if the atof() function consumed every char of the token + const char *ctoken = token.c_str(); + float result = 0.0f; + ctoken = fast_atoreal_move(ctoken, result); + + if (ctoken != token.c_str() + token.length()) + ThrowException(format() << "Expected a floating point number, but found \"" << token << "\"."); + + return result; +} + +// ------------------------------------------------------------------------------------------------ +// Aborts the file reading with an exception +AI_WONT_RETURN void BVHLoader::ThrowException(const std::string &pError) { + throw DeadlyImportError(format() << mFileName << ":" << mLine << " - " << pError); +} + +// ------------------------------------------------------------------------------------------------ +// Constructs an animation for the motion data and stores it in the given scene +void BVHLoader::CreateAnimation(aiScene *pScene) { + // create the animation + pScene->mNumAnimations = 1; + pScene->mAnimations = new aiAnimation *[1]; + aiAnimation *anim = new aiAnimation; + pScene->mAnimations[0] = anim; + + // put down the basic parameters + anim->mName.Set("Motion"); + anim->mTicksPerSecond = 1.0 / double(mAnimTickDuration); + anim->mDuration = double(mAnimNumFrames - 1); + + // now generate the tracks for all nodes + anim->mNumChannels = static_cast(mNodes.size()); + anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; + + // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown + for (unsigned int i = 0; i < anim->mNumChannels; ++i) + anim->mChannels[i] = NULL; + + for (unsigned int a = 0; a < anim->mNumChannels; a++) { + const Node &node = mNodes[a]; + const std::string nodeName = std::string(node.mNode->mName.data); + aiNodeAnim *nodeAnim = new aiNodeAnim; + anim->mChannels[a] = nodeAnim; + nodeAnim->mNodeName.Set(nodeName); + std::map channelMap; + + //Build map of channels + for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) { + channelMap[node.mChannels[channel]] = channel; + } + + // translational part, if given + if (node.mChannels.size() == 6) { + nodeAnim->mNumPositionKeys = mAnimNumFrames; + nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames]; + aiVectorKey *poskey = nodeAnim->mPositionKeys; + for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) { + poskey->mTime = double(fr); + + // Now compute all translations + for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) { + //Find channel in node + std::map::iterator mapIter = channelMap.find(channel); + + if (mapIter == channelMap.end()) + throw DeadlyImportError("Missing position channel in node " + nodeName); + else { + int channelIdx = mapIter->second; + switch (channel) { + case Channel_PositionX: + poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channelIdx]; + break; + case Channel_PositionY: + poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channelIdx]; + break; + case Channel_PositionZ: + poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channelIdx]; + break; + + default: + break; + } + } + } + ++poskey; + } + } else { + // if no translation part is given, put a default sequence + aiVector3D nodePos(node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4); + nodeAnim->mNumPositionKeys = 1; + nodeAnim->mPositionKeys = new aiVectorKey[1]; + nodeAnim->mPositionKeys[0].mTime = 0.0; + nodeAnim->mPositionKeys[0].mValue = nodePos; + } + + // rotation part. Always present. First find value offsets + { + + // Then create the number of rotation keys + nodeAnim->mNumRotationKeys = mAnimNumFrames; + nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames]; + aiQuatKey *rotkey = nodeAnim->mRotationKeys; + for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) { + aiMatrix4x4 temp; + aiMatrix3x3 rotMatrix; + for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1)) { + //Find channel in node + std::map::iterator mapIter = channelMap.find(channel); + + if (mapIter == channelMap.end()) + throw DeadlyImportError("Missing rotation channel in node " + nodeName); + else { + int channelIdx = mapIter->second; + // translate ZXY euler angels into a quaternion + const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; + + // Compute rotation transformations in the right order + switch (channel) { + case Channel_RotationX: + aiMatrix4x4::RotationX(angle, temp); + rotMatrix *= aiMatrix3x3(temp); + break; + case Channel_RotationY: + aiMatrix4x4::RotationY(angle, temp); + rotMatrix *= aiMatrix3x3(temp); + break; + case Channel_RotationZ: + aiMatrix4x4::RotationZ(angle, temp); + rotMatrix *= aiMatrix3x3(temp); + break; + default: + break; + } + } + } + + rotkey->mTime = double(fr); + rotkey->mValue = aiQuaternion(rotMatrix); + ++rotkey; + } + } + + // scaling part. Always just a default track + { + nodeAnim->mNumScalingKeys = 1; + nodeAnim->mScalingKeys = new aiVectorKey[1]; + nodeAnim->mScalingKeys[0].mTime = 0.0; + nodeAnim->mScalingKeys[0].mValue.Set(1.0f, 1.0f, 1.0f); + } + } +} + +#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER diff --git a/code/BVH/BVHLoader.h b/code/AssetLib/BVH/BVHLoader.h similarity index 82% rename from code/BVH/BVHLoader.h rename to code/AssetLib/BVH/BVHLoader.h index 93a3e5e83..c2ecbd102 100644 --- a/code/BVH/BVHLoader.h +++ b/code/AssetLib/BVH/BVHLoader.h @@ -53,8 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiNode; -namespace Assimp -{ +namespace Assimp { // -------------------------------------------------------------------------------- /** Loader class to read Motion Capturing data from a .bvh file. @@ -63,12 +62,10 @@ namespace Assimp * the hierarchy. It contains no actual mesh data, but we generate a dummy mesh * inside the loader just to be able to see something. */ -class BVHLoader : public BaseImporter -{ +class BVHLoader : public BaseImporter { /** Possible animation channels for which the motion data holds the values */ - enum ChannelType - { + enum ChannelType { Channel_PositionX, Channel_PositionY, Channel_PositionZ, @@ -78,61 +75,57 @@ class BVHLoader : public BaseImporter }; /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */ - struct Node - { - const aiNode* mNode; + struct Node { + const aiNode *mNode; std::vector mChannels; std::vector mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames - Node() - : mNode(nullptr) - { } + Node() : + mNode(nullptr) {} - explicit Node( const aiNode* pNode) : mNode( pNode) { } + explicit Node(const aiNode *pNode) : + mNode(pNode) {} }; public: - BVHLoader(); ~BVHLoader(); public: /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const; + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const; - void SetupProperties(const Importer* pImp); - const aiImporterDesc* GetInfo () const; + void SetupProperties(const Importer *pImp); + const aiImporterDesc *GetInfo() const; protected: - - /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); protected: /** Reads the file */ - void ReadStructure( aiScene* pScene); + void ReadStructure(aiScene *pScene); /** Reads the hierarchy */ - void ReadHierarchy( aiScene* pScene); + void ReadHierarchy(aiScene *pScene); /** Reads a node and recursively its childs and returns the created node. */ - aiNode* ReadNode(); + aiNode *ReadNode(); /** Reads an end node and returns the created node. */ - aiNode* ReadEndSite( const std::string& pParentName); + aiNode *ReadEndSite(const std::string &pParentName); /** Reads a node offset for the given node */ - void ReadNodeOffset( aiNode* pNode); + void ReadNodeOffset(aiNode *pNode); /** Reads the animation channels into the given node */ - void ReadNodeChannels( BVHLoader::Node& pNode); + void ReadNodeChannels(BVHLoader::Node &pNode); /** Reads the motion data */ - void ReadMotion( aiScene* pScene); + void ReadMotion(aiScene *pScene); /** Retrieves the next token */ std::string GetNextToken(); @@ -141,10 +134,10 @@ protected: float GetNextTokenAsFloat(); /** Aborts the file reading with an exception */ - AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void ThrowException(const std::string &pError) AI_WONT_RETURN_SUFFIX; /** Constructs an animation for the motion data and stores it in the given scene */ - void CreateAnimation( aiScene* pScene); + void CreateAnimation(aiScene *pScene); protected: /** Filename, for a verbose error message */ diff --git a/code/Blender/BlenderBMesh.cpp b/code/AssetLib/Blender/BlenderBMesh.cpp similarity index 55% rename from code/Blender/BlenderBMesh.cpp rename to code/AssetLib/Blender/BlenderBMesh.cpp index 937d9d073..b20f108bb 100644 --- a/code/Blender/BlenderBMesh.cpp +++ b/code/AssetLib/Blender/BlenderBMesh.cpp @@ -44,137 +44,117 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER +#include "BlenderBMesh.h" #include "BlenderDNA.h" #include "BlenderScene.h" -#include "BlenderBMesh.h" #include "BlenderTessellator.h" -namespace Assimp -{ - template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix() - { - static auto prefix = "BLEND_BMESH: "; - return prefix; - } +namespace Assimp { +template <> +const char *LogFunctions::Prefix() { + static auto prefix = "BLEND_BMESH: "; + return prefix; } +} // namespace Assimp using namespace Assimp; using namespace Assimp::Blender; using namespace Assimp::Formatter; // ------------------------------------------------------------------------------------------------ -BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ): - BMesh( mesh ), - triMesh( NULL ) -{ +BlenderBMeshConverter::BlenderBMeshConverter(const Mesh *mesh) : + BMesh(mesh), + triMesh(nullptr) { + // empty } // ------------------------------------------------------------------------------------------------ -BlenderBMeshConverter::~BlenderBMeshConverter( ) -{ - DestroyTriMesh( ); +BlenderBMeshConverter::~BlenderBMeshConverter() { + DestroyTriMesh(); } // ------------------------------------------------------------------------------------------------ -bool BlenderBMeshConverter::ContainsBMesh( ) const -{ +bool BlenderBMeshConverter::ContainsBMesh() const { // TODO - Should probably do some additional verification here return BMesh->totpoly && BMesh->totloop && BMesh->totvert; } // ------------------------------------------------------------------------------------------------ -const Mesh* BlenderBMeshConverter::TriangulateBMesh( ) -{ - AssertValidMesh( ); - AssertValidSizes( ); - PrepareTriMesh( ); +const Mesh *BlenderBMeshConverter::TriangulateBMesh() { + AssertValidMesh(); + AssertValidSizes(); + PrepareTriMesh(); - for ( int i = 0; i < BMesh->totpoly; ++i ) - { - const MPoly& poly = BMesh->mpoly[ i ]; - ConvertPolyToFaces( poly ); + for (int i = 0; i < BMesh->totpoly; ++i) { + const MPoly &poly = BMesh->mpoly[i]; + ConvertPolyToFaces(poly); } return triMesh; } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::AssertValidMesh( ) -{ - if ( !ContainsBMesh( ) ) - { - ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" ); +void BlenderBMeshConverter::AssertValidMesh() { + if (!ContainsBMesh()) { + ThrowException("BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first"); } } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::AssertValidSizes( ) -{ - if ( BMesh->totpoly != static_cast( BMesh->mpoly.size( ) ) ) - { - ThrowException( "BMesh poly array has incorrect size" ); +void BlenderBMeshConverter::AssertValidSizes() { + if (BMesh->totpoly != static_cast(BMesh->mpoly.size())) { + ThrowException("BMesh poly array has incorrect size"); } - if ( BMesh->totloop != static_cast( BMesh->mloop.size( ) ) ) - { - ThrowException( "BMesh loop array has incorrect size" ); + if (BMesh->totloop != static_cast(BMesh->mloop.size())) { + ThrowException("BMesh loop array has incorrect size"); } } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::PrepareTriMesh( ) -{ - if ( triMesh ) - { - DestroyTriMesh( ); +void BlenderBMeshConverter::PrepareTriMesh() { + if (triMesh) { + DestroyTriMesh(); } - triMesh = new Mesh( *BMesh ); + triMesh = new Mesh(*BMesh); triMesh->totface = 0; - triMesh->mface.clear( ); + triMesh->mface.clear(); } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::DestroyTriMesh( ) -{ +void BlenderBMeshConverter::DestroyTriMesh() { delete triMesh; - triMesh = NULL; + triMesh = nullptr; } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly ) -{ - const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ]; +void BlenderBMeshConverter::ConvertPolyToFaces(const MPoly &poly) { + const MLoop *polyLoop = &BMesh->mloop[poly.loopstart]; - if ( poly.totloop == 3 || poly.totloop == 4 ) - { - AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 ); + if (poly.totloop == 3 || poly.totloop == 4) { + AddFace(polyLoop[0].v, polyLoop[1].v, polyLoop[2].v, poly.totloop == 4 ? polyLoop[3].v : 0); // UVs are optional, so only convert when present. - if ( BMesh->mloopuv.size() ) - { - if ( (poly.loopstart + poly.totloop ) > static_cast( BMesh->mloopuv.size() ) ) - { - ThrowException( "BMesh uv loop array has incorrect size" ); + if (BMesh->mloopuv.size()) { + if ((poly.loopstart + poly.totloop) > static_cast(BMesh->mloopuv.size())) { + ThrowException("BMesh uv loop array has incorrect size"); } - const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ]; - AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 ); + const MLoopUV *loopUV = &BMesh->mloopuv[poly.loopstart]; + AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : 0); } - } - else if ( poly.totloop > 4 ) - { + } else if (poly.totloop > 4) { #if ASSIMP_BLEND_WITH_GLU_TESSELLATE - BlenderTessellatorGL tessGL( *this ); - tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); + BlenderTessellatorGL tessGL(*this); + tessGL.Tessellate(polyLoop, poly.totloop, triMesh->mvert); #elif ASSIMP_BLEND_WITH_POLY_2_TRI - BlenderTessellatorP2T tessP2T( *this ); - tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); + BlenderTessellatorP2T tessP2T(*this); + tessP2T.Tessellate(polyLoop, poly.totloop, triMesh->mvert); #endif } } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 ) -{ +void BlenderBMeshConverter::AddFace(int v1, int v2, int v3, int v4) { MFace face; face.v1 = v1; face.v2 = v2; @@ -183,24 +163,22 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 ) face.flag = 0; // TODO - Work out how materials work face.mat_nr = 0; - triMesh->mface.push_back( face ); - triMesh->totface = static_cast(triMesh->mface.size( )); + triMesh->mface.push_back(face); + triMesh->totface = static_cast(triMesh->mface.size()); } // ------------------------------------------------------------------------------------------------ -void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 ) -{ +void BlenderBMeshConverter::AddTFace(const float *uv1, const float *uv2, const float *uv3, const float *uv4) { MTFace mtface; - memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 ); - memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 ); - memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 ); + memcpy(&mtface.uv[0], uv1, sizeof(float) * 2); + memcpy(&mtface.uv[1], uv2, sizeof(float) * 2); + memcpy(&mtface.uv[2], uv3, sizeof(float) * 2); - if ( uv4 ) - { - memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 ); + if (uv4) { + memcpy(&mtface.uv[3], uv4, sizeof(float) * 2); } - triMesh->mtface.push_back( mtface ); + triMesh->mtface.push_back(mtface); } #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER diff --git a/code/Blender/BlenderBMesh.h b/code/AssetLib/Blender/BlenderBMesh.h similarity index 100% rename from code/Blender/BlenderBMesh.h rename to code/AssetLib/Blender/BlenderBMesh.h diff --git a/code/AssetLib/Blender/BlenderCustomData.cpp b/code/AssetLib/Blender/BlenderCustomData.cpp new file mode 100644 index 000000000..c752da4e0 --- /dev/null +++ b/code/AssetLib/Blender/BlenderCustomData.cpp @@ -0,0 +1,181 @@ +#include "BlenderCustomData.h" +#include "BlenderDNA.h" +#include +#include + +namespace Assimp { +namespace Blender { +/** + * @brief read/convert of Structure array to memory + */ +template +bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) { + for (size_t i = 0; i < cnt; ++i) { + T read; + s.Convert(read, db); + *p = read; + p++; + } + return true; +} + +/** + * @brief pointer to function read memory for n CustomData types + */ +typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db); +typedef ElemBase *(*PCreate)(const size_t cnt); +typedef void (*PDestroy)(ElemBase *); + +#define IMPL_STRUCT_READ(ty) \ + bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \ + ty *ptr = dynamic_cast(v); \ + if (nullptr == ptr) { \ + return false; \ + } \ + return read(db.dna[#ty], ptr, cnt, db); \ + } + +#define IMPL_STRUCT_CREATE(ty) \ + ElemBase *create##ty(const size_t cnt) { \ + return new ty[cnt]; \ + } + +#define IMPL_STRUCT_DESTROY(ty) \ + void destroy##ty(ElemBase *pE) { \ + ty *p = dynamic_cast(pE); \ + delete[] p; \ + } + +/** + * @brief helper macro to define Structure functions + */ +#define IMPL_STRUCT(ty) \ + IMPL_STRUCT_READ(ty) \ + IMPL_STRUCT_CREATE(ty) \ + IMPL_STRUCT_DESTROY(ty) + +// supported structures for CustomData +IMPL_STRUCT(MVert) +IMPL_STRUCT(MEdge) +IMPL_STRUCT(MFace) +IMPL_STRUCT(MTFace) +IMPL_STRUCT(MTexPoly) +IMPL_STRUCT(MLoopUV) +IMPL_STRUCT(MLoopCol) +IMPL_STRUCT(MPoly) +IMPL_STRUCT(MLoop) + +/** + * @brief describes the size of data and the read function to be used for single CustomerData.type + */ +struct CustomDataTypeDescription { + PRead Read; ///< function to read one CustomData type element + PCreate Create; ///< function to allocate n type elements + PDestroy Destroy; + + CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy) : + Read(read), Create(create), Destroy(destroy) {} +}; + +/** + * @brief helper macro to define Structure type specific CustomDataTypeDescription + * @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function + */ +#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \ + CustomDataTypeDescription { &read##ty, &create##ty, &destroy##ty } + +/** + * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type + */ +#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \ + CustomDataTypeDescription { nullptr, nullptr, nullptr } + +/** + * @brief descriptors for data pointed to from CustomDataLayer.data + * @note some of the CustomData uses already well defined Structures + * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures + * use a special readfunction for that cases + */ +std::array customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION } }; + +bool isValidCustomDataType(const int cdtype) { + return cdtype >= 0 && cdtype < CD_NUMTYPES; +} + +bool readCustomData(std::shared_ptr &out, const int cdtype, const size_t cnt, const FileDatabase &db) { + if (!isValidCustomDataType(cdtype)) { + throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index")); + } + + const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype]; + if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) { + // allocate cnt elements and parse them from file + out.reset(cdtd.Create(cnt), cdtd.Destroy); + return cdtd.Read(out.get(), cnt, db); + } + return false; +} + +std::shared_ptr getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) { + for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) { + if (it->get()->type == cdtype && name == it->get()->name) { + return *it; + } + } + return nullptr; +} + +const ElemBase *getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) { + const std::shared_ptr pLayer = getCustomDataLayer(customdata, cdtype, name); + if (pLayer && pLayer->data) { + return pLayer->data.get(); + } + return nullptr; +} +} // namespace Blender +} // namespace Assimp diff --git a/code/Blender/BlenderCustomData.h b/code/AssetLib/Blender/BlenderCustomData.h similarity index 100% rename from code/Blender/BlenderCustomData.h rename to code/AssetLib/Blender/BlenderCustomData.h diff --git a/code/Blender/BlenderDNA.cpp b/code/AssetLib/Blender/BlenderDNA.cpp similarity index 73% rename from code/Blender/BlenderDNA.cpp rename to code/AssetLib/Blender/BlenderDNA.cpp index 53fb84824..69f139ec5 100644 --- a/code/Blender/BlenderDNA.cpp +++ b/code/AssetLib/Blender/BlenderDNA.cpp @@ -45,25 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * serialized set of data structures. */ - #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #include "BlenderDNA.h" #include -#include #include +#include using namespace Assimp; using namespace Assimp::Blender; using namespace Assimp::Formatter; -static bool match4(StreamReaderAny& stream, const char* string) { - ai_assert( nullptr != string ); +static bool match4(StreamReaderAny &stream, const char *string) { + ai_assert(nullptr != string); char tmp[4]; - tmp[ 0 ] = ( stream ).GetI1(); - tmp[ 1 ] = ( stream ).GetI1(); - tmp[ 2 ] = ( stream ).GetI1(); - tmp[ 3 ] = ( stream ).GetI1(); - return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]); + tmp[0] = (stream).GetI1(); + tmp[1] = (stream).GetI1(); + tmp[2] = (stream).GetI1(); + tmp[3] = (stream).GetI1(); + return (tmp[0] == string[0] && tmp[1] == string[1] && tmp[2] == string[2] && tmp[3] == string[3]); } struct Type { @@ -72,75 +71,76 @@ struct Type { }; // ------------------------------------------------------------------------------------------------ -void DNAParser::Parse () -{ - StreamReaderAny& stream = *db.reader.get(); - DNA& dna = db.dna; +void DNAParser::Parse() { + StreamReaderAny &stream = *db.reader.get(); + DNA &dna = db.dna; - if(!match4(stream,"SDNA")) { + if (!match4(stream, "SDNA")) { throw DeadlyImportError("BlenderDNA: Expected SDNA chunk"); } // name dictionary - if(!match4(stream,"NAME")) { + if (!match4(stream, "NAME")) { throw DeadlyImportError("BlenderDNA: Expected NAME field"); } - std::vector names (stream.GetI4()); - for(std::string& s : names) { + std::vector names(stream.GetI4()); + for (std::string &s : names) { while (char c = stream.GetI1()) { s += c; } } // type dictionary - for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); - if(!match4(stream,"TYPE")) { + for (; stream.GetCurrentPos() & 0x3; stream.GetI1()) + ; + if (!match4(stream, "TYPE")) { throw DeadlyImportError("BlenderDNA: Expected TYPE field"); } - std::vector types (stream.GetI4()); - for(Type& s : types) { + std::vector types(stream.GetI4()); + for (Type &s : types) { while (char c = stream.GetI1()) { s.name += c; } } // type length dictionary - for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); - if(!match4(stream,"TLEN")) { + for (; stream.GetCurrentPos() & 0x3; stream.GetI1()) + ; + if (!match4(stream, "TLEN")) { throw DeadlyImportError("BlenderDNA: Expected TLEN field"); } - for(Type& s : types) { + for (Type &s : types) { s.size = stream.GetI2(); } // structures dictionary - for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); - if(!match4(stream,"STRC")) { + for (; stream.GetCurrentPos() & 0x3; stream.GetI1()) + ; + if (!match4(stream, "STRC")) { throw DeadlyImportError("BlenderDNA: Expected STRC field"); } size_t end = stream.GetI4(), fields = 0; dna.structures.reserve(end); - for(size_t i = 0; i != end; ++i) { + for (size_t i = 0; i != end; ++i) { uint16_t n = stream.GetI2(); if (n >= types.size()) { throw DeadlyImportError((format(), - "BlenderDNA: Invalid type index in structure name" ,n, - " (there are only ", types.size(), " entries)" - )); + "BlenderDNA: Invalid type index in structure name", n, + " (there are only ", types.size(), " entries)")); } // maintain separate indexes dna.indices[types[n].name] = dna.structures.size(); dna.structures.push_back(Structure()); - Structure& s = dna.structures.back(); - s.name = types[n].name; + Structure &s = dna.structures.back(); + s.name = types[n].name; //s.index = dna.structures.size()-1; n = stream.GetI2(); @@ -152,12 +152,11 @@ void DNAParser::Parse () uint16_t j = stream.GetI2(); if (j >= types.size()) { throw DeadlyImportError((format(), - "BlenderDNA: Invalid type index in structure field ", j, - " (there are only ", types.size(), " entries)" - )); + "BlenderDNA: Invalid type index in structure field ", j, + " (there are only ", types.size(), " entries)")); } s.fields.push_back(Field()); - Field& f = s.fields.back(); + Field &f = s.fields.back(); f.offset = offset; f.type = types[j].name; @@ -166,9 +165,8 @@ void DNAParser::Parse () j = stream.GetI2(); if (j >= names.size()) { throw DeadlyImportError((format(), - "BlenderDNA: Invalid name index in structure field ", j, - " (there are only ", names.size(), " entries)" - )); + "BlenderDNA: Invalid name index in structure field ", j, + " (there are only ", names.size(), " entries)")); } f.name = names[j]; @@ -191,26 +189,25 @@ void DNAParser::Parse () const std::string::size_type rb = f.name.find('['); if (rb == std::string::npos) { throw DeadlyImportError((format(), - "BlenderDNA: Encountered invalid array declaration ", - f.name - )); + "BlenderDNA: Encountered invalid array declaration ", + f.name)); } f.flags |= FieldFlag_Array; - DNA::ExtractArraySize(f.name,f.array_sizes); - f.name = f.name.substr(0,rb); + DNA::ExtractArraySize(f.name, f.array_sizes); + f.name = f.name.substr(0, rb); f.size *= f.array_sizes[0] * f.array_sizes[1]; } // maintain separate indexes - s.indices[f.name] = s.fields.size()-1; + s.indices[f.name] = s.fields.size() - 1; offset += f.size; } s.size = offset; } - ASSIMP_LOG_DEBUG_F( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields"); + ASSIMP_LOG_DEBUG_F("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields"); #ifdef ASSIMP_BUILD_BLENDER_DEBUG dna.DumpToFile(); @@ -220,13 +217,11 @@ void DNAParser::Parse () dna.RegisterConverters(); } - #ifdef ASSIMP_BUILD_BLENDER_DEBUG #include // ------------------------------------------------------------------------------------------------ -void DNA :: DumpToFile() -{ +void DNA ::DumpToFile() { // we don't bother using the VFS here for this is only for debugging. // (and all your bases are belong to us). @@ -235,12 +230,14 @@ void DNA :: DumpToFile() ASSIMP_LOG_ERROR("Could not dump dna to dna.txt"); return; } - f << "Field format: type name offset size" << "\n"; - f << "Structure format: name size" << "\n"; + f << "Field format: type name offset size" + << "\n"; + f << "Structure format: name size" + << "\n"; - for(const Structure& s : structures) { + for (const Structure &s : structures) { f << s.name << " " << s.size << "\n\n"; - for(const Field& ff : s.fields) { + for (const Field &ff : s.fields) { f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << "\n"; } f << "\n"; @@ -252,11 +249,9 @@ void DNA :: DumpToFile() #endif // ------------------------------------------------------------------------------------------------ -/*static*/ void DNA :: ExtractArraySize( - const std::string& out, - size_t array_sizes[2] -) -{ +/*static*/ void DNA ::ExtractArraySize( + const std::string &out, + size_t array_sizes[2]) { array_sizes[0] = array_sizes[1] = 1; std::string::size_type pos = out.find('['); if (pos++ == std::string::npos) { @@ -264,7 +259,7 @@ void DNA :: DumpToFile() } array_sizes[0] = strtoul10(&out[pos]); - pos = out.find('[',pos); + pos = out.find('[', pos); if (pos++ == std::string::npos) { return; } @@ -272,36 +267,32 @@ void DNA :: DumpToFile() } // ------------------------------------------------------------------------------------------------ -std::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure( - const Structure& structure, - const FileDatabase& db -) const -{ - std::map::const_iterator it = converters.find(structure.name); +std::shared_ptr DNA ::ConvertBlobToStructure( + const Structure &structure, + const FileDatabase &db) const { + std::map::const_iterator it = converters.find(structure.name); if (it == converters.end()) { - return std::shared_ptr< ElemBase >(); + return std::shared_ptr(); } - std::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); - (structure.*((*it).second.second))(ret,db); + std::shared_ptr ret = (structure.*((*it).second.first))(); + (structure.*((*it).second.second))(ret, db); return ret; } // ------------------------------------------------------------------------------------------------ -DNA::FactoryPair DNA :: GetBlobToStructureConverter( - const Structure& structure, - const FileDatabase& /*db*/ -) const -{ - std::map::const_iterator it = converters.find(structure.name); +DNA::FactoryPair DNA ::GetBlobToStructureConverter( + const Structure &structure, + const FileDatabase & /*db*/ +) const { + std::map::const_iterator it = converters.find(structure.name); return it == converters.end() ? FactoryPair() : (*it).second; } // basing on http://www.blender.org/development/architecture/notes-on-sdna/ // ------------------------------------------------------------------------------------------------ -void DNA :: AddPrimitiveStructures() -{ +void DNA ::AddPrimitiveStructures() { // NOTE: these are just dummies. Their presence enforces // Structure::Convert to be called on these // empty structures. These converters are special @@ -311,30 +302,27 @@ void DNA :: AddPrimitiveStructures() // in question. indices["int"] = structures.size(); - structures.push_back( Structure() ); + structures.push_back(Structure()); structures.back().name = "int"; structures.back().size = 4; indices["short"] = structures.size(); - structures.push_back( Structure() ); + structures.push_back(Structure()); structures.back().name = "short"; structures.back().size = 2; - indices["char"] = structures.size(); - structures.push_back( Structure() ); + structures.push_back(Structure()); structures.back().name = "char"; structures.back().size = 1; - indices["float"] = structures.size(); - structures.push_back( Structure() ); + structures.push_back(Structure()); structures.back().name = "float"; structures.back().size = 4; - indices["double"] = structures.size(); - structures.push_back( Structure() ); + structures.push_back(Structure()); structures.back().name = "double"; structures.back().size = 8; @@ -342,8 +330,7 @@ void DNA :: AddPrimitiveStructures() } // ------------------------------------------------------------------------------------------------ -void SectionParser :: Next() -{ +void SectionParser ::Next() { stream.SetCurrentPos(current.start + current.size); const char tmp[] = { @@ -352,7 +339,7 @@ void SectionParser :: Next() (const char)stream.GetI1(), (const char)stream.GetI1() }; - current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1); + current.id = std::string(tmp, tmp[3] ? 4 : tmp[2] ? 3 : tmp[1] ? 2 : 1); current.size = stream.GetI4(); current.address.val = ptr64 ? stream.GetU8() : stream.GetU4(); @@ -370,6 +357,4 @@ void SectionParser :: Next() #endif } - - #endif diff --git a/code/Blender/BlenderDNA.h b/code/AssetLib/Blender/BlenderDNA.h similarity index 76% rename from code/Blender/BlenderDNA.h rename to code/AssetLib/Blender/BlenderDNA.h index 16ce960e2..7e04bad19 100644 --- a/code/Blender/BlenderDNA.h +++ b/code/AssetLib/Blender/BlenderDNA.h @@ -49,26 +49,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include #include -#include +#include #include +#include // enable verbose log output. really verbose, so be careful. #ifdef ASSIMP_BUILD_DEBUG -# define ASSIMP_BUILD_BLENDER_DEBUG +#define ASSIMP_BUILD_BLENDER_DEBUG #endif // #define ASSIMP_BUILD_BLENDER_NO_STATS -namespace Assimp { +namespace Assimp { -template class StreamReader; -typedef StreamReader StreamReaderAny; +template +class StreamReader; +typedef StreamReader StreamReaderAny; namespace Blender { -class FileDatabase; +class FileDatabase; struct FileBlockHead; template