diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..eba6d586f --- /dev/null +++ b/.clang-format @@ -0,0 +1,127 @@ +# Commented out parameters are those with the same value as base LLVM style +# We can uncomment them if we want to change their value, or enforce the +# chosen value in case the base style changes (last sync: Clang 6.0.1). +--- +### General config, applies to all languages ### +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +# AlignEscapedNewlines: Right +# AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +# AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +# BinPackArguments: true +# BinPackParameters: true +# BraceWrapping: +# AfterClass: false +# AfterControlStatement: false +# AfterEnum: false +# AfterFunction: false +# AfterNamespace: false +# AfterObjCDeclaration: false +# AfterStruct: false +# AfterUnion: false +# AfterExternBlock: false +# BeforeCatch: false +# BeforeElse: false +# IndentBraces: false +# SplitEmptyFunction: true +# SplitEmptyRecord: true +# SplitEmptyNamespace: true +# BreakBeforeBinaryOperators: None +# BreakBeforeBraces: Attach +# BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +# BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +# BreakStringLiterals: true +ColumnLimit: 0 +# CommentPragmas: '^ IWYU pragma:' +# CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# FixNamespaceComments: true +# ForEachMacros: +# - foreach +# - Q_FOREACH +# - BOOST_FOREACH +# IncludeBlocks: Preserve +IncludeCategories: + - Regex: '".*"' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 +# IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +# IndentPPDirectives: None +IndentWidth: 4 +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true +# KeepEmptyLinesAtTheStartOfBlocks: true +# MacroBlockBegin: '' +# MacroBlockEnd: '' +# MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# PenaltyBreakAssignment: 2 +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +# PointerAlignment: Right +# RawStringFormats: +# - Delimiter: pb +# Language: TextProto +# BasedOnStyle: google +# ReflowComments: true +# SortIncludes: true +# SortUsingDeclarations: true +# SpaceAfterCStyleCast: false +# SpaceAfterTemplateKeyword: true +# SpaceBeforeAssignmentOperators: true +# SpaceBeforeParens: ControlStatements +# SpaceInEmptyParentheses: false +# SpacesBeforeTrailingComments: 1 +# SpacesInAngles: false +# SpacesInContainerLiterals: true +# SpacesInCStyleCastParentheses: false +# SpacesInParentheses: false +# SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Always +--- +### C++ specific config ### +Language: Cpp +Standard: Cpp11 +--- +### ObjC specific config ### +Language: ObjC +Standard: Cpp11 +ObjCBlockIndentWidth: 4 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +--- +### Java specific config ### +Language: Java +# BreakAfterJavaFieldAnnotations: false +... diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..e750822ab --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +patreon: assimp +ko_fi: kimkulling diff --git a/.gitignore b/.gitignore index 2a3b68a50..e975976bf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,23 +2,38 @@ build .project *.kdev4* +.DS_Store + +# build artefacts +*.o +*.a # Visual Studio *.sln *.ncb *.vcproj +*.vcxproj.user +*.VC.db +*.VC.db-shm +*.VC.db-wal +*.VC.opendb +*.ipch # Output bin/ lib/ +# QtCreator +CMakeLists.txt.user # Generated assimp.pc +assimp.aps revision.h contrib/zlib/zconf.h contrib/zlib/zlib.pc include/assimp/config.h +unit.vcxproj.user # CMake CMakeCache.txt @@ -28,6 +43,7 @@ cmake_uninstall.cmake *.dir/ assimp-config.cmake assimp-config-version.cmake +assimpTargets*.cmake # MakeFile Makefile @@ -38,6 +54,7 @@ tools/assimp_cmd/Makefile # Tests test/results +test/readlinetest* # Python __pycache__ @@ -84,3 +101,9 @@ lib64/assimp-vc120-mt.exp xcuserdata cmake-build-debug +install_manifest.txt +tools/assimp_qt_viewer/moc_glview.cpp +tools/assimp_qt_viewer/moc_glview.cpp_parameters +tools/assimp_qt_viewer/moc_mainwindow.cpp +tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters +tools/assimp_qt_viewer/ui_mainwindow.h diff --git a/.travis.sh b/.travis.sh index fb42bd40d..f0f0f5d70 100755 --- a/.travis.sh +++ b/.travis.sh @@ -7,7 +7,8 @@ # function generate() { OPTIONS="-DASSIMP_WERROR=ON" - + OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO" + if [ "$DISABLE_EXPORTERS" = "YES" ] ; then OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES" else diff --git a/.travis.yml b/.travis.yml index 0b8d2f328..8fe39d59c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,16 +27,11 @@ compiler: env: global: - # COVERITY_SCAN_TOKEN - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc=" - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME} matrix: include: - # disabled until clang 5.0 analyzer issues are fixed - # - os: linux - # compiler: clang - # env: ANALYZE=ON - os: linux compiler: clang env: ASAN=ON @@ -51,7 +46,7 @@ matrix: env: ANALYZE=ON - os: linux compiler: gcc - env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON + env: ENABLE_COVERALLS=ON - os: linux compiler: gcc env: SHARED_BUILD=ON @@ -60,8 +55,7 @@ install: - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi before_script: - # init coverage to 0 (optional) - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi + cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES script: - export COVERALLS_SERVICE_NAME=travis-ci @@ -76,6 +70,6 @@ addons: project: name: "assimp/assimp" notification_email: kim.kulling@googlemail.com - build_command_prepend: "cmake" - build_command: "make" + build_command_prepend: "cmake ./" + build_command: "make -j4" branch_pattern: coverity_scan diff --git a/AssimpConfig.cmake.in b/AssimpConfig.cmake.in deleted file mode 100644 index 5bb705a41..000000000 --- a/AssimpConfig.cmake.in +++ /dev/null @@ -1,21 +0,0 @@ -# - Config file for the FooBar package -# It defines the following variables -# FOOBAR_INCLUDE_DIRS - include directories for FooBar -# FOOBAR_LIBRARIES - libraries to link against -# FOOBAR_EXECUTABLE - the bar executable - -# Compute paths -get_filename_component(FOOBAR_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -if(EXISTS "${FOOBAR_CMAKE_DIR}/CMakeCache.txt") - # In build tree - include("${FOOBAR_CMAKE_DIR}/FooBarBuildTreeSettings.cmake") -else() - set(FOOBAR_INCLUDE_DIRS "${FOOBAR_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@") -endif() - -# Our library dependencies (contains definitions for IMPORTED targets) -include("${FOOBAR_CMAKE_DIR}/FooBarLibraryDepends.cmake") - -# These are IMPORTED targets created by FooBarLibraryDepends.cmake -set(FOOBAR_LIBRARIES foo) -set(FOOBAR_EXECUTABLE bar) diff --git a/BUILDBINARIES_EXAMPLE.bat b/BUILDBINARIES_EXAMPLE.bat new file mode 100644 index 000000000..2dd13a542 --- /dev/null +++ b/BUILDBINARIES_EXAMPLE.bat @@ -0,0 +1,26 @@ +:: This is an example file to generate binaries using Windows Operating System +:: This script is configured to be executed from the source directory + +:: Compiled binaries will be placed in BINARIES_DIR\code\CONFIG + +:: NOTE +:: The build process will generate a config.h file that is placed in BINARIES_DIR\include +:: This file must be merged with SOURCE_DIR\include +:: You should write yourself a script that copies the files where you want them. +:: Also see: https://github.com/assimp/assimp/pull/2646 + +SET SOURCE_DIR=. + +:: For generators see "cmake --help" +SET GENERATOR=Visual Studio 15 2017 + +SET BINARIES_DIR="./BINARIES/Win32" +cmake CMakeLists.txt -G "%GENERATOR%" -S %SOURCE_DIR% -B %BINARIES_DIR% +cmake --build %BINARIES_DIR% --config release + +SET BINARIES_DIR="./BINARIES/x64" +cmake CMakeLists.txt -G "%GENERATOR% Win64" -S %SOURCE_DIR% -B %BINARIES_DIR% +cmake --build %BINARIES_DIR% --config debug +cmake --build %BINARIES_DIR% --config release + +PAUSE diff --git a/Build.md b/Build.md new file mode 100644 index 000000000..4b7513313 --- /dev/null +++ b/Build.md @@ -0,0 +1,88 @@ +# Build Instructions + +## Build on all platforms using vcpkg +You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: +```bash + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + vcpkg install assimp +``` +The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + +## Manual build instructions + +### Install CMake +Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via +```bash +sudo apt-get install cmake +``` + +### Get the source +Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via: +```bash +git clone https://github.com/assimp/assimp.git +``` + +### Build instructions for Windows with Visual-Studio + +First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/ +To generate the build environment for your IDE open a command prompt, navigate to your repo and type: +```bash +cmake CMakeLists.txt +``` +This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it. + +### Build instructions for Windows with UWP +See + +### Build instructions for Linux / Unix +Open a terminal and got to your repository. You can generate the makefiles and build the library via: + +```bash +cmake CMakeLists.txt +make -j4 +``` +The option -j descripes the number of parallel processes for the build. In this case make will try to use 4 cores for the build. + +If you want to use a IDE for linux you can try QTCreator for instance. + +### Build instructions for MinGW + Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag +required to compile some of assimp's files, especially for debug builds. +Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work. + +Please see [CMake Cross Compiling](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling) for general information on CMake Toolchains. + +Some users have had success building assimp using MinGW on Linux using [polly](https://github.com/ruslo/polly/). + +The following toolchain, which is not maintained by assimp, seems to work on Linux: [linux-mingw-w64-gnuxx11.cmake](https://github.com/ruslo/polly/blob/master/linux-mingw-w64-gnuxx11.cmake) + +The following toolchain may or may not be helpful for building assimp using MinGW on Windows (untested): + [mingw-cxx17.cmake](https://github.com/ruslo/polly/blob/master/mingw-cxx17.cmake) + +Besides the toolchain, compilation should be the same as for Linux / Unix. + +### CMake build options +The cmake-build-environment provides options to configure the build. The following options can be used: +- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib. +- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle +- **ASSIMP_DOUBLE_PRECISION( default OFF )**: All data will be stored as double values. +- **ASSIMP_OPT_BUILD_PACKAGES ( default OFF)**: Set to ON to generate CPack configuration files and packaging targets +- **ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF )**: Android JNI IOSystem support is active +- **ASSIMP_NO_EXPORT ( default OFF )**: Disable Assimp's export functionality +- **ASSIMP_BUILD_ZLIB ( default OFF )**: Build your own zlib +- **ASSIMP_BUILD_ASSIMP_TOOLS ( default ON )**: If the supplementary tools for Assimp are built in addition to the library. +- **ASSIMP_BUILD_SAMPLES ( default OFF )**: If the official samples are built as well (needs Glut). +- **ASSIMP_BUILD_TESTS ( default ON )**: If the test suite for Assimp is built in addition to the library. +- **ASSIMP_COVERALLS ( default OFF )**: Enable this to measure test coverage. +- **ASSIMP_ERROR_MAX( default OFF)**: Enable all warnings. +- **ASSIMP_WERROR( default OFF )**: Treat warnings as errors. +- **ASSIMP_ASAN ( default OFF )**: Enable AddressSanitizer. +- **ASSIMP_UBSAN ( default OFF )**: Enable Undefined Behavior sanitizer. +- **SYSTEM_IRRXML ( default OFF )**: Use system installed Irrlicht/IrrXML library. +- **BUILD_DOCS ( default OFF )**: Build documentation using Doxygen. +- **INJECT_DEBUG_POSTFIX( default ON )**: Inject debug postfix in .a/.so lib names +- **IGNORE_GIT_HASH ( default OFF )**: Don't call git to get the hash. +- **ASSIMP_INSTALL_PDB ( default ON )**: Install MSVC debug files. diff --git a/CHANGES b/CHANGES index d5faab2e0..c0c73b98c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,264 @@ ---------------------------------------------------------------------- CHANGELOG ---------------------------------------------------------------------- +4.1.0 (2017-12): +- FEATURES: + - Export 3MF ( experimental ) + - Import / Export glTF 2 + - Introduce new zib-lib to eb able to export zip-archives +- FIXES/HOUSEKEEPING: + - Added missing include to stdlib.h and remove load library call + - Fix install for builds with MSVC compiler and NMake. + - Update list of supported file formats. + - Add TriLib to the official list of supported ports. + - Re-enabling PACK_STRUCT for MDL files. + - Use std.::unique_ptr + - Update D3MFExporter.h + - Update MD3Loader.cpp, using index + - Fix all warnings on MSVC14 + - Copy assimp dll to unit folder on windows + - Update jvm port supported formats + - Add support for building Mac OS X Framework bundles + - Check for nullptr dereferencing before copying scene data + - Update ValidateDataStructure.h, typo + - Enable data structure validation in cases where it doesn't cause failures + - Remove some dead assignments + - fast_atof: Silence some uninitialized variable warnings + - Check for area test if the face is a triangle. + - Set mNumUVComponents to 0 when deleting texture coordinate sets + - Only scale the root node because this will rescale all children nodes as well. + - Issue 1514: Fix frame pointer arithmetic + - Prevent failing stringstream to crash the export process + - powf -> pow + - add Defines.h to include folder for install. + - Android: + - Fix android build + - Fix assimp for cross compile for android + - Use define for D_FILE_OFFSET_BITS only for not-android systems. + - FBX: + - Fix handling with embedded textures + - FBX 7500 Binary reading + - Remove dead assignment + - Fix export of deleted meshes; Add LazyDict::Remove method + - Log an error instead of letting the fbx-importer crash. ( issue 213 ) + - Replace bad pointer casting with memcpy + - Remove useless const qualifier from return value + - Add explicit instantiation of log_prefix so other FBX source files can see it + - add missing inversion of postrotation matrix for fbx. + - FIReader: Silence uninitialized variable warning + - Update version check in FBX reader to check for version >= 7500 + - Use actual min/max of anim keys when start/stop time is missing +- GLTF1: + - Fix output of glTF 1 version string + - Fix delete / delete[] mismatch in glTFAsset + - Don’t ignore rgba(1,1,1,1) color properties + - glTF2 primitives fixes + - Don’t ignore rgba(1,1,1,1) color properties + - Fix delete / delete[] mismatch in glTFAsset + - Remove KHR_binary_glTF code + - glTF nodes can only hold one mesh. this simply assigns to and check’s a Node’s Mesh + - version in glb header is stored as uint32_t +- GLTF2: + - node name conflict fix + - Fix transform matrices multiplication order + - Preserve node names when importing + - Add support for tangents in import + - Fix typo on gltf2 camera parameters + - Moved byteStride from accessor to bufferView + - Implemented reading binary glTF2 (glb) files + - Fix signed/unsigned warning + - Add postprocess step for scaling + - Fix shininess to roughness conversion + - Prefer “BLEND” over “MASK” as an alphaMode default + - Approximate specularity / glossiness in metallicRoughness materials + - Diffuse color and diffuse texture import and export improvements + - Addressed some mismatched news/deletes caused by the new glTF2 sources. + - Fix delete / delete[] mismatches in glTF2 importer + - use correct name of exporter to gltf2 + - Fix possible infinite loop when exporting to gltf2 + - Fix glTF2::Asset::FindUniqueID() when the input string is >= 256 chars + - Fix glTF2 alphaMode storage and reading + - Fix glTF 2.0 multi-primitive support + - Load gltf .bin files from correct directory + - Add support for importing both glTF and glTF2 files + - ampler improvements; Add new LazyDict method + - Changes to GLTF2 materials + - Remove Light, Technique references + - Start removing materials common, and adding pbrSpecularGlossiness + - Use !ObjectEmpty() vs. MemberCount() > 0 + - Working read, import, export, and write of gltf2 (pbr) material + - Check in gltf2 models to test directory + - Remove un-needed test models + - Start managing and importing gltf2 pbr materials + - Update glTF2 Asset to use indexes + - Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List + - glTF2: Fix animation export + - use opacity for diffuse alpha + alphaMode +- STL: + - Restore import of multi mesh binary STLs +- Blender: + - Silence warning about uninitialized member +- MDLImporter: + - Don't take address of packed struct member +- assimp_cmd: + - Fix strict-aliasing warnings +- Open3DGC: + - Fix strict-aliasing warnings + - Add assertions to silence static analyzer warnings + - Remove redundant const qualifiers from return types + - Fix some uninitialized variable warnings + - Remove OPEN3DGC and compression references +- unzip: + - Remove dead assignment + - Bail on bad compression method + - Fix possibly uninitialized variables +- clipper: + - Add assertion to silence a static analyzer warning +- OpenDDLExport: + - Reduce scope of a variable + - Remove dead variable + - Remove dead assignment + - Fix another potential memory leak +- X3DImporter: + - Add assertions to silence static analyzer warnings + - Add missing unittest + - Workaround for buggy Android NDK (issue #1361) +- TerragenLoader: + - Remove unused variable +- SIBImporter: + - Add assertions to silence static analyzer warnings +- IFC: + - Remove dead code + - Add explicit instantiation of log_prefix so IFCMaterial.cpp can see it +- PLY: + - Remove dead assignment and reduce scope of a variable + - fix vertex attribute lookup. +- OpenGEX: + - Add assertion to silence a static analyzer warning + - Fix for TextureFile with number in file name + - Return early when element is TextureFile +- NFF: + - Add assertions to silence static analyzer warnings + - Split up some complicated assignments +- Raw: Fix misleading indentation warning + - Reduce scope of a variable +- LWO + - Reduce scope of a variable +- IRRLoader: + - Fix confusing boolean casting +- AssbinExporter: + - Add assertion to silence a static analyzer warning +- ASE: + - Add assertion to silence a static analyzer warning +- AMFImporter: + - Add assertion to silence a static analyzer warning + - Add a block +- OptimizeGraph: + - Fix possible null pointer dereference + - RemoveRedundantMaterials: + - Add assertion to silence a static analyzer warning +- ImproveCacheLocality: + - Add assertion to silence a static analyzer warning +- RemoveRedundantMaterials: + - Set pointer to nullptr after deleting it +- Travis: + - Disable unit tests in scan-build config + - Move slower builds earlier to improve parallelization + - Add static analysis to build + - Remove unused branch rule for travis. + - Add Clang UBSan build configuration + - Treat warnings as errors, without typos this time +- Unittests: + - Add VS-based source groups for the unittests. +- Collada: + - export tag + - Update ColladaExporter.cpp + - Silence uninitialized variable warning + - Add support for line strip primitives +- Obj Wavefront: + - check in exporting against out-of-bounds-access . + - Issue 1351: use correct name for obj-meshname export for groups. + - fix mem-lead: face will be not released in case of an error. + - Anatoscope obj exporter nomtl + - Raise exception when obj file contains invalid face indices + - Added alternative displacement texture token in OBJ MTL material. + - Obj: rename attribute from exporter. + - Fix OBJ discarding all material names if the material library is missing +- Step: + - use correct lookup for utf32 +- MD2: + - Fix MD2 frames containing garbage +- STL + - add missing const. + - Fix memory-alignment bug. + - Fix issue 104: deal with more solids in one STL file. +- CMake + - Fix issue 213: use correct include folder for assimp +- Doxygen + - Fix issue 1513: put irrXML onto exclucde list for doxygen run +- PyAssimp: + - Search for libassimp.so in LD_LIBRARY_PATH if available. + - Fix operator precedence issue in header check + - Split setup.py into multiple lines + - Detect if Anaconda and fixed 3d_viewer for Python 3 + - created a python3 version of the 3dviewer and fixed the / = float in py3 +- Blender: + - Fix invalid access to mesh array when the array is empty. + - Fix short overflow. + - Silence warning about inline function which is declared but not defined +- JAssimp + - Changed license header for IHMC contributions from Apache 2.0 to BSD + - Add Node metadata to the Jassmip Java API + - Added supported for custom IO Systems in Java. Implemented ClassLoader IO System + - Added a link to pure jvm assimp port +- Clang sanitizer: + - Undefined Behavior sanitizer + - Fixed a divide by zero error in IFCBoolean that was latent, but nevertheless a bug +- B3DImporter: + - Replace bad pointer casting with memcpy +- AppVeyor: + - Cleanup and Addition of VS 2017 and running Tests + - Fixed File Size reported as 0 in tests that use temporary files + - x86 isn't a valid VS platform. Win32 it is, then. + - Replaced the worker image name, which doesn't work as generator name, with a manually created generator name. + - Cleaned up appveyor setup, added VS 2017 to the build matrix and attempted to add running of tests. + - Treat warnings as errors on Appveyor + - Disable warning 4351 on MSVC 2013 +- OpenGEXImporter: + - Copy materials to scene + - Store RefInfo in unique_ptr so they get automatically cleaned up + - Fix IOStream leak + - Store ChildInfo in unique_ptr so they get automatically cleaned up + - improve logging to be able to detect error-prone situations. +- AMFImporter: + - Fix memory leak +- UnrealLoader: + - Fix IOStream leak +- Upgrade RapidJSON to get rid of a clang warning +- zlib: + - Update zlib contribution + - Removed unnecessary files from zlib contribution + - Replaced unsigned long for the crc table to z_crc_t, to match what is returned by get-crc_table +- MakeVerboseFormat: + - Fix delete / delete[] mismatches in MakeVerboseFormat +- MaterialSystem: + - Fix out-of-bounds read in MaterialSystem unit test +- SIB: + - Added support for SIB models from Silo 2.5 +- AssbinExporter: + - Fix strict aliasing violation + - Add Write specialization for aiColor3D +- DefaultLogger: + - Whitespace cleanup to fix GCC misleading indentation warning +- MDP: + - Fix encoding issues. + - PreTransformVertices: + - fix name lost in mesh and nodes when load with flag +- C4D: + - Fixes for C4D importer +- Unzip: + - Latest greatest. + 4.0.1 (2017-07-28) - FIXES/HOUSEKEEPING: - fix version test. diff --git a/CMakeLists.txt b/CMakeLists.txt index 83e1be081..23b6f6d61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- -# Copyright (c) 2006-2018, assimp team - +# Copyright (c) 2006-2019, assimp team +# # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -34,15 +34,32 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #---------------------------------------------------------------------- -SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required -CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) -PROJECT( Assimp ) +SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW) + +CMAKE_MINIMUM_REQUIRED( VERSION 3.0 ) + +# Toggles the use of the hunter package manager +option(HUNTER_ENABLED "Enable Hunter package manager support" OFF) + +include("cmake/HunterGate.cmake") +HunterGate( + URL "https://github.com/ruslo/hunter/archive/v0.23.176.tar.gz" + SHA1 "2e9ae973d028660b735ac4c6142725ca36a0048a" +) + +IF(HUNTER_ENABLED) + add_definitions(-DASSIMP_USE_HUNTER) +ENDIF(HUNTER_ENABLED) + +PROJECT( Assimp VERSION 5.0.0 ) # All supported options ############################################### + OPTION( BUILD_SHARED_LIBS "Build package with shared libraries." ON ) + OPTION( BUILD_FRAMEWORK "Build package as Mac OS X Framework bundle." OFF @@ -83,6 +100,10 @@ OPTION ( ASSIMP_COVERALLS "Enable this to measure test coverage." OFF ) +OPTION ( ASSIMP_ERROR_MAX + "Enable all warnings." + OFF +) OPTION ( ASSIMP_WERROR "Treat warnings as errors." OFF @@ -103,6 +124,22 @@ OPTION ( BUILD_DOCS "Build documentation using Doxygen." OFF ) +OPTION( INJECT_DEBUG_POSTFIX + "Inject debug postfix in .a/.so/.dll lib names" + ON +) + +OPTION ( IGNORE_GIT_HASH + "Don't call git to get the hash." + OFF +) + +IF (IOS AND NOT HUNTER_ENABLED) + IF (NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "Release") + ENDIF (NOT CMAKE_BUILD_TYPE) + ADD_DEFINITIONS(-DENABLE_BITCODE) +ENDIF (IOS AND NOT HUNTER_ENABLED) # Use subset of Windows.h if (WIN32) @@ -114,6 +151,10 @@ IF(MSVC) "Install MSVC debug files." ON ) + IF(NOT (MSVC_VERSION LESS 1900)) + # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier) + ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) + ENDIF() ENDIF(MSVC) IF (BUILD_FRAMEWORK) @@ -129,35 +170,37 @@ ELSE() ENDIF(NOT BUILD_SHARED_LIBS) # Define here the needed parameters -SET (ASSIMP_VERSION_MAJOR 4) -SET (ASSIMP_VERSION_MINOR 1) -SET (ASSIMP_VERSION_PATCH 0) +SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +SET (ASSIMP_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +SET (ASSIMP_VERSION_PATCH ${PROJECT_VERSION_PATCH}) SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) -SET (ASSIMP_SOVERSION 4) -SET (PROJECT_VERSION "${ASSIMP_VERSION}") +SET (ASSIMP_SOVERSION 5) SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) +if(NOT HUNTER_ENABLED) + # Enable C++11 support globally + set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) +endif() -# Enable C++1 globally -set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) +IF(NOT IGNORE_GIT_HASH) + # Get the current working branch + EXECUTE_PROCESS( + COMMAND git rev-parse --abbrev-ref HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE GIT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) -# Get the current working branch -EXECUTE_PROCESS( - COMMAND git rev-parse --abbrev-ref HEAD - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET -) - -# Get the latest abbreviated commit hash of the working branch -EXECUTE_PROCESS( - COMMAND git log -1 --format=%h - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET -) + # Get the latest abbreviated commit hash of the working branch + EXECUTE_PROCESS( + COMMAND git rev-parse --short=8 HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE GIT_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) +ENDIF() IF(NOT GIT_COMMIT_HASH) SET(GIT_COMMIT_HASH 0) @@ -177,8 +220,9 @@ CONFIGURE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h ) -INCLUDE_DIRECTORIES( +INCLUDE_DIRECTORIES( BEFORE ./ + code/ include ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include @@ -197,33 +241,55 @@ ENDIF( UNIX ) # Grouped compiler settings IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) + IF(NOT HUNTER_ENABLED) + SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}") + SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") + ENDIF() # hide all not-exported symbols - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + SET(CMAKE_CXX_FLAGS "-g -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) # enable multi-core compilation with MSVC ADD_COMPILE_OPTIONS(/MP) - IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") - ADD_COMPILE_OPTIONS( /bigobj ) - ENDIF() + ADD_COMPILE_OPTIONS( /bigobj ) # disable "elements of array '' will be default initialized" warning on MSVC2013 IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" ) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + IF(NOT HUNTER_ENABLED) + SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}") + SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") + ENDIF() + SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" ) + SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}") ELSEIF( CMAKE_COMPILER_IS_MINGW ) - SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -std=c++11" ) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) + message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.") + ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3) + message(WARNING "MinGW is old, if you experience errors, update MinGW.") + ENDIF() + IF(NOT HUNTER_ENABLED) + SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") + SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") + ENDIF() + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}") + SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}") ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ENDIF() -IF (IOS) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") -ENDIF() +IF ( IOS AND NOT HUNTER_ENABLED) + IF (CMAKE_BUILD_TYPE STREQUAL "Debug") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og") + ELSE() + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") + # Experimental for pdb generation + ENDIF() +ENDIF( IOS AND NOT HUNTER_ENABLED) IF (ASSIMP_COVERALLS) MESSAGE(STATUS "Coveralls enabled") @@ -232,6 +298,16 @@ IF (ASSIMP_COVERALLS) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") ENDIF() +IF (ASSIMP_ERROR_MAX) + MESSAGE(STATUS "Turning on all warnings") + IF (MSVC) + ADD_COMPILE_OPTIONS(/W4) # NB: there is a /Wall option, pedantic mode + ELSE() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + ENDIF() +ENDIF() + IF (ASSIMP_WERROR) MESSAGE(STATUS "Treating warnings as errors") IF (MSVC) @@ -275,7 +351,9 @@ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING "Path the tool executables are installed to." ) -IF (CMAKE_BUILD_TYPE STREQUAL "Debug") +get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) + +IF (INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug")) SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools") ELSE() SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools") @@ -288,10 +366,72 @@ IF (NOT TARGET uninstall) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() -# cmake configuration files -CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) -CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) -INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) +IF(HUNTER_ENABLED) + set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") + set(INCLUDE_INSTALL_DIR "include") + + set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") + + # Configuration + set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") + set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") + set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") + set(NAMESPACE "${PROJECT_NAME}::") + + # Include module with fuction 'write_basic_package_version_file' + include(CMakePackageConfigHelpers) + + # Note: PROJECT_VERSION is used as a VERSION + write_basic_package_version_file("${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion) + + # Use variables: + # * TARGETS_EXPORT_NAME + # * PROJECT_NAME + configure_package_config_file( + "cmake/assimp-hunter-config.cmake.in" + "${PROJECT_CONFIG}" + INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" + ) + + install( + FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" + DESTINATION "${CONFIG_INSTALL_DIR}" + ) + + install( + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${NAMESPACE}" + DESTINATION "${CONFIG_INSTALL_DIR}" + ) +ELSE(HUNTER_ENABLED) + # cmake configuration files + if(${BUILD_SHARED_LIBS}) + set(BUILD_LIB_TYPE SHARED) + else() + set(BUILD_LIB_TYPE STATIC) + endif() + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE) + IF (is_multi_config) + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-debug.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" @ONLY IMMEDIATE) + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-release.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake" @ONLY IMMEDIATE) + SET(PACKAGE_TARGETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake") + ELSEIF (CMAKE_BUILD_TYPE STREQUAL Debug) + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-debug.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" @ONLY IMMEDIATE) + SET(PACKAGE_TARGETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake") + ELSE() + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-release.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake" @ONLY IMMEDIATE) + SET(PACKAGE_TARGETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake") + ENDIF() + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) + #we should generated these scripts after CMake VERSION 3.0.2 using export(EXPORT ...) and write_basic_package_version_file(...) + INSTALL(FILES + "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" + ${PACKAGE_TARGETS_FILE} + DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) +ENDIF(HUNTER_ENABLED) FIND_PACKAGE( DirectX ) @@ -306,28 +446,58 @@ ENDIF( SYSTEM_IRRXML ) # Search for external dependencies, and build them from source if not found # Search for zlib -IF ( NOT ASSIMP_BUILD_ZLIB ) - FIND_PACKAGE(ZLIB) -ENDIF( NOT ASSIMP_BUILD_ZLIB ) +IF(HUNTER_ENABLED) + hunter_add_package(ZLIB) + find_package(ZLIB CONFIG REQUIRED) -IF( NOT ZLIB_FOUND ) - MESSAGE(STATUS "compiling zlib from souces") - INCLUDE(CheckIncludeFile) - INCLUDE(CheckTypeSize) - INCLUDE(CheckFunctionExists) - # compile from sources - ADD_SUBDIRECTORY(contrib/zlib) - SET(ZLIB_FOUND 1) - SET(ZLIB_LIBRARIES zlibstatic) - SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) -ELSE(NOT ZLIB_FOUND) - ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) - SET(ZLIB_LIBRARIES_LINKED -lz) -ENDIF(NOT ZLIB_FOUND) -INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) + add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB) + set(ZLIB_FOUND TRUE) + set(ZLIB_LIBRARIES ZLIB::zlib) + set(ASSIMP_BUILD_MINIZIP TRUE) +ELSE(HUNTER_ENABLED) + IF ( NOT ASSIMP_BUILD_ZLIB ) + FIND_PACKAGE(ZLIB) + ENDIF( NOT ASSIMP_BUILD_ZLIB ) -# Search for unzip -use_pkgconfig(UNZIP minizip) + IF( NOT ZLIB_FOUND ) + MESSAGE(STATUS "compiling zlib from sources") + INCLUDE(CheckIncludeFile) + INCLUDE(CheckTypeSize) + INCLUDE(CheckFunctionExists) + + # Explicitly turn off ASM686 and AMD64 cmake options. + # The AMD64 option causes a build failure on MSVC and the ASM builds seem to have problems: + # https://github.com/madler/zlib/issues/41#issuecomment-125848075 + # Also prevents these options from "polluting" the cmake options if assimp is being + # included as a submodule. + set( ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE ) + set( AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE ) + + # compile from sources + ADD_SUBDIRECTORY(contrib/zlib) + SET(ZLIB_FOUND 1) + SET(ZLIB_LIBRARIES zlibstatic) + SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) + # need to ensure we don't link with system zlib or minizip as well. + SET(ASSIMP_BUILD_MINIZIP 1) + ELSE(NOT ZLIB_FOUND) + ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) + SET(ZLIB_LIBRARIES_LINKED -lz) + ENDIF(NOT ZLIB_FOUND) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) +ENDIF(HUNTER_ENABLED) + +IF( NOT IOS ) + IF( NOT ASSIMP_BUILD_MINIZIP ) + use_pkgconfig(UNZIP minizip) + ENDIF( NOT ASSIMP_BUILD_MINIZIP ) +ELSE ( NOT IOS ) + IF( NOT BUILD_SHARED_LIBS ) + IF( NOT ASSIMP_BUILD_MINIZIP ) + use_pkgconfig(UNZIP minizip) + ENDIF( NOT ASSIMP_BUILD_MINIZIP ) + ENDIF ( NOT BUILD_SHARED_LIBS ) +ENDIF ( NOT IOS ) IF ( ASSIMP_NO_EXPORT ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT) @@ -400,49 +570,27 @@ ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) -ADD_SUBDIRECTORY(contrib) +IF(NOT HUNTER_ENABLED) + ADD_SUBDIRECTORY(contrib) +ENDIF(NOT HUNTER_ENABLED) ADD_SUBDIRECTORY( code/ ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) + # The viewer for windows only IF ( WIN32 AND DirectX_D3DX9_LIBRARY ) OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) IF ( ASSIMP_BUILD_ASSIMP_VIEW ) ADD_SUBDIRECTORY( tools/assimp_view/ ) ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW ) ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY ) - + # Te command line tool ADD_SUBDIRECTORY( tools/assimp_cmd/ ) - - # Check dependencies for assimp_qt_viewer. - # Why here? Maybe user do not want Qt viewer and have no Qt. - # Why assimp_qt_viewer/CMakeLists.txt still contain similar check? - # Because viewer can be build independently of Assimp. - FIND_PACKAGE(Qt5Widgets QUIET) - FIND_PACKAGE(DevIL QUIET) - FIND_PACKAGE(OpenGL QUIET) - IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND) - ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ ) - ELSE() - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "") - IF (NOT Qt5_FOUND) - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5") - ENDIF (NOT Qt5_FOUND) - - IF (NOT IL_FOUND) - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL") - ENDIF (NOT IL_FOUND) - - IF (NOT OPENGL_FOUND) - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL") - ENDIF (NOT OPENGL_FOUND) - - MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}") - ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_SAMPLES) IF ( WIN32 ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) + ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 ) ENDIF ( WIN32 ) ADD_SUBDIRECTORY( samples/SimpleOpenGL/ ) ENDIF ( ASSIMP_BUILD_SAMPLES ) @@ -457,7 +605,7 @@ INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTAL IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) # Packing information - SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}") + SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}.{ASSIMP_VERSION_MINOR}") SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") SET(CPACK_PACKAGE_VENDOR "https://github.com/assimp") SET(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") @@ -487,8 +635,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" ) SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}") SET(CPACK_DEBIAN_PACKAGE_SUGGESTS) - SET(CPACK_DEBIAN_PACKAGE_NAME "assimp") - SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging) + set(cPACK_DEBIAN_PACKAGE_NAME "assimp") + SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging) SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) SET(CPACK_DEBIAN_CHANGELOG) execute_process(COMMAND lsb_release -is @@ -508,18 +656,22 @@ if(WIN32) if (CMAKE_SIZEOF_VOID_P EQUAL 8) SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin64/") SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib64/") - elseif() + else() SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin32/") SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/") ENDIF() - IF(MSVC12) - SET(ASSIMP_MSVC_VERSION "vc120") - ELSEIF(MSVC14) - SET(ASSIMP_MSVC_VERSION "vc140") - ELSEIF(MSVC15) - SET(ASSIMP_MSVC_VERSION "vc141") - ENDIF(MSVC12) + IF(MSVC_TOOLSET_VERSION) + set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}") + ELSE() + IF(MSVC12) + SET(ASSIMP_MSVC_VERSION "vc120") + ELSEIF(MSVC14) + SET(ASSIMP_MSVC_VERSION "vc140") + ELSEIF(MSVC15) + SET(ASSIMP_MSVC_VERSION "vc141") + ENDIF(MSVC12) + ENDIF() IF(MSVC12 OR MSVC14 OR MSVC15 ) ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..82ef07a65 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# How to contribute + +If you want to contribute, follow these steps: + +- First, create your own clone of assimp. +- When you want to fix a bug or add a new feature, create a branch on your own fork following [these instructions](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). +- Push it to your fork of the repository and open a pull request. +- A pull request will start our continuous integration service, which checks if the build works for Linux and Windows. + It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fail, fix it and the tests will be restarted automatically. + - At the end, we will perform a code review and merge your branch to the master branch. diff --git a/INSTALL b/INSTALL index 3baaddc4a..350a5f109 100644 --- a/INSTALL +++ b/INSTALL @@ -35,10 +35,16 @@ http://www.cmake.org/. For Unix: -1. cmake CMakeLists.txt -G 'Unix Makefiles' -2. make +1. mkdir build && cd build +2. cmake .. -G 'Unix Makefiles' +3. make -j4 For Windows: 1. Open a command prompt -2. cmake CMakeLists.txt -2. Open your default IDE and build it +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/Readme.md b/Readme.md index 4ee8a0e90..863e64f08 100644 --- a/Readme.md +++ b/Readme.md @@ -1,7 +1,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 build status ### +### Current project status ### [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp) @@ -10,10 +10,15 @@ A library to import and export various 3d-model-formats including scene-post-pro [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) +[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS. +[Check the latest doc](https://assimp-docs.readthedocs.io/en/latest/). + Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases). @@ -30,36 +35,44 @@ One-off donations via PayPal: Please check our Wiki as well: https://github.com/assimp/assimp/wiki +If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb + #### Supported file formats #### __Importers__: - 3D -- 3DS -- 3MF +- [3DS](https://en.wikipedia.org/wiki/.3ds) +- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format) - AC -- AC3D +- [AC3D](https://en.wikipedia.org/wiki/AC3D) - ACC - AMJ - ASE - ASK - B3D -- BLEND (Blender) -- BVH -- COB +- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format)) +- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy) - CMS -- DAE/Collada -- DXF +- COB +- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA) +- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF) - ENFF -- FBX -- glTF 1.0 + GLB -- glTF 2.0 +- [FBX](https://en.wikipedia.org/wiki/FBX) +- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB +- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0): + At the moment for glTF2.0 the following extensions are supported: + + KHR_lights_punctual ( 5.0 ) + + KHR_materials_pbrSpecularGlossiness ( 5.0 ) + + KHR_materials_unlit ( 5.0 ) + + KHR_texture_transform ( 5.1 under test ) - HMB - IFC-STEP - IRR / IRRMESH -- LWO +- [LWO](https://en.wikipedia.org/wiki/LightWave_3D) - LWS - LXO +- [M3D](https://bztsrc.gitlab.io/model3d) - MD2 - MD3 - MD5 @@ -70,10 +83,10 @@ __Importers__: - MS3D - NDO - NFF -- OBJ -- OFF -- OGEX -- PLY +- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file) +- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format)) +- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange) +- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) - PMX - PRJ - Q3O @@ -82,19 +95,19 @@ __Importers__: - SCN - SIB - SMD -- STL -- STP +- [STP](https://en.wikipedia.org/wiki/ISO_10303-21) +- [STL](https://en.wikipedia.org/wiki/STL_(file_format)) - TER - UC - VTA - X -- X3D +- [X3D](https://en.wikipedia.org/wiki/X3D) - XGL - ZGL Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): -- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) +- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) IMporting geometry + node hierarchy are currently supported __Exporters__: @@ -113,22 +126,23 @@ __Exporters__: - FBX ( experimental ) ### Building ### -Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do. +Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do. ### Ports ### * [Android](port/AndroidJNI/README.md) * [Python](port/PyAssimp/README.md) -* [.NET](port/AssimpNET/Readme.md) +* [.NET](https://github.com/kebby/assimp-net) * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) * [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) +* [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port. ### Other tools ### [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. #### Repository structure #### -Open Asset Import Library is implemented in C++. The directory structure is: +Open Asset Import Library is implemented in C++. The directory structure looks like: /code Source code /contrib Third-party libraries @@ -140,9 +154,12 @@ Open Asset Import Library is implemented in C++. The directory structure is: /tools Tools (old assimp viewer, command line `assimp`) /samples A small number of samples to illustrate possible use cases for Assimp - /workspaces Build environments for vc,xcode,... (deprecated, - CMake has superseeded all legacy build options!) +The source code is organized in the following way: + + code/Common The base implementation for importers and the infrastructure + code/PostProcessing The post-processing steps + code/ Implementation for import and export for the format ### Where to get help ### For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format. diff --git a/appveyor.yml b/appveyor.yml index 1b87286f6..fa0a125f0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,6 +17,8 @@ image: - Visual Studio 2013 - Visual Studio 2015 - Visual Studio 2017 + - Visual Studio 2019 + - MinGW platform: - Win32 @@ -27,11 +29,18 @@ configuration: Release install: - set PATH=C:\Ruby24-x64\bin;%PATH% - set CMAKE_DEFINES -DASSIMP_WERROR=ON + - if [%COMPILER%]==[MinGW] set PATH=C:\MinGW\bin;%PATH% - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 - - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 - - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" set CMAKE_GENERATOR_NAME=Visual Studio 16 2019 + - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" -A %platform% . + # Rename sh.exe as sh.exe in PATH interferes with MinGW - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 + + - rename "C:\Program Files\Git\usr\bin\sh.exe" "sh2.exe" + - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5" + - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe + - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe cache: - code\assimp.dir\%CONFIGURATION% @@ -50,6 +59,13 @@ build: project: Assimp.sln after_build: + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" ( + if "%platform%"=="x64" ( + iscc packaging\windows-innosetup\script_x64.iss + ) else ( + iscc packaging\windows-innosetup\script_x86.iss + ) + ) - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\* test_script: diff --git a/assimp-config.cmake.in b/assimp-config.cmake.in index 5031c8f8d..0ab9fd071 100644 --- a/assimp-config.cmake.in +++ b/assimp-config.cmake.in @@ -1,62 +1 @@ -# - Find Assimp Installation -# -# Users can set the following variables before calling the module: -# ASSIMP_DIR - The preferred installation prefix for searching for ASSIMP. Set by the user. -# -# ASSIMP_ROOT_DIR - the root directory where the installation can be found -# ASSIMP_CXX_FLAGS - extra flags for compilation -# ASSIMP_LINK_FLAGS - extra flags for linking -# ASSIMP_INCLUDE_DIRS - include directories -# ASSIMP_LIBRARY_DIRS - link directories -# ASSIMP_LIBRARIES - libraries to link plugins with -# ASSIMP_Boost_VERSION - the boost version assimp was compiled with -get_filename_component(_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) -get_filename_component(_PREFIX "${_PREFIX}" PATH) -get_filename_component(_PREFIX "${_PREFIX}" PATH) -get_filename_component(ASSIMP_ROOT_DIR "${_PREFIX}" PATH) - -if( MSVC ) - # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix - if( MSVC70 OR MSVC71 ) - set(MSVC_PREFIX "vc70") - elseif( MSVC80 ) - set(MSVC_PREFIX "vc80") - elseif( MSVC90 ) - set(MSVC_PREFIX "vc90") - elseif( MSVC10 ) - set(MSVC_PREFIX "vc100") - elseif( MSVC11 ) - set(MSVC_PREFIX "vc110") - elseif( MSVC12 ) - set(MSVC_PREFIX "vc120") - elseif( MSVC14 ) - set(MSVC_PREFIX "vc140") - else() - set(MSVC_PREFIX "vc150") - endif() - set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) -else() - set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" ) -endif() - -set( ASSIMP_CXX_FLAGS ) # dynamically linked library -set( ASSIMP_LINK_FLAGS "" ) -set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") -set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") -set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX}) -set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@) - -# for compatibility with pkg-config -set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") -set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") - -MARK_AS_ADVANCED( - ASSIMP_ROOT_DIR - ASSIMP_CXX_FLAGS - ASSIMP_LINK_FLAGS - ASSIMP_INCLUDE_DIRS - ASSIMP_LIBRARIES - ASSIMP_CFLAGS_OTHER - ASSIMP_LDFLAGS_OTHER - ASSIMP_LIBRARY_SUFFIX -) +include(${CMAKE_CURRENT_LIST_DIR}/assimpTargets.cmake) diff --git a/assimp.pc.in b/assimp.pc.in index 02cf59dc4..c659e19f2 100644 --- a/assimp.pc.in +++ b/assimp.pc.in @@ -1,7 +1,7 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@/ libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@ -includedir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_INCLUDE_INSTALL_DIR@ +includedir=@CMAKE_INSTALL_PREFIX@/../include/@ASSIMP_INCLUDE_INSTALL_DIR@ Name: @CMAKE_PROJECT_NAME@ Description: Import various well-known 3D model formats in an uniform manner. diff --git a/assimpTargets-debug.cmake.in b/assimpTargets-debug.cmake.in new file mode 100644 index 000000000..e4ccbfba9 --- /dev/null +++ b/assimpTargets-debug.cmake.in @@ -0,0 +1,123 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Debug". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@) + +if(MSVC) + if(MSVC_TOOLSET_VERSION) + set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}") + else() + if( MSVC70 OR MSVC71 ) + set(MSVC_PREFIX "vc70") + elseif( MSVC80 ) + set(MSVC_PREFIX "vc80") + elseif( MSVC90 ) + set(MSVC_PREFIX "vc90") + elseif( MSVC10 ) + set(MSVC_PREFIX "vc100") + elseif( MSVC11 ) + set(MSVC_PREFIX "vc110") + elseif( MSVC12 ) + set(MSVC_PREFIX "vc120") + elseif( MSVC_VERSION LESS 1910) + set(MSVC_PREFIX "vc140") + elseif( MSVC_VERSION LESS 1920) + set(MSVC_PREFIX "vc141") + elseif( MSVC_VERSION LESS 1930) + set(MSVC_PREFIX "vc142") + else() + set(MSVC_PREFIX "vc150") + endif() + endif() + set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) + + file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX) + + if(ASSIMP_BUILD_SHARED_LIBS) + set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") + set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") + + # Import target "assimp::assimp" for configuration "Debug" + set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/${importLibraryName}" + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}") + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" ) + else() + set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") + + # Import target "assimp::assimp" for configuration "Debug" + set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}") + endif() + +else() + set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" ) + if(ASSIMP_BUILD_SHARED_LIBS) + if(WIN32) + # Handle MinGW compiler. + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") + elseif(APPLE) + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@.@ASSIMP_VERSION_MAJOR@@CMAKE_SHARED_LIBRARY_SUFFIX@") + else() + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") + endif() + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_SONAME_DEBUG "${sharedLibraryName}" + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) + else() + set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" ) + endif() +endif() + + + + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) + +get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH) +set( ASSIMP_CXX_FLAGS ) # dynamically linked library +set( ASSIMP_LINK_FLAGS "" ) +set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") +set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") +if(ASSIMP_BUILD_SHARED_LIBS) + set( ASSIMP_LIBRARIES ${sharedLibraryName}) +else() + set( ASSIMP_LIBRARIES ${staticLibraryName}) +endif() + +# for compatibility with pkg-config +set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") +set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") + +MARK_AS_ADVANCED( + ASSIMP_ROOT_DIR + ASSIMP_CXX_FLAGS + ASSIMP_LINK_FLAGS + ASSIMP_INCLUDE_DIRS + ASSIMP_LIBRARIES + ASSIMP_CFLAGS_OTHER + ASSIMP_LDFLAGS_OTHER + ASSIMP_LIBRARY_SUFFIX + ASSIMP_BUILD_SHARED_LIBS +) diff --git a/assimpTargets-release.cmake.in b/assimpTargets-release.cmake.in new file mode 100644 index 000000000..79b643a9a --- /dev/null +++ b/assimpTargets-release.cmake.in @@ -0,0 +1,122 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@) + +if(MSVC) + if(MSVC_TOOLSET_VERSION) + set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}") + else() + if( MSVC70 OR MSVC71 ) + set(MSVC_PREFIX "vc70") + elseif( MSVC80 ) + set(MSVC_PREFIX "vc80") + elseif( MSVC90 ) + set(MSVC_PREFIX "vc90") + elseif( MSVC10 ) + set(MSVC_PREFIX "vc100") + elseif( MSVC11 ) + set(MSVC_PREFIX "vc110") + elseif( MSVC12 ) + set(MSVC_PREFIX "vc120") + elseif( MSVC_VERSION LESS 1910) + set(MSVC_PREFIX "vc140") + elseif( MSVC_VERSION LESS 1920) + set(MSVC_PREFIX "vc141") + elseif( MSVC_VERSION LESS 1930) + set(MSVC_PREFIX "vc142") + else() + set(MSVC_PREFIX "vc150") + endif() + endif() + set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) + + file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX) + + if(ASSIMP_BUILD_SHARED_LIBS) + set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@") + set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_IMPORT_LIBRARY_SUFFIX@") + + # Import target "assimp::assimp" for configuration "Release" + set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/${importLibraryName}" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}") + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" ) + else() + set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@") + + # Import target "assimp::assimp" for configuration "Release" + set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}") + endif() + +else() + set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" ) + if(ASSIMP_BUILD_SHARED_LIBS) + if(WIN32) + # Handle MinGW compiler. + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") + elseif(APPLE) + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}.@ASSIMP_VERSION_MAJOR@@CMAKE_SHARED_LIBRARY_SUFFIX@") + else() + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") + endif() + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_SONAME_RELEASE "${sharedLibraryName}" + + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) + else() + set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@") + set_target_properties(assimp::assimp PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}" + ) + list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" ) + endif() +endif() + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) + +get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH) + +set( ASSIMP_CXX_FLAGS ) # dynamically linked library +set( ASSIMP_LINK_FLAGS "" ) +set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") +set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") +if(ASSIMP_BUILD_SHARED_LIBS) + set( ASSIMP_LIBRARIES ${sharedLibraryName}) +else() + set( ASSIMP_LIBRARIES ${staticLibraryName}) +endif() + +# for compatibility with pkg-config +set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") +set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") + +MARK_AS_ADVANCED( + ASSIMP_ROOT_DIR + ASSIMP_CXX_FLAGS + ASSIMP_LINK_FLAGS + ASSIMP_INCLUDE_DIRS + ASSIMP_LIBRARIES + ASSIMP_CFLAGS_OTHER + ASSIMP_LDFLAGS_OTHER + ASSIMP_LIBRARY_SUFFIX + ASSIMP_BUILD_SHARED_LIBS +) diff --git a/assimpTargets.cmake.in b/assimpTargets.cmake.in new file mode 100644 index 000000000..b1c618c3a --- /dev/null +++ b/assimpTargets.cmake.in @@ -0,0 +1,104 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6) +# Required for the evaluation of "if(@BUILD_SHARED_LIBS@)" below to function +cmake_policy(SET CMP0012 NEW) + +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget assimp::assimp) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + unset(_targetsDefined) + unset(_targetsNotDefined) + unset(_expectedTargets) + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target assimp::assimp +add_library(assimp::assimp @BUILD_LIB_TYPE@ IMPORTED) + +set_target_properties(assimp::assimp PROPERTIES + COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION" + INTERFACE_assimp_MAJOR_VERSION "1" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include" + #INTERFACE_LINK_LIBRARIES "TxtUtils::TxtUtils;MealyMachine::MealyMachine" +) + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") +endif() + +# Load information for each installed configuration. +get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(GLOB CONFIG_FILES "${_DIR}/assimpTargets-*.cmake") +foreach(f ${CONFIG_FILES}) + include(${f}) +endforeach() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/cmake-modules/Findassimp.cmake b/cmake-modules/Findassimp.cmake index 95f3250b3..663645574 100644 --- a/cmake-modules/Findassimp.cmake +++ b/cmake-modules/Findassimp.cmake @@ -54,14 +54,18 @@ else(WIN32) find_path( assimp_INCLUDE_DIRS - NAMES postprocess.h scene.h version.h config.h cimport.h - PATHS /usr/local/include/ + NAMES assimp/postprocess.h assimp/scene.h assimp/version.h assimp/config.h assimp/cimport.h + PATHS /usr/local/include + PATHS /usr/include/ + ) find_library( assimp_LIBRARIES NAMES assimp PATHS /usr/local/lib/ + PATHS /usr/lib64/ + PATHS /usr/lib/ ) if (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) @@ -78,4 +82,4 @@ else(WIN32) endif (assimp_FIND_REQUIRED) endif (assimp_FOUND) -endif(WIN32) \ No newline at end of file +endif(WIN32) diff --git a/cmake/HunterGate.cmake b/cmake/HunterGate.cmake new file mode 100644 index 000000000..887557a58 --- /dev/null +++ b/cmake/HunterGate.cmake @@ -0,0 +1,540 @@ +# Copyright (c) 2013-2018, Ruslan Baratov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a gate file to Hunter package manager. +# Include this file using `include` command and add package you need, example: +# +# cmake_minimum_required(VERSION 3.2) +# +# include("cmake/HunterGate.cmake") +# HunterGate( +# URL "https://github.com/path/to/hunter/archive.tar.gz" +# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" +# ) +# +# project(MyProject) +# +# hunter_add_package(Foo) +# hunter_add_package(Boo COMPONENTS Bar Baz) +# +# Projects: +# * https://github.com/hunter-packages/gate/ +# * https://github.com/ruslo/hunter + +option(HUNTER_ENABLED "Enable Hunter package manager support" ON) + +if(HUNTER_ENABLED) + if(CMAKE_VERSION VERSION_LESS "3.2") + message( + FATAL_ERROR + "At least CMake version 3.2 required for Hunter dependency management." + " Update CMake or set HUNTER_ENABLED to OFF." + ) + endif() +endif() + +include(CMakeParseArguments) # cmake_parse_arguments + +option(HUNTER_STATUS_PRINT "Print working status" ON) +option(HUNTER_STATUS_DEBUG "Print a lot info" OFF) +option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON) + +set(HUNTER_WIKI "https://github.com/ruslo/hunter/wiki") + +function(hunter_gate_status_print) + if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + message(STATUS "[hunter] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_status_debug) + if(HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + string(TIMESTAMP timestamp) + message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_wiki wiki_page) + message("------------------------------ WIKI -------------------------------") + message(" ${HUNTER_WIKI}/${wiki_page}") + message("-------------------------------------------------------------------") + message("") + message(FATAL_ERROR "") +endfunction() + +function(hunter_gate_internal_error) + message("") + foreach(print_message ${ARGV}) + message("[hunter ** INTERNAL **] ${print_message}") + endforeach() + message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_wiki("error.internal") +endfunction() + +function(hunter_gate_fatal_error) + cmake_parse_arguments(hunter "" "WIKI" "" "${ARGV}") + string(COMPARE EQUAL "${hunter_WIKI}" "" have_no_wiki) + if(have_no_wiki) + hunter_gate_internal_error("Expected wiki") + endif() + message("") + foreach(x ${hunter_UNPARSED_ARGUMENTS}) + message("[hunter ** FATAL ERROR **] ${x}") + endforeach() + message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_wiki("${hunter_WIKI}") +endfunction() + +function(hunter_gate_user_error) + hunter_gate_fatal_error(${ARGV} WIKI "error.incorrect.input.data") +endfunction() + +function(hunter_gate_self root version sha1 result) + string(COMPARE EQUAL "${root}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("root is empty") + endif() + + string(COMPARE EQUAL "${version}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("version is empty") + endif() + + string(COMPARE EQUAL "${sha1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("sha1 is empty") + endif() + + string(SUBSTRING "${sha1}" 0 7 archive_id) + + if(EXISTS "${root}/cmake/Hunter") + set(hunter_self "${root}") + else() + set( + hunter_self + "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked" + ) + endif() + + set("${result}" "${hunter_self}" PARENT_SCOPE) +endfunction() + +# Set HUNTER_GATE_ROOT cmake variable to suitable value. +function(hunter_gate_detect_root) + # Check CMake variable + string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty) + if(not_empty) + set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable") + return() + endif() + + # Check environment variable + string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty) + if(not_empty) + set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by environment variable") + return() + endif() + + # Check HOME environment variable + string(COMPARE NOTEQUAL "$ENV{HOME}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable") + return() + endif() + + # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only) + if(WIN32) + string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using SYSTEMDRIVE environment variable" + ) + return() + endif() + + string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using USERPROFILE environment variable" + ) + return() + endif() + endif() + + hunter_gate_fatal_error( + "Can't detect HUNTER_ROOT" + WIKI "error.detect.hunter.root" + ) +endfunction() + +function(hunter_gate_download dir) + string( + COMPARE + NOTEQUAL + "$ENV{HUNTER_DISABLE_AUTOINSTALL}" + "" + disable_autoinstall + ) + if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL) + hunter_gate_fatal_error( + "Hunter not found in '${dir}'" + "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'" + "Settings:" + " HUNTER_ROOT: ${HUNTER_GATE_ROOT}" + " HUNTER_SHA1: ${HUNTER_GATE_SHA1}" + WIKI "error.run.install" + ) + endif() + string(COMPARE EQUAL "${dir}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("Empty 'dir' argument") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_SHA1 empty") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_URL empty") + endif() + + set(done_location "${dir}/DONE") + set(sha1_location "${dir}/SHA1") + + set(build_dir "${dir}/Build") + set(cmakelists "${dir}/CMakeLists.txt") + + hunter_gate_status_debug("Locking directory: ${dir}") + file(LOCK "${dir}" DIRECTORY GUARD FUNCTION) + hunter_gate_status_debug("Lock done") + + if(EXISTS "${done_location}") + # while waiting for lock other instance can do all the job + hunter_gate_status_debug("File '${done_location}' found, skip install") + return() + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(MAKE_DIRECTORY "${build_dir}") # check directory permissions + + # Disabling languages speeds up a little bit, reduces noise in the output + # and avoids path too long windows error + file( + WRITE + "${cmakelists}" + "cmake_minimum_required(VERSION 3.2)\n" + "project(HunterDownload LANGUAGES NONE)\n" + "include(ExternalProject)\n" + "ExternalProject_Add(\n" + " Hunter\n" + " URL\n" + " \"${HUNTER_GATE_URL}\"\n" + " URL_HASH\n" + " SHA1=${HUNTER_GATE_SHA1}\n" + " DOWNLOAD_DIR\n" + " \"${dir}\"\n" + " TLS_VERIFY\n" + " ${HUNTER_TLS_VERIFY}\n" + " SOURCE_DIR\n" + " \"${dir}/Unpacked\"\n" + " CONFIGURE_COMMAND\n" + " \"\"\n" + " BUILD_COMMAND\n" + " \"\"\n" + " INSTALL_COMMAND\n" + " \"\"\n" + ")\n" + ) + + if(HUNTER_STATUS_DEBUG) + set(logging_params "") + else() + set(logging_params OUTPUT_QUIET) + endif() + + hunter_gate_status_debug("Run generate") + + # Need to add toolchain file too. + # Otherwise on Visual Studio + MDD this will fail with error: + # "Could not find an appropriate version of the Windows 10 SDK installed on this machine" + if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") + get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE) + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}") + else() + # 'toolchain_arg' can't be empty + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=") + endif() + + string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make) + if(no_make) + set(make_arg "") + else() + # Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM + set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") + endif() + + execute_process( + COMMAND + "${CMAKE_COMMAND}" + "-H${dir}" + "-B${build_dir}" + "-G${CMAKE_GENERATOR}" + "${toolchain_arg}" + ${make_arg} + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error( + "Configure project failed." + "To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}" + "In directory ${dir}" + ) + endif() + + hunter_gate_status_print( + "Initializing Hunter workspace (${HUNTER_GATE_SHA1})" + " ${HUNTER_GATE_URL}" + " -> ${dir}" + ) + execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error("Build project failed") + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}") + file(WRITE "${done_location}" "DONE") + + hunter_gate_status_debug("Finished") +endfunction() + +# Must be a macro so master file 'cmake/Hunter' can +# apply all variables easily just by 'include' command +# (otherwise PARENT_SCOPE magic needed) +macro(HunterGate) + if(HUNTER_GATE_DONE) + # variable HUNTER_GATE_DONE set explicitly for external project + # (see `hunter_download`) + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() + + # First HunterGate command will init Hunter, others will be ignored + get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET) + + if(NOT HUNTER_ENABLED) + # Empty function to avoid error "unknown function" + function(hunter_add_package) + endfunction() + + set( + _hunter_gate_disabled_mode_dir + "${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode" + ) + if(EXISTS "${_hunter_gate_disabled_mode_dir}") + hunter_gate_status_debug( + "Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}" + ) + list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}") + endif() + elseif(_hunter_gate_done) + hunter_gate_status_debug("Secondary HunterGate (use old settings)") + hunter_gate_self( + "${HUNTER_CACHED_ROOT}" + "${HUNTER_VERSION}" + "${HUNTER_SHA1}" + _hunter_self + ) + include("${_hunter_self}/cmake/Hunter") + else() + set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}") + + string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name) + if(_have_project_name) + hunter_gate_fatal_error( + "Please set HunterGate *before* 'project' command. " + "Detected project: ${PROJECT_NAME}" + WIKI "error.huntergate.before.project" + ) + endif() + + cmake_parse_arguments( + HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV} + ) + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1) + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url) + string( + COMPARE + NOTEQUAL + "${HUNTER_GATE_UNPARSED_ARGUMENTS}" + "" + _have_unparsed + ) + string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global) + string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath) + + if(_have_unparsed) + hunter_gate_user_error( + "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}" + ) + endif() + if(_empty_sha1) + hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory") + endif() + if(_empty_url) + hunter_gate_user_error("URL suboption of HunterGate is mandatory") + endif() + if(_have_global) + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)") + endif() + endif() + if(HUNTER_GATE_LOCAL) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)") + endif() + endif() + if(_have_filepath) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)") + endif() + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)") + endif() + endif() + + hunter_gate_detect_root() # set HUNTER_GATE_ROOT + + # Beautify path, fix probable problems with windows path slashes + get_filename_component( + HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE + ) + hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}") + if(NOT HUNTER_ALLOW_SPACES_IN_PATH) + string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces) + if(NOT _contain_spaces EQUAL -1) + hunter_gate_fatal_error( + "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces." + "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error" + "(Use at your own risk!)" + WIKI "error.spaces.in.hunter.root" + ) + endif() + endif() + + string( + REGEX + MATCH + "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*" + HUNTER_GATE_VERSION + "${HUNTER_GATE_URL}" + ) + string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty) + if(_is_empty) + set(HUNTER_GATE_VERSION "unknown") + endif() + + hunter_gate_self( + "${HUNTER_GATE_ROOT}" + "${HUNTER_GATE_VERSION}" + "${HUNTER_GATE_SHA1}" + _hunter_self + ) + + set(_master_location "${_hunter_self}/cmake/Hunter") + if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter") + # Hunter downloaded manually (e.g. by 'git clone') + set(_unused "xxxxxxxxxx") + set(HUNTER_GATE_SHA1 "${_unused}") + set(HUNTER_GATE_VERSION "${_unused}") + else() + get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE) + set(_done_location "${_archive_id_location}/DONE") + set(_sha1_location "${_archive_id_location}/SHA1") + + # Check Hunter already downloaded by HunterGate + if(NOT EXISTS "${_done_location}") + hunter_gate_download("${_archive_id_location}") + endif() + + if(NOT EXISTS "${_done_location}") + hunter_gate_internal_error("hunter_gate_download failed") + endif() + + if(NOT EXISTS "${_sha1_location}") + hunter_gate_internal_error("${_sha1_location} not found") + endif() + file(READ "${_sha1_location}" _sha1_value) + string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal) + if(NOT _is_equal) + hunter_gate_internal_error( + "Short SHA1 collision:" + " ${_sha1_value} (from ${_sha1_location})" + " ${HUNTER_GATE_SHA1} (HunterGate)" + ) + endif() + if(NOT EXISTS "${_master_location}") + hunter_gate_user_error( + "Master file not found:" + " ${_master_location}" + "try to update Hunter/HunterGate" + ) + endif() + endif() + include("${_master_location}") + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() +endmacro() diff --git a/cmake/assimp-hunter-config.cmake.in b/cmake/assimp-hunter-config.cmake.in new file mode 100644 index 000000000..34762ac54 --- /dev/null +++ b/cmake/assimp-hunter-config.cmake.in @@ -0,0 +1,14 @@ +@PACKAGE_INIT@ + +find_package(RapidJSON CONFIG REQUIRED) +find_package(ZLIB CONFIG REQUIRED) +find_package(utf8 CONFIG REQUIRED) +find_package(irrXML CONFIG REQUIRED) +find_package(minizip CONFIG REQUIRED) +find_package(openddlparser CONFIG REQUIRED) +find_package(poly2tri CONFIG REQUIRED) +find_package(polyclipping CONFIG REQUIRED) +find_package(zip CONFIG REQUIRED) + +include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/code/3DSConverter.cpp b/code/3DS/3DSConverter.cpp similarity index 96% rename from code/3DSConverter.cpp rename to code/3DS/3DSConverter.cpp index 081da1bcf..3c3da36a3 100644 --- a/code/3DSConverter.cpp +++ b/code/3DS/3DSConverter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "3DSLoader.h" -#include "TargetAnimation.h" +#include "Common/TargetAnimation.h" #include #include #include @@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() unsigned int idx( NotSet ); for (unsigned int i = 0; i < mScene->mMaterials.size();++i) { - std::string &s = mScene->mMaterials[i].mName; + std::string s = mScene->mMaterials[i].mName; for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) { *it = static_cast< char >( ::tolower( *it ) ); } @@ -120,7 +120,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() else if ( (*a) >= mScene->mMaterials.size()) { (*a) = idx; - DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material"); + ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material"); ++cnt; } } @@ -132,7 +132,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f); mScene->mMaterials.push_back(sMat); - DefaultLogger::get()->info("3DS: Generating default material"); + ASSIMP_LOG_INFO("3DS: Generating default material"); } } @@ -147,12 +147,12 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh) { if ((*i).mIndices[a] >= sMesh.mPositions.size()) { - DefaultLogger::get()->warn("3DS: Vertex index overflow)"); + ASSIMP_LOG_WARN("3DS: Vertex index overflow)"); (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1; } if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) { - DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)"); + ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)"); (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1; } } @@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type) mat.AddProperty( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); // Setup the texture mapping mode - mat.AddProperty((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); - mat.AddProperty((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); + 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)); // Mirroring - double the scaling values // FIXME: this is not really correct ... @@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, case D3DS::Discreet3DS::Blinn : eShading = aiShadingMode_Blinn; break; } - mat.AddProperty( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); + int eShading_ = static_cast(eShading); + mat.AddProperty(&eShading_, 1, AI_MATKEY_SHADING_MODEL); // DIFFUSE texture if( oldMat.sTexDiffuse.mMapName.length() > 0) @@ -497,7 +499,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, pvCurrent->x *= -1.f; t2->x *= -1.f; } - DefaultLogger::get()->info("3DS: Flipping mesh X-Axis"); + ASSIMP_LOG_INFO("3DS: Flipping mesh X-Axis"); } // Handle pivot point @@ -573,11 +575,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, pcIn->aTargetPositionKeys.size() > 1) { aiAnimation* anim = pcSOut->mAnimations[0]; - ai_assert(NULL != anim); + ai_assert(nullptr != anim); if (pcIn->aCameraRollKeys.size() > 1) { - DefaultLogger::get()->debug("3DS: Converting camera roll track ..."); + 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 @@ -597,7 +599,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, #if 0 if (pcIn->aTargetPositionKeys.size() > 1) { - DefaultLogger::get()->debug("3DS: Converting target track ..."); + ASSIMP_LOG_DEBUG("3DS: Converting target track ..."); // Camera or spot light - need to convert the separate // target position channel to our representation @@ -743,7 +745,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) // | | | | | // MESH_0 MESH_1 MESH_2 ... MESH_N CAMERA_0 .... // - DefaultLogger::get()->warn("No hierarchy information has been found in the file. "); + 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()); diff --git a/code/3DSExporter.cpp b/code/3DS/3DSExporter.cpp similarity index 98% rename from code/3DSExporter.cpp rename to code/3DS/3DSExporter.cpp index fcd24d8aa..1117a52ef 100644 --- a/code/3DSExporter.cpp +++ b/code/3DS/3DSExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -43,15 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER -#include "3DSExporter.h" -#include "3DSLoader.h" -#include "3DSHelper.h" +#include "3DS/3DSExporter.h" +#include "3DS/3DSLoader.h" +#include "3DS/3DSHelper.h" +#include "PostProcessing/SplitLargeMeshes.h" + #include -#include "SplitLargeMeshes.h" #include #include #include #include + #include using namespace Assimp; @@ -381,7 +383,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type // TODO: handle embedded textures properly if (path.data[0] == '*') { - DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str())); + ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str())); return; } diff --git a/code/3DSExporter.h b/code/3DS/3DSExporter.h similarity index 98% rename from code/3DSExporter.h rename to code/3DS/3DSExporter.h index 5db58a4cb..035b562cf 100644 --- a/code/3DSExporter.h +++ b/code/3DS/3DSExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3DSHelper.h b/code/3DS/3DSHelper.h similarity index 97% rename from code/3DSHelper.h rename to code/3DS/3DSHelper.h index 7476438bd..8eb4cd97c 100644 --- a/code/3DSHelper.h +++ b/code/3DS/3DSHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace D3DS { -#include "./../include/assimp/Compiler/pushpack1.h" +#include // --------------------------------------------------------------------------- /** Discreet3DS class: Helper class for loading 3ds files. Defines chunks @@ -66,7 +66,7 @@ namespace D3DS { */ class Discreet3DS { private: - Discreet3DS() { + Discreet3DS() AI_NO_EXCEPT { // empty } @@ -328,19 +328,17 @@ struct Face : public FaceWithSmoothingGroup // --------------------------------------------------------------------------- /** Helper structure representing a texture */ -struct Texture -{ +struct Texture { //! Default constructor - Texture() - : mOffsetU (0.0) - , mOffsetV (0.0) - , mScaleU (1.0) - , mScaleV (1.0) - , mRotation (0.0) - , mMapMode (aiTextureMapMode_Wrap) - , bPrivate() - , iUVSrc (0) - { + Texture() AI_NO_EXCEPT + : mOffsetU (0.0) + , mOffsetV (0.0) + , mScaleU (1.0) + , mScaleV (1.0) + , mRotation (0.0) + , mMapMode (aiTextureMapMode_Wrap) + , bPrivate() + , iUVSrc (0) { mTextureBlend = get_qnan(); } @@ -365,7 +363,7 @@ struct Texture int iUVSrc; }; -#include "./../include/assimp/Compiler/poppack1.h" +#include // --------------------------------------------------------------------------- /** Helper structure representing a 3ds material */ @@ -394,7 +392,7 @@ struct Material //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it - Material(Material &&other) + Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)) , mDiffuse(std::move(other.mDiffuse)) , mSpecularExponent(std::move(other.mSpecularExponent)) @@ -418,7 +416,7 @@ struct Material } - Material &operator=(Material &&other) { + Material &operator=(Material &&other) AI_NO_EXCEPT { if (this == &other) { return *this; } @@ -447,7 +445,7 @@ struct Material } - ~Material() {} + virtual ~Material() {} //! Name of the material diff --git a/code/3DSLoader.cpp b/code/3DS/3DSLoader.cpp similarity index 95% rename from code/3DSLoader.cpp rename to code/3DS/3DSLoader.cpp index 92a64e3d8..3c659d0b0 100644 --- a/code/3DSLoader.cpp +++ b/code/3DS/3DSLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -50,9 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER -// internal headers #include "3DSLoader.h" -#include #include #include #include @@ -71,7 +69,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - "3ds prj" + "3ds prj" }; @@ -127,7 +125,7 @@ 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 { std::string extension = GetExtension(pFile); - if(extension == "3ds" || extension == "prj" ) { + if(extension == "3ds" || extension == "prj") { return true; } @@ -161,19 +159,21 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); - this->stream = &stream; // We should have at least one chunk if (stream.GetRemainingSize() < 16) { throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile); } + this->stream = &stream; // Allocate our temporary 3DS representation - mScene = new D3DS::Scene(); + D3DS::Scene _scene; + mScene = &_scene; // Initialize members + D3DS::Node _rootNode("UNNAMED"); mLastNodeIndex = -1; - mCurrentNode = new D3DS::Node("UNNAMED"); + mCurrentNode = &_rootNode; mRootNode = mCurrentNode; mRootNode->mHierarchyPos = -1; mRootNode->mHierarchyIndex = -1; @@ -193,7 +193,6 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // file. for (auto &mesh : mScene->mMeshes) { if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { - delete mScene; throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile); } CheckIndices(mesh); @@ -201,7 +200,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, ComputeNormalsWithSmoothingsGroups(mesh); } - // Replace all occurrences of the default material with a + // Replace all occurences of the default material with a // valid material. Generate it if no material containing // DEFAULT in its name has been found in the file ReplaceDefaultMaterial(); @@ -218,10 +217,8 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // Now apply the master scaling factor to the scene ApplyMasterScale(pScene); - // Delete our internal scene representation and the root - // node, so the whole hierarchy will follow - delete mRootNode; - delete mScene; + // Our internal scene representation and the root + // node will be automatically deleted, so the whole hierarchy will follow AI_DEBUG_INVALIDATE_PTR(mRootNode); AI_DEBUG_INVALIDATE_PTR(mScene); @@ -250,16 +247,18 @@ void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) // Reads a new chunk from the file void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut) { - ai_assert(pcOut != NULL); + ai_assert(pcOut != nullptr); pcOut->Flag = stream->GetI2(); pcOut->Size = stream->GetI4(); - if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) + if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) { throw DeadlyImportError("Chunk is too large"); + } - if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) - DefaultLogger::get()->error("3DS: Chunk overflow"); + if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) { + ASSIMP_LOG_ERROR("3DS: Chunk overflow"); + } } // ------------------------------------------------------------------------------------------------ @@ -320,7 +319,7 @@ void Discreet3DSImporter::ParseEditorChunk() // print the version number char buff[10]; ASSIMP_itoa10(buff,stream->GetI2()); - DefaultLogger::get()->info(std::string("3DS file format version: ") + buff); + ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff); } break; }; @@ -361,7 +360,7 @@ void Discreet3DSImporter::ParseObjectChunk() if (is_qnan(mClrAmbient.r)) { // We failed to read the ambient base color. - DefaultLogger::get()->error("3DS: Failed to read ambient base color"); + ASSIMP_LOG_ERROR("3DS: Failed to read ambient base color"); mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f; } break; @@ -463,7 +462,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) if (len < 1e-5) { // There are some files with lookat == position. Don't know why or whether it's ok or not. - DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector"); + ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector"); camera->mLookAt = aiVector3D(0.0,1.0,0.0); } @@ -629,9 +628,9 @@ void Discreet3DSImporter::SkipTCBInfo() if (!flags) { // Currently we can't do anything with these values. They occur // quite rare, so it wouldn't be worth the effort implementing - // them. 3DS ist not really suitable for complex animations, + // them. 3DS is not really suitable for complex animations, // so full support is not required. - DefaultLogger::get()->warn("3DS: Skipping TCB animation info"); + ASSIMP_LOG_WARN("3DS: Skipping TCB animation info"); } if (flags & Discreet3DS::KEY_USE_TENS) { @@ -732,7 +731,6 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // If object name is DUMMY, take this one instead if (mCurrentNode->mName == "$$$DUMMY") { - //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object"); mCurrentNode->mName = std::string(sz); break; } @@ -743,7 +741,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) if ( Discreet3DS::CHUNK_TRACKINFO != parent) { - DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object"); + ASSIMP_LOG_WARN("3DS: Skipping pivot subchunk for non usual object"); break; } @@ -805,7 +803,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) { // roll keys are accepted for cameras only if (parent != Discreet3DS::CHUNK_TRACKCAMERA) { - DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object"); + ASSIMP_LOG_WARN("3DS: Ignoring roll track for non-camera object"); break; } bool sortKeys = false; @@ -845,7 +843,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // CAMERA FOV KEYFRAME case Discreet3DS::CHUNK_TRACKFOV: { - DefaultLogger::get()->error("3DS: Skipping FOV animation track. " + ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. " "This is not supported"); } break; @@ -985,7 +983,7 @@ void Discreet3DSImporter::ParseFaceChunk() } } if (0xcdcdcdcd == idx) { - DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz); + ASSIMP_LOG_ERROR_F( "3DS: Unknown material: ", sz); } // Now continue and read all material indices @@ -995,7 +993,7 @@ void Discreet3DSImporter::ParseFaceChunk() // check range if (fidx >= mMesh.mFaceMaterials.size()) { - DefaultLogger::get()->error("3DS: Invalid face index in face material list"); + ASSIMP_LOG_ERROR("3DS: Invalid face index in face material list"); } else mMesh.mFaceMaterials[fidx] = idx; }} @@ -1110,7 +1108,7 @@ void Discreet3DSImporter::ParseMaterialChunk() if (!cnt) { // This may not be, we use the default name instead - DefaultLogger::get()->error("3DS: Empty material name"); + ASSIMP_LOG_ERROR("3DS: Empty material name"); } else mScene->mMaterials.back().mName = std::string(sz,cnt); } @@ -1123,7 +1121,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read DIFFUSE chunk"); pc->r = pc->g = pc->b = 1.0f; }} break; @@ -1135,7 +1133,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read SPECULAR chunk"); pc->r = pc->g = pc->b = 1.0f; }} break; @@ -1147,7 +1145,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read AMBIENT chunk"); pc->r = pc->g = pc->b = 0.0f; }} break; @@ -1159,7 +1157,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read EMISSIVE chunk"); pc->r = pc->g = pc->b = 0.0f; }} break; @@ -1293,7 +1291,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) pcOut->mScaleU = stream->GetF4(); if (0.0f == pcOut->mScaleU) { - DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1."); + ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1."); pcOut->mScaleU = 1.0f; } break; @@ -1302,7 +1300,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) pcOut->mScaleV = stream->GetF4(); if (0.0f == pcOut->mScaleV) { - DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1."); + ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1."); pcOut->mScaleV = 1.0f; } break; @@ -1344,15 +1342,16 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) // ------------------------------------------------------------------------------------------------ // Read a percentage chunk -ai_real Discreet3DSImporter::ParsePercentageChunk() -{ +ai_real Discreet3DSImporter::ParsePercentageChunk() { Discreet3DS::Chunk chunk; ReadChunk(&chunk); - if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) - return stream->GetF4(); - else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) + if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) { + return stream->GetF4() * ai_real(100) / ai_real(0xFFFF); + } else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) { return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)0xFFFF; + } + return get_qnan(); } diff --git a/code/3DSLoader.h b/code/3DS/3DSLoader.h similarity index 99% rename from code/3DSLoader.h rename to code/3DS/3DSLoader.h index eb311a81b..f57e6a8e3 100644 --- a/code/3DSLoader.h +++ b/code/3DS/3DSLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3MFXmlTags.h b/code/3MF/3MFXmlTags.h similarity index 99% rename from code/3MFXmlTags.h rename to code/3MF/3MFXmlTags.h index e869c33c1..ea6aeede0 100644 --- a/code/3MFXmlTags.h +++ b/code/3MF/3MFXmlTags.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFExporter.cpp b/code/3MF/D3MFExporter.cpp similarity index 98% rename from code/D3MFExporter.cpp rename to code/3MF/D3MFExporter.cpp index 204e6f77b..1f388ad3e 100644 --- a/code/D3MFExporter.cpp +++ b/code/3MF/D3MFExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -55,7 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "3MFXmlTags.h" #include "D3MFOpcPackage.h" -#include +#ifdef ASSIMP_USE_HUNTER +# include +#else +# include +#endif namespace Assimp { @@ -222,7 +226,7 @@ void D3MFExporter::writeMetaData() { return; } - const aiString *key; + const aiString *key = nullptr; const aiMetadataEntry *entry(nullptr); for ( size_t i = 0; i < numMetaEntries; ++i ) { mScene->mMetaData->Get( i, key, entry ); diff --git a/code/D3MFExporter.h b/code/3MF/D3MFExporter.h similarity index 98% rename from code/D3MFExporter.h rename to code/3MF/D3MFExporter.h index 110862b99..e82120247 100644 --- a/code/D3MFExporter.h +++ b/code/3MF/D3MFExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFImporter.cpp b/code/3MF/D3MFImporter.cpp similarity index 95% rename from code/D3MFImporter.cpp rename to code/3MF/D3MFImporter.cpp index 2732c73c4..682de684a 100644 --- a/code/D3MFImporter.cpp +++ b/code/3MF/D3MFImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -58,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "D3MFOpcPackage.h" -#include #include #include "3MFXmlTags.h" #include @@ -115,10 +115,10 @@ public: // import the metadata if ( !mMetaData.empty() ) { const size_t numMeta( mMetaData.size() ); - scene->mMetaData = aiMetadata::Alloc( numMeta ); + scene->mMetaData = aiMetadata::Alloc(static_cast( numMeta ) ); for ( size_t i = 0; i < numMeta; ++i ) { aiString val( mMetaData[ i ].value ); - scene->mMetaData->Set( i, mMetaData[ i ].name, val ); + scene->mMetaData->Set(static_cast( i ), mMetaData[ i ].name, val ); } } @@ -297,8 +297,9 @@ private: 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 ) { + if ( 9 != len && 7 != len) { return false; } @@ -313,26 +314,28 @@ private: ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.r = static_cast( strtol( comp, NULL, 16 ) ); + diffuse.r = static_cast( strtol( comp, NULL, 16 ) ) / ai_real(255.0); comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); + diffuse.g = static_cast< ai_real >( 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 ) ); + diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / ai_real(255.0); + if(7 == len) + return true; comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); + diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ) / ai_real(255.0); return true; } @@ -396,7 +399,7 @@ private: return false; } } - DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag"); + ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag"); return false; } @@ -416,8 +419,6 @@ private: } //namespace D3MF -static const std::string Extension = "3mf"; - static const aiImporterDesc desc = { "3mf Importer", "", @@ -428,7 +429,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - Extension.c_str() + "3mf" }; D3MFImporter::D3MFImporter() @@ -442,13 +443,13 @@ D3MFImporter::~D3MFImporter() { bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { const std::string extension( GetExtension( filename ) ); - if(extension == Extension ) { + if(extension == desc.mFileExtensions ) { return true; } else if ( !extension.length() || checkSig ) { if ( nullptr == pIOHandler ) { return false; } - if ( !D3MF::D3MFOpcPackage::isZipArchive( pIOHandler, filename ) ) { + if ( !ZipArchiveIOSystem::isZipArchive( pIOHandler, filename ) ) { return false; } D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename ); diff --git a/code/D3MFImporter.h b/code/3MF/D3MFImporter.h similarity index 98% rename from code/D3MFImporter.h rename to code/3MF/D3MFImporter.h index 701d056e2..3dbdf07bf 100644 --- a/code/D3MFImporter.h +++ b/code/3MF/D3MFImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3MF/D3MFOpcPackage.cpp b/code/3MF/D3MFOpcPackage.cpp new file mode 100644 index 000000000..873ba8ee8 --- /dev/null +++ b/code/3MF/D3MFOpcPackage.cpp @@ -0,0 +1,207 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER + +#include "D3MFOpcPackage.h" +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "3MFXmlTags.h" + +namespace Assimp { + +namespace D3MF { +// ------------------------------------------------------------------------------------------------ + +typedef std::shared_ptr OpcPackageRelationshipPtr; + +class OpcPackageRelationshipReader { +public: + OpcPackageRelationshipReader(XmlReader* xmlReader) { + while(xmlReader->read()) { + if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && + xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) + { + ParseRootNode(xmlReader); + } + } + } + + void ParseRootNode(XmlReader* xmlReader) + { + ParseAttributes(xmlReader); + + while(xmlReader->read()) + { + if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && + xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) + { + ParseChildNode(xmlReader); + } + } + } + + void ParseAttributes(XmlReader*) { + // empty + } + + bool validateRels( OpcPackageRelationshipPtr &relPtr ) { + if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) { + return false; + } + return true; + } + + void ParseChildNode(XmlReader* xmlReader) { + OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); + + relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str()); + relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str()); + relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str()); + if ( validateRels( relPtr ) ) { + m_relationShips.push_back( relPtr ); + } + } + + std::vector m_relationShips; +}; + +// ------------------------------------------------------------------------------------------------ +D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) +: mRootStream(nullptr) +, mZipArchive() { + mZipArchive.reset( new ZipArchiveIOSystem( pIOHandler, rFile ) ); + if(!mZipArchive->isOpen()) { + throw DeadlyImportError("Failed to open file " + rFile+ "."); + } + + std::vector fileList; + mZipArchive->getFileList(fileList); + + for (auto& file: fileList) { + if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) { + //PkgRelationshipReader pkgRelReader(file, archive); + ai_assert(mZipArchive->Exists(file.c_str())); + + IOStream *fileStream = mZipArchive->Open(file.c_str()); + + ai_assert(fileStream != nullptr); + + std::string rootFile = ReadPackageRootRelationship(fileStream); + if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) { + rootFile = rootFile.substr( 1 ); + if ( rootFile[ 0 ] == '/' ) { + // deal with zip-bug + rootFile = rootFile.substr( 1 ); + } + } + + ASSIMP_LOG_DEBUG(rootFile); + + mZipArchive->Close(fileStream); + + mRootStream = mZipArchive->Open(rootFile.c_str()); + ai_assert( mRootStream != nullptr ); + if ( nullptr == mRootStream ) { + throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile ); + } + + } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { + ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file); + } else { + ASSIMP_LOG_WARN_F("Ignored file of unknown type: ",file); + } + + } +} + +D3MFOpcPackage::~D3MFOpcPackage() { + mZipArchive->Close(mRootStream); +} + +IOStream* D3MFOpcPackage::RootStream() const { + return mRootStream; +} + +static const std::string ModelRef = "3D/3dmodel.model"; + +bool D3MFOpcPackage::validate() { + if ( nullptr == mRootStream || nullptr == mZipArchive ) { + return false; + } + + return mZipArchive->Exists( ModelRef.c_str() ); +} + +std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { + std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); + std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); + + OpcPackageRelationshipReader reader(xml.get()); + + auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){ + return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; + }); + + if ( itr == reader.m_relationShips.end() ) { + throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE ); + } + + return (*itr)->target; +} + +} // Namespace D3MF +} // Namespace Assimp + +#endif //ASSIMP_BUILD_NO_3MF_IMPORTER diff --git a/code/D3MFOpcPackage.h b/code/3MF/D3MFOpcPackage.h similarity index 92% rename from code/D3MFOpcPackage.h rename to code/3MF/D3MFOpcPackage.h index 6d7b3d478..87d172116 100644 --- a/code/D3MFOpcPackage.h +++ b/code/3MF/D3MFOpcPackage.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -49,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { + class ZipArchiveIOSystem; + namespace D3MF { using XmlReader = irr::io::IrrXMLReader ; @@ -60,22 +62,19 @@ struct OpcPackageRelationship { std::string target; }; -class D3MFZipArchive; - class D3MFOpcPackage { public: D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile ); ~D3MFOpcPackage(); IOStream* RootStream() const; bool validate(); - static bool isZipArchive( IOSystem* pIOHandler, const std::string& rFile ); protected: std::string ReadPackageRootRelationship(IOStream* stream); private: IOStream* mRootStream; - std::unique_ptr mZipArchive; + std::unique_ptr mZipArchive; }; } // Namespace D3MF diff --git a/code/ACLoader.cpp b/code/AC/ACLoader.cpp similarity index 94% rename from code/ACLoader.cpp rename to code/AC/ACLoader.cpp index 3f8653d5d..d4c4bd1a6 100644 --- a/code/ACLoader.cpp +++ b/code/AC/ACLoader.cpp @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include "Importer.h" +#include "Common/Importer.h" #include #include #include @@ -85,7 +85,7 @@ static const aiImporterDesc desc = { #define AI_AC_SKIP_TO_NEXT_TOKEN() \ if (!SkipSpaces(&buffer)) \ { \ - DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \ + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \ continue; \ } @@ -101,7 +101,7 @@ static const aiImporterDesc desc = { { \ if (IsLineEnd( *buffer )) \ { \ - DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \ + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \ out = "ERROR"; \ break; \ } \ @@ -120,7 +120,7 @@ static const aiImporterDesc desc = { { \ if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \ { \ - DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \ + ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \ continue; \ } \ buffer += name_length+1; \ @@ -217,7 +217,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast(mLights->size())-1); obj.name = std::string( light->mName.data ); - DefaultLogger::get()->debug("AC3D: Light source encountered"); + ASSIMP_LOG_DEBUG("AC3D: Light source encountered"); obj.type = Object::Light; } else if (!ASSIMP_strincmp(buffer,"group",5)) @@ -307,12 +307,12 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) { if (!GetNextLine()) { - DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet"); + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet"); break; } else if (!IsNumeric(*buffer)) { - DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet"); + ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet"); --buffer; // make sure the line is processed a second time break; } @@ -338,8 +338,8 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) // example writes no surf chunks if (!Q3DWorkAround) { - DefaultLogger::get()->warn("AC3D: SURF token was expected"); - DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled"); + ASSIMP_LOG_WARN("AC3D: SURF token was expected"); + ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled"); } --buffer; // make sure the line is processed a second time // break; --- see fix notes above @@ -384,7 +384,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) { if(!GetNextLine()) { - DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete"); + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete"); break; } surf.entries.push_back(Surface::SurfaceEntry()); @@ -405,7 +405,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) } } } - DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected"); + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected"); } // ------------------------------------------------------------------------------------------------ @@ -478,7 +478,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, therefore: if no surfaces are defined return point data only */ - DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, " + ASSIMP_LOG_INFO("AC3D: No surfaces defined in object definition, " "a point list is returned"); meshes.push_back(new aiMesh()); @@ -519,12 +519,12 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, unsigned int idx = (*it).mat; if (idx >= needMat.size()) { - DefaultLogger::get()->error("AC3D: material index is out of range"); + ASSIMP_LOG_ERROR("AC3D: material index is out of range"); idx = 0; } if ((*it).entries.empty()) { - DefaultLogger::get()->warn("AC3D: surface her zero vertex references"); + ASSIMP_LOG_WARN("AC3D: surface her zero vertex references"); } // validate all vertex indices to make sure we won't crash here @@ -533,7 +533,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, { if ((*it2).first >= object.vertices.size()) { - DefaultLogger::get()->warn("AC3D: Invalid vertex reference"); + ASSIMP_LOG_WARN("AC3D: Invalid vertex reference"); (*it2).first = 0; } } @@ -561,7 +561,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, if ((*it).flags & 0xf) { - DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown"); + ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown"); (*it).flags &= ~(0xf); } @@ -712,7 +712,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, if (object.subDiv) { if (configEvalSubdivision) { std::unique_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); - DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name); + ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: "+object.name); std::vector cpy(meshes.size()-oldm,NULL); div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true); @@ -721,7 +721,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, // previous meshes are deleted vy Subdivide(). } else { - DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: " + ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " +object.name); } } @@ -813,7 +813,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile, unsigned int version = HexDigitToDecimal( buffer[4] ); char msg[3]; ASSIMP_itoa10(msg,3,version); - DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg); + ASSIMP_LOG_INFO_F("AC3D file format version: ", msg); std::vector materials; materials.reserve(5); @@ -857,7 +857,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile, } if (materials.empty()) { - DefaultLogger::get()->warn("AC3D: No material has been found"); + ASSIMP_LOG_WARN("AC3D: No material has been found"); materials.push_back(Material()); } diff --git a/code/ACLoader.h b/code/AC/ACLoader.h similarity index 99% rename from code/ACLoader.h rename to code/AC/ACLoader.h index 86af9afb6..cab2c3ae5 100644 --- a/code/ACLoader.h +++ b/code/AC/ACLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/AMFImporter.cpp b/code/AMF/AMFImporter.cpp similarity index 99% rename from code/AMFImporter.cpp rename to code/AMF/AMFImporter.cpp index d20be6b9f..dedb6dcdd 100644 --- a/code/AMFImporter.cpp +++ b/code/AMF/AMFImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -83,7 +83,7 @@ void AMFImporter::Clear() mMaterial_Converted.clear(); mTexture_Converted.clear(); // Delete all elements - if(mNodeElement_List.size()) + if(!mNodeElement_List.empty()) { for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; } @@ -230,7 +230,7 @@ casu_cres: if(!skipped_before[sk_idx]) { skipped_before[sk_idx] = true; - LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + "."); + ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); } } diff --git a/code/AMFImporter.hpp b/code/AMF/AMFImporter.hpp similarity index 65% rename from code/AMFImporter.hpp rename to code/AMF/AMFImporter.hpp index 060cbf10a..2b8086a06 100644 --- a/code/AMFImporter.hpp +++ b/code/AMF/AMFImporter.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -63,8 +63,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Header files, stdlib. #include -namespace Assimp -{ +namespace Assimp { + /// \class AMFImporter /// Class that holding scene graph which include: geometry, metadata, materials etc. /// @@ -99,100 +99,49 @@ namespace Assimp /// new - and children , , , , , /// old - and children , , , , , /// -class AMFImporter : public BaseImporter -{ - /***********************************************/ - /******************** Types ********************/ - /***********************************************/ - +class AMFImporter : public BaseImporter { private: + struct SPP_Material;// forward declaration - struct SPP_Material;// forward declaration + /// \struct SPP_Composite + /// Data type for post-processing step. More suitable container for part of material's composition. + struct SPP_Composite { + SPP_Material* Material;///< Pointer to material - part of composition. + std::string Formula;///< Formula for calculating ratio of \ref Material. + }; - /// \struct SPP_Composite - /// Data type for postprocessing step. More suitable container for part of material's composition. - struct SPP_Composite - { - SPP_Material* Material;///< Pointer to material - part of composition. - std::string Formula;///< Formula for calculating ratio of \ref Material. - }; + /// \struct SPP_Material + /// Data type for post-processing step. More suitable container for material. + struct SPP_Material { + std::string ID;///< Material ID. + std::list Metadata;///< Metadata of material. + CAMFImporter_NodeElement_Color* Color;///< Color of material. + std::list Composition;///< List of child materials if current material is composition of few another. - /// \struct SPP_Material - /// Data type for postprocessing step. More suitable container for material. - struct SPP_Material - { - std::string ID;///< Material ID. - std::list Metadata;///< Metadata of material. - CAMFImporter_NodeElement_Color* Color;///< Color of material. - std::list Composition;///< List of child materials if current material is composition of few another. + /// Return color calculated for specified coordinate. + /// \param [in] pX - "x" coordinate. + /// \param [in] pY - "y" coordinate. + /// \param [in] pZ - "z" coordinate. + /// \return calculated color. + aiColor4D GetColor(const float pX, const float pY, const float pZ) const; + }; - /// \fn aiColor4D GetColor(const float pX, const float pY, const float pZ) const - /// Return color calculated for specified coordinate. - /// \param [in] pX - "x" coordinate. - /// \param [in] pY - "y" coordinate. - /// \param [in] pZ - "z" coordinate. - /// \return calculated color. - aiColor4D GetColor(const float pX, const float pY, const float pZ) const; - }; + /// Data type for post-processing step. More suitable container for texture. + struct SPP_Texture { + std::string ID; + size_t Width, Height, Depth; + bool Tiled; + char FormatHint[9];// 8 for string + 1 for terminator. + uint8_t *Data; + }; - /// \struct SPP_Texture - /// Data type for post-processing step. More suitable container for texture. - struct SPP_Texture - { - std::string ID; - size_t Width, Height, Depth; - bool Tiled; - char FormatHint[ 9 ];// 8 for string + 1 for terminator. - uint8_t *Data; - }; + /// Data type for post-processing step. Contain face data. + struct SComplexFace { + aiFace Face;///< Face vertices. + const CAMFImporter_NodeElement_Color* Color;///< Face color. Equal to nullptr if color is not set for the face. + const CAMFImporter_NodeElement_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face. + }; - /// \struct SComplexFace - /// Data type for post-processing step. Contain face data. - struct SComplexFace - { - aiFace Face;///< Face vertices. - const CAMFImporter_NodeElement_Color* Color;///< Face color. Equal to nullptr if color is not set for the face. - const CAMFImporter_NodeElement_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face. - }; - - - - /***********************************************/ - /****************** Constants ******************/ - /***********************************************/ - -private: - - static const aiImporterDesc Description; - - /***********************************************/ - /****************** Variables ******************/ - /***********************************************/ - -private: - - CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element. - std::list mNodeElement_List;///< All elements of scene graph. - irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object - std::string mUnit; - std::list mMaterial_Converted;///< List of converted materials for postprocessing step. - std::list mTexture_Converted;///< List of converted textures for postprocessing step. - - /***********************************************/ - /****************** Functions ******************/ - /***********************************************/ - -private: - - /// \fn AMFImporter(const AMFImporter& pScene) - /// Disabled copy constructor. - AMFImporter(const AMFImporter& pScene); - - /// \fn AMFImporter& operator=(const AMFImporter& pScene) - /// Disabled assign operator. - AMFImporter& operator=(const AMFImporter& pScene); - - /// \fn void Clear() /// Clear all temporary data. void Clear(); @@ -200,7 +149,6 @@ private: /************* Functions: find set *************/ /***********************************************/ - /// \fn bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, aiNode** pNode) const /// Find specified node element in node elements list ( \ref mNodeElement_List). /// \param [in] pID - ID(name) of requested node element. /// \param [in] pType - type of node element. @@ -208,7 +156,6 @@ private: /// \return true - if the node element is found, else - false. bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const; - /// \fn bool Find_ConvertedNode(const std::string& pID, std::list& pNodeList, aiNode** pNode) const /// Find requested aiNode in node list. /// \param [in] pID - ID(name) of requested node. /// \param [in] pNodeList - list of nodes where to find the node. @@ -216,15 +163,13 @@ private: /// \return true - if the node is found, else - false. bool Find_ConvertedNode(const std::string& pID, std::list& pNodeList, aiNode** pNode) const; - /// \fn bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const /// Find material in list for converted materials. Use at postprocessing step. /// \param [in] pID - material ID. /// \param [out] pConvertedMaterial - pointer to found converted material (\ref SPP_Material). /// \return true - if the material is found, else - false. bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const; - /// \fn bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A, uint32_t* pConvertedTextureIndex = nullptr) const - /// Find texture in list of converted textures. Use at postprocessing step, + /// Find texture in list of converted textures. Use at postprocessing step, /// \param [in] pID_R - ID of source "red" texture. /// \param [in] pID_G - ID of source "green" texture. /// \param [in] pID_B - ID of source "blue" texture. @@ -235,11 +180,7 @@ private: bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A, uint32_t* pConvertedTextureIndex = nullptr) const; - /***********************************************/ - /********* Functions: postprocess set **********/ - /***********************************************/ - /// \fn void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector& pVertexCoordinateArray, std::vector& pVertexColorArray) const /// Get data stored in and place it to arrays. /// \param [in] pNodeElement - reference to node element which kept data. /// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in . @@ -248,7 +189,6 @@ private: void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector& pVertexCoordinateArray, std::vector& pVertexColorArray) const; - /// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A) /// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new /// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it /// to converted textures list. @@ -260,27 +200,23 @@ private: /// \return index of the texture in array of the converted textures. size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A); - /// \fn void PostprocessHelper_SplitFacesByTextureID(std::list& pInputList, std::list > pOutputList_Separated) /// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc). /// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after /// processing. /// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing. void PostprocessHelper_SplitFacesByTextureID(std::list& pInputList, std::list >& pOutputList_Separated); - /// \fn void Postprocess_AddMetadata(const std::list& pMetadataList, aiNode& pSceneNode) const /// Check if child elements of node element is metadata and add it to scene node. /// \param [in] pMetadataList - reference to list with collected metadata. /// \param [out] pSceneNode - scene node in which metadata will be added. void Postprocess_AddMetadata(const std::list& pMetadataList, aiNode& pSceneNode) const; - /// \fn void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list& pMeshList, aiNode** pSceneNode) /// To create aiMesh and aiNode for it from . /// \param [in] pNodeElement - reference to node element which kept data. /// \param [out] pMeshList - reference to a list with all aiMesh of the scene. /// \param [out] pSceneNode - pointer to place where new aiNode will be created. void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list& pMeshList, aiNode** pSceneNode); - /// \fn void 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) /// Create mesh for every in . /// \param [in] pNodeElement - reference to node element which kept data. /// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all 's. @@ -294,27 +230,20 @@ private: const std::vector& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor, std::list& pMeshList, aiNode& pSceneNode); - /// \fn void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial) /// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material. /// \param [in] pMaterial - source CAMFImporter_NodeElement_Material. void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial); - /// \fn void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list& pNodeList) const /// Create and add to aiNode's list new part of scene graph defined by . /// \param [in] pConstellation - reference to node. /// \param [out] pNodeList - reference to aiNode's list. void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list& pNodeList) const; - /// \fn void Postprocess_BuildScene() /// Build Assimp scene graph in aiScene from collected data. /// \param [out] pScene - pointer to aiScene where tree will be built. void Postprocess_BuildScene(aiScene* pScene); - /***********************************************/ - /************* Functions: throw set ************/ - /***********************************************/ - /// \fn void Throw_CloseNotFound(const std::string& pNode) /// Call that function when close tag of node not found and exception must be raised. /// E.g.: /// @@ -324,19 +253,16 @@ private: /// \param [in] pNode - node name in which exception happened. void Throw_CloseNotFound(const std::string& pNode); - /// \fn void Throw_IncorrectAttr(const std::string& pAttrName) /// Call that function when attribute name is incorrect and exception must be raised. /// \param [in] pAttrName - attribute name. /// \throw DeadlyImportError. void Throw_IncorrectAttr(const std::string& pAttrName); - /// \fn void Throw_IncorrectAttrValue(const std::string& pAttrName) /// Call that function when attribute value is incorrect and exception must be raised. /// \param [in] pAttrName - attribute name. /// \throw DeadlyImportError. void Throw_IncorrectAttrValue(const std::string& pAttrName); - /// \fn void Throw_MoreThanOnceDefined(const std::string& pNode, const std::string& pDescription) /// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised. /// E.g.: /// @@ -348,216 +274,158 @@ private: /// \param [in] pDescription - message about error. E.g. what the node defined while exception raised. void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription); - /// \fn void Throw_ID_NotFound(const std::string& pID) const /// Call that function when referenced element ID are not found in graph and exception must be raised. /// \param [in] pID - ID of of element which not found. /// \throw DeadlyImportError. void Throw_ID_NotFound(const std::string& pID) const; - /***********************************************/ - /************** Functions: LOG set *************/ - /***********************************************/ - - /// \fn void LogInfo(const std::string& pMessage) - /// Short variant for calling \ref DefaultLogger::get()->info() - void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); } - - /// \fn void LogWarning(const std::string& pMessage) - /// Short variant for calling \ref DefaultLogger::get()->warn() - void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); } - - /// \fn void LogError(const std::string& pMessage) - /// Short variant for calling \ref DefaultLogger::get()->error() - void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); } - - /***********************************************/ - /************** Functions: XML set *************/ - /***********************************************/ - - /// \fn void XML_CheckNode_MustHaveChildren() /// Check if current node have children: .... If not then exception will throwed. void XML_CheckNode_MustHaveChildren(); - /// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName) /// Check if current node name is equal to pNodeName. /// \param [in] pNodeName - name for checking. /// return true if current node name is equal to pNodeName, else - false. bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; } - /// \fn void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) /// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node. /// \param [in] pParentNodeName - parent node name. Used for reporting. void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName); - /// \fn bool XML_SearchNode(const std::string& pNodeName) /// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end. /// \param [in] pNodeName - requested node name. /// return true - if node is found, else - false. bool XML_SearchNode(const std::string& pNodeName); - /// \fn bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \return read data. bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx); - /// \fn float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \return read data. float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx); - /// \fn uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \return read data. uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx); - /// \fn float XML_ReadNode_GetVal_AsFloat() /// Read node value. /// \return read data. float XML_ReadNode_GetVal_AsFloat(); - /// \fn uint32_t XML_ReadNode_GetVal_AsU32() /// Read node value. /// \return read data. uint32_t XML_ReadNode_GetVal_AsU32(); - /// \fn void XML_ReadNode_GetVal_AsString(std::string& pValue) /// Read node value. /// \return read data. void XML_ReadNode_GetVal_AsString(std::string& pValue); - /***********************************************/ - /******** Functions: parse set private *********/ - /***********************************************/ - - /// \fn void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode) /// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called. /// \param [in] pNode - new current node. void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode); - /// \fn void ParseHelper_Group_End() /// This function must be called when exiting from grouping node. \ref ParseHelper_Group_Begin. void ParseHelper_Node_Exit(); - /// \fn void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString) /// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it /// must be converted to right form - "0.xxx". /// \param [in] pInStr - pointer to input string which can contain incorrect form of values. /// \param [out[ pOutString - output string with right form of values. void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString); - /// \fn void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const /// Decode Base64-encoded data. /// \param [in] pInputBase64 - reference to input Base64-encoded string. /// \param [out] pOutputData - reference to output array for decoded data. void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const; - /// \fn void ParseNode_Root() /// Parse node of the file. void ParseNode_Root(); - /******** Functions: top nodes *********/ - - /// \fn void ParseNode_Constellation() /// Parse node of the file. void ParseNode_Constellation(); - /// \fn void ParseNode_Constellation() /// Parse node of the file. void ParseNode_Instance(); - /// \fn void ParseNode_Material() /// Parse node of the file. void ParseNode_Material(); - /// \fn void ParseNode_Metadata() /// Parse node. void ParseNode_Metadata(); - /// \fn void ParseNode_Object() /// Parse node of the file. void ParseNode_Object(); - /// \fn void ParseNode_Texture() /// Parse node of the file. void ParseNode_Texture(); - /******** Functions: geometry nodes *********/ - - /// \fn void ParseNode_Coordinates() /// Parse node of the file. void ParseNode_Coordinates(); - /// \fn void ParseNode_Edge() /// Parse node of the file. void ParseNode_Edge(); - /// \fn void ParseNode_Mesh() /// Parse node of the file. void ParseNode_Mesh(); - /// \fn void ParseNode_Triangle() /// Parse node of the file. void ParseNode_Triangle(); - /// \fn void ParseNode_Vertex() /// Parse node of the file. void ParseNode_Vertex(); - /// \fn void ParseNode_Vertices() /// Parse node of the file. void ParseNode_Vertices(); - /// \fn void ParseNode_Volume() /// Parse node of the file. void ParseNode_Volume(); - /******** Functions: material nodes *********/ - - /// \fn void ParseNode_Color() /// Parse node of the file. void ParseNode_Color(); - /// \fn void ParseNode_TexMap(const bool pUseOldName = false) /// Parse of node of the file. /// \param [in] pUseOldName - if true then use old name of node(and children) - , instead of new name - . void ParseNode_TexMap(const bool pUseOldName = false); public: - - /// \fn AMFImporter() /// Default constructor. - AMFImporter() - : mNodeElement_Cur(nullptr), mReader(nullptr) - {} + AMFImporter() AI_NO_EXCEPT + : mNodeElement_Cur(nullptr) + , mReader(nullptr) { + // empty + } - /// \fn ~AMFImporter() /// Default destructor. ~AMFImporter(); - /***********************************************/ - /******** Functions: parse set, public *********/ - /***********************************************/ - - /// \fn void ParseFile(const std::string& pFile, IOSystem* pIOHandler) /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph. - /// Also exception can be throwed if trouble will found. + /// Also exception can be thrown if trouble will found. /// \param [in] pFile - name of file to be parsed. /// \param [in] pIOHandler - pointer to IO helper object. void ParseFile(const std::string& pFile, IOSystem* pIOHandler); - /***********************************************/ - /********* Functions: BaseImporter set *********/ - /***********************************************/ - bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const; void GetExtensionList(std::set& pExtensionList); void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); const aiImporterDesc* GetInfo ()const; -};// class AMFImporter + AMFImporter(const AMFImporter& pScene) = delete; + AMFImporter& operator=(const AMFImporter& pScene) = delete; + +private: + static const aiImporterDesc Description; + + CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element. + std::list mNodeElement_List;///< All elements of scene graph. + irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object + std::string mUnit; + std::list mMaterial_Converted;///< List of converted materials for postprocessing step. + std::list mTexture_Converted;///< List of converted textures for postprocessing step. + +}; }// namespace Assimp diff --git a/code/AMFImporter_Geometry.cpp b/code/AMF/AMFImporter_Geometry.cpp similarity index 99% rename from code/AMFImporter_Geometry.cpp rename to code/AMF/AMFImporter_Geometry.cpp index d4d648fbd..f1538e3fb 100644 --- a/code/AMFImporter_Geometry.cpp +++ b/code/AMF/AMFImporter_Geometry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter_Macro.hpp b/code/AMF/AMFImporter_Macro.hpp similarity index 90% rename from code/AMFImporter_Macro.hpp rename to code/AMF/AMFImporter_Macro.hpp index afa120028..f60c5fbbb 100644 --- a/code/AMFImporter_Macro.hpp +++ b/code/AMF/AMFImporter_Macro.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_ATTRREAD_CHECK_REF -/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then +/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then /// "continue" will called. /// \param [in] pAttrName - attribute name. /// \param [out] pVarName - output variable name. @@ -84,7 +84,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_ATTRREAD_CHECK_RET -/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. +/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. /// If result was read then "continue" will called. /// \param [in] pAttrName - attribute name. /// \param [out] pVarName - output variable name. @@ -130,7 +130,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } while(false) /// \def MACRO_NODECHECK_READCOMP_F -/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float". +/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float". /// If result was read then "continue" will called. Also check if node data already read then raise exception. /// \param [in] pNodeName - node name. /// \param [in, out] pReadFlag - read flag. @@ -147,7 +147,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_NODECHECK_READCOMP_U32 -/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t". +/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t". /// If result was read then "continue" will called. Also check if node data already read then raise exception. /// \param [in] pNodeName - node name. /// \param [in, out] pReadFlag - read flag. diff --git a/code/AMFImporter_Material.cpp b/code/AMF/AMFImporter_Material.cpp similarity index 85% rename from code/AMFImporter_Material.cpp rename to code/AMF/AMFImporter_Material.cpp index 77f49d39e..2f36df061 100644 --- a/code/AMFImporter_Material.cpp +++ b/code/AMF/AMFImporter_Material.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -68,10 +68,9 @@ namespace Assimp // Multi elements - No. // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The // values can be specified as constants, or as a formula depending on the coordinates. -void AMFImporter::ParseNode_Color() -{ -std::string profile; -CAMFImporter_NodeElement* ne; +void AMFImporter::ParseNode_Color() { + std::string profile; + CAMFImporter_NodeElement* ne; // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; @@ -98,15 +97,19 @@ CAMFImporter_NodeElement* ne; MACRO_NODECHECK_LOOPEND("color"); ParseHelper_Node_Exit(); // check that all components was defined - if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined."); - // check if is absent. Then manualy add "a == 1". - if(!read_flag[3]) als.Color.a = 1; + if (!(read_flag[0] && read_flag[1] && read_flag[2])) { + throw DeadlyImportError("Not all color components are defined."); + } - }// if(!mReader->isEmptyElement()) + // check if is absent. Then manually add "a == 1". + if (!read_flag[3]) { + als.Color.a = 1; + } + } else { mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else + } als.Composed = false; mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. @@ -119,10 +122,9 @@ CAMFImporter_NodeElement* ne; // An available material. // Multi elements - Yes. // Parent element - . -void AMFImporter::ParseNode_Material() -{ -std::string id; -CAMFImporter_NodeElement* ne; +void AMFImporter::ParseNode_Material() { + std::string id; + CAMFImporter_NodeElement* ne; // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; @@ -131,9 +133,11 @@ CAMFImporter_NodeElement* ne; // create new object. ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur); - // and assign read data + + // and assign read data ((CAMFImporter_NodeElement_Material*)ne)->ID = id; - // Check for child nodes + + // Check for child nodes if(!mReader->isEmptyElement()) { bool col_read = false; @@ -154,11 +158,11 @@ CAMFImporter_NodeElement* ne; if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; } MACRO_NODECHECK_LOOPEND("material"); ParseHelper_Node_Exit(); - }// if(!mReader->isEmptyElement()) + } else { mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element - }// if(!mReader->isEmptyElement()) else + } mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. } @@ -181,14 +185,13 @@ CAMFImporter_NodeElement* ne; // Parent element - . void AMFImporter::ParseNode_Texture() { -std::string id; -uint32_t width = 0; -uint32_t height = 0; -uint32_t depth = 1; -std::string type; -bool tiled = false; -std::string enc64_data; -CAMFImporter_NodeElement* ne; + std::string id; + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 1; + std::string type; + bool tiled = false; + std::string enc64_data; // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; @@ -201,20 +204,34 @@ CAMFImporter_NodeElement* ne; MACRO_ATTRREAD_LOOPEND; // create new texture object. - ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur); + CAMFImporter_NodeElement *ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur); CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience // Check for child nodes - if(!mReader->isEmptyElement()) XML_ReadNode_GetVal_AsString(enc64_data); + if (!mReader->isEmptyElement()) { + XML_ReadNode_GetVal_AsString(enc64_data); + } // check that all components was defined - if(id.empty()) throw DeadlyImportError("ID for texture must be defined."); - if(width < 1) Throw_IncorrectAttrValue("width"); - if(height < 1) Throw_IncorrectAttrValue("height"); - if(depth < 1) Throw_IncorrectAttrValue("depth"); - if(type != "grayscale") Throw_IncorrectAttrValue("type"); - if(enc64_data.empty()) throw DeadlyImportError("Texture data not defined."); + if (id.empty()) { + throw DeadlyImportError("ID for texture must be defined."); + } + if (width < 1) { + Throw_IncorrectAttrValue("width"); + } + if (height < 1) { + Throw_IncorrectAttrValue("height"); + } + if (depth < 1) { + Throw_IncorrectAttrValue("depth"); + } + if (type != "grayscale") { + Throw_IncorrectAttrValue("type"); + } + if (enc64_data.empty()) { + throw DeadlyImportError("Texture data not defined."); + } // copy data als.ID = id; als.Width = width; @@ -222,8 +239,11 @@ CAMFImporter_NodeElement* ne; als.Depth = depth; als.Tiled = tiled; ParseHelper_Decode_Base64(enc64_data, als.Data); - // check data size - if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size."); + + // check data size + if ((width * height * depth) != als.Data.size()) { + throw DeadlyImportError("Texture has incorrect data size."); + } mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph. @@ -243,10 +263,8 @@ CAMFImporter_NodeElement* ne; // , , , , , . Old name: , , , , , . // Multi elements - No. // Texture coordinates for every vertex of triangle. -void AMFImporter::ParseNode_TexMap(const bool pUseOldName) -{ -std::string rtexid, gtexid, btexid, atexid; -CAMFImporter_NodeElement* ne; +void AMFImporter::ParseNode_TexMap(const bool pUseOldName) { + std::string rtexid, gtexid, btexid, atexid; // Read attributes for node . MACRO_ATTRREAD_LOOPBEG; @@ -257,7 +275,7 @@ CAMFImporter_NodeElement* ne; MACRO_ATTRREAD_LOOPEND; // create new texture coordinates object. - ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur); + CAMFImporter_NodeElement *ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur); CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience // check data diff --git a/code/AMFImporter_Node.hpp b/code/AMF/AMFImporter_Node.hpp similarity index 74% rename from code/AMFImporter_Node.hpp rename to code/AMF/AMFImporter_Node.hpp index cdbedf2c7..a1bf9f008 100644 --- a/code/AMFImporter_Node.hpp +++ b/code/AMF/AMFImporter_Node.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -62,7 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// \class CAMFImporter_NodeElement /// Base class for elements of nodes. class CAMFImporter_NodeElement { - public: /// Define what data type contain node element. enum EType { @@ -96,15 +95,11 @@ public: /// Destructor, virtual.. // empty } -private: - /// Disabled copy constructor. - CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement); - - /// Disabled assign operator. - CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement); - - /// Disabled default constructor. - CAMFImporter_NodeElement(); + /// Disabled copy constructor and co. + CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement) = delete; + CAMFImporter_NodeElement(CAMFImporter_NodeElement&&) = delete; + CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement) = delete; + CAMFImporter_NodeElement() = delete; protected: /// In constructor inheritor must set element type. @@ -121,9 +116,7 @@ protected: /// \struct CAMFImporter_NodeElement_Constellation /// A collection of objects or constellations with specific relative locations. -struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent) +struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement { /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent) @@ -134,9 +127,7 @@ struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement /// \struct CAMFImporter_NodeElement_Instance /// Part of constellation. -struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ +struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement { std::string ObjectID;///< ID of object for instantiation. /// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to @@ -147,237 +138,185 @@ struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement /// instance of the object in the current constellation. Rotations shall be executed in order of x first, then y, then z. aiVector3D Rotation; - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Instance, pParent) {} - -};// struct CAMFImporter_NodeElement_Instance +}; /// \struct CAMFImporter_NodeElement_Metadata /// Structure that define metadata node. -struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ +struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement { - std::string Type;///< Type of "Value". + std::string Type;///< Type of "Value". std::string Value;///< Value. - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Metadata, pParent) {} - -};// struct CAMFImporter_NodeElement_Metadata +}; /// \struct CAMFImporter_NodeElement_Root /// Structure that define root node. -struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ +struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement { std::string Unit;///< The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron". std::string Version;///< Version of format. - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Root, pParent) {} - -};// struct CAMFImporter_NodeElement_Root +}; /// \struct CAMFImporter_NodeElement_Color /// Structure that define object node. -struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ +struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement { + bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color. + std::string Color_Composed[4]; ///< By components formulas of composed color. [0..3] - RGBA. + aiColor4D Color; ///< Constant color. + std::string Profile; ///< The ICC color space used to interpret the three color channels r, g and b.. - bool Composed;///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color. - std::string Color_Composed[4];///< By components formulas of composed color. [0..3] => RGBA. - aiColor4D Color;///< Constant color. - std::string Profile;///< The ICC color space used to interpret the three color channels , and .. - - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent) - /// Constructor. - /// \param [in] pParent - pointer to parent node. + /// @brief Constructor. + /// @param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent) - : CAMFImporter_NodeElement(ENET_Color, pParent) - {} - -};// struct CAMFImporter_NodeElement_Color + : CAMFImporter_NodeElement(ENET_Color, pParent) + , Composed( false ) + , Color() + , Profile() { + // empty + } +}; /// \struct CAMFImporter_NodeElement_Material /// Structure that define material node. -struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent) +struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement { + /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Material, pParent) {} -};// struct CAMFImporter_NodeElement_Material +}; /// \struct CAMFImporter_NodeElement_Object /// Structure that define object node. -struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent) - /// Constructor. +struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement { + + /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Object, pParent) {} - -};// struct CAMFImporter_NodeElement_Object +}; /// \struct CAMFImporter_NodeElement_Mesh /// Structure that define mesh node. -struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent) +struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement { /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Mesh, pParent) {} - -};// struct CAMFImporter_NodeElement_Mesh +}; /// \struct CAMFImporter_NodeElement_Vertex /// Structure that define vertex node. -struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent) +struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement { /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Vertex, pParent) {} - -};// struct CAMFImporter_NodeElement_Vertex +}; /// \struct CAMFImporter_NodeElement_Edge /// Structure that define edge node. -struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent) +struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement { /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Edge, pParent) {} -};// struct CAMFImporter_NodeElement_Vertex +}; /// \struct CAMFImporter_NodeElement_Vertices /// Structure that define vertices node. -struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement -{ - /// \fn CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent) +struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement { /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Vertices, pParent) {} - -};// struct CAMFImporter_NodeElement_Vertices +}; /// \struct CAMFImporter_NodeElement_Volume /// Structure that define volume node. -struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ - +struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement { std::string MaterialID;///< Which material to use. std::string Type;///< What this volume describes can be “region” or “support”. If none specified, “object” is assumed. - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Volume, pParent) {} - -};// struct CAMFImporter_NodeElement_Volume +}; /// \struct CAMFImporter_NodeElement_Coordinates /// Structure that define coordinates node. struct CAMFImporter_NodeElement_Coordinates : public CAMFImporter_NodeElement { - /****************** Variables ******************/ - aiVector3D Coordinate;///< Coordinate. - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent) : CAMFImporter_NodeElement(ENET_Coordinates, pParent) {} -};// struct CAMFImporter_NodeElement_Coordinates +}; /// \struct CAMFImporter_NodeElement_TexMap /// Structure that define texture coordinates node. -struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ - +struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement { aiVector3D TextureCoordinate[3];///< Texture coordinates. std::string TextureID_R;///< Texture ID for red color component. std::string TextureID_G;///< Texture ID for green color component. std::string TextureID_B;///< Texture ID for blue color component. std::string TextureID_A;///< Texture ID for alpha color component. - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent) - : CAMFImporter_NodeElement(ENET_TexMap, pParent) - {} - -};// struct CAMFImporter_NodeElement_TexMap + : CAMFImporter_NodeElement(ENET_TexMap, pParent) + , TextureCoordinate{} + , TextureID_R() + , TextureID_G() + , TextureID_B() + , TextureID_A() { + // empty + } +}; /// \struct CAMFImporter_NodeElement_Triangle /// Structure that define triangle node. -struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ - +struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement { size_t V[3];///< Triangle vertices. - /****************** Functions ******************/ - - /// \fn CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent) - : CAMFImporter_NodeElement(ENET_Triangle, pParent) - {} - -};// struct CAMFImporter_NodeElement_Triangle + : CAMFImporter_NodeElement(ENET_Triangle, pParent) { + // empty + } +}; /// Structure that define texture node. struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement { @@ -396,6 +335,6 @@ struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement { , Tiled( false ){ // empty } -};// struct CAMFImporter_NodeElement_Texture +}; #endif // INCLUDED_AI_AMF_IMPORTER_NODE_H diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMF/AMFImporter_Postprocess.cpp similarity index 98% rename from code/AMFImporter_Postprocess.cpp rename to code/AMF/AMFImporter_Postprocess.cpp index 192544fcb..79b5e15e2 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMF/AMFImporter_Postprocess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -66,7 +66,7 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /* aiColor4D tcol; // Check if stored data are supported. - if(Composition.size() != 0) + if(!Composition.empty()) { throw DeadlyImportError("IME. GetColor for composition"); } @@ -321,7 +321,7 @@ void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list 0) pOutputList_Separated.push_back(face_list_cur); + if(!face_list_cur.empty()) pOutputList_Separated.push_back(face_list_cur); - } while(pInputList.size() > 0); + } while(!pInputList.empty()); } void AMFImporter::Postprocess_AddMetadata(const std::list& metadataList, aiNode& sceneNode) const @@ -712,7 +712,7 @@ std::list mesh_idx; }// for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child) // if meshes was created then assign new indices with current aiNode - if(mesh_idx.size() > 0) + if(!mesh_idx.empty()) { std::list::const_iterator mit = mesh_idx.begin(); @@ -770,7 +770,7 @@ std::list ch_node; // find referenced object if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID); - // create node for apllying transformation + // create node for applying transformation t_node = new aiNode; t_node->mParent = con_node; // apply transformation @@ -787,7 +787,7 @@ std::list ch_node; }// for(const CAMFImporter_NodeElement* ne: pConstellation.Child) // copy found aiNode's as children - if(ch_node.size() == 0) throw DeadlyImportError(" must have at least one ."); + if(ch_node.empty()) throw DeadlyImportError(" must have at least one ."); size_t ch_idx = 0; @@ -883,13 +883,13 @@ 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++) + 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++) + ++next_it; + for(; next_it != node_list.end(); ++next_it) { if((*next_it)->FindNode((*nl_it)->mName) != nullptr) { @@ -907,7 +907,7 @@ nl_clean_loop: // // // Nodes - if(node_list.size() > 0) + if(!node_list.empty()) { std::list::const_iterator nl_it = node_list.begin(); @@ -924,7 +924,7 @@ nl_clean_loop: // // Meshes - if(mesh_list.size() > 0) + if(!mesh_list.empty()) { std::list::const_iterator ml_it = mesh_list.begin(); diff --git a/code/ASELoader.cpp b/code/ASE/ASELoader.cpp similarity index 98% rename from code/ASELoader.cpp rename to code/ASE/ASELoader.cpp index 32b0eae2d..8e99214a8 100644 --- a/code/ASELoader.cpp +++ b/code/ASE/ASELoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -53,7 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ASELoader.h" #include #include -#include "TargetAnimation.h" +#include "Common/TargetAnimation.h" + #include #include #include @@ -88,23 +89,25 @@ ASEImporter::ASEImporter() , mBuffer() , pcScene() , configRecomputeNormals() -, noSkeletonMesh() -{} +, noSkeletonMesh() { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -ASEImporter::~ASEImporter() -{} +ASEImporter::~ASEImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // 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); - if( extension == "ase" || extension == "ask") + if (extension == "ase" || extension == "ask") { return true; + } if ((!extension.length() || cs) && pIOHandler) { const char* tokens[] = {"*3dsmax_asciiexport"}; @@ -115,15 +118,13 @@ bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool // ------------------------------------------------------------------------------------------------ // 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); @@ -133,12 +134,11 @@ void ASEImporter::SetupProperties(const Importer* pImp) // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void ASEImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ + aiScene* pScene, IOSystem* pIOHandler) { std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open ASE file " + pFile + "."); } @@ -200,7 +200,7 @@ void ASEImporter::InternReadFile( const std::string& pFile, ConvertMeshes(*i,avOutMeshes); } if (tookNormals) { - DefaultLogger::get()->debug("ASE: Taking normals from the file. Use " + ASSIMP_LOG_DEBUG("ASE: Taking normals from the file. Use " "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you " "experience problems"); } @@ -297,15 +297,15 @@ void ASEImporter::BuildAnimations(const std::vector& nodes) // TODO: Implement Bezier & TCB support if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. " + ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. " "This is not supported."); } if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. " + ASSIMP_LOG_WARN("ASE: Rotation controller uses Bezier/TCB keys. " "This is not supported."); } if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. " + ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. " "This is not supported."); } @@ -624,7 +624,7 @@ void ASEImporter::AddNodes (const std::vector& nodes, node->mNumChildren++; // What we did is so great, it is at least worth a debug message - DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")"); + ASSIMP_LOG_DEBUG("ASE: Generating separate target node ("+snode->mName+")"); } } @@ -947,7 +947,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // validate the material index of the mesh if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) { mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1; - DefaultLogger::get()->warn("Material index is out of range"); + ASSIMP_LOG_WARN("Material index is out of range"); } // If the material the mesh is assigned to is consisting of submeshes, split it @@ -957,11 +957,11 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh std::vector* aiSplit = new std::vector[vSubMaterials.size()]; - // build a list of all faces per submaterial + // build a list of all faces per sub-material for (unsigned int i = 0; i < mesh.mFaces.size();++i) { // check range if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) { - DefaultLogger::get()->warn("Submaterial index is out of range"); + ASSIMP_LOG_WARN("Submaterial index is out of range"); // use the last material instead aiSplit[vSubMaterials.size()-1].push_back(i); @@ -1299,7 +1299,7 @@ void ASEImporter::BuildMaterialIndices() } } - // Dekete our temporary array + // Delete our temporary array delete[] pcIntMaterials; } diff --git a/code/ASELoader.h b/code/ASE/ASELoader.h similarity index 99% rename from code/ASELoader.h rename to code/ASE/ASELoader.h index 7f71bf49d..b497aa48b 100644 --- a/code/ASELoader.h +++ b/code/ASE/ASELoader.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team - +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ASEParser.cpp b/code/ASE/ASEParser.cpp similarity index 98% rename from code/ASEParser.cpp rename to code/ASE/ASEParser.cpp index b953f8d96..913e7b118 100644 --- a/code/ASEParser.cpp +++ b/code/ASE/ASEParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -45,20 +45,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the ASE parser class */ - #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER // internal headers -#include "TextureTransform.h" +#include "PostProcessing/TextureTransform.h" #include "ASELoader.h" + #include #include using namespace Assimp; using namespace Assimp::ASE; - // ------------------------------------------------------------------------------------------------ // Begin an ASE parsing function @@ -151,7 +150,7 @@ void Parser::LogWarning(const char* szWarn) #endif // output the warning to the logger ... - DefaultLogger::get()->warn(szTemp); + ASSIMP_LOG_WARN(szTemp); } // ------------------------------------------------------------------------------------------------ @@ -167,7 +166,7 @@ void Parser::LogInfo(const char* szWarn) #endif // output the information to the logger ... - DefaultLogger::get()->info(szTemp); + ASSIMP_LOG_INFO(szTemp); } // ------------------------------------------------------------------------------------------------ @@ -758,7 +757,7 @@ void Parser::ParseLV3MapBlock(Texture& map) SkipToNextToken(); if (temp != "Bitmap" && temp != "Normal Bump") { - DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp); + ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp); parsePath = false; } continue; @@ -773,7 +772,7 @@ void Parser::ParseLV3MapBlock(Texture& map) { // Files with 'None' as map name are produced by // an Maja to ASE exporter which name I forgot .. - DefaultLogger::get()->warn("ASE: Skipping invalid map entry"); + ASSIMP_LOG_WARN("ASE: Skipping invalid map entry"); map.mMapName = ""; } @@ -1072,7 +1071,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET)) { - DefaultLogger::get()->error("ASE: Found target animation channel " + ASSIMP_LOG_ERROR("ASE: Found target animation channel " "but the node is neither a camera nor a spot light"); anim = NULL; } @@ -1098,7 +1097,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels - DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation"); + ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation"); SkipSection(); } else ParseLV3ScaleAnimationBlock(*anim); @@ -1112,7 +1111,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels - DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation"); + ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation"); SkipSection(); } else ParseLV3RotAnimationBlock(*anim); @@ -1295,12 +1294,14 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh) { mode = 2; } - else DefaultLogger::get()->error("ASE: Ignoring target transform, " - "this is no spot light or target camera"); + else { + ASSIMP_LOG_ERROR("ASE: Ignoring target transform, " + "this is no spot light or target camera"); + } } else { - DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp); + ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp); // mode = 0 } continue; @@ -1916,7 +1917,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) else if (index == face.mIndices[2]) index = 2; else { - DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); + ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); continue; } // We'll renormalize later @@ -1928,7 +1929,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) ParseLV4MeshFloatTriple(&vNormal.x,faceIdx); if (faceIdx >= sMesh.mFaces.size()) { - DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section"); + ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section"); continue; } diff --git a/code/ASEParser.h b/code/ASE/ASEParser.h similarity index 93% rename from code/ASEParser.h rename to code/ASE/ASEParser.h index 8715fdfab..988cbda8d 100644 --- a/code/ASEParser.h +++ b/code/ASE/ASEParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -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 "3DSLoader.h" +#include "3DS/3DSLoader.h" namespace Assimp { namespace ASE { @@ -71,21 +71,20 @@ struct Material : public D3DS::Material //! Default constructor has been deleted Material() = delete; - //! Constructor with explicit name explicit Material(const std::string &name) : D3DS::Material(name) , pcInstance(NULL) - , bNeed (false) - {} - + , bNeed (false) { + // empty + } Material(const Material &other) = default; Material &operator=(const Material &other) = default; //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it - Material(Material &&other) + Material(Material &&other) AI_NO_EXCEPT : D3DS::Material(std::move(other)) , avSubMaterials(std::move(other.avSubMaterials)) , pcInstance(std::move(other.pcInstance)) @@ -95,7 +94,7 @@ struct Material : public D3DS::Material } - Material &operator=(Material &&other) { + Material &operator=(Material &&other) AI_NO_EXCEPT { if (this == &other) { return *this; } @@ -127,19 +126,12 @@ struct Material : public D3DS::Material // --------------------------------------------------------------------------- /** Helper structure to represent an ASE file face */ -struct Face : public FaceWithSmoothingGroup -{ +struct Face : public FaceWithSmoothingGroup { //! Default constructor. Initializes everything with 0 - Face() - { - mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - { - amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0; - } - - iMaterial = DEFAULT_MATINDEX; - iFace = 0; + Face() AI_NO_EXCEPT + : iMaterial(DEFAULT_MATINDEX) + , iFace(0) { + // empty } //! special value to indicate that no material index has @@ -147,8 +139,6 @@ struct Face : public FaceWithSmoothingGroup //! will replace this value later. static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF; - - //! Indices into each list of texture coordinates unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3]; @@ -166,15 +156,15 @@ struct Face : public FaceWithSmoothingGroup // --------------------------------------------------------------------------- /** Helper structure to represent an ASE file bone */ -struct Bone -{ +struct Bone { //! Constructor Bone() = delete; //! Construction from an existing name explicit Bone( const std::string& name) - : mName (name) - {} + : mName(name) { + // empty + } //! Name of the bone std::string mName; @@ -182,33 +172,27 @@ struct Bone // --------------------------------------------------------------------------- /** Helper structure to represent an ASE file bone vertex */ -struct BoneVertex -{ +struct BoneVertex { //! Bone and corresponding vertex weight. //! -1 for unrequired bones .... std::vector > mBoneWeights; - - //! Position of the bone vertex. - //! MUST be identical to the vertex position - //aiVector3D mPosition; }; // --------------------------------------------------------------------------- /** Helper structure to represent an ASE file animation */ -struct Animation -{ - enum Type - { +struct Animation { + enum Type { TRACK = 0x0, BEZIER = 0x1, TCB = 0x2 } mRotationType, mScalingType, mPositionType; - Animation() - : mRotationType (TRACK) - , mScalingType (TRACK) - , mPositionType (TRACK) - {} + Animation() AI_NO_EXCEPT + : mRotationType (TRACK) + , mScalingType (TRACK) + , mPositionType (TRACK) { + // empty + } //! List of track rotation keyframes std::vector< aiQuatKey > akeyRotations; @@ -218,19 +202,16 @@ struct Animation //! List of track scaling keyframes std::vector< aiVectorKey > akeyScaling; - }; // --------------------------------------------------------------------------- /** Helper structure to represent the inheritance information of an ASE node */ -struct InheritanceInfo -{ +struct InheritanceInfo { //! Default constructor - InheritanceInfo() - { - // set the inheritance flag for all axes by default to true - for (unsigned int i = 0; i < 3;++i) + InheritanceInfo() AI_NO_EXCEPT { + for ( size_t i=0; i<3; ++i ) { abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true; + } } //! Inherit the parent's position?, axis order is x,y,z @@ -245,23 +226,24 @@ struct InheritanceInfo // --------------------------------------------------------------------------- /** Represents an ASE file node. Base class for mesh, light and cameras */ -struct BaseNode -{ - enum Type {Light, Camera, Mesh, Dummy} mType; - +struct BaseNode { + enum Type { + Light, + Camera, + Mesh, + Dummy + } mType; //! Construction from an existing name BaseNode(Type _mType, const std::string &name) : mType (_mType) , mName (name) - , mProcessed (false) - { + , mProcessed (false) { // Set mTargetPosition to qnan const ai_real qnan = get_qnan(); mTargetPosition.x = qnan; } - //! Name of the mesh std::string mName; @@ -291,24 +273,23 @@ struct BaseNode // --------------------------------------------------------------------------- /** Helper structure to represent an ASE file mesh */ -struct Mesh : public MeshWithSmoothingGroups, public BaseNode -{ +struct Mesh : public MeshWithSmoothingGroups, public BaseNode { //! Default constructor has been deleted Mesh() = delete; - //! Construction from an existing name explicit Mesh(const std::string &name) - : BaseNode (BaseNode::Mesh, name) + : BaseNode( BaseNode::Mesh, name ) + , mVertexColors() + , mBoneVertices() + , mBones() , iMaterialIndex(Face::DEFAULT_MATINDEX) - , bSkip (false) - { - // use 2 texture vertex components by default - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + , bSkip (false) { + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { this->mNumUVComponents[c] = 2; + } } - //! List of all texture coordinate sets std::vector amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; @@ -396,12 +377,11 @@ struct Camera : public BaseNode // --------------------------------------------------------------------------- /** Helper structure to represent an ASE helper object (dummy) */ -struct Dummy : public BaseNode -{ +struct Dummy : public BaseNode { //! Constructor - Dummy() - : BaseNode (BaseNode::Dummy, "DUMMY") - { + Dummy() AI_NO_EXCEPT + : BaseNode (BaseNode::Dummy, "DUMMY") { + // empty } }; @@ -416,18 +396,17 @@ struct Dummy : public BaseNode // ------------------------------------------------------------------------------- /** \brief Class to parse ASE files */ -class Parser -{ - +class Parser { private: - - Parser() {} + Parser() AI_NO_EXCEPT { + // empty + } public: // ------------------------------------------------------------------- //! Construct a parser from a given input file which is - //! guaranted to be terminated with zero. + //! guaranteed to be terminated with zero. //! @param szFile Input file //! @param fileFormatDefault Assumed file format version. If the //! file format is specified in the file the new value replaces diff --git a/code/Assbin/AssbinExporter.cpp b/code/Assbin/AssbinExporter.cpp new file mode 100644 index 000000000..76c823f82 --- /dev/null +++ b/code/Assbin/AssbinExporter.cpp @@ -0,0 +1,846 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +/** @file AssbinExporter.cpp + * ASSBIN exporter main code + */ + +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER + +#include "Common/assbin_chunks.h" +#include "PostProcessing/ProcessHelper.h" + +#include +#include +#include +#include +#include + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +#else +# include "../contrib/zlib/zlib.h" +#endif + +#include + +namespace Assimp { + +template +size_t Write(IOStream * stream, const T& v) { + return stream->Write( &v, sizeof(T), 1 ); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiString +template <> +inline +size_t Write(IOStream * stream, const aiString& s) { + const size_t s2 = (uint32_t)s.length; + stream->Write(&s,4,1); + stream->Write(s.data,s2,1); + + return s2+4; +} + +// ----------------------------------------------------------------------------------- +// Serialize an unsigned int as uint32_t +template <> +inline +size_t Write(IOStream * stream, const unsigned int& w) { + const uint32_t t = (uint32_t)w; + if (w > t) { + // this shouldn't happen, integers in Assimp data structures never exceed 2^32 + throw DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); + } + + stream->Write(&t,4,1); + + return 4; +} + +// ----------------------------------------------------------------------------------- +// Serialize an unsigned int as uint16_t +template <> +inline +size_t Write(IOStream * stream, const uint16_t& w) { + static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); + stream->Write(&w,2,1); + + return 2; +} + +// ----------------------------------------------------------------------------------- +// Serialize a float +template <> +inline +size_t Write(IOStream * stream, const float& f) { + static_assert(sizeof(float)==4, "sizeof(float)==4"); + stream->Write(&f,4,1); + + return 4; +} + +// ----------------------------------------------------------------------------------- +// Serialize a double +template <> +inline +size_t Write(IOStream * stream, const double& f) { + static_assert(sizeof(double)==8, "sizeof(double)==8"); + stream->Write(&f,8,1); + + return 8; +} + +// ----------------------------------------------------------------------------------- +// Serialize a vec3 +template <> +inline +size_t Write(IOStream * stream, const aiVector3D& v) { + size_t t = Write(stream,v.x); + t += Write(stream,v.y); + t += Write(stream,v.z); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline +size_t Write(IOStream * stream, const aiColor3D& v) { + size_t t = Write(stream,v.r); + t += Write(stream,v.g); + t += Write(stream,v.b); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline +size_t Write(IOStream * stream, const aiColor4D& v) { + size_t t = Write(stream,v.r); + t += Write(stream,v.g); + t += Write(stream,v.b); + t += Write(stream,v.a); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a quaternion +template <> +inline +size_t Write(IOStream * stream, const aiQuaternion& v) { + size_t t = Write(stream,v.w); + t += Write(stream,v.x); + t += Write(stream,v.y); + t += Write(stream,v.z); + ai_assert(t == 16); + + return 16; +} + +// ----------------------------------------------------------------------------------- +// Serialize a vertex weight +template <> +inline +size_t Write(IOStream * stream, const aiVertexWeight& v) { + size_t t = Write(stream,v.mVertexId); + + return t+Write(stream,v.mWeight); +} + +// ----------------------------------------------------------------------------------- +// Serialize a mat4x4 +template <> +inline +size_t Write(IOStream * stream, const aiMatrix4x4& m) { + for (unsigned int i = 0; i < 4;++i) { + for (unsigned int i2 = 0; i2 < 4;++i2) { + Write(stream,m[i][i2]); + } + } + + return 64; +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiVectorKey +template <> +inline +size_t Write(IOStream * stream, const aiVectorKey& v) { + const size_t t = Write(stream,v.mTime); + return t + Write(stream,v.mValue); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiQuatKey +template <> +inline +size_t Write(IOStream * stream, const aiQuatKey& v) { + const size_t t = Write(stream,v.mTime); + return t + Write(stream,v.mValue); +} + +template +inline +size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) { + T minc, maxc; + ArrayBounds(in,size,minc,maxc); + + const size_t t = Write(stream,minc); + return t + Write(stream,maxc); +} + +// We use this to write out non-byte arrays so that we write using the specializations. +// This way we avoid writing out extra bytes that potentially come from struct alignment. +template +inline +size_t WriteArray(IOStream * stream, const T* in, unsigned int size) { + size_t n = 0; + for (unsigned int i=0; i(stream,in[i]); + + return n; +} + +// ---------------------------------------------------------------------------------- +/** @class AssbinChunkWriter + * @brief Chunk writer mechanism for the .assbin file structure + * + * This is a standard in-memory IOStream (most of the code is based on BlobIOStream), + * the difference being that this takes another IOStream as a "container" in the + * constructor, and when it is destroyed, it appends the magic number, the chunk size, + * and the chunk contents to the container stream. This allows relatively easy chunk + * chunk construction, even recursively. + */ +class AssbinChunkWriter : public IOStream +{ +private: + + uint8_t* buffer; + uint32_t magic; + IOStream * container; + size_t cur_size, cursor, initial; + +private: + // ------------------------------------------------------------------- + void Grow(size_t need = 0) + { + size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); + + const uint8_t* const old = buffer; + buffer = new uint8_t[new_size]; + + if (old) { + memcpy(buffer,old,cur_size); + delete[] old; + } + + cur_size = new_size; + } + +public: + + AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) + : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial) + { + } + + virtual ~AssbinChunkWriter() + { + if (container) { + container->Write( &magic, sizeof(uint32_t), 1 ); + container->Write( &cursor, sizeof(uint32_t), 1 ); + container->Write( buffer, 1, cursor ); + } + if (buffer) delete[] buffer; + } + + void * GetBufferPointer() { return buffer; } + + // ------------------------------------------------------------------- + virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { + return 0; + } + virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { + return aiReturn_FAILURE; + } + virtual size_t Tell() const { + return cursor; + } + virtual void Flush() { + // not implemented + } + + virtual size_t FileSize() const { + return cursor; + } + + // ------------------------------------------------------------------- + virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) { + pSize *= pCount; + if (cursor + pSize > cur_size) { + Grow(cursor + pSize); + } + + memcpy(buffer+cursor, pvBuffer, pSize); + cursor += pSize; + + return pCount; + } + +}; + +// ---------------------------------------------------------------------------------- +/** @class AssbinExport + * @brief Assbin exporter class + * + * This class performs the .assbin exporting, and is responsible for the file layout. + */ +class AssbinExport +{ +private: + bool shortened; + bool compressed; + +protected: + // ----------------------------------------------------------------------------------- + void WriteBinaryNode( IOStream * container, const aiNode* node) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); + + unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); + + Write(&chunk,node->mName); + Write(&chunk,node->mTransformation); + Write(&chunk,node->mNumChildren); + Write(&chunk,node->mNumMeshes); + Write(&chunk,nb_metadata); + + for (unsigned int i = 0; i < node->mNumMeshes;++i) { + Write(&chunk,node->mMeshes[i]); + } + + for (unsigned int i = 0; i < node->mNumChildren;++i) { + WriteBinaryNode( &chunk, node->mChildren[i] ); + } + + for (unsigned int i = 0; i < nb_metadata; ++i) { + const aiString& key = node->mMetaData->mKeys[i]; + aiMetadataType type = node->mMetaData->mValues[i].mType; + void* value = node->mMetaData->mValues[i].mData; + + Write(&chunk, key); + Write(&chunk, 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; +#ifdef SWIG + case FORCE_32BIT: +#endif // SWIG + default: + break; + } + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryTexture(IOStream * container, const aiTexture* tex) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE ); + + Write(&chunk,tex->mWidth); + Write(&chunk,tex->mHeight); + chunk.Write( tex->achFormatHint, sizeof(char), 4 ); + + if(!shortened) { + if (!tex->mHeight) { + chunk.Write(tex->pcData,1,tex->mWidth); + } + else { + chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4); + } + } + + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryBone(IOStream * container, const aiBone* b) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE ); + + Write(&chunk,b->mName); + Write(&chunk,b->mNumWeights); + Write(&chunk,b->mOffsetMatrix); + + // for the moment we write dumb min/max values for the bones, too. + // maybe I'll add a better, hash-like solution later + if (shortened) { + WriteBounds(&chunk,b->mWeights,b->mNumWeights); + } // else write as usual + else WriteArray(&chunk,b->mWeights,b->mNumWeights); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMesh(IOStream * container, const aiMesh* mesh) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH ); + + Write(&chunk,mesh->mPrimitiveTypes); + Write(&chunk,mesh->mNumVertices); + Write(&chunk,mesh->mNumFaces); + Write(&chunk,mesh->mNumBones); + Write(&chunk,mesh->mMaterialIndex); + + // first of all, write bits for all existent vertex components + unsigned int c = 0; + if (mesh->mVertices) { + c |= ASSBIN_MESH_HAS_POSITIONS; + } + if (mesh->mNormals) { + c |= ASSBIN_MESH_HAS_NORMALS; + } + if (mesh->mTangents && mesh->mBitangents) { + c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS; + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!mesh->mTextureCoords[n]) { + break; + } + c |= ASSBIN_MESH_HAS_TEXCOORD(n); + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!mesh->mColors[n]) { + break; + } + c |= ASSBIN_MESH_HAS_COLOR(n); + } + Write(&chunk,c); + + aiVector3D minVec, maxVec; + if (mesh->mVertices) { + if (shortened) { + WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mVertices,mesh->mNumVertices); + } + if (mesh->mNormals) { + if (shortened) { + WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mNormals,mesh->mNumVertices); + } + if (mesh->mTangents && mesh->mBitangents) { + if (shortened) { + WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices); + WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices); + } // else write as usual + else { + WriteArray(&chunk,mesh->mTangents,mesh->mNumVertices); + WriteArray(&chunk,mesh->mBitangents,mesh->mNumVertices); + } + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!mesh->mColors[n]) + break; + + if (shortened) { + WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mColors[n],mesh->mNumVertices); + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!mesh->mTextureCoords[n]) + break; + + // write number of UV components + Write(&chunk,mesh->mNumUVComponents[n]); + + if (shortened) { + WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); + } + + // write faces. There are no floating-point calculations involved + // in these, so we can write a simple hash over the face data + // to the dump file. We generate a single 32 Bit hash for 512 faces + // using Assimp's standard hashing function. + if (shortened) { + unsigned int processed = 0; + for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { + + uint32_t hash = 0; + for (unsigned int a = 0; a < job;++a) { + + const aiFace& f = mesh->mFaces[processed+a]; + uint32_t tmp = f.mNumIndices; + hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); + for (unsigned int i = 0; i < f.mNumIndices; ++i) { + static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); + tmp = static_cast( f.mIndices[i] ); + hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); + } + } + Write(&chunk,hash); + } + } + else // else write as usual + { + // if there are less than 2^16 vertices, we can simply use 16 bit integers ... + for (unsigned int i = 0; i < mesh->mNumFaces;++i) { + const aiFace& f = mesh->mFaces[i]; + + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); + Write(&chunk,f.mNumIndices); + + for (unsigned int a = 0; a < f.mNumIndices;++a) { + if (mesh->mNumVertices < (1u<<16)) { + Write(&chunk,f.mIndices[a]); + } + else Write(&chunk,f.mIndices[a]); + } + } + } + + // write bones + if (mesh->mNumBones) { + for (unsigned int a = 0; a < mesh->mNumBones;++a) { + const aiBone* b = mesh->mBones[a]; + WriteBinaryBone(&chunk,b); + } + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY ); + + Write(&chunk,prop->mKey); + Write(&chunk,prop->mSemantic); + Write(&chunk,prop->mIndex); + + Write(&chunk,prop->mDataLength); + Write(&chunk,(unsigned int)prop->mType); + chunk.Write(prop->mData,1,prop->mDataLength); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL); + + Write(&chunk,mat->mNumProperties); + for (unsigned int i = 0; i < mat->mNumProperties;++i) { + WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM ); + + Write(&chunk,nd->mNodeName); + Write(&chunk,nd->mNumPositionKeys); + Write(&chunk,nd->mNumRotationKeys); + Write(&chunk,nd->mNumScalingKeys); + Write(&chunk,nd->mPreState); + Write(&chunk,nd->mPostState); + + if (nd->mPositionKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); + + } // else write as usual + else WriteArray(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); + } + if (nd->mRotationKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); + + } // else write as usual + else WriteArray(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); + } + if (nd->mScalingKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); + + } // else write as usual + else WriteArray(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); + } + } + + + // ----------------------------------------------------------------------------------- + void WriteBinaryAnim( IOStream * container, const aiAnimation* anim ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION ); + + Write(&chunk,anim->mName); + Write(&chunk,anim->mDuration); + Write(&chunk,anim->mTicksPerSecond); + Write(&chunk,anim->mNumChannels); + + for (unsigned int a = 0; a < anim->mNumChannels;++a) { + const aiNodeAnim* nd = anim->mChannels[a]; + WriteBinaryNodeAnim(&chunk,nd); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryLight( IOStream * container, const aiLight* l ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT ); + + Write(&chunk,l->mName); + Write(&chunk,l->mType); + + if (l->mType != aiLightSource_DIRECTIONAL) { + Write(&chunk,l->mAttenuationConstant); + Write(&chunk,l->mAttenuationLinear); + Write(&chunk,l->mAttenuationQuadratic); + } + + Write(&chunk,l->mColorDiffuse); + Write(&chunk,l->mColorSpecular); + Write(&chunk,l->mColorAmbient); + + if (l->mType == aiLightSource_SPOT) { + Write(&chunk,l->mAngleInnerCone); + Write(&chunk,l->mAngleOuterCone); + } + + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryCamera( IOStream * container, const aiCamera* cam ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA ); + + Write(&chunk,cam->mName); + Write(&chunk,cam->mPosition); + Write(&chunk,cam->mLookAt); + Write(&chunk,cam->mUp); + Write(&chunk,cam->mHorizontalFOV); + Write(&chunk,cam->mClipPlaneNear); + Write(&chunk,cam->mClipPlaneFar); + Write(&chunk,cam->mAspect); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryScene( IOStream * container, const aiScene* scene) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE ); + + // basic scene information + Write(&chunk,scene->mFlags); + Write(&chunk,scene->mNumMeshes); + Write(&chunk,scene->mNumMaterials); + Write(&chunk,scene->mNumAnimations); + Write(&chunk,scene->mNumTextures); + Write(&chunk,scene->mNumLights); + Write(&chunk,scene->mNumCameras); + + // write node graph + WriteBinaryNode( &chunk, scene->mRootNode ); + + // write all meshes + for (unsigned int i = 0; i < scene->mNumMeshes;++i) { + const aiMesh* mesh = scene->mMeshes[i]; + WriteBinaryMesh( &chunk,mesh); + } + + // write materials + for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { + const aiMaterial* mat = scene->mMaterials[i]; + WriteBinaryMaterial(&chunk,mat); + } + + // write all animations + for (unsigned int i = 0; i < scene->mNumAnimations;++i) { + const aiAnimation* anim = scene->mAnimations[i]; + WriteBinaryAnim(&chunk,anim); + } + + + // write all textures + for (unsigned int i = 0; i < scene->mNumTextures;++i) { + const aiTexture* mesh = scene->mTextures[i]; + WriteBinaryTexture(&chunk,mesh); + } + + // write lights + for (unsigned int i = 0; i < scene->mNumLights;++i) { + const aiLight* l = scene->mLights[i]; + WriteBinaryLight(&chunk,l); + } + + // write cameras + for (unsigned int i = 0; i < scene->mNumCameras;++i) { + const aiCamera* cam = scene->mCameras[i]; + WriteBinaryCamera(&chunk,cam); + } + + } + +public: + AssbinExport() + : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters + { + } + + // ----------------------------------------------------------------------------------- + // Write a binary model dump + void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) + { + IOStream * out = pIOSystem->Open( pFile, "wb" ); + if (!out) return; + + time_t tt = time(NULL); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + + // header + char s[64]; + memset( s, 0, 64 ); +#if _MSC_VER >= 1400 + sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p)); +#else + ai_snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p)); +#endif + out->Write( s, 44, 1 ); + // == 44 bytes + + Write( out, ASSBIN_VERSION_MAJOR ); + Write( out, ASSBIN_VERSION_MINOR ); + Write( out, aiGetVersionRevision() ); + Write( out, aiGetCompileFlags() ); + Write( out, shortened ); + Write( out, compressed ); + // == 20 bytes + + char buff[256]; + strncpy(buff,pFile,256); + out->Write(buff,sizeof(char),256); + + char cmd[] = "\0"; + strncpy(buff,cmd,128); + out->Write(buff,sizeof(char),128); + + // leave 64 bytes free for future extensions + memset(buff,0xcd,64); + out->Write(buff,sizeof(char),64); + // == 435 bytes + + // ==== total header size: 512 bytes + ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH ); + + // Up to here the data is uncompressed. For compressed files, the rest + // is compressed using standard DEFLATE from zlib. + if (compressed) + { + AssbinChunkWriter uncompressedStream( NULL, 0 ); + WriteBinaryScene( &uncompressedStream, pScene ); + + uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); + uLongf compressedSize = (uLongf)compressBound(uncompressedSize); + uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; + + int res = compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); + if(res != Z_OK) + { + delete [] compressedBuffer; + pIOSystem->Close(out); + throw DeadlyExportError("Compression failed."); + } + + out->Write( &uncompressedSize, sizeof(uint32_t), 1 ); + out->Write( compressedBuffer, sizeof(char), compressedSize ); + + delete[] compressedBuffer; + } + else + { + WriteBinaryScene( out, pScene ); + } + + pIOSystem->Close( out ); + } +}; + +void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { + AssbinExport exporter; + exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); +} +} // end of namespace Assimp + +#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/AssbinExporter.h b/code/Assbin/AssbinExporter.h similarity index 87% rename from code/AssbinExporter.h rename to code/Assbin/AssbinExporter.h index 2539984c3..3e13639bb 100644 --- a/code/AssbinExporter.h +++ b/code/Assbin/AssbinExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -46,6 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASSBINEXPORTER_H_INC #define AI_ASSBINEXPORTER_H_INC -// nothing really needed here - reserved for future use like properties +#include -#endif +// nothing really needed here - reserved for future use like properties +namespace Assimp { + +void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/); + +} + +#endif // AI_ASSBINEXPORTER_H_INC diff --git a/code/AssbinLoader.cpp b/code/Assbin/AssbinLoader.cpp similarity index 68% rename from code/AssbinLoader.cpp rename to code/Assbin/AssbinLoader.cpp index 65b29b737..becc3f8fc 100644 --- a/code/AssbinLoader.cpp +++ b/code/Assbin/AssbinLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -50,13 +50,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER // internal headers -#include "AssbinLoader.h" -#include "assbin_chunks.h" +#include "Assbin/AssbinLoader.h" +#include "Common/assbin_chunks.h" #include #include #include #include #include +#include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include @@ -67,7 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; static const aiImporterDesc desc = { - ".assbin Importer", + "Assimp Binary Importer", "Gargaj / Conspiracy", "", "", @@ -79,16 +80,17 @@ static const aiImporterDesc desc = { "assbin" }; -const aiImporterDesc* AssbinImporter::GetInfo() const -{ +// ----------------------------------------------------------------------------------- +const aiImporterDesc* AssbinImporter::GetInfo() const { return &desc; } -bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const -{ +// ----------------------------------------------------------------------------------- +bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const { IOStream * in = pIOHandler->Open(pFile); - if (!in) + if (nullptr == in) { return false; + } char s[32]; in->Read( s, sizeof(char), 32 ); @@ -98,17 +100,19 @@ bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bo return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0; } +// ----------------------------------------------------------------------------------- template -T Read(IOStream * stream) -{ +T Read(IOStream * stream) { T t; - stream->Read( &t, sizeof(T), 1 ); + size_t res = stream->Read( &t, sizeof(T), 1 ); + if(res != 1) + throw DeadlyImportError("Unexpected EOF"); return t; } +// ----------------------------------------------------------------------------------- template <> -aiVector3D Read(IOStream * stream) -{ +aiVector3D Read(IOStream * stream) { aiVector3D v; v.x = Read(stream); v.y = Read(stream); @@ -116,9 +120,9 @@ aiVector3D Read(IOStream * stream) return v; } +// ----------------------------------------------------------------------------------- template <> -aiColor4D Read(IOStream * stream) -{ +aiColor4D Read(IOStream * stream) { aiColor4D c; c.r = Read(stream); c.g = Read(stream); @@ -127,9 +131,9 @@ aiColor4D Read(IOStream * stream) return c; } +// ----------------------------------------------------------------------------------- template <> -aiQuaternion Read(IOStream * stream) -{ +aiQuaternion Read(IOStream * stream) { aiQuaternion v; v.w = Read(stream); v.x = Read(stream); @@ -138,28 +142,29 @@ aiQuaternion Read(IOStream * stream) return v; } +// ----------------------------------------------------------------------------------- template <> -aiString Read(IOStream * stream) -{ +aiString Read(IOStream * stream) { aiString s; stream->Read(&s.length,4,1); - stream->Read(s.data,s.length,1); + if(s.length) + stream->Read(s.data,s.length,1); s.data[s.length] = 0; return s; } +// ----------------------------------------------------------------------------------- template <> -aiVertexWeight Read(IOStream * stream) -{ +aiVertexWeight Read(IOStream * stream) { aiVertexWeight w; w.mVertexId = Read(stream); w.mWeight = Read(stream); return w; } +// ----------------------------------------------------------------------------------- template <> -aiMatrix4x4 Read(IOStream * stream) -{ +aiMatrix4x4 Read(IOStream * stream) { aiMatrix4x4 m; for (unsigned int i = 0; i < 4;++i) { for (unsigned int i2 = 0; i2 < 4;++i2) { @@ -169,76 +174,85 @@ aiMatrix4x4 Read(IOStream * stream) return m; } +// ----------------------------------------------------------------------------------- template <> -aiVectorKey Read(IOStream * stream) -{ +aiVectorKey Read(IOStream * stream) { aiVectorKey v; v.mTime = Read(stream); v.mValue = Read(stream); return v; } +// ----------------------------------------------------------------------------------- template <> -aiQuatKey Read(IOStream * stream) -{ +aiQuatKey Read(IOStream * stream) { aiQuatKey v; v.mTime = Read(stream); v.mValue = Read(stream); return v; } +// ----------------------------------------------------------------------------------- template -void ReadArray(IOStream * stream, T * out, unsigned int size) -{ - for (unsigned int i=0; i(stream); +void ReadArray( IOStream *stream, T * out, unsigned int size) { + ai_assert( nullptr != stream ); + ai_assert( nullptr != out ); + + for (unsigned int i=0; i(stream); + } } -template void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) -{ +// ----------------------------------------------------------------------------------- +template +void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) { // not sure what to do here, the data isn't really useful. stream->Seek( sizeof(T) * n, aiOrigin_CUR ); } -void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AINODE); +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* parent ) { + if(Read(stream) != ASSBIN_CHUNK_AINODE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); - *node = new aiNode(); + std::unique_ptr node(new aiNode()); - (*node)->mName = Read(stream); - (*node)->mTransformation = Read(stream); - (*node)->mNumChildren = Read(stream); - (*node)->mNumMeshes = Read(stream); + node->mName = Read(stream); + node->mTransformation = Read(stream); + unsigned numChildren = Read(stream); + unsigned numMeshes = Read(stream); unsigned int nb_metadata = Read(stream); if(parent) { - (*node)->mParent = parent; + node->mParent = parent; } - if ((*node)->mNumMeshes) { - (*node)->mMeshes = new unsigned int[(*node)->mNumMeshes]; - for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) { - (*node)->mMeshes[i] = Read(stream); + if (numMeshes) + { + node->mMeshes = new unsigned int[numMeshes]; + for (unsigned int i = 0; i < numMeshes; ++i) { + node->mMeshes[i] = Read(stream); + node->mNumMeshes++; } } - if ((*node)->mNumChildren) { - (*node)->mChildren = new aiNode*[(*node)->mNumChildren]; - for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) { - ReadBinaryNode( stream, &(*node)->mChildren[i], *node ); + if (numChildren) { + node->mChildren = new aiNode*[numChildren]; + for (unsigned int i = 0; i < numChildren; ++i) { + ReadBinaryNode( stream, &node->mChildren[i], node.get() ); + node->mNumChildren++; } } if ( nb_metadata > 0 ) { - (*node)->mMetaData = aiMetadata::Alloc(nb_metadata); + node->mMetaData = aiMetadata::Alloc(nb_metadata); for (unsigned int i = 0; i < nb_metadata; ++i) { - (*node)->mMetaData->mKeys[i] = Read(stream); - (*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read(stream); - void* data( nullptr ); + node->mMetaData->mKeys[i] = Read(stream); + node->mMetaData->mValues[i].mType = (aiMetadataType) Read(stream); + void* data = nullptr; - switch ((*node)->mMetaData->mValues[i].mType) { + switch (node->mMetaData->mValues[i].mType) { case AI_BOOL: data = new bool(Read(stream)); break; @@ -267,17 +281,16 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p break; } - (*node)->mMetaData->mValues[i].mData = data; + node->mMetaData->mValues[i].mData = data; } } + *onode = node.release(); } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIBONE); +void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) { + if(Read(stream) != ASSBIN_CHUNK_AIBONE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); b->mName = Read(stream); @@ -286,23 +299,23 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) // for the moment we write dumb min/max values for the bones, too. // maybe I'll add a better, hash-like solution later - if (shortened) - { + if (shortened) { ReadBounds(stream,b->mWeights,b->mNumWeights); - } // else write as usual - else - { + } else { + // else write as usual b->mWeights = new aiVertexWeight[b->mNumWeights]; ReadArray(stream,b->mWeights,b->mNumWeights); } } - -void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMESH); +// ----------------------------------------------------------------------------------- +static bool fitsIntoUI16(unsigned int mNumVertices) { + return ( mNumVertices < (1u<<16) ); +} +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) { + if(Read(stream) != ASSBIN_CHUNK_AIMESH) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); mesh->mPrimitiveTypes = Read(stream); @@ -314,70 +327,61 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) // first of all, write bits for all existent vertex components unsigned int c = Read(stream); - if (c & ASSBIN_MESH_HAS_POSITIONS) - { + if (c & ASSBIN_MESH_HAS_POSITIONS) { if (shortened) { ReadBounds(stream,mesh->mVertices,mesh->mNumVertices); - } // else write as usual - else - { + } else { + // else write as usual mesh->mVertices = new aiVector3D[mesh->mNumVertices]; ReadArray(stream,mesh->mVertices,mesh->mNumVertices); } } - if (c & ASSBIN_MESH_HAS_NORMALS) - { + if (c & ASSBIN_MESH_HAS_NORMALS) { if (shortened) { ReadBounds(stream,mesh->mNormals,mesh->mNumVertices); - } // else write as usual - else - { + } else { + // else write as usual mesh->mNormals = new aiVector3D[mesh->mNumVertices]; ReadArray(stream,mesh->mNormals,mesh->mNumVertices); } } - if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) - { + if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) { if (shortened) { ReadBounds(stream,mesh->mTangents,mesh->mNumVertices); ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices); - } // else write as usual - else - { + } else { + // else write as usual mesh->mTangents = new aiVector3D[mesh->mNumVertices]; ReadArray(stream,mesh->mTangents,mesh->mNumVertices); mesh->mBitangents = new aiVector3D[mesh->mNumVertices]; ReadArray(stream,mesh->mBitangents,mesh->mNumVertices); } } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) - { - if (!(c & ASSBIN_MESH_HAS_COLOR(n))) + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!(c & ASSBIN_MESH_HAS_COLOR(n))) { break; + } - if (shortened) - { + if (shortened) { ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices); - } // else write as usual - else - { + } else { + // else write as usual mesh->mColors[n] = new aiColor4D[mesh->mNumVertices]; ReadArray(stream,mesh->mColors[n],mesh->mNumVertices); } } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) - { - if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) { break; + } // write number of UV components mesh->mNumUVComponents[n] = Read(stream); if (shortened) { ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices); - } // else write as usual - else - { + } else { + // else write as usual mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices]; ReadArray(stream,mesh->mTextureCoords[n],mesh->mNumVertices); } @@ -389,9 +393,8 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) // using Assimp's standard hashing function. if (shortened) { Read(stream); - } - else // else write as usual - { + } else { + // else write as usual // if there are less than 2^16 vertices, we can simply use 16 bit integers ... mesh->mFaces = new aiFace[mesh->mNumFaces]; for (unsigned int i = 0; i < mesh->mNumFaces;++i) { @@ -402,12 +405,10 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) f.mIndices = new unsigned int[f.mNumIndices]; for (unsigned int a = 0; a < f.mNumIndices;++a) { - if (mesh->mNumVertices < (1u<<16)) - { + // Check if unsigned short ( 16 bit ) are big enought for the indices + if ( fitsIntoUI16( mesh->mNumVertices ) ) { f.mIndices[a] = Read(stream); - } - else - { + } else { f.mIndices[a] = Read(stream); } } @@ -424,11 +425,10 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) } } -void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY); +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) { + if(Read(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); prop->mKey = Read(stream); @@ -442,11 +442,9 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL); +void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) { + if(Read(stream) != ASSBIN_CHUNK_AIMATERIAL) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); mat->mNumAllocated = mat->mNumProperties = Read(stream); @@ -465,11 +463,9 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM); +void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) { + if(Read(stream) != ASSBIN_CHUNK_AINODEANIM) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); nd->mNodeName = Read(stream); @@ -493,9 +489,8 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) if (shortened) { ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys); - } // else write as usual - else - { + } else { + // else write as usual nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; ReadArray(stream,nd->mRotationKeys,nd->mNumRotationKeys); } @@ -504,22 +499,18 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) if (shortened) { ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys); - } // else write as usual - else - { + } else { + // else write as usual nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys]; ReadArray(stream,nd->mScalingKeys,nd->mNumScalingKeys); } } } - // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION); +void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) { + if(Read(stream) != ASSBIN_CHUNK_AIANIMATION) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); anim->mName = Read (stream); @@ -527,8 +518,7 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) anim->mTicksPerSecond = Read (stream); anim->mNumChannels = Read(stream); - if (anim->mNumChannels) - { + if (anim->mNumChannels) { anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ]; for (unsigned int a = 0; a < anim->mNumChannels;++a) { anim->mChannels[a] = new aiNodeAnim(); @@ -537,11 +527,10 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) } } -void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE); +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) { + if(Read(stream) != ASSBIN_CHUNK_AITEXTURE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); tex->mWidth = Read(stream); @@ -552,21 +541,17 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) if (!tex->mHeight) { tex->pcData = new aiTexel[ tex->mWidth ]; stream->Read(tex->pcData,1,tex->mWidth); - } - else { + } else { tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ]; stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4); } } - } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT); +void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) { + if(Read(stream) != ASSBIN_CHUNK_AILIGHT) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); l->mName = Read(stream); @@ -586,15 +571,12 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) l->mAngleInnerCone = Read(stream); l->mAngleOuterCone = Read(stream); } - } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA); +void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) { + if(Read(stream) != ASSBIN_CHUNK_AICAMERA) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); cam->mName = Read(stream); @@ -607,11 +589,10 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) cam->mAspect = Read(stream); } -void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) -{ - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AISCENE); +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { + if(Read(stream) != ASSBIN_CHUNK_AISCENE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); scene->mFlags = Read(stream); @@ -623,13 +604,13 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) scene->mNumCameras = Read(stream); // Read node graph - scene->mRootNode = new aiNode[1]; + //scene->mRootNode = new aiNode[1]; ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL ); // Read all meshes - if (scene->mNumMeshes) - { + if (scene->mNumMeshes) { scene->mMeshes = new aiMesh*[scene->mNumMeshes]; + memset(scene->mMeshes, 0, scene->mNumMeshes*sizeof(aiMesh*)); for (unsigned int i = 0; i < scene->mNumMeshes;++i) { scene->mMeshes[i] = new aiMesh(); ReadBinaryMesh( stream,scene->mMeshes[i]); @@ -637,9 +618,9 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) } // Read materials - if (scene->mNumMaterials) - { + if (scene->mNumMaterials) { scene->mMaterials = new aiMaterial*[scene->mNumMaterials]; + memset(scene->mMaterials, 0, scene->mNumMaterials*sizeof(aiMaterial*)); for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { scene->mMaterials[i] = new aiMaterial(); ReadBinaryMaterial(stream,scene->mMaterials[i]); @@ -647,9 +628,9 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) } // Read all animations - if (scene->mNumAnimations) - { + if (scene->mNumAnimations) { scene->mAnimations = new aiAnimation*[scene->mNumAnimations]; + memset(scene->mAnimations, 0, scene->mNumAnimations*sizeof(aiAnimation*)); for (unsigned int i = 0; i < scene->mNumAnimations;++i) { scene->mAnimations[i] = new aiAnimation(); ReadBinaryAnim(stream,scene->mAnimations[i]); @@ -657,9 +638,9 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) } // Read all textures - if (scene->mNumTextures) - { + if (scene->mNumTextures) { scene->mTextures = new aiTexture*[scene->mNumTextures]; + memset(scene->mTextures, 0, scene->mNumTextures*sizeof(aiTexture*)); for (unsigned int i = 0; i < scene->mNumTextures;++i) { scene->mTextures[i] = new aiTexture(); ReadBinaryTexture(stream,scene->mTextures[i]); @@ -667,9 +648,9 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) } // Read lights - if (scene->mNumLights) - { + if (scene->mNumLights) { scene->mLights = new aiLight*[scene->mNumLights]; + memset(scene->mLights, 0, scene->mNumLights*sizeof(aiLight*)); for (unsigned int i = 0; i < scene->mNumLights;++i) { scene->mLights[i] = new aiLight(); ReadBinaryLight(stream,scene->mLights[i]); @@ -677,9 +658,9 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) } // Read cameras - if (scene->mNumCameras) - { + if (scene->mNumCameras) { scene->mCameras = new aiCamera*[scene->mNumCameras]; + memset(scene->mCameras, 0, scene->mNumCameras*sizeof(aiCamera*)); for (unsigned int i = 0; i < scene->mNumCameras;++i) { scene->mCameras[i] = new aiCamera(); ReadBinaryCamera(stream,scene->mCameras[i]); @@ -688,16 +669,22 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) } -void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) -{ +// ----------------------------------------------------------------------------------- +void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { IOStream * stream = pIOHandler->Open(pFile,"rb"); - if (!stream) + if (nullptr == stream) { return; + } - stream->Seek( 44, aiOrigin_CUR ); // signature + // signature + stream->Seek( 44, aiOrigin_CUR ); + + unsigned int versionMajor = Read(stream); + unsigned int versionMinor = Read(stream); + if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) { + throw DeadlyImportError( "Invalid version, data format not compatible!" ); + } - /*unsigned int versionMajor =*/ Read(stream); - /*unsigned int versionMinor =*/ Read(stream); /*unsigned int versionRevision =*/ Read(stream); /*unsigned int compileFlags =*/ Read(stream); @@ -711,17 +698,24 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, stream->Seek( 128, aiOrigin_CUR ); // options stream->Seek( 64, aiOrigin_CUR ); // padding - if (compressed) - { + if (compressed) { uLongf uncompressedSize = Read(stream); uLongf compressedSize = static_cast(stream->FileSize() - stream->Tell()); unsigned char * compressedData = new unsigned char[ compressedSize ]; - stream->Read( compressedData, 1, compressedSize ); + size_t len = stream->Read( compressedData, 1, compressedSize ); + ai_assert(len == compressedSize); unsigned char * uncompressedData = new unsigned char[ uncompressedSize ]; - uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize ); + int res = uncompress( uncompressedData, &uncompressedSize, compressedData, (uLong) len ); + if(res != Z_OK) + { + delete [] uncompressedData; + delete [] compressedData; + pIOHandler->Close(stream); + throw DeadlyImportError("Zlib decompression failed."); + } MemoryIOStream io( uncompressedData, uncompressedSize ); @@ -729,9 +723,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, delete[] uncompressedData; delete[] compressedData; - } - else - { + } else { ReadBinaryScene(stream,pScene); } diff --git a/code/AssbinLoader.h b/code/Assbin/AssbinLoader.h similarity index 69% rename from code/AssbinLoader.h rename to code/Assbin/AssbinLoader.h index 9ffd84a16..9f2dde125 100644 --- a/code/AssbinLoader.h +++ b/code/Assbin/AssbinLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -70,32 +70,33 @@ namespace Assimp { class AssbinImporter : public BaseImporter { private: - bool shortened; - bool compressed; + bool shortened; + bool compressed; public: - virtual bool CanRead( - const std::string& pFile, - IOSystem* pIOHandler, - bool checkSig + virtual bool CanRead( + const std::string& pFile, + IOSystem* pIOHandler, + bool checkSig ) const; - virtual const aiImporterDesc* GetInfo() const; - virtual void InternReadFile( + virtual const aiImporterDesc* GetInfo() const; + virtual void InternReadFile( const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler + aiScene* pScene, + IOSystem* pIOHandler ); - void ReadBinaryScene( IOStream * stream, aiScene* pScene ); - void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent ); - void ReadBinaryMesh( IOStream * stream, aiMesh* mesh ); - void ReadBinaryBone( IOStream * stream, aiBone* bone ); - void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat); - void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop); - void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd); - void ReadBinaryAnim( IOStream * stream, aiAnimation* anim ); - void ReadBinaryTexture(IOStream * stream, aiTexture* tex); - void ReadBinaryLight( IOStream * stream, aiLight* l ); - void ReadBinaryCamera( IOStream * stream, aiCamera* cam ); + void ReadHeader(); + void ReadBinaryScene( IOStream * stream, aiScene* pScene ); + void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent ); + void ReadBinaryMesh( IOStream * stream, aiMesh* mesh ); + void ReadBinaryBone( IOStream * stream, aiBone* bone ); + void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat); + void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop); + void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd); + void ReadBinaryAnim( IOStream * stream, aiAnimation* anim ); + void ReadBinaryTexture(IOStream * stream, aiTexture* tex); + void ReadBinaryLight( IOStream * stream, aiLight* l ); + void ReadBinaryCamera( IOStream * stream, aiCamera* cam ); }; } // end of namespace Assimp diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp deleted file mode 100644 index cc404396b..000000000 --- a/code/AssbinExporter.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2018, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ -/** @file AssbinExporter.cpp - * ASSBIN exporter main code - */ - -#ifndef ASSIMP_BUILD_NO_EXPORT -#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER - -#include "assbin_chunks.h" -#include -#include -#include -#include -#include "ProcessHelper.h" -#include - -#ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -#else -# include "../contrib/zlib/zlib.h" -#endif - -#include - -using namespace Assimp; - -namespace Assimp { - -template -size_t Write(IOStream * stream, const T& v) -{ - return stream->Write( &v, sizeof(T), 1 ); -} - - -// ----------------------------------------------------------------------------------- -// Serialize an aiString -template <> -inline size_t Write(IOStream * stream, const aiString& s) -{ - const size_t s2 = (uint32_t)s.length; - stream->Write(&s,4,1); - stream->Write(s.data,s2,1); - return s2+4; -} - -// ----------------------------------------------------------------------------------- -// Serialize an unsigned int as uint32_t -template <> -inline size_t Write(IOStream * stream, const unsigned int& w) -{ - const uint32_t t = (uint32_t)w; - if (w > t) { - // this shouldn't happen, integers in Assimp data structures never exceed 2^32 - throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); - } - - stream->Write(&t,4,1); - return 4; -} - -// ----------------------------------------------------------------------------------- -// Serialize an unsigned int as uint16_t -template <> -inline size_t Write(IOStream * stream, const uint16_t& w) -{ - static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); - stream->Write(&w,2,1); - return 2; -} - -// ----------------------------------------------------------------------------------- -// Serialize a float -template <> -inline size_t Write(IOStream * stream, const float& f) -{ - static_assert(sizeof(float)==4, "sizeof(float)==4"); - stream->Write(&f,4,1); - return 4; -} - -// ----------------------------------------------------------------------------------- -// Serialize a double -template <> -inline size_t Write(IOStream * stream, const double& f) -{ - static_assert(sizeof(double)==8, "sizeof(double)==8"); - stream->Write(&f,8,1); - return 8; -} - -// ----------------------------------------------------------------------------------- -// Serialize a vec3 -template <> -inline size_t Write(IOStream * stream, const aiVector3D& v) -{ - size_t t = Write(stream,v.x); - t += Write(stream,v.y); - t += Write(stream,v.z); - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a color value -template <> -inline size_t Write(IOStream * stream, const aiColor3D& v) -{ - size_t t = Write(stream,v.r); - t += Write(stream,v.g); - t += Write(stream,v.b); - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a color value -template <> -inline size_t Write(IOStream * stream, const aiColor4D& v) -{ - size_t t = Write(stream,v.r); - t += Write(stream,v.g); - t += Write(stream,v.b); - t += Write(stream,v.a); - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a quaternion -template <> -inline size_t Write(IOStream * stream, const aiQuaternion& v) -{ - size_t t = Write(stream,v.w); - t += Write(stream,v.x); - t += Write(stream,v.y); - t += Write(stream,v.z); - ai_assert(t == 16); - return 16; -} - - -// ----------------------------------------------------------------------------------- -// Serialize a vertex weight -template <> -inline size_t Write(IOStream * stream, const aiVertexWeight& v) -{ - size_t t = Write(stream,v.mVertexId); - return t+Write(stream,v.mWeight); -} - -// ----------------------------------------------------------------------------------- -// Serialize a mat4x4 -template <> -inline size_t Write(IOStream * stream, const aiMatrix4x4& m) -{ - for (unsigned int i = 0; i < 4;++i) { - for (unsigned int i2 = 0; i2 < 4;++i2) { - Write(stream,m[i][i2]); - } - } - return 64; -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiVectorKey -template <> -inline size_t Write(IOStream * stream, const aiVectorKey& v) -{ - const size_t t = Write(stream,v.mTime); - return t + Write(stream,v.mValue); -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiQuatKey -template <> -inline size_t Write(IOStream * stream, const aiQuatKey& v) -{ - const size_t t = Write(stream,v.mTime); - return t + Write(stream,v.mValue); -} - -template -inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) -{ - T minc,maxc; - ArrayBounds(in,size,minc,maxc); - - const size_t t = Write(stream,minc); - return t + Write(stream,maxc); -} - -// We use this to write out non-byte arrays so that we write using the specializations. -// This way we avoid writing out extra bytes that potentially come from struct alignment. -template -inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) -{ - size_t n = 0; - for (unsigned int i=0; i(stream,in[i]); - return n; -} - - // ---------------------------------------------------------------------------------- - /** @class AssbinChunkWriter - * @brief Chunk writer mechanism for the .assbin file structure - * - * This is a standard in-memory IOStream (most of the code is based on BlobIOStream), - * the difference being that this takes another IOStream as a "container" in the - * constructor, and when it is destroyed, it appends the magic number, the chunk size, - * and the chunk contents to the container stream. This allows relatively easy chunk - * chunk construction, even recursively. - */ - class AssbinChunkWriter : public IOStream - { - private: - - uint8_t* buffer; - uint32_t magic; - IOStream * container; - size_t cur_size, cursor, initial; - - private: - // ------------------------------------------------------------------- - void Grow(size_t need = 0) - { - size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); - - const uint8_t* const old = buffer; - buffer = new uint8_t[new_size]; - - if (old) { - memcpy(buffer,old,cur_size); - delete[] old; - } - - cur_size = new_size; - } - - public: - - AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) - : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial) - { - } - - virtual ~AssbinChunkWriter() - { - if (container) { - container->Write( &magic, sizeof(uint32_t), 1 ); - container->Write( &cursor, sizeof(uint32_t), 1 ); - container->Write( buffer, 1, cursor ); - } - if (buffer) delete[] buffer; - } - - void * GetBufferPointer() { return buffer; } - - // ------------------------------------------------------------------- - virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; } - virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; } - virtual size_t Tell() const { return cursor; } - virtual void Flush() { } - - virtual size_t FileSize() const - { - return cursor; - } - - // ------------------------------------------------------------------- - virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) - { - pSize *= pCount; - if (cursor + pSize > cur_size) { - Grow(cursor + pSize); - } - - memcpy(buffer+cursor, pvBuffer, pSize); - cursor += pSize; - - return pCount; - } - - }; - - // ---------------------------------------------------------------------------------- - /** @class AssbinExport - * @brief Assbin exporter class - * - * This class performs the .assbin exporting, and is responsible for the file layout. - */ - class AssbinExport - { - private: - bool shortened; - bool compressed; - - protected: - - // ----------------------------------------------------------------------------------- - void WriteBinaryNode( IOStream * container, const aiNode* node) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); - - unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); - - Write(&chunk,node->mName); - Write(&chunk,node->mTransformation); - Write(&chunk,node->mNumChildren); - Write(&chunk,node->mNumMeshes); - Write(&chunk,nb_metadata); - - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - Write(&chunk,node->mMeshes[i]); - } - - for (unsigned int i = 0; i < node->mNumChildren;++i) { - WriteBinaryNode( &chunk, node->mChildren[i] ); - } - - for (unsigned int i = 0; i < nb_metadata; ++i) { - const aiString& key = node->mMetaData->mKeys[i]; - aiMetadataType type = node->mMetaData->mValues[i].mType; - void* value = node->mMetaData->mValues[i].mData; - - Write(&chunk, key); - Write(&chunk, 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; -#ifdef SWIG - case FORCE_32BIT: -#endif // SWIG - default: - break; - } - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryTexture(IOStream * container, const aiTexture* tex) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE ); - - Write(&chunk,tex->mWidth); - Write(&chunk,tex->mHeight); - chunk.Write( tex->achFormatHint, sizeof(char), 4 ); - - if(!shortened) { - if (!tex->mHeight) { - chunk.Write(tex->pcData,1,tex->mWidth); - } - else { - chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4); - } - } - - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryBone(IOStream * container, const aiBone* b) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE ); - - Write(&chunk,b->mName); - Write(&chunk,b->mNumWeights); - Write(&chunk,b->mOffsetMatrix); - - // for the moment we write dumb min/max values for the bones, too. - // maybe I'll add a better, hash-like solution later - if (shortened) { - WriteBounds(&chunk,b->mWeights,b->mNumWeights); - } // else write as usual - else WriteArray(&chunk,b->mWeights,b->mNumWeights); - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryMesh(IOStream * container, const aiMesh* mesh) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH ); - - Write(&chunk,mesh->mPrimitiveTypes); - Write(&chunk,mesh->mNumVertices); - Write(&chunk,mesh->mNumFaces); - Write(&chunk,mesh->mNumBones); - Write(&chunk,mesh->mMaterialIndex); - - // first of all, write bits for all existent vertex components - unsigned int c = 0; - if (mesh->mVertices) { - c |= ASSBIN_MESH_HAS_POSITIONS; - } - if (mesh->mNormals) { - c |= ASSBIN_MESH_HAS_NORMALS; - } - if (mesh->mTangents && mesh->mBitangents) { - c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS; - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (!mesh->mTextureCoords[n]) { - break; - } - c |= ASSBIN_MESH_HAS_TEXCOORD(n); - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { - if (!mesh->mColors[n]) { - break; - } - c |= ASSBIN_MESH_HAS_COLOR(n); - } - Write(&chunk,c); - - aiVector3D minVec, maxVec; - if (mesh->mVertices) { - if (shortened) { - WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mVertices,mesh->mNumVertices); - } - if (mesh->mNormals) { - if (shortened) { - WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mNormals,mesh->mNumVertices); - } - if (mesh->mTangents && mesh->mBitangents) { - if (shortened) { - WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices); - WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices); - } // else write as usual - else { - WriteArray(&chunk,mesh->mTangents,mesh->mNumVertices); - WriteArray(&chunk,mesh->mBitangents,mesh->mNumVertices); - } - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { - if (!mesh->mColors[n]) - break; - - if (shortened) { - WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mColors[n],mesh->mNumVertices); - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (!mesh->mTextureCoords[n]) - break; - - // write number of UV components - Write(&chunk,mesh->mNumUVComponents[n]); - - if (shortened) { - WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); - } - - // write faces. There are no floating-point calculations involved - // in these, so we can write a simple hash over the face data - // to the dump file. We generate a single 32 Bit hash for 512 faces - // using Assimp's standard hashing function. - if (shortened) { - unsigned int processed = 0; - for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { - - uint32_t hash = 0; - for (unsigned int a = 0; a < job;++a) { - - const aiFace& f = mesh->mFaces[processed+a]; - uint32_t tmp = f.mNumIndices; - hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); - for (unsigned int i = 0; i < f.mNumIndices; ++i) { - static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); - tmp = static_cast( f.mIndices[i] ); - hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); - } - } - Write(&chunk,hash); - } - } - else // else write as usual - { - // if there are less than 2^16 vertices, we can simply use 16 bit integers ... - for (unsigned int i = 0; i < mesh->mNumFaces;++i) { - const aiFace& f = mesh->mFaces[i]; - - static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); - Write(&chunk,f.mNumIndices); - - for (unsigned int a = 0; a < f.mNumIndices;++a) { - if (mesh->mNumVertices < (1u<<16)) { - Write(&chunk,f.mIndices[a]); - } - else Write(&chunk,f.mIndices[a]); - } - } - } - - // write bones - if (mesh->mNumBones) { - for (unsigned int a = 0; a < mesh->mNumBones;++a) { - const aiBone* b = mesh->mBones[a]; - WriteBinaryBone(&chunk,b); - } - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY ); - - Write(&chunk,prop->mKey); - Write(&chunk,prop->mSemantic); - Write(&chunk,prop->mIndex); - - Write(&chunk,prop->mDataLength); - Write(&chunk,(unsigned int)prop->mType); - chunk.Write(prop->mData,1,prop->mDataLength); - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL); - - Write(&chunk,mat->mNumProperties); - for (unsigned int i = 0; i < mat->mNumProperties;++i) { - WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]); - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM ); - - Write(&chunk,nd->mNodeName); - Write(&chunk,nd->mNumPositionKeys); - Write(&chunk,nd->mNumRotationKeys); - Write(&chunk,nd->mNumScalingKeys); - Write(&chunk,nd->mPreState); - Write(&chunk,nd->mPostState); - - if (nd->mPositionKeys) { - if (shortened) { - WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); - - } // else write as usual - else WriteArray(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); - } - if (nd->mRotationKeys) { - if (shortened) { - WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); - - } // else write as usual - else WriteArray(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); - } - if (nd->mScalingKeys) { - if (shortened) { - WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); - - } // else write as usual - else WriteArray(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); - } - } - - - // ----------------------------------------------------------------------------------- - void WriteBinaryAnim( IOStream * container, const aiAnimation* anim ) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION ); - - Write(&chunk,anim->mName); - Write(&chunk,anim->mDuration); - Write(&chunk,anim->mTicksPerSecond); - Write(&chunk,anim->mNumChannels); - - for (unsigned int a = 0; a < anim->mNumChannels;++a) { - const aiNodeAnim* nd = anim->mChannels[a]; - WriteBinaryNodeAnim(&chunk,nd); - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryLight( IOStream * container, const aiLight* l ) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT ); - - Write(&chunk,l->mName); - Write(&chunk,l->mType); - - if (l->mType != aiLightSource_DIRECTIONAL) { - Write(&chunk,l->mAttenuationConstant); - Write(&chunk,l->mAttenuationLinear); - Write(&chunk,l->mAttenuationQuadratic); - } - - Write(&chunk,l->mColorDiffuse); - Write(&chunk,l->mColorSpecular); - Write(&chunk,l->mColorAmbient); - - if (l->mType == aiLightSource_SPOT) { - Write(&chunk,l->mAngleInnerCone); - Write(&chunk,l->mAngleOuterCone); - } - - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryCamera( IOStream * container, const aiCamera* cam ) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA ); - - Write(&chunk,cam->mName); - Write(&chunk,cam->mPosition); - Write(&chunk,cam->mLookAt); - Write(&chunk,cam->mUp); - Write(&chunk,cam->mHorizontalFOV); - Write(&chunk,cam->mClipPlaneNear); - Write(&chunk,cam->mClipPlaneFar); - Write(&chunk,cam->mAspect); - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryScene( IOStream * container, const aiScene* scene) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE ); - - // basic scene information - Write(&chunk,scene->mFlags); - Write(&chunk,scene->mNumMeshes); - Write(&chunk,scene->mNumMaterials); - Write(&chunk,scene->mNumAnimations); - Write(&chunk,scene->mNumTextures); - Write(&chunk,scene->mNumLights); - Write(&chunk,scene->mNumCameras); - - // write node graph - WriteBinaryNode( &chunk, scene->mRootNode ); - - // write all meshes - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - const aiMesh* mesh = scene->mMeshes[i]; - WriteBinaryMesh( &chunk,mesh); - } - - // write materials - for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { - const aiMaterial* mat = scene->mMaterials[i]; - WriteBinaryMaterial(&chunk,mat); - } - - // write all animations - for (unsigned int i = 0; i < scene->mNumAnimations;++i) { - const aiAnimation* anim = scene->mAnimations[i]; - WriteBinaryAnim(&chunk,anim); - } - - - // write all textures - for (unsigned int i = 0; i < scene->mNumTextures;++i) { - const aiTexture* mesh = scene->mTextures[i]; - WriteBinaryTexture(&chunk,mesh); - } - - // write lights - for (unsigned int i = 0; i < scene->mNumLights;++i) { - const aiLight* l = scene->mLights[i]; - WriteBinaryLight(&chunk,l); - } - - // write cameras - for (unsigned int i = 0; i < scene->mNumCameras;++i) { - const aiCamera* cam = scene->mCameras[i]; - WriteBinaryCamera(&chunk,cam); - } - - } - - public: - AssbinExport() - : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters - { - } - - // ----------------------------------------------------------------------------------- - // Write a binary model dump - void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) - { - IOStream * out = pIOSystem->Open( pFile, "wb" ); - if (!out) return; - - time_t tt = time(NULL); - tm* p = gmtime(&tt); - - // header - char s[64]; - memset( s, 0, 64 ); -#if _MSC_VER >= 1400 - sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p)); -#else - ai_snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p)); -#endif - out->Write( s, 44, 1 ); - // == 44 bytes - - Write( out, ASSBIN_VERSION_MAJOR ); - Write( out, ASSBIN_VERSION_MINOR ); - Write( out, aiGetVersionRevision() ); - Write( out, aiGetCompileFlags() ); - Write( out, shortened ); - Write( out, compressed ); - // == 20 bytes - - char buff[256]; - strncpy(buff,pFile,256); - out->Write(buff,sizeof(char),256); - - char cmd[] = "\0"; - strncpy(buff,cmd,128); - out->Write(buff,sizeof(char),128); - - // leave 64 bytes free for future extensions - memset(buff,0xcd,64); - out->Write(buff,sizeof(char),64); - // == 435 bytes - - // ==== total header size: 512 bytes - ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH ); - - // Up to here the data is uncompressed. For compressed files, the rest - // is compressed using standard DEFLATE from zlib. - if (compressed) - { - AssbinChunkWriter uncompressedStream( NULL, 0 ); - WriteBinaryScene( &uncompressedStream, pScene ); - - uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); - uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.); - uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; - - compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); - - out->Write( &uncompressedSize, sizeof(uint32_t), 1 ); - out->Write( compressedBuffer, sizeof(char), compressedSize ); - - delete[] compressedBuffer; - } - else - { - WriteBinaryScene( out, pScene ); - } - - pIOSystem->Close( out ); - } - }; - -void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) -{ - AssbinExport exporter; - exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); -} -} // end of namespace Assimp - -#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER -#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/Assjson/cencode.c b/code/Assjson/cencode.c new file mode 100644 index 000000000..db99e7efa --- /dev/null +++ b/code/Assjson/cencode.c @@ -0,0 +1,109 @@ +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include "cencode.h" // changed from + +const int CHARS_PER_LINE = 72; + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar++ = '\n'; + + return codechar - code_out; +} + diff --git a/code/Assjson/cencode.h b/code/Assjson/cencode.h new file mode 100644 index 000000000..c1e3464af --- /dev/null +++ b/code/Assjson/cencode.h @@ -0,0 +1,31 @@ +/* +cencode.h - c header for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CENCODE_H +#define BASE64_CENCODE_H + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +#endif /* BASE64_CENCODE_H */ diff --git a/code/Assjson/json_exporter.cpp b/code/Assjson/json_exporter.cpp new file mode 100644 index 000000000..e9fa72496 --- /dev/null +++ b/code/Assjson/json_exporter.cpp @@ -0,0 +1,809 @@ +/* +Assimp2Json +Copyright (c) 2011, Alexander C. Gessler + +Licensed under a 3-clause BSD license. See the LICENSE file for more information. + +*/ + +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define CURRENT_FORMAT_VERSION 100 + +// grab scoped_ptr from assimp to avoid a dependency on boost. +//#include + +#include "mesh_splitter.h" + +extern "C" { + #include "cencode.h" +} +namespace Assimp { + +void ExportAssimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*); + +// small utility class to simplify serializing the aiScene to Json +class JSONWriter { +public: + enum { + Flag_DoNotIndent = 0x1, + Flag_WriteSpecialFloats = 0x2, + }; + + JSONWriter(Assimp::IOStream& out, unsigned int flags = 0u) + : out(out) + , first() + , flags(flags) { + // make sure that all formatting happens using the standard, C locale and not the user's current locale + buff.imbue(std::locale("C")); + } + + ~JSONWriter() { + Flush(); + } + + void Flush() { + const std::string s = buff.str(); + out.Write(s.c_str(), s.length(), 1); + buff.clear(); + } + + void PushIndent() { + indent += '\t'; + } + + void PopIndent() { + indent.erase(indent.end() - 1); + } + + void Key(const std::string& name) { + AddIndentation(); + Delimit(); + buff << '\"' + name + "\": "; + } + + template + void Element(const Literal& name) { + AddIndentation(); + Delimit(); + + LiteralToString(buff, name) << '\n'; + } + + template + void SimpleValue(const Literal& s) { + LiteralToString(buff, s) << '\n'; + } + + void SimpleValue(const void* buffer, size_t len) { + base64_encodestate s; + base64_init_encodestate(&s); + + char* const out = new char[std::max(len * 2, static_cast(16u))]; + const int n = base64_encode_block(reinterpret_cast(buffer), static_cast(len), out, &s); + out[n + base64_encode_blockend(out + n, &s)] = '\0'; + + // base64 encoding may add newlines, but JSON strings may not contain 'real' newlines + // (only escaped ones). Remove any newlines in out. + for (char* cur = out; *cur; ++cur) { + if (*cur == '\n') { + *cur = ' '; + } + } + + buff << '\"' << out << "\"\n"; + delete[] out; + } + + void StartObj(bool is_element = false) { + // if this appears as a plain array element, we need to insert a delimiter and we should also indent it + if (is_element) { + AddIndentation(); + if (!first) { + buff << ','; + } + } + first = true; + buff << "{\n"; + PushIndent(); + } + + void EndObj() { + PopIndent(); + AddIndentation(); + first = false; + buff << "}\n"; + } + + void StartArray(bool is_element = false) { + // if this appears as a plain array element, we need to insert a delimiter and we should also indent it + if (is_element) { + AddIndentation(); + if (!first) { + buff << ','; + } + } + first = true; + buff << "[\n"; + PushIndent(); + } + + void EndArray() { + PopIndent(); + AddIndentation(); + buff << "]\n"; + first = false; + } + + void AddIndentation() { + if (!(flags & Flag_DoNotIndent)) { + buff << indent; + } + } + + void Delimit() { + if (!first) { + buff << ','; + } + else { + buff << ' '; + first = false; + } + } + +private: + template + std::stringstream& LiteralToString(std::stringstream& stream, const Literal& s) { + stream << s; + return stream; + } + + std::stringstream& LiteralToString(std::stringstream& stream, const aiString& s) { + std::string t; + + // escape backslashes and single quotes, both would render the JSON invalid if left as is + t.reserve(s.length); + for (size_t i = 0; i < s.length; ++i) { + + if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') { + t.push_back('\\'); + } + + t.push_back(s.data[i]); + } + stream << "\""; + stream << t; + stream << "\""; + return stream; + } + + std::stringstream& LiteralToString(std::stringstream& stream, float f) { + if (!std::numeric_limits::is_iec559) { + // on a non IEEE-754 platform, we make no assumptions about the representation or existence + // of special floating-point numbers. + stream << f; + return stream; + } + + // JSON does not support writing Inf/Nan + // [RFC 4672: "Numeric values that cannot be represented as sequences of digits + // (such as Infinity and NaN) are not permitted."] + // Nevertheless, many parsers will accept the special keywords Infinity, -Infinity and NaN + if (std::numeric_limits::infinity() == fabs(f)) { + if (flags & Flag_WriteSpecialFloats) { + stream << (f < 0 ? "\"-" : "\"") + std::string("Infinity\""); + return stream; + } + // we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr + // std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl; + stream << "0.0"; + return stream; + } + // f!=f is the most reliable test for NaNs that I know of + else if (f != f) { + if (flags & Flag_WriteSpecialFloats) { + stream << "\"NaN\""; + return stream; + } + // we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr + // std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl; + stream << "0.0"; + return stream; + } + + stream << f; + return stream; + } + +private: + Assimp::IOStream& out; + std::string indent, newline; + std::stringstream buff; + bool first; + + unsigned int flags; +}; + +void Write(JSONWriter& out, const aiVector3D& ai, bool is_elem = true) { + out.StartArray(is_elem); + out.Element(ai.x); + out.Element(ai.y); + out.Element(ai.z); + out.EndArray(); +} + +void Write(JSONWriter& out, const aiQuaternion& ai, bool is_elem = true) { + out.StartArray(is_elem); + out.Element(ai.w); + out.Element(ai.x); + out.Element(ai.y); + out.Element(ai.z); + out.EndArray(); +} + +void Write(JSONWriter& out, const aiColor3D& ai, bool is_elem = true) { + out.StartArray(is_elem); + out.Element(ai.r); + out.Element(ai.g); + out.Element(ai.b); + out.EndArray(); +} + +void Write(JSONWriter& out, const aiMatrix4x4& ai, bool is_elem = true) { + out.StartArray(is_elem); + for (unsigned int x = 0; x < 4; ++x) { + for (unsigned int y = 0; y < 4; ++y) { + out.Element(ai[x][y]); + } + } + out.EndArray(); +} + +void Write(JSONWriter& out, const aiBone& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("offsetmatrix"); + Write(out, ai.mOffsetMatrix, false); + + out.Key("weights"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumWeights; ++i) { + out.StartArray(true); + out.Element(ai.mWeights[i].mVertexId); + out.Element(ai.mWeights[i].mWeight); + out.EndArray(); + } + out.EndArray(); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiFace& ai, bool is_elem = true) { + out.StartArray(is_elem); + for (unsigned int i = 0; i < ai.mNumIndices; ++i) { + out.Element(ai.mIndices[i]); + } + out.EndArray(); +} + +void Write(JSONWriter& out, const aiMesh& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("materialindex"); + out.SimpleValue(ai.mMaterialIndex); + + out.Key("primitivetypes"); + out.SimpleValue(ai.mPrimitiveTypes); + + out.Key("vertices"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mVertices[i].x); + out.Element(ai.mVertices[i].y); + out.Element(ai.mVertices[i].z); + } + out.EndArray(); + + if (ai.HasNormals()) { + out.Key("normals"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mNormals[i].x); + out.Element(ai.mNormals[i].y); + out.Element(ai.mNormals[i].z); + } + out.EndArray(); + } + + if (ai.HasTangentsAndBitangents()) { + out.Key("tangents"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mTangents[i].x); + out.Element(ai.mTangents[i].y); + out.Element(ai.mTangents[i].z); + } + out.EndArray(); + + out.Key("bitangents"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mBitangents[i].x); + out.Element(ai.mBitangents[i].y); + out.Element(ai.mBitangents[i].z); + } + out.EndArray(); + } + + if (ai.GetNumUVChannels()) { + out.Key("numuvcomponents"); + out.StartArray(); + for (unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) { + out.Element(ai.mNumUVComponents[n]); + } + out.EndArray(); + + out.Key("texturecoords"); + out.StartArray(); + for (unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) { + const unsigned int numc = ai.mNumUVComponents[n] ? ai.mNumUVComponents[n] : 2; + + out.StartArray(true); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + for (unsigned int c = 0; c < numc; ++c) { + out.Element(ai.mTextureCoords[n][i][c]); + } + } + out.EndArray(); + } + out.EndArray(); + } + + if (ai.GetNumColorChannels()) { + out.Key("colors"); + out.StartArray(); + for (unsigned int n = 0; n < ai.GetNumColorChannels(); ++n) { + out.StartArray(true); + for (unsigned int i = 0; i < ai.mNumVertices; ++i) { + out.Element(ai.mColors[n][i].r); + out.Element(ai.mColors[n][i].g); + out.Element(ai.mColors[n][i].b); + out.Element(ai.mColors[n][i].a); + } + out.EndArray(); + } + out.EndArray(); + } + + if (ai.mNumBones) { + out.Key("bones"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumBones; ++n) { + Write(out, *ai.mBones[n]); + } + out.EndArray(); + } + + out.Key("faces"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumFaces; ++n) { + Write(out, ai.mFaces[n]); + } + out.EndArray(); + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiNode& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("transformation"); + Write(out, ai.mTransformation, false); + + if (ai.mNumMeshes) { + out.Key("meshes"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumMeshes; ++n) { + out.Element(ai.mMeshes[n]); + } + out.EndArray(); + } + + if (ai.mNumChildren) { + out.Key("children"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumChildren; ++n) { + Write(out, *ai.mChildren[n]); + } + out.EndArray(); + } + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("properties"); + out.StartArray(); + for (unsigned int i = 0; i < ai.mNumProperties; ++i) { + const aiMaterialProperty* const prop = ai.mProperties[i]; + out.StartObj(true); + out.Key("key"); + out.SimpleValue(prop->mKey); + out.Key("semantic"); + out.SimpleValue(prop->mSemantic); + out.Key("index"); + out.SimpleValue(prop->mIndex); + + out.Key("type"); + out.SimpleValue(prop->mType); + + out.Key("value"); + switch (prop->mType) { + case aiPTI_Float: + if (prop->mDataLength / sizeof(float) > 1) { + out.StartArray(); + for (unsigned int i = 0; i < prop->mDataLength / sizeof(float); ++i) { + out.Element(reinterpret_cast(prop->mData)[i]); + } + out.EndArray(); + } + else { + out.SimpleValue(*reinterpret_cast(prop->mData)); + } + break; + + case aiPTI_Integer: + if (prop->mDataLength / sizeof(int) > 1) { + out.StartArray(); + for (unsigned int i = 0; i < prop->mDataLength / sizeof(int); ++i) { + out.Element(reinterpret_cast(prop->mData)[i]); + } + out.EndArray(); + } else { + out.SimpleValue(*reinterpret_cast(prop->mData)); + } + break; + + case aiPTI_String: + { + aiString s; + aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s); + out.SimpleValue(s); + } + break; + case aiPTI_Buffer: + { + // binary data is written as series of hex-encoded octets + out.SimpleValue(prop->mData, prop->mDataLength); + } + break; + default: + assert(false); + } + + out.EndObj(); + } + + out.EndArray(); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiTexture& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("width"); + out.SimpleValue(ai.mWidth); + + out.Key("height"); + out.SimpleValue(ai.mHeight); + + out.Key("formathint"); + out.SimpleValue(aiString(ai.achFormatHint)); + + out.Key("data"); + if (!ai.mHeight) { + out.SimpleValue(ai.pcData, ai.mWidth); + } + else { + out.StartArray(); + for (unsigned int y = 0; y < ai.mHeight; ++y) { + out.StartArray(true); + for (unsigned int x = 0; x < ai.mWidth; ++x) { + const aiTexel& tx = ai.pcData[y*ai.mWidth + x]; + out.StartArray(true); + out.Element(static_cast(tx.r)); + out.Element(static_cast(tx.g)); + out.Element(static_cast(tx.b)); + out.Element(static_cast(tx.a)); + out.EndArray(); + } + out.EndArray(); + } + out.EndArray(); + } + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiLight& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("type"); + out.SimpleValue(ai.mType); + + if (ai.mType == aiLightSource_SPOT || ai.mType == aiLightSource_UNDEFINED) { + out.Key("angleinnercone"); + out.SimpleValue(ai.mAngleInnerCone); + + out.Key("angleoutercone"); + out.SimpleValue(ai.mAngleOuterCone); + } + + out.Key("attenuationconstant"); + out.SimpleValue(ai.mAttenuationConstant); + + out.Key("attenuationlinear"); + out.SimpleValue(ai.mAttenuationLinear); + + out.Key("attenuationquadratic"); + out.SimpleValue(ai.mAttenuationQuadratic); + + out.Key("diffusecolor"); + Write(out, ai.mColorDiffuse, false); + + out.Key("specularcolor"); + Write(out, ai.mColorSpecular, false); + + out.Key("ambientcolor"); + Write(out, ai.mColorAmbient, false); + + if (ai.mType != aiLightSource_POINT) { + out.Key("direction"); + Write(out, ai.mDirection, false); + + } + + if (ai.mType != aiLightSource_DIRECTIONAL) { + out.Key("position"); + Write(out, ai.mPosition, false); + } + + out.EndObj(); +} + +void Write(JSONWriter& out, const aiNodeAnim& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mNodeName); + + out.Key("prestate"); + out.SimpleValue(ai.mPreState); + + out.Key("poststate"); + out.SimpleValue(ai.mPostState); + + if (ai.mNumPositionKeys) { + out.Key("positionkeys"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumPositionKeys; ++n) { + const aiVectorKey& pos = ai.mPositionKeys[n]; + out.StartArray(true); + out.Element(pos.mTime); + Write(out, pos.mValue); + out.EndArray(); + } + out.EndArray(); + } + + if (ai.mNumRotationKeys) { + out.Key("rotationkeys"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumRotationKeys; ++n) { + const aiQuatKey& rot = ai.mRotationKeys[n]; + out.StartArray(true); + out.Element(rot.mTime); + Write(out, rot.mValue); + out.EndArray(); + } + out.EndArray(); + } + + if (ai.mNumScalingKeys) { + out.Key("scalingkeys"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumScalingKeys; ++n) { + const aiVectorKey& scl = ai.mScalingKeys[n]; + out.StartArray(true); + out.Element(scl.mTime); + Write(out, scl.mValue); + out.EndArray(); + } + out.EndArray(); + } + out.EndObj(); +} + +void Write(JSONWriter& out, const aiAnimation& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("tickspersecond"); + out.SimpleValue(ai.mTicksPerSecond); + + out.Key("duration"); + out.SimpleValue(ai.mDuration); + + out.Key("channels"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumChannels; ++n) { + Write(out, *ai.mChannels[n]); + } + out.EndArray(); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiCamera& ai, bool is_elem = true) { + out.StartObj(is_elem); + + out.Key("name"); + out.SimpleValue(ai.mName); + + out.Key("aspect"); + out.SimpleValue(ai.mAspect); + + out.Key("clipplanefar"); + out.SimpleValue(ai.mClipPlaneFar); + + out.Key("clipplanenear"); + out.SimpleValue(ai.mClipPlaneNear); + + out.Key("horizontalfov"); + out.SimpleValue(ai.mHorizontalFOV); + + out.Key("up"); + Write(out, ai.mUp, false); + + out.Key("lookat"); + Write(out, ai.mLookAt, false); + + out.EndObj(); +} + +void WriteFormatInfo(JSONWriter& out) { + out.StartObj(); + out.Key("format"); + out.SimpleValue("\"assimp2json\""); + out.Key("version"); + out.SimpleValue(CURRENT_FORMAT_VERSION); + out.EndObj(); +} + +void Write(JSONWriter& out, const aiScene& ai) { + out.StartObj(); + + out.Key("__metadata__"); + WriteFormatInfo(out); + + out.Key("rootnode"); + Write(out, *ai.mRootNode, false); + + out.Key("flags"); + out.SimpleValue(ai.mFlags); + + if (ai.HasMeshes()) { + out.Key("meshes"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumMeshes; ++n) { + Write(out, *ai.mMeshes[n]); + } + out.EndArray(); + } + + if (ai.HasMaterials()) { + out.Key("materials"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumMaterials; ++n) { + Write(out, *ai.mMaterials[n]); + } + out.EndArray(); + } + + if (ai.HasAnimations()) { + out.Key("animations"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumAnimations; ++n) { + Write(out, *ai.mAnimations[n]); + } + out.EndArray(); + } + + if (ai.HasLights()) { + out.Key("lights"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumLights; ++n) { + Write(out, *ai.mLights[n]); + } + out.EndArray(); + } + + if (ai.HasCameras()) { + out.Key("cameras"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumCameras; ++n) { + Write(out, *ai.mCameras[n]); + } + out.EndArray(); + } + + if (ai.HasTextures()) { + out.Key("textures"); + out.StartArray(); + for (unsigned int n = 0; n < ai.mNumTextures; ++n) { + Write(out, *ai.mTextures[n]); + } + out.EndArray(); + } + out.EndObj(); +} + + +void ExportAssimp2Json(const char* file, Assimp::IOSystem* io, const aiScene* scene, const Assimp::ExportProperties*) { + std::unique_ptr str(io->Open(file, "wt")); + if (!str) { + //throw Assimp::DeadlyExportError("could not open output file"); + } + + // get a copy of the scene so we can modify it + aiScene* scenecopy_tmp; + aiCopyScene(scene, &scenecopy_tmp); + + try { + // split meshes so they fit into a 16 bit index buffer + MeshSplitter splitter; + splitter.SetLimit(1 << 16); + splitter.Execute(scenecopy_tmp); + + // XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters + JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats); + Write(s, *scenecopy_tmp); + + } + catch (...) { + aiFreeScene(scenecopy_tmp); + throw; + } + aiFreeScene(scenecopy_tmp); +} + +} + +#endif // ASSIMP_BUILD_NO_ASSJSON_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/Assjson/mesh_splitter.cpp b/code/Assjson/mesh_splitter.cpp new file mode 100644 index 000000000..24385f9a0 --- /dev/null +++ b/code/Assjson/mesh_splitter.cpp @@ -0,0 +1,320 @@ +/* +Assimp2Json +Copyright (c) 2011, Alexander C. Gessler + +Licensed under a 3-clause BSD license. See the LICENSE file for more information. + +*/ + +#include "mesh_splitter.h" + +#include + +// ---------------------------------------------------------------------------- +// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process. +// it is refactored and the coding style is slightly improved, though. +// ---------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------------ +// Executes the post processing step on the given imported data. +void MeshSplitter::Execute( aiScene* pScene) { + std::vector > source_mesh_map; + + for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { + SplitMesh(a, pScene->mMeshes[a],source_mesh_map); + } + + const unsigned int size = static_cast(source_mesh_map.size()); + if (size != pScene->mNumMeshes) { + // it seems something has been split. rebuild the mesh list + delete[] pScene->mMeshes; + pScene->mNumMeshes = size; + pScene->mMeshes = new aiMesh*[size](); + + for (unsigned int i = 0; i < size;++i) { + pScene->mMeshes[i] = source_mesh_map[i].first; + } + + // now we need to update all nodes + UpdateNode(pScene->mRootNode,source_mesh_map); + } +} + + +// ------------------------------------------------------------------------------------------------ +void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vector >& source_mesh_map) { + // TODO: should better use std::(multi)set for source_mesh_map. + + // for every index in out list build a new entry + std::vector aiEntries; + aiEntries.reserve(pcNode->mNumMeshes + 1); + for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) { + for (unsigned int a = 0, end = static_cast(source_mesh_map.size()); a < end;++a) { + if (source_mesh_map[a].second == pcNode->mMeshes[i]) { + aiEntries.push_back(a); + } + } + } + + // now build the new list + delete pcNode->mMeshes; + pcNode->mNumMeshes = static_cast(aiEntries.size()); + pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; + + for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) { + pcNode->mMeshes[b] = aiEntries[b]; + } + + // recursively update children + for (unsigned int i = 0, end = pcNode->mNumChildren; i < end;++i) { + UpdateNode ( pcNode->mChildren[i], source_mesh_map ); + } + return; +} + +#define WAS_NOT_COPIED 0xffffffff + +typedef std::pair PerVertexWeight; +typedef std::vector VertexWeightTable; + +// ------------------------------------------------------------------------------------------------ +VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) { + if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) { + return nullptr; + } + + VertexWeightTable* const avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices]; + for (unsigned int i = 0; i < pMesh->mNumBones;++i) { + + aiBone* bone = pMesh->mBones[i]; + for (unsigned int a = 0; a < bone->mNumWeights;++a) { + const aiVertexWeight& weight = bone->mWeights[a]; + avPerVertexWeights[weight.mVertexId].push_back( std::make_pair(i,weight.mWeight) ); + } + } + return avPerVertexWeights; +} + +// ------------------------------------------------------------------------------------------------ +void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector >& source_mesh_map) { + // TODO: should better use std::(multi)set for source_mesh_map. + + if (in_mesh->mNumVertices <= LIMIT) { + source_mesh_map.push_back(std::make_pair(in_mesh,a)); + return; + } + + // build a per-vertex weight list if necessary + VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(in_mesh); + + // we need to split this mesh into sub meshes. Estimate submesh size + const unsigned int sub_meshes = (in_mesh->mNumVertices / LIMIT) + 1; + + // create a std::vector to remember which vertices have already + // been copied and to which position (i.e. output index) + std::vector was_copied_to; + was_copied_to.resize(in_mesh->mNumVertices,WAS_NOT_COPIED); + + // Try to find a good estimate for the number of output faces + // per mesh. Add 12.5% as buffer + unsigned int size_estimated = in_mesh->mNumFaces / sub_meshes; + size_estimated += size_estimated / 8; + + // now generate all submeshes + unsigned int base = 0; + while (true) { + const unsigned int out_vertex_index = LIMIT; + + aiMesh* out_mesh = new aiMesh(); + out_mesh->mNumVertices = 0; + out_mesh->mMaterialIndex = in_mesh->mMaterialIndex; + + // the name carries the adjacency information between the meshes + out_mesh->mName = in_mesh->mName; + + typedef std::vector BoneWeightList; + if (in_mesh->HasBones()) { + out_mesh->mBones = new aiBone*[in_mesh->mNumBones](); + } + + // clear the temporary helper array + if (base) { + std::fill(was_copied_to.begin(), was_copied_to.end(), WAS_NOT_COPIED); + } + + std::vector vFaces; + + // reserve enough storage for most cases + if (in_mesh->HasPositions()) { + out_mesh->mVertices = new aiVector3D[out_vertex_index]; + } + + if (in_mesh->HasNormals()) { + out_mesh->mNormals = new aiVector3D[out_vertex_index]; + } + + if (in_mesh->HasTangentsAndBitangents()) { + out_mesh->mTangents = new aiVector3D[out_vertex_index]; + out_mesh->mBitangents = new aiVector3D[out_vertex_index]; + } + + for (unsigned int c = 0; in_mesh->HasVertexColors(c);++c) { + out_mesh->mColors[c] = new aiColor4D[out_vertex_index]; + } + + for (unsigned int c = 0; in_mesh->HasTextureCoords(c);++c) { + out_mesh->mNumUVComponents[c] = in_mesh->mNumUVComponents[c]; + out_mesh->mTextureCoords[c] = new aiVector3D[out_vertex_index]; + } + vFaces.reserve(size_estimated); + + // (we will also need to copy the array of indices) + while (base < in_mesh->mNumFaces) { + const unsigned int iNumIndices = in_mesh->mFaces[base].mNumIndices; + + // doesn't catch degenerates but is quite fast + unsigned int iNeed = 0; + for (unsigned int v = 0; v < iNumIndices;++v) { + unsigned int index = in_mesh->mFaces[base].mIndices[v]; + + // check whether we do already have this vertex + if (WAS_NOT_COPIED == was_copied_to[index]) { + iNeed++; + } + } + if (out_mesh->mNumVertices + iNeed > out_vertex_index) { + // don't use this face + break; + } + + vFaces.push_back(aiFace()); + aiFace& rFace = vFaces.back(); + + // setup face type and number of indices + rFace.mNumIndices = iNumIndices; + rFace.mIndices = new unsigned int[iNumIndices]; + + // need to update the output primitive types + switch (rFace.mNumIndices) + { + case 1: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + } + + // and copy the contents of the old array, offset them by current base + for (unsigned int v = 0; v < iNumIndices;++v) { + const unsigned int index = in_mesh->mFaces[base].mIndices[v]; + + // check whether we do already have this vertex + if (WAS_NOT_COPIED != was_copied_to[index]) { + rFace.mIndices[v] = was_copied_to[index]; + continue; + } + + // copy positions + out_mesh->mVertices[out_mesh->mNumVertices] = (in_mesh->mVertices[index]); + + // copy normals + if (in_mesh->HasNormals()) { + out_mesh->mNormals[out_mesh->mNumVertices] = (in_mesh->mNormals[index]); + } + + // copy tangents/bi-tangents + if (in_mesh->HasTangentsAndBitangents()) { + out_mesh->mTangents[out_mesh->mNumVertices] = (in_mesh->mTangents[index]); + out_mesh->mBitangents[out_mesh->mNumVertices] = (in_mesh->mBitangents[index]); + } + + // texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { + if (in_mesh->HasTextureCoords( c)) { + out_mesh->mTextureCoords[c][out_mesh->mNumVertices] = in_mesh->mTextureCoords[c][index]; + } + } + // vertex colors + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) { + if (in_mesh->HasVertexColors( c)) { + out_mesh->mColors[c][out_mesh->mNumVertices] = in_mesh->mColors[c][index]; + } + } + // check whether we have bone weights assigned to this vertex + rFace.mIndices[v] = out_mesh->mNumVertices; + if (avPerVertexWeights) { + VertexWeightTable& table = avPerVertexWeights[ out_mesh->mNumVertices ]; + for (VertexWeightTable::const_iterator iter = table.begin(), end = table.end(); iter != end;++iter) { + // allocate the bone weight array if necessary and store it in the mBones field (HACK!) + BoneWeightList* weight_list = reinterpret_cast(out_mesh->mBones[(*iter).first]); + if (!weight_list) { + weight_list = new BoneWeightList(); + out_mesh->mBones[(*iter).first] = reinterpret_cast(weight_list); + } + weight_list->push_back(aiVertexWeight(out_mesh->mNumVertices,(*iter).second)); + } + } + + was_copied_to[index] = out_mesh->mNumVertices; + out_mesh->mNumVertices++; + } + base++; + if(out_mesh->mNumVertices == out_vertex_index) { + // break here. The face is only added if it was complete + break; + } + } + + // check which bones we'll need to create for this submesh + if (in_mesh->HasBones()) { + aiBone** ppCurrent = out_mesh->mBones; + for (unsigned int k = 0; k < in_mesh->mNumBones;++k) { + // check whether the bone exists + BoneWeightList* const weight_list = reinterpret_cast(out_mesh->mBones[k]); + + if (weight_list) { + const aiBone* const bone_in = in_mesh->mBones[k]; + aiBone* const bone_out = new aiBone(); + *ppCurrent++ = bone_out; + bone_out->mName = aiString(bone_in->mName); + bone_out->mOffsetMatrix =bone_in->mOffsetMatrix; + bone_out->mNumWeights = (unsigned int)weight_list->size(); + bone_out->mWeights = new aiVertexWeight[bone_out->mNumWeights]; + + // copy the vertex weights + ::memcpy(bone_out->mWeights, &(*weight_list)[0],bone_out->mNumWeights * sizeof(aiVertexWeight)); + + delete weight_list; + out_mesh->mNumBones++; + } + } + } + + // copy the face list to the mesh + out_mesh->mFaces = new aiFace[vFaces.size()]; + out_mesh->mNumFaces = (unsigned int)vFaces.size(); + + for (unsigned int p = 0; p < out_mesh->mNumFaces;++p) { + out_mesh->mFaces[p] = vFaces[p]; + } + + // add the newly created mesh to the list + source_mesh_map.push_back(std::make_pair(out_mesh,a)); + + if (base == in_mesh->mNumFaces) { + break; + } + } + + // delete the per-vertex weight list again + delete[] avPerVertexWeights; + + // now delete the old mesh data + delete in_mesh; +} diff --git a/code/Assjson/mesh_splitter.h b/code/Assjson/mesh_splitter.h new file mode 100644 index 000000000..326f73b41 --- /dev/null +++ b/code/Assjson/mesh_splitter.h @@ -0,0 +1,61 @@ +/* +Assimp2Json +Copyright (c) 2011, Alexander C. Gessler + +Licensed under a 3-clause BSD license. See the LICENSE file for more information. + +*/ + +#ifndef INCLUDED_MESH_SPLITTER +#define INCLUDED_MESH_SPLITTER + +// ---------------------------------------------------------------------------- +// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process. +// it is refactored and the coding style is slightly improved, though. +// ---------------------------------------------------------------------------- + +#include + +struct aiScene; +struct aiMesh; +struct aiNode; + +// --------------------------------------------------------------------------- +/** Splits meshes of unique vertices into meshes with no more vertices than + * a given, configurable threshold value. + */ +class MeshSplitter +{ + +public: + + void SetLimit(unsigned int l) { + LIMIT = l; + } + + unsigned int GetLimit() const { + return LIMIT; + } + +public: + + // ------------------------------------------------------------------- + /** Executes the post processing step on the given imported data. + * At the moment a process is not supposed to fail. + * @param pScene The imported data to work at. + */ + void Execute( aiScene* pScene); + + +private: + + void UpdateNode(aiNode* pcNode, const std::vector >& source_mesh_map); + void SplitMesh (unsigned int index, aiMesh* mesh, std::vector >& source_mesh_map); + +public: + + unsigned int LIMIT; +}; + +#endif // INCLUDED_MESH_SPLITTER + diff --git a/code/AssxmlExporter.cpp b/code/Assxml/AssxmlExporter.cpp similarity index 99% rename from code/AssxmlExporter.cpp rename to code/Assxml/AssxmlExporter.cpp index c9e125d0d..afdecbaf6 100644 --- a/code/AssxmlExporter.cpp +++ b/code/Assxml/AssxmlExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -46,13 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER -#include +#include "PostProcessing/ProcessHelper.h" + #include -#include "ProcessHelper.h" #include #include #include +#include + #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include #else @@ -184,8 +186,13 @@ static std::string encodeXML(const std::string& data) { static void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { time_t tt = ::time( NULL ); - tm* p = ::gmtime( &tt ); - ai_assert( nullptr != p ); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + ai_assert(nullptr != p); // write header std::string header( @@ -550,8 +557,6 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { mesh->mNormals[n].z); } } - else { - } ioprintf(io,"\t\t\n"); } diff --git a/code/AssxmlExporter.h b/code/Assxml/AssxmlExporter.h similarity index 98% rename from code/AssxmlExporter.h rename to code/Assxml/AssxmlExporter.h index 3db496db2..8ca887eea 100644 --- a/code/AssxmlExporter.h +++ b/code/Assxml/AssxmlExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/B3DImporter.cpp b/code/B3D/B3DImporter.cpp similarity index 85% rename from code/B3DImporter.cpp rename to code/B3D/B3DImporter.cpp index e4572f8eb..c9eb89ebc 100644 --- a/code/B3DImporter.cpp +++ b/code/B3D/B3DImporter.cpp @@ -3,9 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team - - +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -49,17 +47,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER // internal headers -#include "B3DImporter.h" -#include "TextureTransform.h" -#include "ConvertToLHProcess.h" +#include "B3D/B3DImporter.h" +#include "PostProcessing/TextureTransform.h" +#include "PostProcessing/ConvertToLHProcess.h" + #include -#include #include #include #include #include #include +#include + using namespace Assimp; using namespace std; @@ -76,7 +76,6 @@ static const aiImporterDesc desc = { "b3d" }; -// (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings #ifdef _MSC_VER # pragma warning (disable: 4018) #endif @@ -84,10 +83,8 @@ static const aiImporterDesc desc = { //#define DEBUG_B3D template -void DeleteAllBarePointers(std::vector& x) -{ - for(auto p : x) - { +void DeleteAllBarePointers(std::vector& x) { + for(auto p : x) { delete p; } } @@ -100,10 +97,14 @@ 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; + if( pos==string::npos ) { + return false; + } string ext=pFile.substr( pos+1 ); - if( ext.size()!=3 ) return false; + if( ext.size()!=3 ) { + return false; + } return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D'); } @@ -115,30 +116,21 @@ const aiImporterDesc* B3DImporter::GetInfo () const return &desc; } -#ifdef DEBUG_B3D - extern "C"{ void _stdcall AllocConsole(); } -#endif // ------------------------------------------------------------------------------------------------ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){ - -#ifdef DEBUG_B3D - AllocConsole(); - freopen( "conin$","r",stdin ); - freopen( "conout$","w",stdout ); - freopen( "conout$","w",stderr ); - cout<<"Hello world from the B3DImporter!"< file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) + 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."); + if( fileSize<8 ) { + throw DeadlyImportError( "B3D File is too small."); + } _pos=0; _buf.resize( fileSize ); @@ -156,14 +148,17 @@ AI_WONT_RETURN void B3DImporter::Oops(){ // ------------------------------------------------------------------------------------------------ AI_WONT_RETURN void B3DImporter::Fail( string str ){ #ifdef DEBUG_B3D - cout<<"Error in B3D file data: "< &v ){ return p; } - // ------------------------------------------------------------------------------------------------ template T **unique_to_array( vector > &v ){ @@ -281,7 +277,6 @@ T **unique_to_array( vector > &v ){ return p; } - // ------------------------------------------------------------------------------------------------ void B3DImporter::ReadTEXS(){ while( ChunkSize() ){ @@ -374,9 +369,13 @@ void B3DImporter::ReadVRTS(){ v.vertex=ReadVec3(); - if( _vflags & 1 ) v.normal=ReadVec3(); + if( _vflags & 1 ) { + v.normal=ReadVec3(); + } - if( _vflags & 2 ) ReadQuat(); //skip v 4bytes... + if( _vflags & 2 ) { + ReadQuat(); //skip v 4bytes... + } for( int i=0;i<_tcsets;++i ){ float t[4]={0,0,0,0}; @@ -384,53 +383,55 @@ void B3DImporter::ReadVRTS(){ t[j]=ReadFloat(); } t[1]=1-t[1]; - if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] ); + if( !i ) { + v.texcoords=aiVector3D( t[0],t[1],t[2] ); + } } } } // ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadTRIS( int v0 ){ - int matid=ReadInt(); - if( matid==-1 ){ - matid=0; - }else if( matid<0 || matid>=(int)_materials.size() ){ +void B3DImporter::ReadTRIS(int v0) { + int matid = ReadInt(); + if (matid == -1) { + matid = 0; + } else if (matid < 0 || matid >= (int)_materials.size()) { #ifdef DEBUG_B3D - cout<<"material id="< mesh(new aiMesh); + std::unique_ptr mesh(new aiMesh); - mesh->mMaterialIndex=matid; - mesh->mNumFaces=0; - mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE; + mesh->mMaterialIndex = matid; + mesh->mNumFaces = 0; + mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - int n_tris=ChunkSize()/12; - aiFace *face=mesh->mFaces=new aiFace[n_tris]; + int n_tris = ChunkSize() / 12; + aiFace *face = mesh->mFaces = new aiFace[n_tris]; - for( int i=0;i=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){ + for (int i = 0; i < n_tris; ++i) { + int i0 = ReadInt() + v0; + int i1 = ReadInt() + v0; + int i2 = ReadInt() + v0; + if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { #ifdef DEBUG_B3D - cout<<"Bad triangle index: i0="<mNumIndices=3; - face->mIndices=new unsigned[3]; - face->mIndices[0]=i0; - face->mIndices[1]=i1; - face->mIndices[2]=i2; - ++mesh->mNumFaces; - ++face; - } + Fail("Bad triangle index"); + continue; + } + face->mNumIndices = 3; + face->mIndices = new unsigned[3]; + face->mIndices[0] = i0; + face->mIndices[1] = i1; + face->mIndices[2] = i2; + ++mesh->mNumFaces; + ++face; + } - _meshes.emplace_back( std::move(mesh) ); + _meshes.emplace_back(std::move(mesh)); } // ------------------------------------------------------------------------------------------------ @@ -451,29 +452,23 @@ void B3DImporter::ReadMESH(){ } // ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadBONE( int id ){ - while( ChunkSize() ){ - int vertex=ReadInt(); - float weight=ReadFloat(); - if( vertex<0 || vertex>=(int)_vertices.size() ){ - Fail( "Bad vertex index" ); - } +void B3DImporter::ReadBONE(int id) { + while (ChunkSize()) { + int vertex = ReadInt(); + float weight = ReadFloat(); + if (vertex < 0 || vertex >= (int)_vertices.size()) { + Fail("Bad vertex index"); + } - Vertex &v=_vertices[vertex]; - int i; - for( i=0;i<4;++i ){ - if( !v.weights[i] ){ - v.bones[i]=id; - v.weights[i]=weight; - break; - } - } -#ifdef DEBUG_B3D - if( i==4 ){ - cout<<"Too many bone weights"<info(dmp); + ASSIMP_LOG_INFO(dmp); } while( ChunkSize() ){ @@ -631,11 +626,15 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ } ExitChunk(); - if( !_nodes.size() ) Fail( "No nodes" ); + if( !_nodes.size() ) { + Fail( "No nodes" ); + } - if( !_meshes.size() ) Fail( "No meshes" ); + if( !_meshes.size() ) { + Fail( "No meshes" ); + } - //Fix nodes/meshes/bones + // Fix nodes/meshes/bones for(size_t i=0;i<_nodes.size();++i ){ aiNode *node=_nodes[i]; @@ -646,8 +645,12 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ 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 ]; + if( _vflags & 1 ) { + mn=mesh->mNormals=new aiVector3D[ n_verts ]; + } + if( _tcsets ) { + mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ]; + } aiFace *face=mesh->mFaces; diff --git a/code/B3DImporter.h b/code/B3D/B3DImporter.h similarity index 99% rename from code/B3DImporter.h rename to code/B3D/B3DImporter.h index 3cb66e5c7..d52dac34a 100644 --- a/code/B3DImporter.h +++ b/code/B3D/B3DImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BVHLoader.cpp b/code/BVH/BVHLoader.cpp similarity index 86% rename from code/BVHLoader.cpp rename to code/BVH/BVHLoader.cpp index 0b2a818ae..cd9ab0843 100644 --- a/code/BVHLoader.cpp +++ b/code/BVH/BVHLoader.cpp @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -461,6 +462,13 @@ void BVHLoader::CreateAnimation( aiScene* pScene) 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) @@ -472,16 +480,32 @@ void BVHLoader::CreateAnimation( aiScene* pScene) { poskey->mTime = double( fr); - // Now compute all translations in the right order - for( unsigned int channel = 0; channel < 3; ++channel) + // Now compute all translations + for(BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel +1)) { - switch( node.mChannels[channel]) - { - case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); - } + //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; } @@ -497,12 +521,6 @@ void BVHLoader::CreateAnimation( aiScene* pScene) // rotation part. Always present. First find value offsets { - unsigned int rotOffset = 0; - if( node.mChannels.size() == 6) - { - // Offset all further calculations - rotOffset = 3; - } // Then create the number of rotation keys nodeAnim->mNumRotationKeys = mAnimNumFrames; @@ -512,20 +530,33 @@ void BVHLoader::CreateAnimation( aiScene* pScene) { 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); - for( unsigned int channel = 0; channel < 3; ++channel) - { - // translate ZXY euler angels into a quaternion - const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f; + 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 (node.mChannels[rotOffset+channel]) - { - case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); - } + // 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); diff --git a/code/BVHLoader.h b/code/BVH/BVHLoader.h similarity index 99% rename from code/BVHLoader.h rename to code/BVH/BVHLoader.h index a18ad81d9..33b4e2453 100644 --- a/code/BVHLoader.h +++ b/code/BVH/BVHLoader.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderBMesh.cpp b/code/Blender/BlenderBMesh.cpp similarity index 100% rename from code/BlenderBMesh.cpp rename to code/Blender/BlenderBMesh.cpp diff --git a/code/BlenderBMesh.h b/code/Blender/BlenderBMesh.h similarity index 100% rename from code/BlenderBMesh.h rename to code/Blender/BlenderBMesh.h diff --git a/code/Blender/BlenderCustomData.cpp b/code/Blender/BlenderCustomData.cpp new file mode 100644 index 000000000..6561eaf22 --- /dev/null +++ b/code/Blender/BlenderCustomData.cpp @@ -0,0 +1,189 @@ +#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; + } + } +} diff --git a/code/Blender/BlenderCustomData.h b/code/Blender/BlenderCustomData.h new file mode 100644 index 000000000..f61d79a26 --- /dev/null +++ b/code/Blender/BlenderCustomData.h @@ -0,0 +1,89 @@ +#pragma once + +#include "BlenderDNA.h" +#include "BlenderScene.h" +#include + +namespace Assimp { + namespace Blender { + /* CustomData.type from Blender (2.79b) */ + enum CustomDataType { + CD_AUTO_FROM_NAME = -1, + CD_MVERT = 0, +#ifdef DNA_DEPRECATED + CD_MSTICKY = 1, /* DEPRECATED */ +#endif + CD_MDEFORMVERT = 2, + CD_MEDGE = 3, + CD_MFACE = 4, + CD_MTFACE = 5, + CD_MCOL = 6, + CD_ORIGINDEX = 7, + CD_NORMAL = 8, + /* CD_POLYINDEX = 9, */ + CD_PROP_FLT = 10, + CD_PROP_INT = 11, + CD_PROP_STR = 12, + CD_ORIGSPACE = 13, /* for modifier stack face location mapping */ + CD_ORCO = 14, + CD_MTEXPOLY = 15, + CD_MLOOPUV = 16, + CD_MLOOPCOL = 17, + CD_TANGENT = 18, + CD_MDISPS = 19, + CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */ + /* CD_ID_MCOL = 21, */ + CD_TEXTURE_MLOOPCOL = 22, + CD_CLOTH_ORCO = 23, + CD_RECAST = 24, + + /* BMESH ONLY START */ + CD_MPOLY = 25, + CD_MLOOP = 26, + CD_SHAPE_KEYINDEX = 27, + CD_SHAPEKEY = 28, + CD_BWEIGHT = 29, + CD_CREASE = 30, + CD_ORIGSPACE_MLOOP = 31, + CD_PREVIEW_MLOOPCOL = 32, + CD_BM_ELEM_PYPTR = 33, + /* BMESH ONLY END */ + + CD_PAINT_MASK = 34, + CD_GRID_PAINT_MASK = 35, + CD_MVERT_SKIN = 36, + CD_FREESTYLE_EDGE = 37, + CD_FREESTYLE_FACE = 38, + CD_MLOOPTANGENT = 39, + CD_TESSLOOPNORMAL = 40, + CD_CUSTOMLOOPNORMAL = 41, + + CD_NUMTYPES = 42 + }; + + /** + * @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES) + * @param[in] cdtype to check + * @return true when valid + */ + bool isValidCustomDataType(const int cdtype); + + /** + * @brief returns CustomDataLayer ptr for given cdtype and name + * @param[in] customdata CustomData to search for wanted layer + * @param[in] cdtype to search for + * @param[in] name to search for + * @return CustomDataLayer * or nullptr if not found + */ + std::shared_ptr getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name); + + /** + * @brief returns CustomDataLayer data ptr for given cdtype and name + * @param[in] customdata CustomData to search for wanted layer + * @param[in] cdtype to search for + * @param[in] name to search for + * @return * to struct data or nullptr if not found + */ + const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name); + } +} diff --git a/code/BlenderDNA.cpp b/code/Blender/BlenderDNA.cpp similarity index 96% rename from code/BlenderDNA.cpp rename to code/Blender/BlenderDNA.cpp index 1d88f8fa6..f274e02f9 100644 --- a/code/BlenderDNA.cpp +++ b/code/Blender/BlenderDNA.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -210,8 +210,7 @@ void DNAParser::Parse () s.size = offset; } - DefaultLogger::get()->debug((format(),"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(); @@ -228,12 +227,12 @@ void DNAParser::Parse () // ------------------------------------------------------------------------------------------------ void DNA :: DumpToFile() { - // we dont't bother using the VFS here for this is only for debugging. + // we don't bother using the VFS here for this is only for debugging. // (and all your bases are belong to us). std::ofstream f("dna.txt"); if (f.fail()) { - DefaultLogger::get()->error("Could not dump dna to dna.txt"); + ASSIMP_LOG_ERROR("Could not dump dna to dna.txt"); return; } f << "Field format: type name offset size" << "\n"; @@ -248,7 +247,7 @@ void DNA :: DumpToFile() } f << std::flush; - DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt"); + ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt"); } #endif @@ -367,7 +366,7 @@ void SectionParser :: Next() } #ifdef ASSIMP_BUILD_BLENDER_DEBUG - DefaultLogger::get()->debug(current.id); + ASSIMP_LOG_DEBUG(current.id); #endif } diff --git a/code/BlenderDNA.h b/code/Blender/BlenderDNA.h similarity index 94% rename from code/BlenderDNA.h rename to code/Blender/BlenderDNA.h index 3a2455275..375d0c4bf 100644 --- a/code/BlenderDNA.h +++ b/code/Blender/BlenderDNA.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -309,6 +309,28 @@ public: void ReadField(T& out, const char* name, const FileDatabase& db) const; + // -------------------------------------------------------- + /** + * @brief field parsing for dynamic vectors + * @param[in] out vector of struct to be filled + * @param[in] name of field + * @param[in] db to access the file, dna, ... + * @return true when read was successful + */ + template class TOUT, typename T> + bool ReadFieldPtrVector(vector>&out, const char* name, const FileDatabase& db) const; + + /** + * @brief parses raw customdata + * @param[in] out shared_ptr to be filled + * @param[in] cdtype customdata type to read + * @param[in] name of field ptr + * @param[in] db to access the file, dna, ... + * @return true when read was successful + */ + template + bool ReadCustomDataPtr(std::shared_ptr&out, int cdtype, const char* name, const FileDatabase& db) const; + private: // -------------------------------------------------------- @@ -381,7 +403,7 @@ template <> struct Structure :: _defaultInitializer { template void operator ()(T& out, const char* reason = "") { - DefaultLogger::get()->warn(reason); + ASSIMP_LOG_WARN(reason); // ... and let the show go on _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out); @@ -394,7 +416,7 @@ template <> struct Structure :: _defaultInitializer { void operator ()(T& /*out*/,const char* = "") { // obviously, it is crucial that _DefaultInitializer is used // only from within a catch clause. - throw; + throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error"); } }; @@ -663,7 +685,7 @@ public: /** Check whether a specific item is in the cache. * @param s Data type of the item * @param out Output pointer. Unchanged if the - * cache doens't know the item yet. + * cache doesn't know the item yet. * @param ptr Item address to look for. */ template void get ( const Structure& s, @@ -803,6 +825,17 @@ private: FileDatabase& db; }; +/** +* @brief read CustomData's data to ptr to mem +* @param[out] out memory ptr to set +* @param[in] cdtype to read +* @param[in] cnt cnt of elements to read +* @param[in] db to read elements from +* @return true when ok +*/ +bool readCustomData(std::shared_ptr &out, int cdtype, size_t cnt, const FileDatabase &db); + + } // end Blend } // end Assimp diff --git a/code/BlenderDNA.inl b/code/Blender/BlenderDNA.inl similarity index 88% rename from code/BlenderDNA.inl rename to code/Blender/BlenderDNA.inl index 163798a40..65bc1374c 100644 --- a/code/BlenderDNA.inl +++ b/code/Blender/BlenderDNA.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -307,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co } +//-------------------------------------------------------------------------------- +// field parsing for raw untyped data (like CustomDataLayer.data) +template +bool Structure::ReadCustomDataPtr(std::shared_ptr&out, int cdtype, const char* name, const FileDatabase& db) const { + + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); + + Pointer ptrval; + const Field* f; + try { + f = &(*this)[name]; + + // sanity check, should never happen if the genblenddna script is right + if (!(f->flags & FieldFlag_Pointer)) { + throw Error((Formatter::format(), "Field `", name, "` of structure `", + this->name, "` ought to be a pointer")); + } + + db.reader->IncPtr(f->offset); + Convert(ptrval, db); + // actually it is meaningless on which Structure the Convert is called + // because the `Pointer` argument triggers a special implementation. + } + catch (const Error& e) { + _defaultInitializer()(out, e.what()); + out.reset(); + } + + bool readOk = true; + if (ptrval.val) { + // get block for ptr + const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db); + db.reader->SetCurrentPos(block->start + static_cast((ptrval.val - block->address.val))); + // read block->num instances of given type to out + readOk = readCustomData(out, cdtype, block->num, db); + } + + // and recover the previous stream position + db.reader->SetCurrentPos(old); + +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS + ++db.stats().fields_read; +#endif + + return readOk; +} + +//-------------------------------------------------------------------------------- +template class TOUT, typename T> +bool Structure::ReadFieldPtrVector(vector>&out, const char* name, const FileDatabase& db) const { + out.clear(); + + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); + + Pointer ptrval; + const Field* f; + try { + f = &(*this)[name]; + + // sanity check, should never happen if the genblenddna script is right + if (!(f->flags & FieldFlag_Pointer)) { + throw Error((Formatter::format(), "Field `", name, "` of structure `", + this->name, "` ought to be a pointer")); + } + + db.reader->IncPtr(f->offset); + Convert(ptrval, db); + // actually it is meaningless on which Structure the Convert is called + // because the `Pointer` argument triggers a special implementation. + } + catch (const Error& e) { + _defaultInitializer()(out, e.what()); + out.clear(); + return false; + } + + + if (ptrval.val) { + // find the file block the pointer is pointing to + const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db); + db.reader->SetCurrentPos(block->start + static_cast((ptrval.val - block->address.val))); + // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems. + // I really ought to improve StreamReader to work with 64 bit indices exclusively. + + const Structure& s = db.dna[f->type]; + for (size_t i = 0; i < block->num; ++i) { + TOUT p(new T); + s.Convert(*p, db); + out.push_back(p); + } + } + + db.reader->SetCurrentPos(old); + +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS + ++db.stats().fields_read; +#endif + + return true; +} + + //-------------------------------------------------------------------------------- template