diff --git a/.clang-format b/.clang-format index c700d9700..1b47c9d29 100644 --- a/.clang-format +++ b/.clang-format @@ -70,7 +70,7 @@ IncludeCategories: - Regex: '^<.*' Priority: 3 # IncludeIsMainRegex: '(Test)?$' -IndentCaseLabels: false +IndentCaseLabels: false #IndentPPDirectives: AfterHash IndentWidth: 4 # IndentWrappedFunctionNames: false diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 2c5ca438b..9acad9d41 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,14 +7,147 @@ on: branches: [ master ] permissions: - contents: read # to fetch code (actions/checkout) + contents: write # to fetch code (actions/checkout),and release jobs: - job: + build: name: ${{ matrix.name }}-build-and-test runs-on: ${{ matrix.os }} strategy: fail-fast: false + matrix: + name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, windows-latest-clang.exe, ubuntu-latest-clang++] + # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. + include: + - name: windows-latest-clang.exe + os: windows-latest + cxx: clang++.exe + cc: clang.exe + - name: windows-latest-cl.exe + os: windows-latest + cxx: cl.exe + cc: cl.exe + - name: windows-hunter-latest-cl.exe + os: windows-latest + cxx: cl.exe + cc: cl.exe + - name: ubuntu-latest-clang++ + os: ubuntu-latest + cxx: clang++ + cc: clang + - name: macos-latest-clang++ + os: macos-latest + cxx: clang++ + cc: clang + - name: ubuntu-latest-g++ + os: ubuntu-latest + cxx: g++ + cc: gcc + + steps: + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + + - uses: actions/checkout@v4 + with: + submodules: true + + - uses: lukka/get-cmake@latest + + - uses: ilammy/msvc-dev-cmd@v1 + + - name: Set Compiler Environment + uses: lukka/set-shell-env@v1 + with: + CXX: ${{ matrix.cxx }} + CC: ${{ matrix.cc }} + + - name: Cache DX SDK + id: dxcache + if: contains(matrix.name, 'windows') + uses: actions/cache@v4 + with: + path: '${{ github.workspace }}/DX_SDK' + key: ${{ runner.os }}-DX_SDK + restore-keys: | + ${{ runner.os }}-DX_SDK + + - name: Download DXSetup + if: contains(matrix.name, 'windows-latest-cl.exe') && steps.dxcache.outputs.cache-hit != 'true' + run: | + curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe + cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK" + + - name: Set Windows specific CMake arguments + if: contains(matrix.name, 'windows-latest-cl.exe') + id: windows_extra_cmake_args + run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT + + - name: Set Hunter specific CMake arguments + if: contains(matrix.name, 'hunter') + id: hunter_extra_cmake_args + run: echo "args=-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake" >> $GITHUB_OUTPUT + + - name: configure and build + uses: lukka/run-cmake@v3 + env: + DXSDK_DIR: '${{ github.workspace }}/DX_SDK' + + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}' + buildWithCMakeArgs: '--parallel 24 -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: Exclude certain tests in Hunter specific builds + if: contains(matrix.name, 'hunter') + id: hunter_extra_test_args + run: echo "args=--gtest_filter=-utOpenGEXImportExport.Importissue1340_EmptyCameraObject:utColladaZaeImportExport.importBlenFromFileTest" >> $GITHUB_OUTPUT + + - name: test + run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} + shell: bash + + - uses: actions/upload-artifact@v4 + if: matrix.name == 'windows-msvc' + with: + name: 'assimp-bins-${{ matrix.name }}' + path: build/bin/assimp*.exe + + - uses: marvinpinto/action-automatic-releases@latest + if: contains(matrix.name, 'windows-msvc-hunter') + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "master" + prerelease: true + title: "AutoRelease" + files: | + build/bin/assimp*.exe + + create-release: + needs: [build] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') + steps: + - id: create-release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: '${{secrets.GITHUB_TOKEN}}' + with: + tag_name: '${{github.ref}}' + release_name: 'Release ${{github.ref}}' + draft: false + prerelease: true + - run: | + echo '${{steps.create-release.outputs.upload_url}}' > release_upload_url.txt + - uses: actions/upload-artifact@v4 + with: + name: create-release + path: release_upload_url.txt + + upload-release: + strategy: matrix: name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter, windows-msvc-hunter] # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. @@ -44,85 +177,24 @@ jobs: - name: windows-msvc-hunter os: windows-latest toolchain: ninja-vs-win64-cxx17 - + + needs: [create-release] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') steps: - - uses: actions/checkout@v4 - with: - submodules: true - - - uses: lukka/get-cmake@latest - - - uses: ilammy/msvc-dev-cmd@v1 - - - name: Set Compiler Environment - if: "!endsWith(matrix.name, 'hunter')" - uses: lukka/set-shell-env@v1 - with: - CXX: ${{ matrix.cxx }} - CC: ${{ matrix.cc }} - - - name: Set Compiler Environment for Hunter on Windows - if: startsWith(matrix.name, 'windows') && endsWith(matrix.name, 'hunter') - uses: lukka/set-shell-env@v1 - with: - VS160COMNTOOLS: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools - - - name: Checkout Hunter toolchains - if: endsWith(matrix.name, 'hunter') - uses: actions/checkout@v4 - with: - repository: cpp-pm/polly - path: cmake/polly - - - name: Cache DX SDK - id: dxcache - if: contains(matrix.name, 'windows') - uses: actions/cache@v3 - with: - path: '${{ github.workspace }}/DX_SDK' - key: ${{ runner.os }}-DX_SDK - restore-keys: | - ${{ runner.os }}-DX_SDK - - - name: Download DXSetup - if: contains(matrix.name, 'windows') && steps.dxcache.outputs.cache-hit != 'true' - run: | - curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe - cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK" - - - name: Set Windows specific CMake arguments - if: contains(matrix.name, 'windows') - id: windows_extra_cmake_args - run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1" - - - name: Set Hunter specific CMake arguments - if: contains(matrix.name, 'hunter') - id: hunter_extra_cmake_args - run: echo "::set-output name=args::-DBUILD_SHARED_LIBS=OFF -DASSIMP_HUNTER_ENABLED=ON -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/cmake/polly/${{ matrix.toolchain }}.cmake" - - - name: configure and build - uses: lukka/run-cmake@v3 - env: - DXSDK_DIR: '${{ github.workspace }}/DX_SDK' - - with: - cmakeListsOrSettingsJson: CMakeListsTxtAdvanced - cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' - cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}' - buildWithCMakeArgs: '--parallel 24 -v' - buildDirectory: '${{ github.workspace }}/build/' - - - name: Exclude certain tests in Hunter specific builds - if: contains(matrix.name, 'hunter') - id: hunter_extra_test_args - run: echo "::set-output name=args::--gtest_filter=-utOpenGEXImportExport.Importissue1340_EmptyCameraObject:utColladaZaeImportExport.importBlenFromFileTest" - - - name: test - run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} - shell: bash - - - uses: actions/upload-artifact@v3 - if: matrix.name == 'windows-msvc' - with: - name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' - path: build/bin + - uses: softprops/action-gh-release@v2 + with: + name: create-release + - id: upload-url + run: | + echo "url=$(cat create-release/release_upload_url.txt)" >> $GITHUB_OUTPUT + - uses: actions/download-artifact@v4 + with: + name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' + - uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: '${{secrets.GITHUB_TOKEN}}' + with: + files: | + *.zip + diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 000000000..a5ec10c7a --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,52 @@ +name: Build and Publish Prebuilt Binaries + +on: + release: + types: [created] + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: windows-x64 + os: windows-latest + arch: x64 + - name: windows-x86 + os: windows-latest + arch: x86 + cmake_args: -A Win32 + - name: macos-x64 + os: macos-13 + - name: macos-arm64 + os: macos-latest + - name: linux-x64 + os: ubuntu-latest + + steps: + - uses: actions/checkout@v4.2.2 + + - uses: lukka/get-cmake@latest + + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.arch }} + + - name: Build + run: | + cmake -B build -S . ${{ matrix.cmake_args }} -DCMAKE_BUILD_TYPE=Release -DASSIMP_BUILD_TESTS=OFF + cmake --build build --config Release + + - uses: TheDoctor0/zip-release@0.7.6 + with: + filename: ${{ matrix.name }}-${{ github.event.release.tag_name }}.zip + directory: build/bin/ + + - uses: softprops/action-gh-release@v2 + with: + files: build/bin/${{ matrix.name }}-${{ github.event.release.tag_name }}.zip + append_body: true + fail_on_unmatched_files: true diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index a84be8cbc..38f54ce06 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -19,7 +19,7 @@ jobs: dry-run: false language: c++ - name: Upload Crash - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/inno_setup b/.github/workflows/inno_setup new file mode 100644 index 000000000..92f16918e --- /dev/null +++ b/.github/workflows/inno_setup @@ -0,0 +1,51 @@ +name: Build Windows Installer +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + build: + name: Build the Inno Setup Installer + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: lukka/get-cmake@latest + - uses: ilammy/msvc-dev-cmd@v1 + + + - name: Cache DX SDK + id: dxcache + uses: actions/cache@v4 + with: + path: '${{ github.workspace }}/DX_SDK' + key: ${{ runner.os }}-DX_SDK + restore-keys: | + ${{ runner.os }}-DX_SDK + + - name: Download DXSetup + run: | + curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe + cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK" + + - name: Set Windows specific CMake arguments + id: windows_extra_cmake_args + run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1" + + - name: configure and build + uses: lukka/run-cmake@v3 + env: + DXSDK_DIR: '${{ github.workspace }}/DX_SDK' + + with: + cmakeListsOrSettingsJson: CMakeListsTxtAdvanced + cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt' + cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}' + buildWithCMakeArgs: '--parallel 24 -v' + buildDirectory: '${{ github.workspace }}/build/' + + - name: Compile .ISS to .EXE Installer + uses: Minionguyjpro/Inno-Setup-Action@v1.2.5 + with: + path: packaging/windows-innosetup/script_x64.iss + options: /O+ diff --git a/.gitignore b/.gitignore index 09d631ee8..68b6e8de4 100644 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,9 @@ tools/assimp_qt_viewer/ui_mainwindow.h #Generated directory generated/* + +# 3rd party cloned repos/tarballs etc +# meshlab repo, automatically cloned via CMake (to gain 2 source files for VRML file format conversion) +contrib/meshlab/autoclone +# tinyusdz repo, automatically cloned via CMake +contrib/tinyusdz/autoclone diff --git a/Build.md b/Build.md index 9440a0073..440410032 100644 --- a/Build.md +++ b/Build.md @@ -1,36 +1,12 @@ # Build / Install Instructions -## Install 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. - -## Install on Ubuntu -You can install the Asset-Importer-Lib via apt: -``` -sudo apt-get update -sudo apt-get install libassimp-dev -``` - -## Install pyassimp -You need to have pip installed: -``` -pip install pyassimp -``` - ## Manual build instructions - -### Install CMake -Asset-Importer-Lib can be built 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 -``` +### Install prerequisites +You need to install +* cmake +* Your compiler (must support C++17 and C99 at least) +* For Windows + * DX-SDK 9 if you want to use our 3D-Viewer ### Get the source Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via: @@ -38,15 +14,22 @@ Make sure you have a working git-installation. Open a command prompt and clone t git clone https://github.com/assimp/assimp.git ``` ### Build from source: +* For *assimp.lib* without any tools: ```bash cd assimp -cmake CMakeLists.txt +cmake CMakeLists.txt +cmake --build . +``` + +* For assimp with the common tools like *assimp-cmd* +```bash +cd assimp +cmake CMakeLists.txt -DASSIMP_BUILD_ASSIMP_TOOLS=ON cmake --build . ``` Note that by default this builds a shared library into the `bin` directory. If you want to build it as a static library see the build options at the bottom of this file. ### 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 @@ -57,19 +40,8 @@ This will generate the project files for the visual studio. All dependencies use ### 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 describes 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 an 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 + 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. @@ -111,3 +83,31 @@ The cmake-build-environment provides options to configure the build. The followi - **USE_STATIC_CRT (default OFF)**: Link against the static MSVC runtime libraries. - **ASSIMP_BUILD_DRACO (default OFF)**: Build Draco libraries. Primarily for glTF. - **ASSIMP_BUILD_ASSIMP_VIEW (default ON, if DirectX found, OFF otherwise)**: Build Assimp view tool (requires DirectX). + +### Install prebuild binaries +## Install 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. + +### Install on Ubuntu +You can install the Asset-Importer-Lib via apt: +``` +sudo apt-get update +sudo apt-get install libassimp-dev +``` + +### Install pyassimp +You need to have pip installed: +``` +pip install pyassimp +``` + +### Get the SDK from itchi.io +Just check [itchi.io](https://kimkulling.itch.io/the-asset-importer-lib) diff --git a/CHANGES b/CHANGES index c0c73b98c..3c4242239 100644 --- a/CHANGES +++ b/CHANGES @@ -290,7 +290,7 @@ FEATURES: - Added support for 64 bit version header introduced in FbxSdk2016 - Travis: enable coverall support. - PyAssimp: New version of the pyASSIMP 3D viewer, with much improved 3D controls - - Morph animation support for collada + - Morph animation support for collada - Added support for parameters Ni and Tf in OBJ/MTL file format - aiScene: add method to add children - Added new option to IFC importer to control tessellation angle + removed unused IFC option @@ -300,7 +300,7 @@ FEATURES: - travis ci: enable sudo support. - openddlparser: integrate release v0.4.0 - aiMetaData: Added support for metadata in assbin format - + FIXES/HOUSEKEEPING: - Introduce usage of #pragma statement - Put cmake-scripts into their own folder @@ -352,7 +352,7 @@ FIXES/HOUSEKEEPING: - add vertex color export support ( issue 809 ) - Fix memory leak in Collada importer ( issue 1169 ) - add stp to the list of supported extensions for step-files ( issue 1183 ) - - fix clang build ( Issue-1169 ) + - fix clang build ( Issue-1169 ) - fix for FreeBSD - Import FindPkgMacros to main CMake Configuration - Extended support for tessellation parameter to more IFC shapes @@ -375,7 +375,7 @@ FIXES/HOUSEKEEPING: - Obj-Importer: do not break when detecting an overflow ( issue 1244 ) - Obj-Importer: fix parsing of multible line data definitions - Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the complete model - - PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply + - PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply import - manage texture coords on faces in ply import - correction on point cloud faces generation - Utf8: integrate new lib ( issue 1158 ) - fixed CMAKE_MODULE_PATH overwriting previous values @@ -400,7 +400,7 @@ FIXES/HOUSEKEEPING: - Remove std functions deprecated by C++11. - X-Importer: make it deal with lines - use correct path for compilers ( issue 1335 ) - - Collada: add workaround to deal with polygon with holes + - Collada: add workaround to deal with polygon with holes - update python readme - Use unique node names when loading Collada files - Fixed many FBX bugs @@ -429,7 +429,7 @@ FEATURES: - C4D: update to latest Melange-SDK - Add a gitter channel - Coverity check enabled - - Switch to <...> include brackets for public headers + - Switch to <...> include brackets for public headers - Enable export by pyAssimp - CI: check windows build - Add functionality to perform a singlepost-processing step @@ -564,7 +564,7 @@ API CHANGES: currently used, however ...) - Some Assimp::Importer methods are const now. - + 1.1 (2010-04-17) This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700). diff --git a/CMakeLists.txt b/CMakeLists.txt index 88f69174a..b0633b4e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- -# Copyright (c) 2006-2023, assimp team +# Copyright (c) 2006-2025, assimp team # # All rights reserved. # @@ -38,24 +38,76 @@ SET(CMAKE_POLICY_DEFAULT_CMP0012 NEW) SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW) SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW) -CMAKE_MINIMUM_REQUIRED( VERSION 3.10 ) +CMAKE_MINIMUM_REQUIRED( VERSION 3.22 ) + +#================================================================================# +# Model formats not enabled by default +# +# 3rd party projects may not adhere to strict standards enforced by assimp, +# in which case those formats must be opt-in; otherwise the 3rd party code +# would fail assimp CI checks +#================================================================================# +# M3D format import support (assimp integration no longer supported by M3D format author) +# User may override these in their CMake script to provide M3D import/export support +# (M3D importer/exporter was disabled for assimp release 5.1 or later) +OPTION(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off) +OPTION(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off) + +# Experimental USD importer: disabled, need to opt-in +# Note: assimp github PR automatic checks will fail the PR due to compiler warnings in +# the external, 3rd party tinyusdz code which isn't technically part of the PR since it's +# auto-cloned during build; so MUST disable the feature or the PR will be rejected +OPTION(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off) +OPTION(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off) + +# VRML (.wrl/.x3dv) file import support by leveraging X3D importer and 3rd party file +# format converter to convert .wrl/.x3dv files to X3D-compatible .xml +# (Need to make this opt-in because 3rd party code triggers lots of CI code quality warnings) +OPTION(ASSIMP_BUILD_VRML_IMPORTER "Enable VRML (.wrl/.x3dv) file import" off) + +#--------------------------------------------------------------------------------# +# Internal impl for optional model formats +#--------------------------------------------------------------------------------# +# Internal/private M3D logic +if (NOT ASSIMP_BUILD_M3D_IMPORTER) + ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER) +endif () # if (not ASSIMP_BUILD_M3D_IMPORTER) +if (NOT ASSIMP_BUILD_M3D_EXPORTER) + ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER) +endif () # if (not ASSIMP_BUILD_M3D_EXPORTER) + +# Internal/private VRML logic +if (NOT ASSIMP_BUILD_VRML_IMPORTER) + ADD_DEFINITIONS( -DASSIMP_BUILD_NO_VRML_IMPORTER) +endif () # if (not ASSIMP_BUILD_VRML_IMPORTER) +#================================================================================# + +option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on) + +IF(ASSIMP_BUILD_USE_CCACHE) + find_program(CCACHE_PATH ccache) + IF (CCACHE_PATH) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH}) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH}) + ENDIF() +ENDIF() -# Disabled importers: m3d for 5.1 -ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER) -ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER) # Toggles the use of the hunter package manager option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF) IF(ASSIMP_HUNTER_ENABLED) include("cmake-modules/HunterGate.cmake") HunterGate( - URL "https://github.com/cpp-pm/hunter/archive/v0.24.18.tar.gz" - SHA1 "1292e4d661e1770d6d6ca08c12c07cf34a0bf718" + URL "https://github.com/cpp-pm/hunter/archive/v0.25.8.tar.gz" + SHA1 "26c79d587883ec910bce168e25f6ac4595f97033" ) - add_definitions(-DASSIMP_USE_HUNTER) + ADD_DEFINITIONS(-DASSIMP_USE_HUNTER) ENDIF() -PROJECT(Assimp VERSION 5.3.0) +PROJECT(Assimp VERSION 6.0.2 + LANGUAGES C CXX + DESCRIPTION "Open Asset Import Library (Assimp) is a library to import various well-known 3D model formats in a uniform manner." +) # All supported options ############################################### @@ -131,35 +183,35 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH IF (WIN32) OPTION( ASSIMP_BUILD_ZLIB - "Build your own zlib" + "Build your zlib" ON ) ELSE() OPTION( ASSIMP_BUILD_ZLIB - "Build your own zlib" - ON + "Build your zlib" + OFF ) ENDIF() IF (WIN32) - # Use subset of Windows.h + # Use a subset of Windows.h ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) IF(MSVC) OPTION( ASSIMP_INSTALL_PDB - "Install MSVC debug files." + "Create MSVC debug symbol files and add to Install target." ON ) IF(NOT (MSVC_VERSION LESS 1900)) - # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier) + # Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier) ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) ENDIF() - # Link statically against c/c++ lib to avoid missing redistriburable such as + # Link statically against c/c++ lib to avoid missing redistributable such as # "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users # a choice to opt for the shared runtime if they want. option(USE_STATIC_CRT "Link against the static runtime libraries." OFF) - # The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative + # The CMAKE_CXX_FLAGS vars can be overridden by some Visual Studio generators, so we use an alternative # global method here: if (${USE_STATIC_CRT}) add_compile_options( @@ -197,7 +249,7 @@ 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 5) +SET (ASSIMP_SOVERSION 6) SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) set(CMAKE_CXX_STANDARD 17) @@ -249,21 +301,32 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") IF( UNIX ) # Use GNUInstallDirs for Unix predefined directories INCLUDE(GNUInstallDirs) - # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux + # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit Linux IF(NOT ${OPERATING_SYSTEM} MATCHES "Android") - IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux + IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit Linux ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) ENDIF() ENDIF() ENDIF() +IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND WIN32) + ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +ENDIF() + +IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI + ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +endif () + + # Grouped compiler settings ######################################## IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU) IF(NOT ASSIMP_HUNTER_ENABLED) SET(CMAKE_POSITION_INDEPENDENT_CODE ON) ENDIF() - - IF(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13) + + IF(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13 AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") MESSAGE(STATUS "GCC13 detected disabling \"-Wdangling-reference\" in Cpp files as it appears to be a false positive") ADD_COMPILE_OPTIONS("$<$:-Wno-dangling-reference>") ENDIF() @@ -284,22 +347,31 @@ ELSEIF(MSVC) ELSE() # msvc ADD_COMPILE_OPTIONS(/MP /bigobj) ENDIF() - + # disable "elements of array '' will be default initialized" warning on MSVC2013 IF(MSVC12) - ADD_COMPILE_OPTIONS(/wd4351) + ADD_COMPILE_OPTIONS(/wd4351) ENDIF() - # supress warning for double to float conversion if Double precission is activated - ADD_COMPILE_OPTIONS(/wd4244) + # supress warning for double to float conversion if Double precision is activated + ADD_COMPILE_OPTIONS(/wd4244) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") - SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") + # Allow user to disable PDBs + if(ASSIMP_INSTALL_PDB) + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") + elseif((GENERATOR_IS_MULTI_CONFIG) OR (CMAKE_BUILD_TYPE MATCHES Release)) + message("-- MSVC PDB generation disabled. Release binary will not be debuggable.") + endif() + if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS) + # Source code is encoded in UTF-8 + ADD_COMPILE_OPTIONS(/source-charset:utf-8) + endif() ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) IF(NOT ASSIMP_HUNTER_ENABLED) SET(CMAKE_POSITION_INDEPENDENT_CODE ON) ENDIF() - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" ) - SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}") + SET(CMAKE_CXX_FLAGS "-Wno-deprecated-non-prototype -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" ) + SET(CMAKE_C_FLAGS "-Wno-deprecated-non-prototype -fno-strict-aliasing ${CMAKE_C_FLAGS}") ELSEIF( MINGW ) 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.") @@ -311,9 +383,9 @@ ELSEIF( MINGW ) SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") ENDIF() IF (CMAKE_BUILD_TYPE STREQUAL "Debug") - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -g ${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wno-dangling-reference -Wall -Wno-long-long -Wa,-mbig-obj -g ${CMAKE_CXX_FLAGS}") ELSE() - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wno-dangling-reference -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}") ENDIF() SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}") ENDIF() @@ -330,7 +402,7 @@ ENDIF() IF (ASSIMP_COVERALLS) MESSAGE(STATUS "Coveralls enabled") - + INCLUDE(Coveralls) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") @@ -338,7 +410,7 @@ ENDIF() IF (ASSIMP_ASAN) MESSAGE(STATUS "AddressSanitizer enabled") - + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") ENDIF() @@ -422,20 +494,20 @@ ENDIF() set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") IF(ASSIMP_HUNTER_ENABLED) - set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") - set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in") - set(NAMESPACE "${PROJECT_NAME}::") - set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") - set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") - set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") + SET(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") + SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in") + SET(NAMESPACE "${PROJECT_NAME}::") + SET(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") + SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") + SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") ELSE() - set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") - set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in") + SET(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") + SET(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in") string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE) - set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::") - set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets") - set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake") - set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake") + SET(NAMESPACE "${PROJECT_NAME_LOWERCASE}::") + SET(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets") + SET(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}ConfigVersion.cmake") + SET(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME_LOWERCASE}Config.cmake") ENDIF() set(INCLUDE_INSTALL_DIR "include") @@ -452,18 +524,20 @@ configure_package_config_file( INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" ) -install( - FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" - DESTINATION "${CONFIG_INSTALL_DIR}" - COMPONENT ${LIBASSIMP-DEV_COMPONENT} -) +IF(ASSIMP_INSTALL) + INSTALL( + FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" + DESTINATION "${CONFIG_INSTALL_DIR}" + COMPONENT ${LIBASSIMP-DEV_COMPONENT} + ) -install( - EXPORT "${TARGETS_EXPORT_NAME}" - NAMESPACE "${NAMESPACE}" - DESTINATION "${CONFIG_INSTALL_DIR}" - COMPONENT ${LIBASSIMP-DEV_COMPONENT} -) + INSTALL( + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${NAMESPACE}" + DESTINATION "${CONFIG_INSTALL_DIR}" + COMPONENT ${LIBASSIMP-DEV_COMPONENT} + ) +ENDIF() IF( ASSIMP_BUILD_DOCS ) ADD_SUBDIRECTORY(doc) @@ -476,12 +550,12 @@ IF(ASSIMP_HUNTER_ENABLED) find_package(ZLIB CONFIG REQUIRED) add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB) - set(ZLIB_FOUND TRUE) - set(ZLIB_LIBRARIES ZLIB::zlib) - set(ASSIMP_BUILD_MINIZIP TRUE) + SET(ZLIB_FOUND TRUE) + SET(ZLIB_LIBRARIES ZLIB::zlib) + SET(ASSIMP_BUILD_MINIZIP TRUE) ELSE() # If the zlib is already found outside, add an export in case assimpTargets can't find it. - IF( ZLIB_FOUND ) + IF( ZLIB_FOUND AND ASSIMP_INSTALL) INSTALL( TARGETS zlib zlibstatic EXPORT "${TARGETS_EXPORT_NAME}") ENDIF() @@ -505,8 +579,8 @@ ELSE() # 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 ) + 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) @@ -529,7 +603,7 @@ IF( NOT IOS ) ELSE () IF( NOT BUILD_SHARED_LIBS ) IF( NOT ASSIMP_BUILD_MINIZIP ) - use_pkgconfig(UNZIP minizip) + USE_PKGCONFIG(UNZIP minizip) ENDIF() ENDIF () ENDIF () @@ -563,9 +637,9 @@ SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL ) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) - IF ( MSVC ) - SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes") + SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes") + IF (WIN32) # pick the correct prebuilt library IF(MSVC143) SET(C4D_LIB_POSTFIX "_2022") @@ -583,7 +657,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) SET(C4D_LIB_POSTFIX "_2010") ELSE() MESSAGE( FATAL_ERROR - "C4D is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3" + "C4D for Windows is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3" ) ENDIF() @@ -601,68 +675,90 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because # it can be used to communicate with a running Cinema 4D instance SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) - ELSE () - MESSAGE( FATAL_ERROR - "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware" + ELSEIF (APPLE) + SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/osx") + + SET(C4D_DEBUG_LIBRARIES + "${C4D_LIB_BASE_PATH}/debug/libcinewarelib.a" + "${C4D_LIB_BASE_PATH}/debug/libjpeglib.a" ) - ENDIF () + SET(C4D_RELEASE_LIBRARIES + "${C4D_LIB_BASE_PATH}/release/libcinewarelib.a" + "${C4D_LIB_BASE_PATH}/release/libjpeglib.a" + ) + ELSE() + MESSAGE( FATAL_ERROR + "C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware" + ) + ENDIF() ELSE () ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ENDIF () +IF(ASSIMP_BUILD_DRACO_STATIC) + SET(ASSIMP_BUILD_DRACO ON) +ENDIF() + # Draco requires cmake 3.12 IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12") - message(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled") + MESSAGE(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled") SET ( ASSIMP_BUILD_DRACO OFF CACHE BOOL "Disabled: Draco requires newer cmake" FORCE ) ELSE() OPTION ( ASSIMP_BUILD_DRACO "If the Draco libraries are to be built. Primarily for glTF" OFF ) IF ( ASSIMP_BUILD_DRACO ) # Primarily for glTF v2 # Enable Draco glTF feature set - set(DRACO_GLTF ON CACHE BOOL "" FORCE) + SET(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE) # Disable unnecessary or omitted components - set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE) - set(DRACO_WASM OFF CACHE BOOL "" FORCE) - set(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE) - set(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE) - set(DRACO_TESTS OFF CACHE BOOL "" FORCE) + SET(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE) + SET(DRACO_WASM OFF CACHE BOOL "" FORCE) + SET(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE) + SET(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE) + SET(DRACO_TESTS OFF CACHE BOOL "" FORCE) IF(ASSIMP_HUNTER_ENABLED) hunter_add_package(draco) find_package(draco CONFIG REQUIRED) - set(draco_LIBRARIES draco::draco) + SET(draco_LIBRARIES draco::draco) ELSE() # Draco 1.4.1 has many warnings and will not build with /WX or -Werror # See https://github.com/google/draco/issues/672 # and https://github.com/google/draco/issues/673 IF(MSVC) - set(DRACO_CXX_FLAGS "/W0") + SET(DRACO_CXX_FLAGS "/W0") ELSE() - list(APPEND DRACO_CXX_FLAGS + LIST(APPEND DRACO_CXX_FLAGS "-Wno-bool-compare" "-Wno-comment" "-Wno-maybe-uninitialized" "-Wno-sign-compare" "-Wno-unused-local-typedefs" ) - # Draco 1.4.1 does not explicitly export any symbols under GCC/clang - list(APPEND DRACO_CXX_FLAGS - "-fvisibility=default" - ) + + IF(NOT ASSIMP_BUILD_DRACO_STATIC) + # Draco 1.4.1 does not explicitly export any symbols under GCC/clang + LIST(APPEND DRACO_CXX_FLAGS + "-fvisibility=default" + ) + ENDIF() ENDIF() # Don't build or install all of Draco by default ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL ) - if(MSVC OR WIN32) - set(draco_LIBRARIES "draco") - else() - if(BUILD_SHARED_LIBS) - set(draco_LIBRARIES "draco_shared") - else() - set(draco_LIBRARIES "draco_static") - endif() - endif() + IF(ASSIMP_BUILD_DRACO_STATIC) + set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF) + ENDIF() + + IF(MSVC OR WIN32) + SET(draco_LIBRARIES "draco") + ELSE() + IF(ASSIMP_BUILD_DRACO_STATIC) + SET(draco_LIBRARIES "draco_static") + ELSE() + SET(draco_LIBRARIES "draco_shared") + ENDIF() + ENDIF() # Don't build the draco command-line tools by default set_target_properties(draco_encoder draco_decoder PROPERTIES @@ -680,18 +776,20 @@ ELSE() TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder) TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_decoder) - set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src") + SET(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src") # This is probably wrong - INSTALL( TARGETS ${draco_LIBRARIES} - EXPORT "${TARGETS_EXPORT_NAME}" - LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} - FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - COMPONENT ${LIBASSIMP_COMPONENT} - INCLUDES DESTINATION include - ) + IF (ASSIMP_INSTALL) + INSTALL( TARGETS ${draco_LIBRARIES} + EXPORT "${TARGETS_EXPORT_NAME}" + LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} + FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + COMPONENT ${LIBASSIMP_COMPONENT} + INCLUDES DESTINATION include + ) + ENDIF() ENDIF() ENDIF() ENDIF() @@ -735,8 +833,8 @@ IF ( ASSIMP_INSTALL ) ENDIF() CONFIGURE_FILE( - ${CMAKE_CURRENT_LIST_DIR}/revision.h.in - ${CMAKE_CURRENT_BINARY_DIR}/revision.h + ${CMAKE_CURRENT_LIST_DIR}/include/assimp/revision.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/revision.h ) CONFIGURE_FILE( @@ -824,24 +922,24 @@ if(WIN32) IF(MSVC12 OR MSVC14 OR MSVC15 ) ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) IF(CMAKE_GENERATOR MATCHES "^Visual Studio") - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ELSE() - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) - ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ENDIF() ENDIF() ENDIF () diff --git a/CREDITS b/CREDITS index 26e21d2f4..62b449614 100644 --- a/CREDITS +++ b/CREDITS @@ -60,7 +60,7 @@ The GUY who performed some of the CSM mocaps. Contributed fixes for the documentation and the doxygen markup - Zhao Lei -Contributed several bugfixes fixing memory leaks and improving float parsing +Contributed several bugfixes fixing memory leaks and improving float parsing - sueastside Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date. @@ -129,7 +129,7 @@ Contributed a patch to fix the VertexTriangleAdjacency postprocessing step. Contributed the Debian build fixes ( architecture macro ). - gellule -Several LWO and LWS fixes (pivoting). +Several LWO and LWS fixes (pivoting). - Marcel Metz GCC/Linux fixes for the SimpleOpenGL sample. diff --git a/Dockerfile b/Dockerfile index 5da5458f8..21dd41daa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,17 @@ -FROM ubuntu:22.04 +FROM gcc:1.5.1.0 -RUN apt-get update && apt-get install -y ninja-build \ - git cmake build-essential software-properties-common +RUN apt-get update \ + apt-get install --no-install-recommends -y ninja-build cmake zlib1g-dev -RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update +WORKDIR /app -WORKDIR /opt +COPY . . -# Build Assimp -RUN git clone https://github.com/assimp/assimp.git /opt/assimp - -WORKDIR /opt/assimp - -RUN git checkout master \ - && mkdir build && cd build && \ +RUN mkdir build && cd build && \ cmake -G 'Ninja' \ -DCMAKE_BUILD_TYPE=Release \ -DASSIMP_BUILD_ASSIMP_TOOLS=ON \ .. && \ ninja -j4 && ninja install + +CMD ["/app/build/bin/unit"] diff --git a/INSTALL b/INSTALL index 410050b10..e5e5938cb 100644 --- a/INSTALL +++ b/INSTALL @@ -1,17 +1,17 @@ - + ======================================================================== -Open Asset Import Library (assimp) INSTALL +Open Asset Import Library (assimp) INSTALL ======================================================================== ------------------------------ Getting the documentation ------------------------------ -A regularly-updated copy is available at +A regularly-updated copy is available at https://assimp-docs.readthedocs.io/en/latest/ ------------------------------ -Building Assimp +Building Assimp ------------------------------ Just check the build-instructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md diff --git a/Readme.md b/Readme.md index a1f707a95..262456b6a 100644 --- a/Readme.md +++ b/Readme.md @@ -1,57 +1,61 @@ Open Asset Import Library (assimp) ================================== -Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. +Open Asset Import Library is a library that loads various 3D file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. ### Current project status ### -[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) -[![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) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=assimp_assimp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=assimp_assimp) [![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") [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open") +[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20assimp%20Guru-006BFF)](https://gurubase.io/g/assimp) +[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp)
-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. +APIs are provided for C and C++. Various bindings exist to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS. Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. +## Project activity ## +![Alt](https://repobeats.axiom.co/api/embed/997f84e5f9fcf772da1e687f3a4f3a8afdbf4cf0.svg "Repobeats analytics image") + ### Documentation ### -Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). +Read [our latest documentation](https://the-asset-importer-lib-documentation.readthedocs.io/en/latest/). ### Pre-built binaries ### -Please check our [Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib) +Download binaries from [our Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib). -If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb +### Test data ### +Clone [our model database](https://github.com/assimp/assimp-mdb). ### Communities ### -- Ask a question at [The Assimp-Discussion Board](https://github.com/assimp/assimp/discussions) -- Ask on [Assimp-Community on Reddit](https://www.reddit.com/r/Assimp/) -- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). -- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues) - -And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions). +- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2) +- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/). +- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). +- Nothing has worked? File a question or an issue report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues) #### Supported file formats #### -You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md) +See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md). ### Building ### -Take a look [here](https://github.com/assimp/assimp/blob/master/Build.md) to get started. 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. +Start by reading [our build instructions](https://github.com/assimp/assimp/blob/master/Build.md). 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](https://bitbucket.org/Starnick/assimpnet/src/master/) +* [.NET](https://github.com/Saalvage/AssimpNetter) * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Javascript/Node.js Interface](https://github.com/kovacsv/assimpjs) * [Unity 3d Plugin](https://ricardoreis.net/trilib-2/) * [Unreal Engine Plugin](https://github.com/irajsb/UE4_Assimp/) -* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) +* [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. * [Rust](https://github.com/jkvargas/russimp) ### Other tools ### -[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. +[Qt5-ModelViewer](https://github.com/sharjith/ModelViewer-Qt5) is a powerful viewer based on Qt5 and Assimp's import and export abilities.
[Assimp-Viewer](https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental). #### Repository structure #### @@ -59,7 +63,7 @@ Open Asset Import Library is implemented in C++. The directory structure looks l /code Source code /contrib Third-party libraries - /doc Documentation (doxysource and pre-compiled docs) + /doc Documentation (Doxygen source and pre-compiled docs) /fuzz Contains the test code for the Google Fuzzer project /include Public header C and C++ header files /scripts Scripts are used to generate the loading code for some formats @@ -79,7 +83,7 @@ The source code is organized in the following way: code/AssetLib/ Implementation for import and export of the format ### Contributing ### -Contributions to assimp are highly appreciated. The easiest way to get involved is to submit +I would greatly appreciate contributing to assimp. The easiest way to get involved is to submit a pull request with your changes against the main repository's `master` branch. ## Contributors @@ -101,7 +105,7 @@ Become a financial contributor and help us sustain our community. [[Contribute]( #### Organizations -Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)] +You can support the project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)] @@ -111,6 +115,3 @@ Our license is based on the modified, __3-clause BSD__-License. An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp. For the legal details, see the `LICENSE` file. - -### Why this name ### -Sorry, we're germans :-), no English native speakers ... diff --git a/SECURITY.md b/SECURITY.md index e4915cd1c..eee961e7f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,10 +7,10 @@ currently being supported with security updates. | Version | Supported | | ------- | ------------------ | -| 5.2.4 | :white_check_mark: | +| 6.0.2 | :white_check_mark: | ## Reporting a Vulnerability -If you have found any security vulnerability you can contact us via +If you have found any security vulnerability you can contact us via kim.kulling@googlemail.com diff --git a/cmake-modules/DebSourcePPA.cmake b/cmake-modules/DebSourcePPA.cmake index d8a786fb2..ebf129b4f 100644 --- a/cmake-modules/DebSourcePPA.cmake +++ b/cmake-modules/DebSourcePPA.cmake @@ -6,7 +6,7 @@ # Creates source debian files and manages library dependencies # # Features: -# +# # - Automatically generates symbols and run-time dependencies from the build dependencies # - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY # - Simultaneous output of multiple debian source packages for each distribution @@ -114,7 +114,6 @@ foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES}) endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) - file(APPEND ${DEBIAN_CONTROL} "\n" "Standards-Version: 3.8.4\n" "Homepage: ${CPACK_PACKAGE_VENDOR}\n" @@ -173,7 +172,7 @@ foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS}) endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) - + file(APPEND ${DEBIAN_CONTROL} "\n" "Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n" "${DEB_LONG_DESCRIPTION}" diff --git a/cmake-modules/FindDirectX.cmake b/cmake-modules/FindDirectX.cmake index b37bc12a3..adc836902 100644 --- a/cmake-modules/FindDirectX.cmake +++ b/cmake-modules/FindDirectX.cmake @@ -26,7 +26,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK getenv_path(DIRECTX_BASE) # construct search paths - set(DirectX_PREFIX_PATH + set(DirectX_PREFIX_PATH "${DXSDK_DIR}" "${ENV_DXSDK_DIR}" "${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}" "${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}" @@ -66,7 +66,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK find_library(DirectX_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) findpkg_finish(DirectX) - set(DirectX_LIBRARIES ${DirectX_LIBRARIES} + set(DirectX_LIBRARIES ${DirectX_LIBRARIES} ${DirectX_D3DX9_LIBRARY} ${DirectX_DXERR_LIBRARY} ${DirectX_DXGUID_LIBRARY} @@ -82,7 +82,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH) message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}") find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) - find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) + find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY) set(DirectX_D3D11_FOUND TRUE) set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR}) @@ -92,8 +92,8 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK ${DirectX_DXGI_LIBRARY} ${DirectX_DXERR_LIBRARY} ${DirectX_DXGUID_LIBRARY} - ${DirectX_D3DCOMPILER_LIBRARY} - ) + ${DirectX_D3DCOMPILER_LIBRARY} + ) endif () mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY) endif () diff --git a/cmake-modules/Findassimp.cmake b/cmake-modules/Findassimp.cmake index 663645574..c5d7e269b 100644 --- a/cmake-modules/Findassimp.cmake +++ b/cmake-modules/Findassimp.cmake @@ -3,7 +3,7 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) set(ASSIMP_ARCHITECTURE "32") endif(CMAKE_SIZEOF_VOID_P EQUAL 8) - + if(WIN32) set(ASSIMP_ROOT_DIR CACHE PATH "ASSIMP root directory") @@ -17,29 +17,29 @@ if(WIN32) if(MSVC12) set(ASSIMP_MSVC_VERSION "vc120") - elseif(MSVC14) + elseif(MSVC14) set(ASSIMP_MSVC_VERSION "vc140") endif(MSVC12) - + if(MSVC12 OR MSVC14) - + find_path(ASSIMP_LIBRARY_DIR NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib HINTS ${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE} ) - + find_library(ASSIMP_LIBRARY_RELEASE assimp-${ASSIMP_MSVC_VERSION}-mt.lib PATHS ${ASSIMP_LIBRARY_DIR}) find_library(ASSIMP_LIBRARY_DEBUG assimp-${ASSIMP_MSVC_VERSION}-mtd.lib PATHS ${ASSIMP_LIBRARY_DIR}) - - set(ASSIMP_LIBRARY + + set(ASSIMP_LIBRARY optimized ${ASSIMP_LIBRARY_RELEASE} debug ${ASSIMP_LIBRARY_DEBUG} ) - + set(ASSIMP_LIBRARIES "ASSIMP_LIBRARY_RELEASE" "ASSIMP_LIBRARY_DEBUG") - + FUNCTION(ASSIMP_COPY_BINARIES TargetDirectory) ADD_CUSTOM_TARGET(AssimpCopyBinaries COMMAND ${CMAKE_COMMAND} -E copy ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${TargetDirectory}/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll @@ -47,9 +47,37 @@ if(WIN32) COMMENT "Copying Assimp binaries to '${TargetDirectory}'" VERBATIM) ENDFUNCTION(ASSIMP_COPY_BINARIES) - + + if (NOT TARGET ASSIMP) + set(INCLUDE_DIRS ${ASSIMP_ROOT_DIR}/include) + + find_library(ASSIMP_LIB_DEBUG + NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.lib + PATHS ${ASSIMP_LIBRARY_DIR}) + + find_file(ASSIMP_DLL_DEBUG + NAMES assimp-${ASSIMP_MSVC_VERSION}-mtd.dll + PATHS ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}) + + find_library(ASSIMP_LIB_RELEASE + NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.lib + PATHS ${ASSIMP_LIBRARY_DIR}) + + find_file(ASSIMP_DLL_RELEASE + NAMES assimp-${ASSIMP_MSVC_VERSION}-mt.dll + PATHS ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}) + + add_library(ASSIMP SHARED IMPORTED) + set_target_properties(ASSIMP PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}" + IMPORTED_IMPLIB_DEBUG ${ASSIMP_LIB_DEBUG} + IMPORTED_IMPLIB_RELEASE ${ASSIMP_LIB_RELEASE} + IMPORTED_LOCATION_DEBUG ${ASSIMP_DLL_DEBUG} + IMPORTED_LOCATION_RELEASE ${ASSIMP_DLL_RELEASE} + ) + endif() endif() - + else(WIN32) find_path( @@ -81,5 +109,5 @@ else(WIN32) message(FATAL_ERROR "Could not find asset importer library") endif (assimp_FIND_REQUIRED) endif (assimp_FOUND) - + endif(WIN32) diff --git a/cmake-modules/HunterGate.cmake b/cmake-modules/HunterGate.cmake index 6d9cc2401..48bd50658 100644 --- a/cmake-modules/HunterGate.cmake +++ b/cmake-modules/HunterGate.cmake @@ -22,45 +22,16 @@ # OR TORT (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_ERROR_PAGE "https://docs.hunter.sh/en/latest/reference/errors") +set(HUNTER_ERROR_PAGE "https://hunter.readthedocs.io/en/latest/reference/errors") function(hunter_gate_status_print) if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) diff --git a/cmake-modules/PrecompiledHeader.cmake b/cmake-modules/PrecompiledHeader.cmake index 6af7866f5..92ae592c9 100644 --- a/cmake-modules/PrecompiledHeader.cmake +++ b/cmake-modules/PrecompiledHeader.cmake @@ -9,14 +9,14 @@ MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar OBJECT_OUTPUTS "${PrecompiledBinary}") # Do not consider .c files - foreach(fname ${Sources}) + foreach(fname ${Sources}) GET_FILENAME_COMPONENT(fext ${fname} EXT) if(fext STREQUAL ".cpp") SET_SOURCE_FILES_PROPERTIES(${fname} PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledBinary}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\"" - OBJECT_DEPENDS "${PrecompiledBinary}") + OBJECT_DEPENDS "${PrecompiledBinary}") endif(fext STREQUAL ".cpp") - endforeach(fname) + endforeach(fname) ENDIF(MSVC) # Add precompiled header to SourcesVar diff --git a/code/.editorconfig b/code/.editorconfig deleted file mode 100644 index 4a194a317..000000000 --- a/code/.editorconfig +++ /dev/null @@ -1,8 +0,0 @@ -# See for details - -[*.{h,hpp,c,cpp}] -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -indent_size = 4 -indent_style = space diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp index 6d3f09cb7..5718ebbc0 100644 --- a/code/AssetLib/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -91,15 +91,12 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { // now iterate through all meshes and through all faces and // find all faces that are using the default material unsigned int cnt = 0; - for (std::vector::iterator - i = mScene->mMeshes.begin(); - i != mScene->mMeshes.end(); ++i) { - for (std::vector::iterator - a = (*i).mFaceMaterials.begin(); - a != (*i).mFaceMaterials.end(); ++a) { + for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) { + for (auto a = (*i).mFaceMaterials.begin(); a != (*i).mFaceMaterials.end(); ++a) { // NOTE: The additional check seems to be necessary, // some exporters seem to generate invalid data here - if (0xcdcdcdcd == (*a)) { + + if (NotSet == (*a)) { (*a) = idx; ++cnt; } else if ((*a) >= mScene->mMaterials.size()) { @@ -111,7 +108,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { } if (cnt && idx == mScene->mMaterials.size()) { // We need to create our own default material - D3DS::Material sMat("%%%DEFAULT"); + Material sMat("%%%DEFAULT"); sMat.mDiffuse = aiColor3D(0.3f, 0.3f, 0.3f); mScene->mMaterials.push_back(sMat); @@ -121,17 +118,17 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { // ------------------------------------------------------------------------------------------------ // Check whether all indices are valid. Otherwise we'd crash before the validation step is reached -void Discreet3DSImporter::CheckIndices(D3DS::Mesh &sMesh) { - for (std::vector::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) { +void Discreet3DSImporter::CheckIndices(Mesh &sMesh) { + for (auto i = sMesh.mFaces.begin(); i != sMesh.mFaces.end(); ++i) { // check whether all indices are in range for (unsigned int a = 0; a < 3; ++a) { if ((*i).mIndices[a] >= sMesh.mPositions.size()) { ASSIMP_LOG_WARN("3DS: Vertex index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size() - 1; + (*i).mIndices[a] = static_cast(sMesh.mPositions.size() - 1); } if (!sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) { ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size() - 1; + (*i).mIndices[a] = static_cast(sMesh.mTexCoords.size() - 1); } } } @@ -139,7 +136,7 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh &sMesh) { // ------------------------------------------------------------------------------------------------ // Generate out unique verbose format representation -void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) { +void Discreet3DSImporter::MakeUnique(Mesh &sMesh) { // TODO: really necessary? I don't think. Just a waste of memory and time // to do it now in a separate buffer. @@ -150,7 +147,7 @@ void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) { vNew2.resize(sMesh.mFaces.size() * 3); for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size(); ++i) { - D3DS::Face &face = sMesh.mFaces[i]; + Face &face = sMesh.mFaces[i]; // Positions for (unsigned int a = 0; a < 3; ++a, ++base) { @@ -167,10 +164,9 @@ void Discreet3DSImporter::MakeUnique(D3DS::Mesh &sMesh) { // ------------------------------------------------------------------------------------------------ // Convert a 3DS texture to texture keys in an aiMaterial -void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) { +void CopyTexture(aiMaterial &mat, Texture &texture, aiTextureType type) { // Setup the texture name - aiString tex; - tex.Set(texture.mMapName); + aiString tex(texture.mMapName); mat.AddProperty(&tex, AI_MATKEY_TEXTURE(type, 0)); // Setup the texture blend factor @@ -197,13 +193,11 @@ void CopyTexture(aiMaterial &mat, D3DS::Texture &texture, aiTextureType type) { // ------------------------------------------------------------------------------------------------ // Convert a 3DS material to an aiMaterial -void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, - aiMaterial &mat) { +void Discreet3DSImporter::ConvertMaterial(Material &oldMat, aiMaterial &mat) { // NOTE: Pass the background image to the viewer by bypassing the // material system. This is an evil hack, never do it again! - if (0 != mBackgroundImage.length() && bHasBG) { - aiString tex; - tex.Set(mBackgroundImage); + if (mBackgroundImage.empty() && bHasBG) { + aiString tex(mBackgroundImage); mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); // Be sure this is only done for the first material @@ -215,8 +209,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, oldMat.mAmbient.g += mClrAmbient.g; oldMat.mAmbient.b += mClrAmbient.b; - aiString name; - name.Set(oldMat.mName); + aiString name(oldMat.mName); mat.AddProperty(&name, AI_MATKEY_NAME); // Material colors @@ -226,10 +219,9 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, mat.AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); // Phong shininess and shininess strength - if (D3DS::Discreet3DS::Phong == oldMat.mShading || - D3DS::Discreet3DS::Metal == oldMat.mShading) { + if (Discreet3DS::Phong == oldMat.mShading || Discreet3DS::Metal == oldMat.mShading) { if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) { - oldMat.mShading = D3DS::Discreet3DS::Gouraud; + oldMat.mShading = Discreet3DS::Gouraud; } else { mat.AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); mat.AddProperty(&oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); @@ -251,40 +243,41 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, // Shading mode aiShadingMode eShading = aiShadingMode_NoShading; switch (oldMat.mShading) { - case D3DS::Discreet3DS::Flat: + case Discreet3DS::Flat: eShading = aiShadingMode_Flat; break; // I don't know what "Wire" shading should be, // assume it is simple lambertian diffuse shading - case D3DS::Discreet3DS::Wire: { + case Discreet3DS::Wire: { // Set the wireframe flag unsigned int iWire = 1; mat.AddProperty((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME); } [[fallthrough]]; - case D3DS::Discreet3DS::Gouraud: + case Discreet3DS::Gouraud: eShading = aiShadingMode_Gouraud; break; // assume cook-torrance shading for metals. - case D3DS::Discreet3DS::Phong: + case Discreet3DS::Phong: eShading = aiShadingMode_Phong; break; - case D3DS::Discreet3DS::Metal: + case Discreet3DS::Metal: eShading = aiShadingMode_CookTorrance; break; // FIX to workaround a warning with GCC 4 who complained // about a missing case Blinn: here - Blinn isn't a valid // value in the 3DS Loader, it is just needed for ASE - case D3DS::Discreet3DS::Blinn: + case Discreet3DS::Blinn: eShading = aiShadingMode_Blinn; break; } - int eShading_ = static_cast(eShading); + + const int eShading_ = eShading; mat.AddProperty(&eShading_, 1, AI_MATKEY_SHADING_MODEL); // DIFFUSE texture @@ -643,11 +636,17 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, } // Allocate storage for children - pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size(); + const unsigned int size = static_cast(pcIn->mChildren.size()); + + pcOut->mNumChildren = size; + if (size == 0) { + return; + } + pcOut->mChildren = new aiNode *[pcIn->mChildren.size()]; // Recursively process all children - const unsigned int size = static_cast(pcIn->mChildren.size()); + for (unsigned int i = 0; i < size; ++i) { pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i]->mParent = pcOut; @@ -709,7 +708,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) { pcNode->mNumMeshes = 1; // Build a name for the node - pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i); + pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "3DSMesh_%u", i); } // Build dummy nodes for all cameras @@ -777,7 +776,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) { // Convert all meshes in the scene and generate the final output scene. void Discreet3DSImporter::ConvertScene(aiScene *pcOut) { // Allocate enough storage for all output materials - pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size(); + pcOut->mNumMaterials = static_cast(mScene->mMaterials.size()); pcOut->mMaterials = new aiMaterial *[pcOut->mNumMaterials]; // ... and convert the 3DS materials to aiMaterial's @@ -791,17 +790,17 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) { ConvertMeshes(pcOut); // Now copy all light sources to the output scene - pcOut->mNumLights = (unsigned int)mScene->mLights.size(); + pcOut->mNumLights = static_cast(mScene->mLights.size()); if (pcOut->mNumLights) { pcOut->mLights = new aiLight *[pcOut->mNumLights]; - ::memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights); + memcpy(pcOut->mLights, &mScene->mLights[0], sizeof(void *) * pcOut->mNumLights); } // Now copy all cameras to the output scene - pcOut->mNumCameras = (unsigned int)mScene->mCameras.size(); + pcOut->mNumCameras = static_cast(mScene->mCameras.size()); if (pcOut->mNumCameras) { pcOut->mCameras = new aiCamera *[pcOut->mNumCameras]; - ::memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras); + memcpy(pcOut->mCameras, &mScene->mCameras[0], sizeof(void *) * pcOut->mNumCameras); } } diff --git a/code/AssetLib/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp index 1b335a272..443011c0d 100644 --- a/code/AssetLib/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -52,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -102,7 +102,7 @@ private: // preserves the mesh's given name if it has one. |index| is the index // of the mesh in |aiScene::mMeshes|. std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) { - static const char underscore = '_'; + static constexpr char underscore = '_'; char postfix[10] = { 0 }; ASSIMP_itoa10(postfix, index); @@ -208,9 +208,6 @@ Discreet3DSExporter::Discreet3DSExporter(std::shared_ptr &outfile, con } } -// ------------------------------------------------------------------------------------------------ -Discreet3DSExporter::~Discreet3DSExporter() = default; - // ------------------------------------------------------------------------------------------------ int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) { // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec diff --git a/code/AssetLib/3DS/3DSExporter.h b/code/AssetLib/3DS/3DSExporter.h index 66e91e10d..27804d461 100644 --- a/code/AssetLib/3DS/3DSExporter.h +++ b/code/AssetLib/3DS/3DSExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -63,10 +63,10 @@ namespace Assimp { * @brief Helper class to export a given scene to a 3DS file. */ // ------------------------------------------------------------------------------------------------ -class Discreet3DSExporter { +class Discreet3DSExporter final { public: Discreet3DSExporter(std::shared_ptr &outfile, const aiScene* pScene); - ~Discreet3DSExporter(); + ~Discreet3DSExporter() = default; private: void WriteMeshes(); @@ -88,7 +88,6 @@ private: using MeshesByNodeMap = std::multimap; MeshesByNodeMap meshes; - }; } // Namespace Assimp diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 2279d105c..64ddff819 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -365,14 +364,13 @@ struct Texture { #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER - // --------------------------------------------------------------------------- /** Helper structure representing a 3ds material */ struct Material { //! Default constructor has been deleted Material() : mName(), - mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), + mDiffuse(0.6f, 0.6f, 0.6f), mSpecularExponent(ai_real(0.0)), mShininessStrength(ai_real(1.0)), mShading(Discreet3DS::Gouraud), @@ -385,7 +383,7 @@ struct Material { //! Constructor with explicit name explicit Material(const std::string &name) : mName(name), - mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), + mDiffuse(0.6f, 0.6f, 0.6f), mSpecularExponent(ai_real(0.0)), mShininessStrength(ai_real(1.0)), mShading(Discreet3DS::Gouraud), diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index a406ea1d2..1ee0b8b28 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -106,7 +106,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 { - static const uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ }; + static constexpr uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ }; return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]); } diff --git a/code/AssetLib/3DS/3DSLoader.h b/code/AssetLib/3DS/3DSLoader.h index c579507e0..fab1c0950 100644 --- a/code/AssetLib/3DS/3DSLoader.h +++ b/code/AssetLib/3DS/3DSLoader.h @@ -1,10 +1,8 @@ - /* Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -57,14 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiNode; -namespace Assimp { +namespace Assimp { using namespace D3DS; // --------------------------------------------------------------------------------- /** Importer class for 3D Studio r3 and r4 3DS files */ -class Discreet3DSImporter : public BaseImporter { +class Discreet3DSImporter final : public BaseImporter { public: Discreet3DSImporter(); ~Discreet3DSImporter() override = default; @@ -126,7 +124,6 @@ protected: void ParseColorChunk(aiColor3D* p_pcOut, bool p_bAcceptPercent = true); - // ------------------------------------------------------------------- /** Skip a chunk in the file */ diff --git a/code/AssetLib/3MF/3MFTypes.h b/code/AssetLib/3MF/3MFTypes.h index 8207b568b..b123cd7c7 100644 --- a/code/AssetLib/3MF/3MFTypes.h +++ b/code/AssetLib/3MF/3MFTypes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -57,6 +57,7 @@ enum class ResourceType { RT_BaseMaterials, RT_EmbeddedTexture2D, RT_Texture2DGroup, + RT_ColorGroup, RT_Unknown }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) @@ -117,6 +118,21 @@ public: } }; +class ColorGroup : public Resource { +public: + std::vector mColors; + ColorGroup(int id) : + Resource(id){ + // empty + } + + ~ColorGroup() override = default; + + ResourceType getType() const override { + return ResourceType::RT_ColorGroup; + } +}; + class BaseMaterials : public Resource { public: std::vector mMaterialIndex; diff --git a/code/AssetLib/3MF/3MFXmlTags.h b/code/AssetLib/3MF/3MFXmlTags.h index 333d169aa..2efa4c9ff 100644 --- a/code/AssetLib/3MF/3MFXmlTags.h +++ b/code/AssetLib/3MF/3MFXmlTags.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -98,6 +98,11 @@ namespace XmlTag { const char *const texture_cuurd_u = "u"; const char *const texture_cuurd_v = "v"; + // vertex color definitions + const char *const colorgroup = "m:colorgroup"; + const char *const color_item = "m:color"; + const char *const color_vaule = "color"; + // Meta info tags const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; diff --git a/code/AssetLib/3MF/D3MFExporter.cpp b/code/AssetLib/3MF/D3MFExporter.cpp index 4ba3bbf24..64b94e593 100644 --- a/code/AssetLib/3MF/D3MFExporter.cpp +++ b/code/AssetLib/3MF/D3MFExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -249,10 +249,10 @@ void D3MFExporter::writeBaseMaterials() { if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) { hexDiffuseColor = ai_rgba2hex( - (int)((ai_real)color.r) * 255, - (int)((ai_real)color.g) * 255, - (int)((ai_real)color.b) * 255, - (int)((ai_real)color.a) * 255, + (int)(((ai_real)color.r) * 255), + (int)(((ai_real)color.g) * 255), + (int)(((ai_real)color.b) * 255), + (int)(((ai_real)color.a) * 255), true); } else { diff --git a/code/AssetLib/3MF/D3MFExporter.h b/code/AssetLib/3MF/D3MFExporter.h index 680d54f91..7830086d2 100644 --- a/code/AssetLib/3MF/D3MFExporter.h +++ b/code/AssetLib/3MF/D3MFExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index e8529064c..25ba6ef88 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -81,12 +81,17 @@ static constexpr aiImporterDesc desc = { "3mf" }; -bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const { +bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool ) const { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { return false; } - D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); - return opcPackage.validate(); + static constexpr char ModelRef[] = "3D/3dmodel.model"; + ZipArchiveIOSystem archive(pIOHandler, filename); + if (!archive.Exists(ModelRef)) { + return false; + } + + return true; } void D3MFImporter::SetupProperties(const Importer*) { @@ -102,7 +107,7 @@ void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, XmlParser xmlParser; if (xmlParser.parse(opcPackage.RootStream())) { - XmlSerializer xmlSerializer(&xmlParser); + XmlSerializer xmlSerializer(xmlParser); xmlSerializer.ImportXml(pScene); const std::vector &tex = opcPackage.GetEmbeddedTextures(); diff --git a/code/AssetLib/3MF/D3MFImporter.h b/code/AssetLib/3MF/D3MFImporter.h index 9ae68acb0..215b8b870 100644 --- a/code/AssetLib/3MF/D3MFImporter.h +++ b/code/AssetLib/3MF/D3MFImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index e772d8b7e..b54e80e15 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -119,9 +119,9 @@ public: static bool IsEmbeddedTexture( const std::string &filename ) { const std::string extension = BaseImporter::GetExtension(filename); - if (extension == "jpg" || extension == "png") { + if (extension == "jpg" || extension == "png" || extension == "jpeg") { std::string::size_type pos = filename.find("thumbnail"); - if (pos == std::string::npos) { + if (pos != std::string::npos) { return false; } return true; diff --git a/code/AssetLib/3MF/D3MFOpcPackage.h b/code/AssetLib/3MF/D3MFOpcPackage.h index f6803a0ef..05d93ed87 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.h +++ b/code/AssetLib/3MF/D3MFOpcPackage.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/3MF/XmlSerializer.cpp b/code/AssetLib/3MF/XmlSerializer.cpp index 5fcdc0ccc..44293800d 100644 --- a/code/AssetLib/3MF/XmlSerializer.cpp +++ b/code/AssetLib/3MF/XmlSerializer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -57,8 +57,8 @@ static constexpr size_t ColRGBA_Len = 9; static constexpr size_t ColRGB_Len = 7; // format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) -bool validateColorString(const char *color) { - const size_t len = strlen(color); +bool validateColorString(const std::string color) { + const size_t len = color.size(); if (ColRGBA_Len != len && ColRGB_Len != len) { return false; } @@ -75,7 +75,7 @@ aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) { face.mIndices[1] = static_cast(std::atoi(node.attribute(XmlTag::v2).as_string())); face.mIndices[2] = static_cast(std::atoi(node.attribute(XmlTag::v3).as_string())); - texId0 = texId1 = texId2 = -1; + texId0 = texId1 = texId2 = IdNotSet; XmlParser::getIntAttribute(node, XmlTag::p1, texId0); XmlParser::getIntAttribute(node, XmlTag::p2, texId1); XmlParser::getIntAttribute(node, XmlTag::p3, texId2); @@ -157,8 +157,8 @@ aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) { return transformMatrix; } -bool parseColor(const char *color, aiColor4D &diffuse) { - if (nullptr == color) { +bool parseColor(const std::string &color, aiColor4D &diffuse) { + if (color.empty()) { return false; } @@ -178,7 +178,7 @@ bool parseColor(const char *color, aiColor4D &diffuse) { char b[3] = { color[5], color[6], '\0' }; diffuse.b = static_cast(strtol(b, nullptr, 16)) / ai_real(255.0); - const size_t len = strlen(color); + const size_t len = color.size(); if (ColRGB_Len == len) { return true; } @@ -199,11 +199,11 @@ void assignDiffuseColor(XmlNode &node, aiMaterial *mat) { } // namespace -XmlSerializer::XmlSerializer(XmlParser *xmlParser) : +XmlSerializer::XmlSerializer(XmlParser &xmlParser) : mResourcesDictionnary(), mMeshCount(0), mXmlParser(xmlParser) { - ai_assert(nullptr != xmlParser); + // empty } XmlSerializer::~XmlSerializer() { @@ -218,7 +218,7 @@ void XmlSerializer::ImportXml(aiScene *scene) { } scene->mRootNode = new aiNode(XmlTag::RootTag); - XmlNode node = mXmlParser->getRootNode().child(XmlTag::model); + XmlNode node = mXmlParser.getRootNode().child(XmlTag::model); if (node.empty()) { return; } @@ -236,6 +236,8 @@ void XmlSerializer::ImportXml(aiScene *scene) { ReadBaseMaterials(currentNode); } else if (currentNodeName == XmlTag::meta) { ReadMetadata(currentNode); + } else if (currentNodeName == XmlTag::colorgroup) { + ReadColorGroup(currentNode); } } StoreMaterialsInScene(scene); @@ -331,9 +333,49 @@ void XmlSerializer::ReadObject(XmlNode &node) { if (hasPid) { auto it = mResourcesDictionnary.find(pid); - if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) { - BaseMaterials *materials = static_cast(it->second); - mesh->mMaterialIndex = materials->mMaterialIndex[pindex]; + if (hasPindex && it != mResourcesDictionnary.end()) { + if (it->second->getType() == ResourceType::RT_BaseMaterials) { + BaseMaterials *materials = static_cast(it->second); + mesh->mMaterialIndex = materials->mMaterialIndex[pindex]; + } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { + Texture2DGroup *group = static_cast(it->second); + if (mesh->mTextureCoords[0] == nullptr) { + mesh->mNumUVComponents[0] = 2; + for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + mesh->mNumUVComponents[i] = 0; + } + + const std::string name = ai_to_string(group->mTexId); + for (size_t i = 0; i < mMaterials.size(); ++i) { + if (name == mMaterials[i]->GetName().C_Str()) { + mesh->mMaterialIndex = static_cast(i); + } + } + + mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) { + mesh->mTextureCoords[0][vertex_idx] = + aiVector3D(group->mTex2dCoords[pindex].x, group->mTex2dCoords[pindex].y, 0.0f); + } + } else { + for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) { + if (mesh->mTextureCoords[0][vertex_idx].z < 0) { + // use default + mesh->mTextureCoords[0][vertex_idx] = + aiVector3D(group->mTex2dCoords[pindex].x, group->mTex2dCoords[pindex].y, 0.0f); + } + } + } + }else if (it->second->getType() == ResourceType::RT_ColorGroup) { + if (mesh->mColors[0] == nullptr) { + mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; + + ColorGroup *group = static_cast(it->second); + for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) { + mesh->mColors[0][vertex_idx] = group->mColors[pindex]; + } + } + } } } @@ -415,27 +457,36 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { for (XmlNode ¤tNode : node.children()) { const std::string currentName = currentNode.name(); if (currentName == XmlTag::triangle) { - int pid = IdNotSet, p1 = IdNotSet; + int pid = IdNotSet; bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); - bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); - int texId[3]; - Texture2DGroup *group = nullptr; - aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]); - if (hasPid && hasP1) { + int pindex[3]; + aiFace face = ReadTriangle(currentNode, pindex[0], pindex[1], pindex[2]); + if (hasPid && (pindex[0] != IdNotSet || pindex[1] != IdNotSet || pindex[2] != IdNotSet)) { auto it = mResourcesDictionnary.find(pid); if (it != mResourcesDictionnary.end()) { if (it->second->getType() == ResourceType::RT_BaseMaterials) { BaseMaterials *baseMaterials = static_cast(it->second); - mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; + + auto update_material = [&](int idx) { + if (pindex[idx] != IdNotSet) { + mesh->mMaterialIndex = baseMaterials->mMaterialIndex[pindex[idx]]; + } + }; + + update_material(0); + update_material(1); + update_material(2); + } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { + // Load texture coordinates into mesh, when any + Texture2DGroup *group = static_cast(it->second); // fix bug if (mesh->mTextureCoords[0] == nullptr) { mesh->mNumUVComponents[0] = 2; for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { mesh->mNumUVComponents[i] = 0; } - group = static_cast(it->second); const std::string name = ai_to_string(group->mTexId); for (size_t i = 0; i < mMaterials.size(); ++i) { if (name == mMaterials[i]->GetName().C_Str()) { @@ -443,21 +494,44 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { } } mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + for (unsigned int vertex_index = 0; vertex_index < mesh->mNumVertices; vertex_index++) { + mesh->mTextureCoords[0][vertex_index].z = IdNotSet;//mark not set + } } + + auto update_texture = [&](int idx) { + if (pindex[idx] != IdNotSet) { + size_t vertex_index = face.mIndices[idx]; + mesh->mTextureCoords[0][vertex_index] = + aiVector3D(group->mTex2dCoords[pindex[idx]].x, group->mTex2dCoords[pindex[idx]].y, 0.0f); + } + }; + + update_texture(0); + update_texture(1); + update_texture(2); + + } else if (it->second->getType() == ResourceType::RT_ColorGroup) { + // Load vertex color into mesh, when any + ColorGroup *group = static_cast(it->second); + if (mesh->mColors[0] == nullptr) { + mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; + } + + auto update_color = [&](int idx) { + if (pindex[idx] != IdNotSet) { + size_t vertex_index = face.mIndices[idx]; + mesh->mColors[0][vertex_index] = group->mColors[pindex[idx]]; + } + }; + + update_color(0); + update_color(1); + update_color(2); } } } - // Load texture coordinates into mesh, when any - if (group != nullptr) { - size_t i0 = face.mIndices[0]; - size_t i1 = face.mIndices[1]; - size_t i2 = face.mIndices[2]; - mesh->mTextureCoords[0][i0] = aiVector3D(group->mTex2dCoords[texId[0]].x, group->mTex2dCoords[texId[0]].y, 0.0f); - mesh->mTextureCoords[0][i1] = aiVector3D(group->mTex2dCoords[texId[1]].x, group->mTex2dCoords[texId[1]].y, 0.0f); - mesh->mTextureCoords[0][i2] = aiVector3D(group->mTex2dCoords[texId[2]].x, group->mTex2dCoords[texId[2]].y, 0.0f); - } - faces.push_back(face); } } @@ -598,6 +672,38 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater return material; } +void XmlSerializer::ReadColor(XmlNode &node, ColorGroup *colorGroup) { + if (node.empty() || nullptr == colorGroup) { + return; + } + + for (XmlNode currentNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == XmlTag::color_item) { + const char *color = currentNode.attribute(XmlTag::color_vaule).as_string(); + aiColor4D color_value; + if (parseColor(color, color_value)) { + colorGroup->mColors.push_back(color_value); + } + } + } +} + +void XmlSerializer::ReadColorGroup(XmlNode &node) { + if (node.empty()) { + return; + } + + int id = IdNotSet; + if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) { + return; + } + + ColorGroup *group = new ColorGroup(id); + ReadColor(node, group); + mResourcesDictionnary.insert(std::make_pair(id, group)); +} + void XmlSerializer::StoreMaterialsInScene(aiScene *scene) { if (nullptr == scene) { return; diff --git a/code/AssetLib/3MF/XmlSerializer.h b/code/AssetLib/3MF/XmlSerializer.h index 6cf6a70a9..4072a5df5 100644 --- a/code/AssetLib/3MF/XmlSerializer.h +++ b/code/AssetLib/3MF/XmlSerializer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -57,10 +57,11 @@ class D3MFOpcPackage; class Object; class Texture2DGroup; class EmbeddedTexture; +class ColorGroup; -class XmlSerializer { +class XmlSerializer final { public: - XmlSerializer(XmlParser *xmlParser); + XmlSerializer(XmlParser &xmlParser); ~XmlSerializer(); void ImportXml(aiScene *scene); @@ -78,6 +79,8 @@ private: void ReadTextureGroup(XmlNode &node); aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId); void StoreMaterialsInScene(aiScene *scene); + void ReadColorGroup(XmlNode &node); + void ReadColor(XmlNode &node, ColorGroup *colorGroup); private: struct MetaEntry { @@ -89,7 +92,7 @@ private: std::vector mMaterials; std::map mResourcesDictionnary; unsigned int mMeshCount; - XmlParser *mXmlParser; + XmlParser &mXmlParser; }; } // namespace D3MF diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index 1bb77c441..f9ef505c7 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -77,8 +77,8 @@ static constexpr aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // skip to the next token -inline const char *AcSkipToNextToken(const char *buffer) { - if (!SkipSpaces(&buffer)) { +inline const char *AcSkipToNextToken(const char *buffer, const char *end) { + if (!SkipSpaces(&buffer, end)) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); } return buffer; @@ -86,13 +86,13 @@ inline const char *AcSkipToNextToken(const char *buffer) { // ------------------------------------------------------------------------------------------------ // read a string (may be enclosed in double quotation marks). buffer must point to " -inline const char *AcGetString(const char *buffer, std::string &out) { +inline const char *AcGetString(const char *buffer, const char *end, std::string &out) { if (*buffer == '\0') { throw DeadlyImportError("AC3D: Unexpected EOF in string"); } ++buffer; const char *sz = buffer; - while ('\"' != *buffer) { + while ('\"' != *buffer && buffer != end) { if (IsLineEnd(*buffer)) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); out = "ERROR"; @@ -112,8 +112,8 @@ inline const char *AcGetString(const char *buffer, std::string &out) { // ------------------------------------------------------------------------------------------------ // read 1 to n floats prefixed with an optional predefined identifier template -inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) { - buffer = AcSkipToNextToken(buffer); +inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end, const char *name, size_t name_length, size_t num, T *out) { + buffer = AcSkipToNextToken(buffer, end); if (0 != name_length) { if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected."); @@ -122,7 +122,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name buffer += name_length + 1; } for (unsigned int _i = 0; _i < num; ++_i) { - buffer = AcSkipToNextToken(buffer); + buffer = AcSkipToNextToken(buffer, end); buffer = fast_atoreal_move(buffer, ((float *)out)[_i]); } @@ -132,7 +132,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer AC3DImporter::AC3DImporter() : - buffer(), + mBuffer(), configSplitBFCull(), configEvalSubdivision(), mNumMeshes(), @@ -144,14 +144,10 @@ AC3DImporter::AC3DImporter() : // nothing to be done here } -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -AC3DImporter::~AC3DImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { - static const uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") }; + static constexpr uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") }; return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } @@ -164,17 +160,18 @@ const aiImporterDesc *AC3DImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ // Get a pointer to the next line from the file bool AC3DImporter::GetNextLine() { - SkipLine(&buffer); - return SkipSpaces(&buffer); + SkipLine(&mBuffer.data, mBuffer.end); + return SkipSpaces(&mBuffer.data, mBuffer.end); } // ------------------------------------------------------------------------------------------------ // Parse an object section in an AC file -void AC3DImporter::LoadObjectSection(std::vector &objects) { - if (!TokenMatch(buffer, "OBJECT", 6)) - return; +bool AC3DImporter::LoadObjectSection(std::vector &objects) { + if (!TokenMatch(mBuffer.data, "OBJECT", 6)) { + return false; + } - SkipSpaces(&buffer); + SkipSpaces(&mBuffer.data, mBuffer.end); ++mNumMeshes; @@ -182,7 +179,7 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { Object &obj = objects.back(); aiLight *light = nullptr; - if (!ASSIMP_strincmp(buffer, "light", 5)) { + if (!ASSIMP_strincmp(mBuffer.data, "light", 5)) { // This is a light source. Add it to the list mLights->push_back(light = new aiLight()); @@ -192,68 +189,73 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { light->mAttenuationConstant = 1.f; // Generate a default name for both the light source and the node - // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. - light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast(mLights->size()) - 1); + light->mName.length = ::ai_snprintf(light->mName.data, AI_MAXLEN, "ACLight_%i", static_cast(mLights->size()) - 1); obj.name = std::string(light->mName.data); ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered"); obj.type = Object::Light; - } else if (!ASSIMP_strincmp(buffer, "group", 5)) { + } else if (!ASSIMP_strincmp(mBuffer.data, "group", 5)) { obj.type = Object::Group; - } else if (!ASSIMP_strincmp(buffer, "world", 5)) { + } else if (!ASSIMP_strincmp(mBuffer.data, "world", 5)) { obj.type = Object::World; - } else + } else { obj.type = Object::Poly; + } + while (GetNextLine()) { - if (TokenMatch(buffer, "kids", 4)) { - SkipSpaces(&buffer); - unsigned int num = strtoul10(buffer, &buffer); + if (TokenMatch(mBuffer.data, "kids", 4)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + unsigned int num = strtoul10(mBuffer.data, &mBuffer.data); GetNextLine(); if (num) { // load the children of this object recursively obj.children.reserve(num); - for (unsigned int i = 0; i < num; ++i) - LoadObjectSection(obj.children); + for (unsigned int i = 0; i < num; ++i) { + if (!LoadObjectSection(obj.children)) { + ASSIMP_LOG_WARN("AC3D: wrong number of kids"); + break; + } + } } - return; - } else if (TokenMatch(buffer, "name", 4)) { - SkipSpaces(&buffer); - buffer = AcGetString(buffer, obj.name); + return true; + } else if (TokenMatch(mBuffer.data, "name", 4)) { + SkipSpaces(&mBuffer.data, mBuffer.data); + mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, obj.name); // If this is a light source, we'll also need to store // the name of the node in it. if (light) { light->mName.Set(obj.name); } - } else if (TokenMatch(buffer, "texture", 7)) { - SkipSpaces(&buffer); + } else if (TokenMatch(mBuffer.data, "texture", 7)) { + SkipSpaces(&mBuffer.data, mBuffer.end); std::string texture; - buffer = AcGetString(buffer, texture); + mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, texture); obj.textures.push_back(texture); - } else if (TokenMatch(buffer, "texrep", 6)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat); + } else if (TokenMatch(mBuffer.data, "texrep", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texRepeat); if (!obj.texRepeat.x || !obj.texRepeat.y) obj.texRepeat = aiVector2D(1.f, 1.f); - } else if (TokenMatch(buffer, "texoff", 6)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texOffset); - } else if (TokenMatch(buffer, "rot", 3)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 9, &obj.rotation); - } else if (TokenMatch(buffer, "loc", 3)) { - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &obj.translation); - } else if (TokenMatch(buffer, "subdiv", 6)) { - SkipSpaces(&buffer); - obj.subDiv = strtoul10(buffer, &buffer); - } else if (TokenMatch(buffer, "crease", 6)) { - SkipSpaces(&buffer); - obj.crease = fast_atof(buffer); - } else if (TokenMatch(buffer, "numvert", 7)) { - SkipSpaces(&buffer); + } else if (TokenMatch(mBuffer.data, "texoff", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texOffset); + } else if (TokenMatch(mBuffer.data, "rot", 3)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 9, &obj.rotation); + } else if (TokenMatch(mBuffer.data, "loc", 3)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &obj.translation); + } else if (TokenMatch(mBuffer.data, "subdiv", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + obj.subDiv = strtoul10(mBuffer.data, &mBuffer.data); + } else if (TokenMatch(mBuffer.data, "crease", 6)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + obj.crease = fast_atof(mBuffer.data); + } else if (TokenMatch(mBuffer.data, "numvert", 7)) { + SkipSpaces(&mBuffer.data, mBuffer.end); - unsigned int t = strtoul10(buffer, &buffer); + unsigned int t = strtoul10(mBuffer.data, &mBuffer.data); if (t >= AI_MAX_ALLOC(aiVector3D)) { throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); } @@ -262,59 +264,59 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { if (!GetNextLine()) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet"); break; - } else if (!IsNumeric(*buffer)) { + } else if (!IsNumeric(*mBuffer.data)) { ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet"); - --buffer; // make sure the line is processed a second time + --mBuffer.data; // make sure the line is processed a second time break; } obj.vertices.emplace_back(); aiVector3D &v = obj.vertices.back(); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &v.x); } - } else if (TokenMatch(buffer, "numsurf", 7)) { - SkipSpaces(&buffer); + } else if (TokenMatch(mBuffer.data, "numsurf", 7)) { + SkipSpaces(&mBuffer.data, mBuffer.end); bool Q3DWorkAround = false; - const unsigned int t = strtoul10(buffer, &buffer); + const unsigned int t = strtoul10(mBuffer.data, &mBuffer.data); obj.surfaces.reserve(t); for (unsigned int i = 0; i < t; ++i) { GetNextLine(); - if (!TokenMatch(buffer, "SURF", 4)) { + if (!TokenMatch(mBuffer.data, "SURF", 4)) { // FIX: this can occur for some files - Quick 3D for // example writes no surf chunks if (!Q3DWorkAround) { ASSIMP_LOG_WARN("AC3D: SURF token was expected"); ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled"); } - --buffer; // make sure the line is processed a second time + --mBuffer.data; // make sure the line is processed a second time // break; --- see fix notes above Q3DWorkAround = true; } - SkipSpaces(&buffer); + SkipSpaces(&mBuffer.data, mBuffer.end); obj.surfaces.emplace_back(); Surface &surf = obj.surfaces.back(); - surf.flags = strtoul_cppstyle(buffer); + surf.flags = strtoul_cppstyle(mBuffer.data); while (true) { if (!GetNextLine()) { throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete"); } - if (TokenMatch(buffer, "mat", 3)) { - SkipSpaces(&buffer); - surf.mat = strtoul10(buffer); - } else if (TokenMatch(buffer, "refs", 4)) { + if (TokenMatch(mBuffer.data, "mat", 3)) { + SkipSpaces(&mBuffer.data, mBuffer.end); + surf.mat = strtoul10(mBuffer.data); + } else if (TokenMatch(mBuffer.data, "refs", 4)) { // --- see fix notes above if (Q3DWorkAround) { if (!surf.entries.empty()) { - buffer -= 6; + mBuffer.data -= 6; break; } } - SkipSpaces(&buffer); - const unsigned int m = strtoul10(buffer); + SkipSpaces(&mBuffer.data, mBuffer.end); + const unsigned int m = strtoul10(mBuffer.data); surf.entries.reserve(m); obj.numRefs += m; @@ -327,12 +329,12 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { surf.entries.emplace_back(); Surface::SurfaceEntry &entry = surf.entries.back(); - entry.first = strtoul10(buffer, &buffer); - SkipSpaces(&buffer); - buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second); + entry.first = strtoul10(mBuffer.data, &mBuffer.data); + SkipSpaces(&mBuffer.data, mBuffer.end); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &entry.second); } } else { - --buffer; // make sure the line is processed a second time + --mBuffer.data; // make sure the line is processed a second time break; } } @@ -340,6 +342,8 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { } } ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected"); + + return false; } // ------------------------------------------------------------------------------------------------ @@ -445,7 +449,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, idx = 0; } if ((*it).entries.empty()) { - ASSIMP_LOG_WARN("AC3D: surface her zero vertex references"); + ASSIMP_LOG_WARN("AC3D: surface has zero vertex references"); } // validate all vertex indices to make sure we won't crash here @@ -463,16 +467,15 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, } switch ((*it).GetType()) { - // closed line - case Surface::ClosedLine: - needMat[idx].first += (unsigned int)(*it).entries.size(); - needMat[idx].second += (unsigned int)(*it).entries.size() << 1u; + case Surface::ClosedLine: // closed line + needMat[idx].first += static_cast((*it).entries.size()); + needMat[idx].second += static_cast((*it).entries.size() << 1u); break; // unclosed line case Surface::OpenLine: - needMat[idx].first += (unsigned int)(*it).entries.size() - 1; - needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u; + needMat[idx].first += static_cast((*it).entries.size() - 1); + needMat[idx].second += static_cast(((*it).entries.size() - 1) << 1u); break; // triangle strip @@ -574,15 +577,6 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, const Surface::SurfaceEntry &entry2 = src.entries[i + 1]; const Surface::SurfaceEntry &entry3 = src.entries[i + 2]; - // skip degenerate triangles - if (object.vertices[entry1.first] == object.vertices[entry2.first] || - object.vertices[entry1.first] == object.vertices[entry3.first] || - object.vertices[entry2.first] == object.vertices[entry3.first]) { - mesh->mNumFaces--; - mesh->mNumVertices -= 3; - continue; - } - aiFace &face = *faces++; face.mNumIndices = 3; face.mIndices = new unsigned int[face.mNumIndices]; @@ -701,18 +695,18 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, // generate a name depending on the type of the node switch (object.type) { case Object::Group: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACGroup_%i", mGroupsCounter++); break; case Object::Poly: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACPoly_%i", mPolysCounter++); break; case Object::Light: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACLight_%i", mLightsCounter++); break; // there shouldn't be more than one world, but we don't care case Object::World: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++); + node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACWorld_%i", mWorldsCounter++); break; } } @@ -760,17 +754,18 @@ void AC3DImporter::InternReadFile(const std::string &pFile, std::vector mBuffer2; TextFileToBuffer(file.get(), mBuffer2); - buffer = &mBuffer2[0]; + mBuffer.data = &mBuffer2[0]; + mBuffer.end = &mBuffer2[0] + mBuffer2.size(); mNumMeshes = 0; mLightsCounter = mPolysCounter = mWorldsCounter = mGroupsCounter = 0; - if (::strncmp(buffer, "AC3D", 4)) { + if (::strncmp(mBuffer.data, "AC3D", 4)) { throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found"); } // print the file format version to the console - unsigned int version = HexDigitToDecimal(buffer[4]); + unsigned int version = HexDigitToDecimal(mBuffer.data[4]); char msg[3]; ASSIMP_itoa10(msg, 3, version); ASSIMP_LOG_INFO("AC3D file format version: ", msg); @@ -785,30 +780,31 @@ void AC3DImporter::InternReadFile(const std::string &pFile, mLights = &lights; while (GetNextLine()) { - if (TokenMatch(buffer, "MATERIAL", 8)) { + if (TokenMatch(mBuffer.data, "MATERIAL", 8)) { materials.emplace_back(); Material &mat = materials.back(); // manually parse the material ... sscanf would use the buldin atof ... // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f - buffer = AcSkipToNextToken(buffer); - if ('\"' == *buffer) { - buffer = AcGetString(buffer, mat.name); - buffer = AcSkipToNextToken(buffer); + mBuffer.data = AcSkipToNextToken(mBuffer.data, mBuffer.end); + if ('\"' == *mBuffer.data) { + mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, mat.name); + mBuffer.data = AcSkipToNextToken(mBuffer.data, mBuffer.end); } - buffer = TAcCheckedLoadFloatArray(buffer, "rgb", 3, 3, &mat.rgb); - buffer = TAcCheckedLoadFloatArray(buffer, "amb", 3, 3, &mat.amb); - buffer = TAcCheckedLoadFloatArray(buffer, "emis", 4, 3, &mat.emis); - buffer = TAcCheckedLoadFloatArray(buffer, "spec", 4, 3, &mat.spec); - buffer = TAcCheckedLoadFloatArray(buffer, "shi", 3, 1, &mat.shin); - buffer = TAcCheckedLoadFloatArray(buffer, "trans", 5, 1, &mat.trans); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "rgb", 3, 3, &mat.rgb); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "amb", 3, 3, &mat.amb); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "emis", 4, 3, &mat.emis); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "spec", 4, 3, &mat.spec); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "shi", 3, 1, &mat.shin); + mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "trans", 5, 1, &mat.trans); + } else { + LoadObjectSection(rootObjects); } - LoadObjectSection(rootObjects); } - if (rootObjects.empty() || !mNumMeshes) { + if (rootObjects.empty() || mNumMeshes == 0u) { throw DeadlyImportError("AC3D: No meshes have been loaded"); } if (materials.empty()) { @@ -824,7 +820,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, materials.reserve(mNumMeshes); // generate a dummy root if there are multiple objects on the top layer - Object *root; + Object *root = nullptr; if (1 == rootObjects.size()) root = &rootObjects[0]; else { @@ -837,7 +833,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, delete root; } - if (!::strncmp(pScene->mRootNode->mName.data, "Node", 4)) { + if (::strncmp(pScene->mRootNode->mName.data, "Node", 4) == 0) { pScene->mRootNode->mName.Set(""); } @@ -856,7 +852,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, // copy lights pScene->mNumLights = (unsigned int)lights.size(); - if (lights.size()) { + if (!lights.empty()) { pScene->mLights = new aiLight *[lights.size()]; ::memcpy(pScene->mLights, &lights[0], lights.size() * sizeof(void *)); } diff --git a/code/AssetLib/AC/ACLoader.h b/code/AssetLib/AC/ACLoader.h index 7f8dfd03c..ed9ca0274 100644 --- a/code/AssetLib/AC/ACLoader.h +++ b/code/AssetLib/AC/ACLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -63,7 +63,7 @@ namespace Assimp { class AC3DImporter : public BaseImporter { public: AC3DImporter(); - ~AC3DImporter() override; + ~AC3DImporter() override = default; // Represents an AC3D material struct Material { @@ -103,7 +103,7 @@ public: unsigned int mat, flags; - typedef std::pair SurfaceEntry; + using SurfaceEntry = std::pair; std::vector entries; // Type is low nibble of flags @@ -216,7 +216,7 @@ private: * load subobjects, the method returns after a 'kids 0' was * encountered. * @objects List of output objects*/ - void LoadObjectSection(std::vector &objects); + bool LoadObjectSection(std::vector &objects); // ------------------------------------------------------------------- /** Convert all objects into meshes and nodes. @@ -242,7 +242,7 @@ private: private: // points to the next data line - const char *buffer; + aiBuffer mBuffer; // Configuration option: if enabled, up to two meshes // are generated per material: those faces who have diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index eabdb35e1..9417e9142 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -178,28 +178,6 @@ bool AMFImporter::XML_SearchNode(const std::string &nodeName) { return nullptr != mXmlParser->findNode(nodeName); } -void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) { - size_t instr_len; - - pOutString.clear(); - instr_len = strlen(pInStr); - if (!instr_len) return; - - pOutString.reserve(instr_len * 3 / 2); - // check and correct floats in format ".x". Must be "x.y". - if (pInStr[0] == '.') pOutString.push_back('0'); - - pOutString.push_back(pInStr[0]); - for (size_t ci = 1; ci < instr_len; ci++) { - if ((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) { - pOutString.push_back('0'); - pOutString.push_back('.'); - } else { - pOutString.push_back(pInStr[ci]); - } - } -} - static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/')); } @@ -213,7 +191,10 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std uint8_t arr4[4], arr3[3]; // check input data - if (pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four."); + if (pInputBase64.size() % 4) { + throw DeadlyImportError("Base64-encoded data must have size multiply of four."); + } + // prepare output place pOutputData.clear(); pOutputData.reserve(pInputBase64.size() / 4 * 3); @@ -403,17 +384,17 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) { for (auto ¤tNode : node.children()) { const std::string ¤tName = currentNode.name(); if (currentName == "deltax") { - XmlParser::getValueAsFloat(currentNode, als.Delta.x); + XmlParser::getValueAsReal(currentNode, als.Delta.x); } else if (currentName == "deltay") { - XmlParser::getValueAsFloat(currentNode, als.Delta.y); + XmlParser::getValueAsReal(currentNode, als.Delta.y); } else if (currentName == "deltaz") { - XmlParser::getValueAsFloat(currentNode, als.Delta.z); + XmlParser::getValueAsReal(currentNode, als.Delta.z); } else if (currentName == "rx") { - XmlParser::getValueAsFloat(currentNode, als.Delta.x); + XmlParser::getValueAsReal(currentNode, als.Delta.x); } else if (currentName == "ry") { - XmlParser::getValueAsFloat(currentNode, als.Delta.y); + XmlParser::getValueAsReal(currentNode, als.Delta.y); } else if (currentName == "rz") { - XmlParser::getValueAsFloat(currentNode, als.Delta.z); + XmlParser::getValueAsReal(currentNode, als.Delta.z); } } ParseHelper_Node_Exit(); @@ -493,7 +474,7 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) { // read attribute ne = new AMFMetadata(mNodeElement_Cur); - ((AMFMetadata *)ne)->Type = type; + ((AMFMetadata *)ne)->MetaType = type; ((AMFMetadata *)ne)->Value = value; mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. diff --git a/code/AssetLib/AMF/AMFImporter.hpp b/code/AssetLib/AMF/AMFImporter.hpp index fbaf4fc6d..a80114f68 100644 --- a/code/AssetLib/AMF/AMFImporter.hpp +++ b/code/AssetLib/AMF/AMFImporter.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -168,7 +168,6 @@ public: AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX; void XML_CheckNode_MustHaveChildren(pugi::xml_node &node); bool XML_SearchNode(const std::string &nodeName); - void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString); AMFImporter(const AMFImporter &pScene) = delete; AMFImporter &operator=(const AMFImporter &pScene) = delete; diff --git a/code/AssetLib/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp index 341999f56..1df03231b 100644 --- a/code/AssetLib/AMF/AMFImporter_Geometry.cpp +++ b/code/AssetLib/AMF/AMFImporter_Geometry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -167,11 +167,11 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) { AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience const std::string ¤tName = ai_tolower(currentNode.name()); if (currentName == "x") { - XmlParser::getValueAsFloat(currentNode, als.Coordinate.x); + XmlParser::getValueAsReal(currentNode, als.Coordinate.x); } else if (currentName == "y") { - XmlParser::getValueAsFloat(currentNode, als.Coordinate.y); + XmlParser::getValueAsReal(currentNode, als.Coordinate.y); } else if (currentName == "z") { - XmlParser::getValueAsFloat(currentNode, als.Coordinate.z); + XmlParser::getValueAsReal(currentNode, als.Coordinate.z); } } ParseHelper_Node_Exit(); @@ -202,7 +202,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) { ((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string(); - ((AMFVolume *)ne)->Type = type; + ((AMFVolume *)ne)->VolumeType = type; // Check for child nodes bool col_read = false; if (!node.empty()) { diff --git a/code/AssetLib/AMF/AMFImporter_Material.cpp b/code/AssetLib/AMF/AMFImporter_Material.cpp index 676e74856..e48780e29 100644 --- a/code/AssetLib/AMF/AMFImporter_Material.cpp +++ b/code/AssetLib/AMF/AMFImporter_Material.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -263,26 +263,25 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) { const std::string &name = currentNode.name(); if (name == "utex1") { read_flag[0] = true; - XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x); + XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[0].x); } else if (name == "utex2") { read_flag[1] = true; - XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x); + XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[1].x); } else if (name == "utex3") { read_flag[2] = true; - XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x); + XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[2].x); } else if (name == "vtex1") { read_flag[3] = true; - XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y); + XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[0].y); } else if (name == "vtex2") { read_flag[4] = true; - XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y); + XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[1].y); } else if (name == "vtex3") { read_flag[5] = true; - XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y); + XmlParser::getValueAsReal(currentNode, als.TextureCoordinate[2].y); } } ParseHelper_Node_Exit(); - } else { for (pugi::xml_attribute &attr : node.attributes()) { const std::string name = attr.name(); diff --git a/code/AssetLib/AMF/AMFImporter_Node.hpp b/code/AssetLib/AMF/AMFImporter_Node.hpp index dd27316d3..8fb2abf6a 100644 --- a/code/AssetLib/AMF/AMFImporter_Node.hpp +++ b/code/AssetLib/AMF/AMFImporter_Node.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -56,7 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -/// \class CAMFImporter_NodeElement /// Base class for elements of nodes. class AMFNodeElementBase { public: @@ -87,7 +86,8 @@ public: AMFNodeElementBase *Parent; ///< Parent element. If nullptr then this node is root. std::list Child; ///< Child elements. -public: /// Destructor, virtual.. +public: + /// Destructor, virtual.. virtual ~AMFNodeElementBase() = default; /// Disabled copy constructor and co. @@ -98,15 +98,14 @@ public: /// Destructor, virtual.. protected: /// In constructor inheritor must set element type. - /// \param [in] pType - element type. + /// \param [in] type - element type. /// \param [in] pParent - parent element. - AMFNodeElementBase(const EType pType, AMFNodeElementBase *pParent) : - Type(pType), Parent(pParent) { + AMFNodeElementBase(EType type, AMFNodeElementBase *pParent) : + Type(type), Parent(pParent) { // empty } }; // class IAMFImporter_NodeElement -/// \struct CAMFImporter_NodeElement_Constellation /// A collection of objects or constellations with specific relative locations. struct AMFConstellation : public AMFNodeElementBase { /// Constructor. @@ -116,7 +115,6 @@ struct AMFConstellation : public AMFNodeElementBase { }; // struct CAMFImporter_NodeElement_Constellation -/// \struct CAMFImporter_NodeElement_Instance /// Part of constellation. struct AMFInstance : public AMFNodeElementBase { @@ -135,12 +133,11 @@ struct AMFInstance : public AMFNodeElementBase { AMFNodeElementBase(ENET_Instance, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Metadata /// Structure that define metadata node. struct AMFMetadata : public AMFNodeElementBase { - std::string Type; ///< Type of "Value". - std::string Value; ///< Value. + std::string MetaType; ///< Type of "Value". + std::string Value; ///< Value. /// Constructor. /// \param [in] pParent - pointer to parent node. @@ -148,7 +145,6 @@ struct AMFMetadata : public AMFNodeElementBase { AMFNodeElementBase(ENET_Metadata, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Root /// Structure that define root node. struct AMFRoot : public AMFNodeElementBase { @@ -161,7 +157,6 @@ struct AMFRoot : public AMFNodeElementBase { AMFNodeElementBase(ENET_Root, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Color /// Structure that define object node. struct AMFColor : public AMFNodeElementBase { bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color. @@ -177,7 +172,6 @@ struct AMFColor : public AMFNodeElementBase { } }; -/// \struct CAMFImporter_NodeElement_Material /// Structure that define material node. struct AMFMaterial : public AMFNodeElementBase { @@ -187,7 +181,6 @@ struct AMFMaterial : public AMFNodeElementBase { AMFNodeElementBase(ENET_Material, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Object /// Structure that define object node. struct AMFObject : public AMFNodeElementBase { @@ -206,7 +199,6 @@ struct AMFMesh : public AMFNodeElementBase { AMFNodeElementBase(ENET_Mesh, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Vertex /// Structure that define vertex node. struct AMFVertex : public AMFNodeElementBase { /// Constructor. @@ -215,7 +207,6 @@ struct AMFVertex : public AMFNodeElementBase { AMFNodeElementBase(ENET_Vertex, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Edge /// Structure that define edge node. struct AMFEdge : public AMFNodeElementBase { /// Constructor. @@ -224,7 +215,6 @@ struct AMFEdge : public AMFNodeElementBase { AMFNodeElementBase(ENET_Edge, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Vertices /// Structure that define vertices node. struct AMFVertices : public AMFNodeElementBase { /// Constructor. @@ -233,11 +223,10 @@ struct AMFVertices : public AMFNodeElementBase { AMFNodeElementBase(ENET_Vertices, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Volume /// Structure that define volume node. struct AMFVolume : public AMFNodeElementBase { 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. + std::string VolumeType; ///< What this volume describes can be "region" or "support". If none specified, "object" is assumed. /// Constructor. /// \param [in] pParent - pointer to parent node. @@ -245,7 +234,6 @@ struct AMFVolume : public AMFNodeElementBase { AMFNodeElementBase(ENET_Volume, pParent) {} }; -/// \struct CAMFImporter_NodeElement_Coordinates /// Structure that define coordinates node. struct AMFCoordinates : public AMFNodeElementBase { aiVector3D Coordinate; ///< Coordinate. @@ -256,7 +244,6 @@ struct AMFCoordinates : public AMFNodeElementBase { AMFNodeElementBase(ENET_Coordinates, pParent) {} }; -/// \struct CAMFImporter_NodeElement_TexMap /// Structure that define texture coordinates node. struct AMFTexMap : public AMFNodeElementBase { aiVector3D TextureCoordinate[3]; ///< Texture coordinates. @@ -273,7 +260,6 @@ struct AMFTexMap : public AMFNodeElementBase { } }; -/// \struct CAMFImporter_NodeElement_Triangle /// Structure that define triangle node. struct AMFTriangle : public AMFNodeElementBase { size_t V[3]; ///< Triangle vertices. diff --git a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp index d5160870a..f7a4b0892 100644 --- a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp +++ b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp @@ -1,9 +1,9 @@ -/* +/* --------------------------------------------------------------------------- Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -224,7 +224,8 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string & } // Create format hint. - strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string. + constexpr char templateColor[] = "rgba0000"; + memcpy(converted_texture.FormatHint, templateColor, 8); if (!r.empty()) converted_texture.FormatHint[4] = '8'; if (!g.empty()) converted_texture.FormatHint[5] = '8'; if (!b.empty()) converted_texture.FormatHint[6] = '8'; @@ -332,7 +333,7 @@ void AMFImporter::Postprocess_AddMetadata(const AMFMetaDataArray &metadataList, size_t meta_idx(0); for (const AMFMetadata *metadata : metadataList) { - sceneNode.mMetaData->Set(static_cast(meta_idx++), metadata->Type, aiString(metadata->Value)); + sceneNode.mMetaData->Set(static_cast(meta_idx++), metadata->MetaType, aiString(metadata->Value)); } } @@ -867,7 +868,7 @@ nl_clean_loop: pScene->mTextures[idx]->mHeight = static_cast(tex_convd.Height); pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data; // texture format description. - strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint); + strncpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint, HINTMAXTEXTURELEN); idx++; } // for(const SPP_Texture& tex_convd: mTexture_Converted) diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index f98316661..c63edcf6b 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -124,7 +124,7 @@ void ASEImporter::InternReadFile(const std::string &pFile, // Allocate storage and copy the contents of the file to a memory buffer std::vector mBuffer2; TextFileToBuffer(file.get(), mBuffer2); - + const size_t fileSize = mBuffer2.size(); this->mBuffer = &mBuffer2[0]; this->pcScene = pScene; @@ -146,7 +146,7 @@ void ASEImporter::InternReadFile(const std::string &pFile, }; // Construct an ASE parser and parse the file - ASE::Parser parser(mBuffer, defaultFormat); + ASE::Parser parser(mBuffer, fileSize, defaultFormat); mParser = &parser; mParser->Parse(); @@ -446,10 +446,9 @@ void ASEImporter::BuildLights() { } // ------------------------------------------------------------------------------------------------ -void ASEImporter::AddNodes(const std::vector &nodes, - aiNode *pcParent, const char *szName) { +void ASEImporter::AddNodes(const std::vector &nodes, aiNode *pcParent, const std::string &name) { aiMatrix4x4 m; - AddNodes(nodes, pcParent, szName, m); + AddNodes(nodes, pcParent, name, m); } // ------------------------------------------------------------------------------------------------ @@ -506,10 +505,9 @@ void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) { // ------------------------------------------------------------------------------------------------ // Add child nodes to a given parent node -void ASEImporter::AddNodes(const std::vector &nodes, - aiNode *pcParent, const char *szName, +void ASEImporter::AddNodes(const std::vector &nodes, aiNode *pcParent, const std::string &name, const aiMatrix4x4 &mat) { - const size_t len = szName ? ::strlen(szName) : 0; + const size_t len = name.size(); ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS); // Receives child nodes for the pcParent node @@ -519,16 +517,18 @@ void ASEImporter::AddNodes(const std::vector &nodes, // which has *us* as parent. for (std::vector::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { const BaseNode *snode = *it; - if (szName) { - if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str())) + if (!name.empty()) { + if (len != snode->mParent.length() || name != snode->mParent.c_str()) { continue; - } else if (snode->mParent.length()) + } + } else if (snode->mParent.length()) { continue; + } (*it)->mProcessed = true; // Allocate a new node and add it to the output data structure - apcNodes.push_back(new aiNode()); + apcNodes.push_back(new aiNode); aiNode *node = apcNodes.back(); node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node")); @@ -541,7 +541,7 @@ void ASEImporter::AddNodes(const std::vector &nodes, // Add sub nodes - prevent stack overflow due to recursive parenting if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) { - AddNodes(nodes, node, node->mName.data, snode->mTransform); + AddNodes(nodes, node, node->mName.C_Str(), snode->mTransform); } // Further processing depends on the type of the node @@ -619,7 +619,8 @@ void ASEImporter::BuildNodes(std::vector &nodes) { } // add all nodes - AddNodes(nodes, ch, nullptr); + static const std::string none = ""; + AddNodes(nodes, ch, none); // now iterate through al nodes and find those that have not yet // been added to the nodegraph (= their parent could not be recognized) @@ -730,6 +731,10 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh &mesh) { unsigned int iCurrent = 0, fi = 0; for (std::vector::iterator i = mesh.mFaces.begin(); i != mesh.mFaces.end(); ++i, ++fi) { for (unsigned int n = 0; n < 3; ++n, ++iCurrent) { + const uint32_t curIndex = (*i).mIndices[n]; + if (curIndex >= mesh.mPositions.size()) { + throw DeadlyImportError("ASE: Invalid vertex index in face ", fi, "."); + } mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]]; // add texture coordinates diff --git a/code/AssetLib/ASE/ASELoader.h b/code/AssetLib/ASE/ASELoader.h index 2509671ef..05710718a 100644 --- a/code/AssetLib/ASE/ASELoader.h +++ b/code/AssetLib/ASE/ASELoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -153,13 +153,13 @@ private: * \param matrix Current transform */ void AddNodes(const std::vector& nodes, - aiNode* pcParent,const char* szName); + aiNode* pcParent, const std::string &name); void AddNodes(const std::vector& nodes, - aiNode* pcParent,const char* szName, + aiNode* pcParent, const std::string &name, const aiMatrix4x4& matrix); - void AddMeshes(const ASE::BaseNode* snode,aiNode* node); + void AddMeshes(const ASE::BaseNode* snode, aiNode* node); // ------------------------------------------------------------------- /** Generate a default material and add it to the parser's list @@ -188,5 +188,4 @@ protected: } // end of namespace Assimp - #endif // AI_3DSIMPORTER_H_INC diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index 90f462598..1f7c3c938 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -66,23 +66,24 @@ using namespace Assimp::ASE; // Handle a "top-level" section in the file. EOF is no error in this case. #define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \ - else if ('{' == *filePtr) iDepth++; \ - else if ('}' == *filePtr) { \ + else if ('{' == *mFilePtr) \ + ++iDepth; \ + else if ('}' == *mFilePtr) { \ if (0 == --iDepth) { \ - ++filePtr; \ + ++mFilePtr; \ SkipToNextToken(); \ return; \ } \ } \ - if ('\0' == *filePtr) { \ + if ('\0' == *mFilePtr) { \ return; \ } \ - if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \ + if (IsLineEnd(*mFilePtr) && !bLastWasEndLine) {\ ++iLineNumber; \ bLastWasEndLine = true; \ } else \ bLastWasEndLine = false; \ - ++filePtr; + ++mFilePtr; // ------------------------------------------------------------------------------------------------ // Handle a nested section in the file. EOF is an error in this case @@ -90,30 +91,32 @@ using namespace Assimp::ASE; // @param msg Full name of the section (including the asterisk) #define AI_ASE_HANDLE_SECTION(level, msg) \ - if ('{' == *filePtr) \ + if ('{' == *mFilePtr) \ iDepth++; \ - else if ('}' == *filePtr) { \ + else if ('}' == *mFilePtr) { \ if (0 == --iDepth) { \ - ++filePtr; \ + ++mFilePtr; \ SkipToNextToken(); \ return; \ } \ - } else if ('\0' == *filePtr) { \ + } else if ('\0' == *mFilePtr) { \ LogError("Encountered unexpected EOL while parsing a " msg \ " chunk (Level " level ")"); \ } \ - if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \ + if (IsLineEnd(*mFilePtr) && !bLastWasEndLine) { \ ++iLineNumber; \ bLastWasEndLine = true; \ } else \ bLastWasEndLine = false; \ - ++filePtr; + ++mFilePtr; // ------------------------------------------------------------------------------------------------ -Parser::Parser(const char *szFile, unsigned int fileFormatDefault) { - ai_assert(nullptr != szFile); +Parser::Parser(const char *file, size_t fileLen, unsigned int fileFormatDefault) : + mFilePtr(nullptr), mEnd (nullptr) { + ai_assert(file != nullptr); - filePtr = szFile; + mFilePtr = file; + mEnd = mFilePtr + fileLen; iFileFormat = fileFormatDefault; // make sure that the color values are invalid @@ -177,7 +180,11 @@ AI_WONT_RETURN void Parser::LogError(const char *szWarn) { // ------------------------------------------------------------------------------------------------ bool Parser::SkipToNextToken() { while (true) { - char me = *filePtr; + char me = *mFilePtr; + + if (mFilePtr == mEnd) { + return false; + } // increase the line number counter if necessary if (IsLineEnd(me) && !bLastWasEndLine) { @@ -185,10 +192,14 @@ bool Parser::SkipToNextToken() { bLastWasEndLine = true; } else bLastWasEndLine = false; - if ('*' == me || '}' == me || '{' == me) return true; - if ('\0' == me) return false; + if ('*' == me || '}' == me || '{' == me) { + return true; + } + if ('\0' == me) { + return false; + } - ++filePtr; + ++mFilePtr; } } @@ -197,22 +208,22 @@ bool Parser::SkipSection() { // must handle subsections ... int iCnt = 0; while (true) { - if ('}' == *filePtr) { + if ('}' == *mFilePtr) { --iCnt; if (0 == iCnt) { // go to the next valid token ... - ++filePtr; + ++mFilePtr; SkipToNextToken(); return true; } - } else if ('{' == *filePtr) { + } else if ('{' == *mFilePtr) { ++iCnt; - } else if ('\0' == *filePtr) { + } else if ('\0' == *mFilePtr) { LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]"); return false; - } else if (IsLineEnd(*filePtr)) + } else if (IsLineEnd(*mFilePtr)) ++iLineNumber; - ++filePtr; + ++mFilePtr; } } @@ -220,11 +231,11 @@ bool Parser::SkipSection() { void Parser::Parse() { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Version should be 200. Validate this ... - if (TokenMatch(filePtr, "3DSMAX_ASCIIEXPORT", 18)) { + if (TokenMatch(mFilePtr, "3DSMAX_ASCIIEXPORT", 18)) { unsigned int fmt; ParseLV4MeshLong(fmt); @@ -245,23 +256,23 @@ void Parser::Parse() { continue; } // main scene information - if (TokenMatch(filePtr, "SCENE", 5)) { + if (TokenMatch(mFilePtr, "SCENE", 5)) { ParseLV1SceneBlock(); continue; } // "group" - no implementation yet, in facte // we're just ignoring them for the moment - if (TokenMatch(filePtr, "GROUP", 5)) { + if (TokenMatch(mFilePtr, "GROUP", 5)) { Parse(); continue; } // material list - if (TokenMatch(filePtr, "MATERIAL_LIST", 13)) { + if (TokenMatch(mFilePtr, "MATERIAL_LIST", 13)) { ParseLV1MaterialListBlock(); continue; } // geometric object (mesh) - if (TokenMatch(filePtr, "GEOMOBJECT", 10)) + if (TokenMatch(mFilePtr, "GEOMOBJECT", 10)) { m_vMeshes.emplace_back("UNNAMED"); @@ -269,7 +280,7 @@ void Parser::Parse() { continue; } // helper object = dummy in the hierarchy - if (TokenMatch(filePtr, "HELPEROBJECT", 12)) + if (TokenMatch(mFilePtr, "HELPEROBJECT", 12)) { m_vDummies.emplace_back(); @@ -277,7 +288,7 @@ void Parser::Parse() { continue; } // light object - if (TokenMatch(filePtr, "LIGHTOBJECT", 11)) + if (TokenMatch(mFilePtr, "LIGHTOBJECT", 11)) { m_vLights.emplace_back("UNNAMED"); @@ -285,20 +296,20 @@ void Parser::Parse() { continue; } // camera object - if (TokenMatch(filePtr, "CAMERAOBJECT", 12)) { + if (TokenMatch(mFilePtr, "CAMERAOBJECT", 12)) { m_vCameras.emplace_back("UNNAMED"); ParseLV1ObjectBlock(m_vCameras.back()); continue; } // comment - print it on the console - if (TokenMatch(filePtr, "COMMENT", 7)) { + if (TokenMatch(mFilePtr, "COMMENT", 7)) { std::string out = ""; ParseString(out, "*COMMENT"); LogInfo(("Comment: " + out).c_str()); continue; } // ASC bone weights - if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr, "MESH_SOFTSKINVERTS", 18)) { + if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(mFilePtr, "MESH_SOFTSKINVERTS", 18)) { ParseLV1SoftSkinBlock(); } } @@ -330,24 +341,25 @@ void Parser::ParseLV1SoftSkinBlock() { */ // ************************************************************** while (true) { - if (*filePtr == '}') { - ++filePtr; + if (*mFilePtr == '}') { + ++mFilePtr; return; - } else if (*filePtr == '\0') + } else if (*mFilePtr == '\0') return; - else if (*filePtr == '{') - ++filePtr; + else if (*mFilePtr == '{') + ++mFilePtr; else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr)) { ASE::Mesh *curMesh = nullptr; unsigned int numVerts = 0; - const char *sz = filePtr; - while (!IsSpaceOrNewLine(*filePtr)) - ++filePtr; + const char *sz = mFilePtr; + while (!IsSpaceOrNewLine(*mFilePtr)) { + ++mFilePtr; + } - const unsigned int diff = (unsigned int)(filePtr - sz); + const unsigned int diff = (unsigned int)(mFilePtr - sz); if (diff) { std::string name = std::string(sz, diff); for (std::vector::iterator it = m_vMeshes.begin(); @@ -363,24 +375,24 @@ void Parser::ParseLV1SoftSkinBlock() { // Skip the mesh data - until we find a new mesh // or the end of the *MESH_SOFTSKINVERTS section while (true) { - SkipSpacesAndLineEnd(&filePtr); - if (*filePtr == '}') { - ++filePtr; + SkipSpacesAndLineEnd(&mFilePtr, mEnd); + if (*mFilePtr == '}') { + ++mFilePtr; return; - } else if (!IsNumeric(*filePtr)) + } else if (!IsNumeric(*mFilePtr)) break; - SkipLine(&filePtr); + SkipLine(&mFilePtr, mEnd); } } else { - SkipSpacesAndLineEnd(&filePtr); + SkipSpacesAndLineEnd(&mFilePtr, mEnd); ParseLV4MeshLong(numVerts); // Reserve enough storage curMesh->mBoneVertices.reserve(numVerts); for (unsigned int i = 0; i < numVerts; ++i) { - SkipSpacesAndLineEnd(&filePtr); + SkipSpacesAndLineEnd(&mFilePtr, mEnd); unsigned int numWeights; ParseLV4MeshLong(numWeights); @@ -410,7 +422,7 @@ void Parser::ParseLV1SoftSkinBlock() { me.first = static_cast(curMesh->mBones.size()); curMesh->mBones.emplace_back(bone); } - ParseLV4MeshFloat(me.second); + ParseLV4MeshReal(me.second); // Add the new bone weight to list vert.mBoneWeights.push_back(me); @@ -419,10 +431,10 @@ void Parser::ParseLV1SoftSkinBlock() { } } } - if (*filePtr == '\0') + if (*mFilePtr == '\0') return; - ++filePtr; - SkipSpacesAndLineEnd(&filePtr); + ++mFilePtr; + SkipSpacesAndLineEnd(&mFilePtr, mEnd); } } @@ -430,35 +442,35 @@ void Parser::ParseLV1SoftSkinBlock() { void Parser::ParseLV1SceneBlock() { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (TokenMatch(filePtr, "SCENE_BACKGROUND_STATIC", 23)) + if ('*' == *mFilePtr) { + ++mFilePtr; + if (TokenMatch(mFilePtr, "SCENE_BACKGROUND_STATIC", 23)) { // parse a color triple and assume it is really the bg color ParseLV4MeshFloatTriple(&m_clrBackground.r); continue; } - if (TokenMatch(filePtr, "SCENE_AMBIENT_STATIC", 20)) + if (TokenMatch(mFilePtr, "SCENE_AMBIENT_STATIC", 20)) { // parse a color triple and assume it is really the bg color ParseLV4MeshFloatTriple(&m_clrAmbient.r); continue; } - if (TokenMatch(filePtr, "SCENE_FIRSTFRAME", 16)) { + if (TokenMatch(mFilePtr, "SCENE_FIRSTFRAME", 16)) { ParseLV4MeshLong(iFirstFrame); continue; } - if (TokenMatch(filePtr, "SCENE_LASTFRAME", 15)) { + if (TokenMatch(mFilePtr, "SCENE_LASTFRAME", 15)) { ParseLV4MeshLong(iLastFrame); continue; } - if (TokenMatch(filePtr, "SCENE_FRAMESPEED", 16)) { + if (TokenMatch(mFilePtr, "SCENE_FRAMESPEED", 16)) { ParseLV4MeshLong(iFrameSpeed); continue; } - if (TokenMatch(filePtr, "SCENE_TICKSPERFRAME", 19)) { + if (TokenMatch(mFilePtr, "SCENE_TICKSPERFRAME", 19)) { ParseLV4MeshLong(iTicksPerFrame); continue; } @@ -474,9 +486,9 @@ void Parser::ParseLV1MaterialListBlock() { unsigned int iMaterialCount = 0; unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size(); while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (TokenMatch(filePtr, "MATERIAL_COUNT", 14)) { + if ('*' == *mFilePtr) { + ++mFilePtr; + if (TokenMatch(mFilePtr, "MATERIAL_COUNT", 14)) { ParseLV4MeshLong(iMaterialCount); if (UINT_MAX - iOldMaterialCount < iMaterialCount) { @@ -488,14 +500,20 @@ void Parser::ParseLV1MaterialListBlock() { m_vMaterials.resize(iOldMaterialCount + iMaterialCount, Material("INVALID")); continue; } - if (TokenMatch(filePtr, "MATERIAL", 8)) { + if (TokenMatch(mFilePtr, "MATERIAL", 8)) { + // ensure we have at least one material allocated + if (iMaterialCount == 0) { + LogWarning("*MATERIAL_COUNT unspecified or 0"); + iMaterialCount = 1; + m_vMaterials.resize(iOldMaterialCount + iMaterialCount, Material("INVALID")); + } + unsigned int iIndex = 0; ParseLV4MeshLong(iIndex); if (iIndex >= iMaterialCount) { LogWarning("Out of range: material index is too large"); iIndex = iMaterialCount - 1; - return; } // get a reference to the material @@ -507,7 +525,7 @@ void Parser::ParseLV1MaterialListBlock() { if( iDepth == 1 ){ // CRUDE HACK: support missing brace after "Ascii Scene Exporter v2.51" LogWarning("Missing closing brace in material list"); - --filePtr; + --mFilePtr; return; } } @@ -521,37 +539,37 @@ void Parser::ParseLV2MaterialBlock(ASE::Material &mat) { unsigned int iNumSubMaterials = 0; while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (TokenMatch(filePtr, "MATERIAL_NAME", 13)) { + if ('*' == *mFilePtr) { + ++mFilePtr; + if (TokenMatch(mFilePtr, "MATERIAL_NAME", 13)) { if (!ParseString(mat.mName, "*MATERIAL_NAME")) SkipToNextToken(); continue; } // ambient material color - if (TokenMatch(filePtr, "MATERIAL_AMBIENT", 16)) { + if (TokenMatch(mFilePtr, "MATERIAL_AMBIENT", 16)) { ParseLV4MeshFloatTriple(&mat.mAmbient.r); continue; } // diffuse material color - if (TokenMatch(filePtr, "MATERIAL_DIFFUSE", 16)) { + if (TokenMatch(mFilePtr, "MATERIAL_DIFFUSE", 16)) { ParseLV4MeshFloatTriple(&mat.mDiffuse.r); continue; } // specular material color - if (TokenMatch(filePtr, "MATERIAL_SPECULAR", 17)) { + if (TokenMatch(mFilePtr, "MATERIAL_SPECULAR", 17)) { ParseLV4MeshFloatTriple(&mat.mSpecular.r); continue; } // material shading type - if (TokenMatch(filePtr, "MATERIAL_SHADING", 16)) { - if (TokenMatch(filePtr, "Blinn", 5)) { + if (TokenMatch(mFilePtr, "MATERIAL_SHADING", 16)) { + if (TokenMatch(mFilePtr, "Blinn", 5)) { mat.mShading = Discreet3DS::Blinn; - } else if (TokenMatch(filePtr, "Phong", 5)) { + } else if (TokenMatch(mFilePtr, "Phong", 5)) { mat.mShading = Discreet3DS::Phong; - } else if (TokenMatch(filePtr, "Flat", 4)) { + } else if (TokenMatch(mFilePtr, "Flat", 4)) { mat.mShading = Discreet3DS::Flat; - } else if (TokenMatch(filePtr, "Wire", 4)) { + } else if (TokenMatch(mFilePtr, "Wire", 4)) { mat.mShading = Discreet3DS::Wire; } else { // assume gouraud shading @@ -561,15 +579,15 @@ void Parser::ParseLV2MaterialBlock(ASE::Material &mat) { continue; } // material transparency - if (TokenMatch(filePtr, "MATERIAL_TRANSPARENCY", 21)) { - ParseLV4MeshFloat(mat.mTransparency); + if (TokenMatch(mFilePtr, "MATERIAL_TRANSPARENCY", 21)) { + ParseLV4MeshReal(mat.mTransparency); mat.mTransparency = ai_real(1.0) - mat.mTransparency; continue; } // material self illumination - if (TokenMatch(filePtr, "MATERIAL_SELFILLUM", 18)) { + if (TokenMatch(mFilePtr, "MATERIAL_SELFILLUM", 18)) { ai_real f = 0.0; - ParseLV4MeshFloat(f); + ParseLV4MeshReal(f); mat.mEmissive.r = f; mat.mEmissive.g = f; @@ -577,71 +595,77 @@ void Parser::ParseLV2MaterialBlock(ASE::Material &mat) { continue; } // material shininess - if (TokenMatch(filePtr, "MATERIAL_SHINE", 14)) { - ParseLV4MeshFloat(mat.mSpecularExponent); + if (TokenMatch(mFilePtr, "MATERIAL_SHINE", 14)) { + ParseLV4MeshReal(mat.mSpecularExponent); mat.mSpecularExponent *= 15; continue; } // two-sided material - if (TokenMatch(filePtr, "MATERIAL_TWOSIDED", 17)) { + if (TokenMatch(mFilePtr, "MATERIAL_TWOSIDED", 17)) { mat.mTwoSided = true; continue; } // material shininess strength - if (TokenMatch(filePtr, "MATERIAL_SHINESTRENGTH", 22)) { - ParseLV4MeshFloat(mat.mShininessStrength); + if (TokenMatch(mFilePtr, "MATERIAL_SHINESTRENGTH", 22)) { + ParseLV4MeshReal(mat.mShininessStrength); continue; } // diffuse color map - if (TokenMatch(filePtr, "MAP_DIFFUSE", 11)) { + if (TokenMatch(mFilePtr, "MAP_DIFFUSE", 11)) { // parse the texture block ParseLV3MapBlock(mat.sTexDiffuse); continue; } // ambient color map - if (TokenMatch(filePtr, "MAP_AMBIENT", 11)) { + if (TokenMatch(mFilePtr, "MAP_AMBIENT", 11)) { // parse the texture block ParseLV3MapBlock(mat.sTexAmbient); continue; } // specular color map - if (TokenMatch(filePtr, "MAP_SPECULAR", 12)) { + if (TokenMatch(mFilePtr, "MAP_SPECULAR", 12)) { // parse the texture block ParseLV3MapBlock(mat.sTexSpecular); continue; } // opacity map - if (TokenMatch(filePtr, "MAP_OPACITY", 11)) { + if (TokenMatch(mFilePtr, "MAP_OPACITY", 11)) { // parse the texture block ParseLV3MapBlock(mat.sTexOpacity); continue; } // emissive map - if (TokenMatch(filePtr, "MAP_SELFILLUM", 13)) { + if (TokenMatch(mFilePtr, "MAP_SELFILLUM", 13)) { // parse the texture block ParseLV3MapBlock(mat.sTexEmissive); continue; } // bump map - if (TokenMatch(filePtr, "MAP_BUMP", 8)) { + if (TokenMatch(mFilePtr, "MAP_BUMP", 8)) { // parse the texture block ParseLV3MapBlock(mat.sTexBump); } // specular/shininess map - if (TokenMatch(filePtr, "MAP_SHINESTRENGTH", 17)) { + if (TokenMatch(mFilePtr, "MAP_SHINESTRENGTH", 17)) { // parse the texture block ParseLV3MapBlock(mat.sTexShininess); continue; } // number of submaterials - if (TokenMatch(filePtr, "NUMSUBMTLS", 10)) { + if (TokenMatch(mFilePtr, "NUMSUBMTLS", 10)) { ParseLV4MeshLong(iNumSubMaterials); // allocate enough storage mat.avSubMaterials.resize(iNumSubMaterials, Material("INVALID SUBMATERIAL")); } // submaterial chunks - if (TokenMatch(filePtr, "SUBMATERIAL", 11)) { + if (TokenMatch(mFilePtr, "SUBMATERIAL", 11)) { + // ensure we have at least one material allocated + if (iNumSubMaterials == 0) { + LogWarning("*NUMSUBMTLS unspecified or 0"); + iNumSubMaterials = 1; + mat.avSubMaterials.resize(iNumSubMaterials, Material("INVALID SUBMATERIAL")); + } unsigned int iIndex = 0; ParseLV4MeshLong(iIndex); @@ -678,10 +702,10 @@ void Parser::ParseLV3MapBlock(Texture &map) { bool parsePath = true; std::string temp; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // type of map - if (TokenMatch(filePtr, "MAP_CLASS", 9)) { + if (TokenMatch(mFilePtr, "MAP_CLASS", 9)) { temp.clear(); if (!ParseString(temp, "*MAP_CLASS")) SkipToNextToken(); @@ -692,7 +716,7 @@ void Parser::ParseLV3MapBlock(Texture &map) { continue; } // path to the texture - if (parsePath && TokenMatch(filePtr, "BITMAP", 6)) { + if (parsePath && TokenMatch(mFilePtr, "BITMAP", 6)) { if (!ParseString(map.mMapName, "*BITMAP")) SkipToNextToken(); @@ -706,33 +730,33 @@ void Parser::ParseLV3MapBlock(Texture &map) { continue; } // offset on the u axis - if (TokenMatch(filePtr, "UVW_U_OFFSET", 12)) { - ParseLV4MeshFloat(map.mOffsetU); + if (TokenMatch(mFilePtr, "UVW_U_OFFSET", 12)) { + ParseLV4MeshReal(map.mOffsetU); continue; } // offset on the v axis - if (TokenMatch(filePtr, "UVW_V_OFFSET", 12)) { - ParseLV4MeshFloat(map.mOffsetV); + if (TokenMatch(mFilePtr, "UVW_V_OFFSET", 12)) { + ParseLV4MeshReal(map.mOffsetV); continue; } // tiling on the u axis - if (TokenMatch(filePtr, "UVW_U_TILING", 12)) { - ParseLV4MeshFloat(map.mScaleU); + if (TokenMatch(mFilePtr, "UVW_U_TILING", 12)) { + ParseLV4MeshReal(map.mScaleU); continue; } // tiling on the v axis - if (TokenMatch(filePtr, "UVW_V_TILING", 12)) { - ParseLV4MeshFloat(map.mScaleV); + if (TokenMatch(mFilePtr, "UVW_V_TILING", 12)) { + ParseLV4MeshReal(map.mScaleV); continue; } // rotation around the z-axis - if (TokenMatch(filePtr, "UVW_ANGLE", 9)) { - ParseLV4MeshFloat(map.mRotation); + if (TokenMatch(mFilePtr, "UVW_ANGLE", 9)) { + ParseLV4MeshReal(map.mRotation); continue; } // map blending factor - if (TokenMatch(filePtr, "MAP_AMOUNT", 10)) { - ParseLV4MeshFloat(map.mTextureBlend); + if (TokenMatch(mFilePtr, "MAP_AMOUNT", 10)) { + ParseLV4MeshReal(map.mTextureBlend); continue; } } @@ -743,14 +767,14 @@ void Parser::ParseLV3MapBlock(Texture &map) { // ------------------------------------------------------------------------------------------------ bool Parser::ParseString(std::string &out, const char *szName) { char szBuffer[1024]; - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Unexpected EOL", szName); LogWarning(szBuffer); return false; } // there must be '"' - if ('\"' != *filePtr) { + if ('\"' != *mFilePtr) { ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected " "to be enclosed in double quotation marks", @@ -758,8 +782,8 @@ bool Parser::ParseString(std::string &out, const char *szName) { LogWarning(szBuffer); return false; } - ++filePtr; - const char *sz = filePtr; + ++mFilePtr; + const char *sz = mFilePtr; while (true) { if ('\"' == *sz) break; @@ -773,8 +797,8 @@ bool Parser::ParseString(std::string &out, const char *szName) { } sz++; } - out = std::string(filePtr, (uintptr_t)sz - (uintptr_t)filePtr); - filePtr = sz + 1; + out = std::string(mFilePtr, (uintptr_t)sz - (uintptr_t)mFilePtr); + mFilePtr = sz + 1; return true; } @@ -782,48 +806,48 @@ bool Parser::ParseString(std::string &out, const char *szName) { void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // first process common tokens such as node name and transform // name of the mesh/node - if (TokenMatch(filePtr, "NODE_NAME", 9)) { + if (TokenMatch(mFilePtr, "NODE_NAME", 9)) { if (!ParseString(node.mName, "*NODE_NAME")) SkipToNextToken(); continue; } // name of the parent of the node - if (TokenMatch(filePtr, "NODE_PARENT", 11)) { + if (TokenMatch(mFilePtr, "NODE_PARENT", 11)) { if (!ParseString(node.mParent, "*NODE_PARENT")) SkipToNextToken(); continue; } // transformation matrix of the node - if (TokenMatch(filePtr, "NODE_TM", 7)) { + if (TokenMatch(mFilePtr, "NODE_TM", 7)) { ParseLV2NodeTransformBlock(node); continue; } // animation data of the node - if (TokenMatch(filePtr, "TM_ANIMATION", 12)) { + if (TokenMatch(mFilePtr, "TM_ANIMATION", 12)) { ParseLV2AnimationBlock(node); continue; } if (node.mType == BaseNode::Light) { // light settings - if (TokenMatch(filePtr, "LIGHT_SETTINGS", 14)) { + if (TokenMatch(mFilePtr, "LIGHT_SETTINGS", 14)) { ParseLV2LightSettingsBlock((ASE::Light &)node); continue; } // type of the light source - if (TokenMatch(filePtr, "LIGHT_TYPE", 10)) { - if (!ASSIMP_strincmp("omni", filePtr, 4)) { + if (TokenMatch(mFilePtr, "LIGHT_TYPE", 10)) { + if (!ASSIMP_strincmp("omni", mFilePtr, 4)) { ((ASE::Light &)node).mLightType = ASE::Light::OMNI; - } else if (!ASSIMP_strincmp("target", filePtr, 6)) { + } else if (!ASSIMP_strincmp("target", mFilePtr, 6)) { ((ASE::Light &)node).mLightType = ASE::Light::TARGET; - } else if (!ASSIMP_strincmp("free", filePtr, 4)) { + } else if (!ASSIMP_strincmp("free", mFilePtr, 4)) { ((ASE::Light &)node).mLightType = ASE::Light::FREE; - } else if (!ASSIMP_strincmp("directional", filePtr, 11)) { + } else if (!ASSIMP_strincmp("directional", mFilePtr, 11)) { ((ASE::Light &)node).mLightType = ASE::Light::DIRECTIONAL; } else { LogWarning("Unknown kind of light source"); @@ -832,13 +856,13 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) { } } else if (node.mType == BaseNode::Camera) { // Camera settings - if (TokenMatch(filePtr, "CAMERA_SETTINGS", 15)) { + if (TokenMatch(mFilePtr, "CAMERA_SETTINGS", 15)) { ParseLV2CameraSettingsBlock((ASE::Camera &)node); continue; - } else if (TokenMatch(filePtr, "CAMERA_TYPE", 11)) { - if (!ASSIMP_strincmp("target", filePtr, 6)) { + } else if (TokenMatch(mFilePtr, "CAMERA_TYPE", 11)) { + if (!ASSIMP_strincmp("target", mFilePtr, 6)) { ((ASE::Camera &)node).mCameraType = ASE::Camera::TARGET; - } else if (!ASSIMP_strincmp("free", filePtr, 4)) { + } else if (!ASSIMP_strincmp("free", mFilePtr, 4)) { ((ASE::Camera &)node).mCameraType = ASE::Camera::FREE; } else { LogWarning("Unknown kind of camera"); @@ -848,13 +872,13 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) { } else if (node.mType == BaseNode::Mesh) { // mesh data // FIX: Older files use MESH_SOFTSKIN - if (TokenMatch(filePtr, "MESH", 4) || - TokenMatch(filePtr, "MESH_SOFTSKIN", 13)) { + if (TokenMatch(mFilePtr, "MESH", 4) || + TokenMatch(mFilePtr, "MESH_SOFTSKIN", 13)) { ParseLV2MeshBlock((ASE::Mesh &)node); continue; } // mesh material index - if (TokenMatch(filePtr, "MATERIAL_REF", 12)) { + if (TokenMatch(mFilePtr, "MATERIAL_REF", 12)) { ParseLV4MeshLong(((ASE::Mesh &)node).iMaterialIndex); continue; } @@ -868,18 +892,18 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) { void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (TokenMatch(filePtr, "CAMERA_NEAR", 11)) { - ParseLV4MeshFloat(camera.mNear); + if ('*' == *mFilePtr) { + ++mFilePtr; + if (TokenMatch(mFilePtr, "CAMERA_NEAR", 11)) { + ParseLV4MeshReal(camera.mNear); continue; } - if (TokenMatch(filePtr, "CAMERA_FAR", 10)) { - ParseLV4MeshFloat(camera.mFar); + if (TokenMatch(mFilePtr, "CAMERA_FAR", 10)) { + ParseLV4MeshReal(camera.mFar); continue; } - if (TokenMatch(filePtr, "CAMERA_FOV", 10)) { - ParseLV4MeshFloat(camera.mFOV); + if (TokenMatch(mFilePtr, "CAMERA_FOV", 10)) { + ParseLV4MeshReal(camera.mFOV); continue; } } @@ -891,22 +915,22 @@ void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) { void Parser::ParseLV2LightSettingsBlock(ASE::Light &light) { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (TokenMatch(filePtr, "LIGHT_COLOR", 11)) { + if ('*' == *mFilePtr) { + ++mFilePtr; + if (TokenMatch(mFilePtr, "LIGHT_COLOR", 11)) { ParseLV4MeshFloatTriple(&light.mColor.r); continue; } - if (TokenMatch(filePtr, "LIGHT_INTENS", 12)) { - ParseLV4MeshFloat(light.mIntensity); + if (TokenMatch(mFilePtr, "LIGHT_INTENS", 12)) { + ParseLV4MeshReal(light.mIntensity); continue; } - if (TokenMatch(filePtr, "LIGHT_HOTSPOT", 13)) { - ParseLV4MeshFloat(light.mAngle); + if (TokenMatch(mFilePtr, "LIGHT_HOTSPOT", 13)) { + ParseLV4MeshReal(light.mAngle); continue; } - if (TokenMatch(filePtr, "LIGHT_FALLOFF", 13)) { - ParseLV4MeshFloat(light.mFalloff); + if (TokenMatch(mFilePtr, "LIGHT_FALLOFF", 13)) { + ParseLV4MeshReal(light.mFalloff); continue; } } @@ -920,9 +944,9 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) { ASE::Animation *anim = &mesh.mAnim; while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (TokenMatch(filePtr, "NODE_NAME", 9)) { + if ('*' == *mFilePtr) { + ++mFilePtr; + if (TokenMatch(mFilePtr, "NODE_NAME", 9)) { std::string temp; if (!ParseString(temp, "*NODE_NAME")) SkipToNextToken(); @@ -944,9 +968,9 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) { } // position keyframes - if (TokenMatch(filePtr, "CONTROL_POS_TRACK", 17) || - TokenMatch(filePtr, "CONTROL_POS_BEZIER", 18) || - TokenMatch(filePtr, "CONTROL_POS_TCB", 15)) { + if (TokenMatch(mFilePtr, "CONTROL_POS_TRACK", 17) || + TokenMatch(mFilePtr, "CONTROL_POS_BEZIER", 18) || + TokenMatch(mFilePtr, "CONTROL_POS_TCB", 15)) { if (!anim) SkipSection(); else @@ -954,9 +978,9 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) { continue; } // scaling keyframes - if (TokenMatch(filePtr, "CONTROL_SCALE_TRACK", 19) || - TokenMatch(filePtr, "CONTROL_SCALE_BEZIER", 20) || - TokenMatch(filePtr, "CONTROL_SCALE_TCB", 17)) { + if (TokenMatch(mFilePtr, "CONTROL_SCALE_TRACK", 19) || + TokenMatch(mFilePtr, "CONTROL_SCALE_BEZIER", 20) || + TokenMatch(mFilePtr, "CONTROL_SCALE_TCB", 17)) { if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation"); @@ -966,9 +990,9 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) { continue; } // rotation keyframes - if (TokenMatch(filePtr, "CONTROL_ROT_TRACK", 17) || - TokenMatch(filePtr, "CONTROL_ROT_BEZIER", 18) || - TokenMatch(filePtr, "CONTROL_ROT_TCB", 15)) { + if (TokenMatch(mFilePtr, "CONTROL_ROT_TRACK", 17) || + TokenMatch(mFilePtr, "CONTROL_ROT_BEZIER", 18) || + TokenMatch(mFilePtr, "CONTROL_ROT_TCB", 15)) { if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation"); @@ -987,8 +1011,8 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation &anim) { unsigned int iIndex; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; bool b = false; @@ -996,25 +1020,25 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation &anim) { // we ignore the additional information for bezier's and TCBs // simple scaling keyframe - if (TokenMatch(filePtr, "CONTROL_SCALE_SAMPLE", 20)) { + if (TokenMatch(mFilePtr, "CONTROL_SCALE_SAMPLE", 20)) { b = true; anim.mScalingType = ASE::Animation::TRACK; } // Bezier scaling keyframe - if (TokenMatch(filePtr, "CONTROL_BEZIER_SCALE_KEY", 24)) { + if (TokenMatch(mFilePtr, "CONTROL_BEZIER_SCALE_KEY", 24)) { b = true; anim.mScalingType = ASE::Animation::BEZIER; } // TCB scaling keyframe - if (TokenMatch(filePtr, "CONTROL_TCB_SCALE_KEY", 21)) { + if (TokenMatch(mFilePtr, "CONTROL_TCB_SCALE_KEY", 21)) { b = true; anim.mScalingType = ASE::Animation::TCB; } if (b) { anim.akeyScaling.emplace_back(); aiVectorKey &key = anim.akeyScaling.back(); - ParseLV4MeshFloatTriple(&key.mValue.x, iIndex); + ParseLV4MeshRealTriple(&key.mValue.x, iIndex); key.mTime = (double)iIndex; } } @@ -1026,8 +1050,8 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation &anim) { AI_ASE_PARSER_INIT(); unsigned int iIndex; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; bool b = false; @@ -1035,25 +1059,25 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation &anim) { // we ignore the additional information for bezier's and TCBs // simple scaling keyframe - if (TokenMatch(filePtr, "CONTROL_POS_SAMPLE", 18)) { + if (TokenMatch(mFilePtr, "CONTROL_POS_SAMPLE", 18)) { b = true; anim.mPositionType = ASE::Animation::TRACK; } // Bezier scaling keyframe - if (TokenMatch(filePtr, "CONTROL_BEZIER_POS_KEY", 22)) { + if (TokenMatch(mFilePtr, "CONTROL_BEZIER_POS_KEY", 22)) { b = true; anim.mPositionType = ASE::Animation::BEZIER; } // TCB scaling keyframe - if (TokenMatch(filePtr, "CONTROL_TCB_POS_KEY", 19)) { + if (TokenMatch(mFilePtr, "CONTROL_TCB_POS_KEY", 19)) { b = true; anim.mPositionType = ASE::Animation::TCB; } if (b) { anim.akeyPositions.emplace_back(); aiVectorKey &key = anim.akeyPositions.back(); - ParseLV4MeshFloatTriple(&key.mValue.x, iIndex); + ParseLV4MeshRealTriple(&key.mValue.x, iIndex); key.mTime = (double)iIndex; } } @@ -1065,8 +1089,8 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation &anim) { AI_ASE_PARSER_INIT(); unsigned int iIndex; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; bool b = false; @@ -1074,18 +1098,18 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation &anim) { // we ignore the additional information for bezier's and TCBs // simple scaling keyframe - if (TokenMatch(filePtr, "CONTROL_ROT_SAMPLE", 18)) { + if (TokenMatch(mFilePtr, "CONTROL_ROT_SAMPLE", 18)) { b = true; anim.mRotationType = ASE::Animation::TRACK; } // Bezier scaling keyframe - if (TokenMatch(filePtr, "CONTROL_BEZIER_ROT_KEY", 22)) { + if (TokenMatch(mFilePtr, "CONTROL_BEZIER_ROT_KEY", 22)) { b = true; anim.mRotationType = ASE::Animation::BEZIER; } // TCB scaling keyframe - if (TokenMatch(filePtr, "CONTROL_TCB_ROT_KEY", 19)) { + if (TokenMatch(mFilePtr, "CONTROL_TCB_ROT_KEY", 19)) { b = true; anim.mRotationType = ASE::Animation::TCB; } @@ -1094,8 +1118,8 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation &anim) { aiQuatKey &key = anim.akeyRotations.back(); aiVector3D v; ai_real f; - ParseLV4MeshFloatTriple(&v.x, iIndex); - ParseLV4MeshFloat(f); + ParseLV4MeshRealTriple(&v.x, iIndex); + ParseLV4MeshReal(f); key.mTime = (double)iIndex; key.mValue = aiQuaternion(v, f); } @@ -1108,10 +1132,10 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { AI_ASE_PARSER_INIT(); int mode = 0; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // name of the node - if (TokenMatch(filePtr, "NODE_NAME", 9)) { + if (TokenMatch(mFilePtr, "NODE_NAME", 9)) { std::string temp; if (!ParseString(temp, "*NODE_NAME")) SkipToNextToken(); @@ -1138,28 +1162,28 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { if (mode) { // fourth row of the transformation matrix - and also the // only information here that is interesting for targets - if (TokenMatch(filePtr, "TM_ROW3", 7)) { - ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x)); + if (TokenMatch(mFilePtr, "TM_ROW3", 7)) { + ParseLV4MeshRealTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x)); continue; } if (mode == 1) { // first row of the transformation matrix - if (TokenMatch(filePtr, "TM_ROW0", 7)) { - ParseLV4MeshFloatTriple(mesh.mTransform[0]); + if (TokenMatch(mFilePtr, "TM_ROW0", 7)) { + ParseLV4MeshRealTriple(mesh.mTransform[0]); continue; } // second row of the transformation matrix - if (TokenMatch(filePtr, "TM_ROW1", 7)) { - ParseLV4MeshFloatTriple(mesh.mTransform[1]); + if (TokenMatch(mFilePtr, "TM_ROW1", 7)) { + ParseLV4MeshRealTriple(mesh.mTransform[1]); continue; } // third row of the transformation matrix - if (TokenMatch(filePtr, "TM_ROW2", 7)) { - ParseLV4MeshFloatTriple(mesh.mTransform[2]); + if (TokenMatch(mFilePtr, "TM_ROW2", 7)) { + ParseLV4MeshRealTriple(mesh.mTransform[2]); continue; } // inherited position axes - if (TokenMatch(filePtr, "INHERIT_POS", 11)) { + if (TokenMatch(mFilePtr, "INHERIT_POS", 11)) { unsigned int aiVal[3]; ParseLV4MeshLongTriple(aiVal); @@ -1168,7 +1192,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { continue; } // inherited rotation axes - if (TokenMatch(filePtr, "INHERIT_ROT", 11)) { + if (TokenMatch(mFilePtr, "INHERIT_ROT", 11)) { unsigned int aiVal[3]; ParseLV4MeshLongTriple(aiVal); @@ -1177,7 +1201,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { continue; } // inherited scaling axes - if (TokenMatch(filePtr, "INHERIT_SCL", 11)) { + if (TokenMatch(mFilePtr, "INHERIT_SCL", 11)) { unsigned int aiVal[3]; ParseLV4MeshLongTriple(aiVal); @@ -1202,75 +1226,75 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) { unsigned int iNumCVertices = 0; unsigned int iNumCFaces = 0; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Number of vertices in the mesh - if (TokenMatch(filePtr, "MESH_NUMVERTEX", 14)) { + if (TokenMatch(mFilePtr, "MESH_NUMVERTEX", 14)) { ParseLV4MeshLong(iNumVertices); continue; } // Number of texture coordinates in the mesh - if (TokenMatch(filePtr, "MESH_NUMTVERTEX", 15)) { + if (TokenMatch(mFilePtr, "MESH_NUMTVERTEX", 15)) { ParseLV4MeshLong(iNumTVertices); continue; } // Number of vertex colors in the mesh - if (TokenMatch(filePtr, "MESH_NUMCVERTEX", 15)) { + if (TokenMatch(mFilePtr, "MESH_NUMCVERTEX", 15)) { ParseLV4MeshLong(iNumCVertices); continue; } // Number of regular faces in the mesh - if (TokenMatch(filePtr, "MESH_NUMFACES", 13)) { + if (TokenMatch(mFilePtr, "MESH_NUMFACES", 13)) { ParseLV4MeshLong(iNumFaces); continue; } // Number of UVWed faces in the mesh - if (TokenMatch(filePtr, "MESH_NUMTVFACES", 15)) { + if (TokenMatch(mFilePtr, "MESH_NUMTVFACES", 15)) { ParseLV4MeshLong(iNumTFaces); continue; } // Number of colored faces in the mesh - if (TokenMatch(filePtr, "MESH_NUMCVFACES", 15)) { + if (TokenMatch(mFilePtr, "MESH_NUMCVFACES", 15)) { ParseLV4MeshLong(iNumCFaces); continue; } // mesh vertex list block - if (TokenMatch(filePtr, "MESH_VERTEX_LIST", 16)) { + if (TokenMatch(mFilePtr, "MESH_VERTEX_LIST", 16)) { ParseLV3MeshVertexListBlock(iNumVertices, mesh); continue; } // mesh face list block - if (TokenMatch(filePtr, "MESH_FACE_LIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_FACE_LIST", 14)) { ParseLV3MeshFaceListBlock(iNumFaces, mesh); continue; } // mesh texture vertex list block - if (TokenMatch(filePtr, "MESH_TVERTLIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_TVERTLIST", 14)) { ParseLV3MeshTListBlock(iNumTVertices, mesh); continue; } // mesh texture face block - if (TokenMatch(filePtr, "MESH_TFACELIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_TFACELIST", 14)) { ParseLV3MeshTFaceListBlock(iNumTFaces, mesh); continue; } // mesh color vertex list block - if (TokenMatch(filePtr, "MESH_CVERTLIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_CVERTLIST", 14)) { ParseLV3MeshCListBlock(iNumCVertices, mesh); continue; } // mesh color face block - if (TokenMatch(filePtr, "MESH_CFACELIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_CFACELIST", 14)) { ParseLV3MeshCFaceListBlock(iNumCFaces, mesh); continue; } // mesh normals - if (TokenMatch(filePtr, "MESH_NORMALS", 12)) { + if (TokenMatch(mFilePtr, "MESH_NORMALS", 12)) { ParseLV3MeshNormalListBlock(mesh); continue; } // another mesh UV channel ... - if (TokenMatch(filePtr, "MESH_MAPPINGCHANNEL", 19)) { + if (TokenMatch(mFilePtr, "MESH_MAPPINGCHANNEL", 19)) { unsigned int iIndex(0); ParseLV4MeshLong(iIndex); if (0 == iIndex) { @@ -1295,7 +1319,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) { } } // mesh animation keyframe. Not supported - if (TokenMatch(filePtr, "MESH_ANIMATION", 14)) { + if (TokenMatch(mFilePtr, "MESH_ANIMATION", 14)) { LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. " "Keyframe animation is not supported by Assimp, this element " @@ -1303,7 +1327,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) { //SkipSection(); continue; } - if (TokenMatch(filePtr, "MESH_WEIGHTS", 12)) { + if (TokenMatch(mFilePtr, "MESH_WEIGHTS", 12)) { ParseLV3MeshWeightsBlock(mesh); continue; } @@ -1317,26 +1341,26 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) { unsigned int iNumVertices = 0, iNumBones = 0; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Number of bone vertices ... - if (TokenMatch(filePtr, "MESH_NUMVERTEX", 14)) { + if (TokenMatch(mFilePtr, "MESH_NUMVERTEX", 14)) { ParseLV4MeshLong(iNumVertices); continue; } // Number of bones - if (TokenMatch(filePtr, "MESH_NUMBONE", 12)) { + if (TokenMatch(mFilePtr, "MESH_NUMBONE", 12)) { ParseLV4MeshLong(iNumBones); continue; } // parse the list of bones - if (TokenMatch(filePtr, "MESH_BONE_LIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_BONE_LIST", 14)) { ParseLV4MeshBones(iNumBones, mesh); continue; } // parse the list of bones vertices - if (TokenMatch(filePtr, "MESH_BONE_VERTEX_LIST", 21)) { + if (TokenMatch(mFilePtr, "MESH_BONE_VERTEX_LIST", 21)) { ParseLV4MeshBonesVertices(iNumVertices, mesh); continue; } @@ -1349,14 +1373,14 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); mesh.mBones.resize(iNumBones, Bone("UNNAMED")); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Mesh bone with name ... - if (TokenMatch(filePtr, "MESH_BONE_NAME", 14)) { + if (TokenMatch(mFilePtr, "MESH_BONE_NAME", 14)) { // parse an index ... - if (SkipSpaces(&filePtr)) { - unsigned int iIndex = strtoul10(filePtr, &filePtr); + if (SkipSpaces(&mFilePtr, mEnd)) { + unsigned int iIndex = strtoul10(mFilePtr, &mFilePtr); if (iIndex >= iNumBones) { LogWarning("Bone index is out of bounds"); continue; @@ -1375,32 +1399,35 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes AI_ASE_PARSER_INIT(); mesh.mBoneVertices.resize(iNumVertices); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Mesh bone vertex - if (TokenMatch(filePtr, "MESH_BONE_VERTEX", 16)) { + if (TokenMatch(mFilePtr, "MESH_BONE_VERTEX", 16)) { // read the vertex index - unsigned int iIndex = strtoul10(filePtr, &filePtr); - if (iIndex >= mesh.mPositions.size()) { - iIndex = (unsigned int)mesh.mPositions.size() - 1; + unsigned int iIndex = strtoul10(mFilePtr, &mFilePtr); + if (mesh.mBoneVertices.empty()) { + SkipSection(); + } + if (iIndex >= mesh.mBoneVertices.size() ) { LogWarning("Bone vertex index is out of bounds. Using the largest valid " "bone vertex index instead"); + iIndex = (unsigned int)mesh.mBoneVertices.size() - 1; } // --- ignored ai_real afVert[3]; - ParseLV4MeshFloatTriple(afVert); + ParseLV4MeshRealTriple(afVert); std::pair pairOut; while (true) { // first parse the bone index ... - if (!SkipSpaces(&filePtr)) break; - pairOut.first = strtoul10(filePtr, &filePtr); + if (!SkipSpaces(&mFilePtr, mEnd)) break; + pairOut.first = strtoul10(mFilePtr, &mFilePtr); // then parse the vertex weight - if (!SkipSpaces(&filePtr)) break; - filePtr = fast_atoreal_move(filePtr, pairOut.second); + if (!SkipSpaces(&mFilePtr, mEnd)) break; + mFilePtr = fast_atoreal_move(mFilePtr, pairOut.second); // -1 marks unused entries if (-1 != pairOut.first) { @@ -1421,15 +1448,15 @@ void Parser::ParseLV3MeshVertexListBlock( // allocate enough storage in the array mesh.mPositions.resize(iNumVertices); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Vertex entry - if (TokenMatch(filePtr, "MESH_VERTEX", 11)) { + if (TokenMatch(mFilePtr, "MESH_VERTEX", 11)) { aiVector3D vTemp; unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.x, iIndex); + ParseLV4MeshRealTriple(&vTemp.x, iIndex); if (iIndex >= iNumVertices) { LogWarning("Invalid vertex index. It will be ignored"); @@ -1448,11 +1475,11 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) // allocate enough storage in the face array mesh.mFaces.resize(iNumFaces); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Face entry - if (TokenMatch(filePtr, "MESH_FACE", 9)) { + if (TokenMatch(mFilePtr, "MESH_FACE", 9)) { ASE::Face mFace; ParseLV4MeshFace(mFace); @@ -1475,14 +1502,14 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, // allocate enough storage in the array mesh.amTexCoords[iChannel].resize(iNumVertices); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Vertex entry - if (TokenMatch(filePtr, "MESH_TVERT", 10)) { + if (TokenMatch(mFilePtr, "MESH_TVERT", 10)) { aiVector3D vTemp; unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.x, iIndex); + ParseLV4MeshRealTriple(&vTemp.x, iIndex); if (iIndex >= iNumVertices) { LogWarning("Tvertex has an invalid index. It will be ignored"); @@ -1504,11 +1531,11 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh, unsigned int iChannel) { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Face entry - if (TokenMatch(filePtr, "MESH_TFACE", 10)) { + if (TokenMatch(mFilePtr, "MESH_TFACE", 10)) { unsigned int aiValues[3]; unsigned int iIndex = 0; @@ -1534,26 +1561,26 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) { unsigned int iNumTVertices = 0; unsigned int iNumTFaces = 0; while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Number of texture coordinates in the mesh - if (TokenMatch(filePtr, "MESH_NUMTVERTEX", 15)) { + if (TokenMatch(mFilePtr, "MESH_NUMTVERTEX", 15)) { ParseLV4MeshLong(iNumTVertices); continue; } // Number of UVWed faces in the mesh - if (TokenMatch(filePtr, "MESH_NUMTVFACES", 15)) { + if (TokenMatch(mFilePtr, "MESH_NUMTVFACES", 15)) { ParseLV4MeshLong(iNumTFaces); continue; } // mesh texture vertex list block - if (TokenMatch(filePtr, "MESH_TVERTLIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_TVERTLIST", 14)) { ParseLV3MeshTListBlock(iNumTVertices, mesh, iChannel); continue; } // mesh texture face block - if (TokenMatch(filePtr, "MESH_TFACELIST", 14)) { + if (TokenMatch(mFilePtr, "MESH_TFACELIST", 14)) { ParseLV3MeshTFaceListBlock(iNumTFaces, mesh, iChannel); continue; } @@ -1568,11 +1595,11 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) // allocate enough storage in the array mesh.mVertexColors.resize(iNumVertices); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Vertex entry - if (TokenMatch(filePtr, "MESH_VERTCOL", 12)) { + if (TokenMatch(mFilePtr, "MESH_VERTCOL", 12)) { aiColor4D vTemp; vTemp.a = 1.0f; unsigned int iIndex; @@ -1592,11 +1619,11 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) { AI_ASE_PARSER_INIT(); while (true) { - if ('*' == *filePtr) { - ++filePtr; + if ('*' == *mFilePtr) { + ++mFilePtr; // Face entry - if (TokenMatch(filePtr, "MESH_CFACE", 10)) { + if (TokenMatch(mFilePtr, "MESH_CFACE", 10)) { unsigned int aiValues[3]; unsigned int iIndex = 0; @@ -1629,11 +1656,11 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { // Smooth the vertex and face normals together. The result // will be edgy then, but otherwise everything would be soft ... while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (faceIdx != UINT_MAX && TokenMatch(filePtr, "MESH_VERTEXNORMAL", 17)) { + if ('*' == *mFilePtr) { + ++mFilePtr; + if (faceIdx != UINT_MAX && TokenMatch(mFilePtr, "MESH_VERTEXNORMAL", 17)) { aiVector3D vNormal; - ParseLV4MeshFloatTriple(&vNormal.x, index); + ParseLV4MeshRealTriple(&vNormal.x, index); if (faceIdx >= sMesh.mFaces.size()) continue; @@ -1653,9 +1680,9 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { sMesh.mNormals[faceIdx * 3 + index] += vNormal; continue; } - if (TokenMatch(filePtr, "MESH_FACENORMAL", 15)) { + if (TokenMatch(mFilePtr, "MESH_FACENORMAL", 15)) { aiVector3D vNormal; - ParseLV4MeshFloatTriple(&vNormal.x, faceIdx); + ParseLV4MeshRealTriple(&vNormal.x, faceIdx); if (faceIdx >= sMesh.mFaces.size()) { ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section"); @@ -1675,34 +1702,34 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) { // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshFace(ASE::Face &out) { // skip spaces and tabs - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]"); SkipToNextToken(); return; } // parse the face index - out.iFace = strtoul10(filePtr, &filePtr); + out.iFace = strtoul10(mFilePtr, &mFilePtr); // next character should be ':' - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { // FIX: there are some ASE files which haven't got : here .... LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]"); SkipToNextToken(); return; } // FIX: There are some ASE files which haven't got ':' here - if (':' == *filePtr) ++filePtr; + if (':' == *mFilePtr) ++mFilePtr; // Parse all mesh indices for (unsigned int i = 0; i < 3; ++i) { unsigned int iIndex = 0; - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL"); SkipToNextToken(); return; } - switch (*filePtr) { + switch (*mFilePtr) { case 'A': case 'a': break; @@ -1720,39 +1747,39 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { SkipToNextToken(); return; }; - ++filePtr; + ++mFilePtr; // next character should be ':' - if (!SkipSpaces(&filePtr) || ':' != *filePtr) { + if (!SkipSpaces(&mFilePtr, mEnd) || ':' != *mFilePtr) { LogWarning("Unable to parse *MESH_FACE Element: " "Unexpected EOL. \':\' expected [#2]"); SkipToNextToken(); return; } - ++filePtr; - if (!SkipSpaces(&filePtr)) { + ++mFilePtr; + if (!SkipSpaces(&mFilePtr, mEnd)) { LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " - "Vertex index ecpected [#4]"); + "Vertex index expected [#4]"); SkipToNextToken(); return; } - out.mIndices[iIndex] = strtoul10(filePtr, &filePtr); + out.mIndices[iIndex] = strtoul10(mFilePtr, &mFilePtr); } // now we need to skip the AB, BC, CA blocks. while (true) { - if ('*' == *filePtr) break; - if (IsLineEnd(*filePtr)) { + if ('*' == *mFilePtr) break; + if (IsLineEnd(*mFilePtr)) { //iLineNumber++; return; } - filePtr++; + mFilePtr++; } // parse the smoothing group of the face - if (TokenMatch(filePtr, "*MESH_SMOOTHING", 15)) { - if (!SkipSpaces(&filePtr)) { + if (TokenMatch(mFilePtr, "*MESH_SMOOTHING", 15)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { LogWarning("Unable to parse *MESH_SMOOTHING Element: " "Unexpected EOL. Smoothing group(s) expected [#5]"); SkipToNextToken(); @@ -1762,43 +1789,43 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) { // Parse smoothing groups until we don't anymore see commas // FIX: There needn't always be a value, sad but true while (true) { - if (*filePtr < '9' && *filePtr >= '0') { - uint32_t value = strtoul10(filePtr, &filePtr); + if (*mFilePtr < '9' && *mFilePtr >= '0') { + uint32_t value = strtoul10(mFilePtr, &mFilePtr); if (value < 32) { - out.iSmoothGroup |= (1 << strtoul10(filePtr, &filePtr)); + out.iSmoothGroup |= (1 << strtoul10(mFilePtr, &mFilePtr)); } else { const std::string message = std::string("Unable to set smooth group, value with ") + ai_to_string(value) + std::string(" out of range"); LogWarning(message.c_str()); } } - SkipSpaces(&filePtr); - if (',' != *filePtr) { + SkipSpaces(&mFilePtr, mEnd); + if (',' != *mFilePtr) { break; } - ++filePtr; - SkipSpaces(&filePtr); + ++mFilePtr; + SkipSpaces(&mFilePtr, mEnd); } } // *MESH_MTLID is optional, too while (true) { - if ('*' == *filePtr) { + if ('*' == *mFilePtr) { break; } - if (IsLineEnd(*filePtr)) { + if (IsLineEnd(*mFilePtr)) { return; } - filePtr++; + mFilePtr++; } - if (TokenMatch(filePtr, "*MESH_MTLID", 11)) { - if (!SkipSpaces(&filePtr)) { + if (TokenMatch(mFilePtr, "*MESH_MTLID", 11)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. " "Material index expected [#6]"); SkipToNextToken(); return; } - out.iMaterial = strtoul10(filePtr, &filePtr); + out.iMaterial = strtoul10(mFilePtr, &mFilePtr); } return; } @@ -1820,7 +1847,17 @@ void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut ParseLV4MeshLongTriple(apOut); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) { +void Parser::ParseLV4MeshRealTriple(ai_real *apOut, unsigned int &rIndexOut) { + ai_assert(nullptr != apOut); + + // parse the index + ParseLV4MeshLong(rIndexOut); + + // parse the three others + ParseLV4MeshRealTriple(apOut); +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut) { ai_assert(nullptr != apOut); // parse the index @@ -1830,7 +1867,15 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) { ParseLV4MeshFloatTriple(apOut); } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) { +void Parser::ParseLV4MeshRealTriple(ai_real *apOut) { + ai_assert(nullptr != apOut); + + for (unsigned int i = 0; i < 3; ++i) { + ParseLV4MeshReal(apOut[i]); + } +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFloatTriple(float* apOut) { ai_assert(nullptr != apOut); for (unsigned int i = 0; i < 3; ++i) { @@ -1838,9 +1883,9 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) { } } // ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloat(ai_real &fOut) { +void Parser::ParseLV4MeshReal(ai_real &fOut) { // skip spaces and tabs - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { // LOG LogWarning("Unable to parse float: unexpected EOL [#1]"); fOut = 0.0; @@ -1848,12 +1893,25 @@ void Parser::ParseLV4MeshFloat(ai_real &fOut) { return; } // parse the first float - filePtr = fast_atoreal_move(filePtr, fOut); + mFilePtr = fast_atoreal_move(mFilePtr, fOut); +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFloat(float &fOut) { + // skip spaces and tabs + if (!SkipSpaces(&mFilePtr, mEnd)) { + // LOG + LogWarning("Unable to parse float: unexpected EOL [#1]"); + fOut = 0.0; + ++iLineNumber; + return; + } + // parse the first float + mFilePtr = fast_atoreal_move(mFilePtr, fOut); } // ------------------------------------------------------------------------------------------------ void Parser::ParseLV4MeshLong(unsigned int &iOut) { // Skip spaces and tabs - if (!SkipSpaces(&filePtr)) { + if (!SkipSpaces(&mFilePtr, mEnd)) { // LOG LogWarning("Unable to parse long: unexpected EOL [#1]"); iOut = 0; @@ -1861,7 +1919,7 @@ void Parser::ParseLV4MeshLong(unsigned int &iOut) { return; } // parse the value - iOut = strtoul10(filePtr, &filePtr); + iOut = strtoul10(mFilePtr, &mFilePtr); } } diff --git a/code/AssetLib/ASE/ASEParser.h b/code/AssetLib/ASE/ASEParser.h index c41cd59d3..408c1ee08 100644 --- a/code/AssetLib/ASE/ASEParser.h +++ b/code/AssetLib/ASE/ASEParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -391,11 +391,11 @@ public: // ------------------------------------------------------------------- //! Construct a parser from a given input file which is //! guaranteed to be terminated with zero. - //! @param szFile Input file + //! @param file The name of the input file. //! @param fileFormatDefault Assumed file format version. If the //! file format is specified in the file the new value replaces //! the default value. - Parser(const char *szFile, unsigned int fileFormatDefault); + Parser(const char *file, size_t fileLen, unsigned int fileFormatDefault); // ------------------------------------------------------------------- //! Parses the file into the parsers internal representation @@ -553,13 +553,15 @@ private: //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! \param apOut Output buffer (3 floats) //! \param rIndexOut Output index - void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut); + void ParseLV4MeshRealTriple(ai_real *apOut, unsigned int &rIndexOut); + void ParseLV4MeshFloatTriple(float *apOut, unsigned int &rIndexOut); // ------------------------------------------------------------------- //! Parse a *MESH_VERT block in a file //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! \param apOut Output buffer (3 floats) - void ParseLV4MeshFloatTriple(ai_real *apOut); + void ParseLV4MeshRealTriple(ai_real *apOut); + void ParseLV4MeshFloatTriple(float *apOut); // ------------------------------------------------------------------- //! Parse a *MESH_TFACE block in a file @@ -577,7 +579,8 @@ private: // ------------------------------------------------------------------- //! Parse a single float element //! \param fOut Output float - void ParseLV4MeshFloat(ai_real &fOut); + void ParseLV4MeshReal(ai_real &fOut); + void ParseLV4MeshFloat(float &fOut); // ------------------------------------------------------------------- //! Parse a single int element @@ -617,8 +620,8 @@ private: bool ParseString(std::string &out, const char *szName); public: - //! Pointer to current data - const char *filePtr; + const char *mFilePtr; ////< Pointer to current data + const char *mEnd; ///< The end pointer of the file data //! background color to be passed to the viewer //! QNAN if none was found diff --git a/code/AssetLib/Assbin/AssbinExporter.cpp b/code/AssetLib/Assbin/AssbinExporter.cpp index 149b3c5f3..f9a510a66 100644 --- a/code/AssetLib/Assbin/AssbinExporter.cpp +++ b/code/AssetLib/Assbin/AssbinExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinExporter.h b/code/AssetLib/Assbin/AssbinExporter.h index 8b721994d..a3fa99492 100644 --- a/code/AssetLib/Assbin/AssbinExporter.h +++ b/code/AssetLib/Assbin/AssbinExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinFileWriter.cpp b/code/AssetLib/Assbin/AssbinFileWriter.cpp index 782595bc1..d4e25e16b 100644 --- a/code/AssetLib/Assbin/AssbinFileWriter.cpp +++ b/code/AssetLib/Assbin/AssbinFileWriter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinFileWriter.h b/code/AssetLib/Assbin/AssbinFileWriter.h index cfed3b400..066470a46 100644 --- a/code/AssetLib/Assbin/AssbinFileWriter.h +++ b/code/AssetLib/Assbin/AssbinFileWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp index 6995ea976..b0905298a 100644 --- a/code/AssetLib/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER // internal headers -#include "AssetLib/Assbin/AssbinLoader.h" +#include "AssbinLoader.h" #include "Common/assbin_chunks.h" #include #include @@ -91,10 +91,14 @@ bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, boo } char s[32]; - in->Read(s, sizeof(char), 32); + const size_t read = in->Read(s, sizeof(char), 32); pIOHandler->Close(in); + if (read < 19) { + return false; + } + return strncmp(s, "ASSIMP.binary-dump.", 19) == 0; } @@ -684,6 +688,7 @@ void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, I unsigned int versionMajor = Read(stream); unsigned int versionMinor = Read(stream); if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) { + pIOHandler->Close(stream); throw DeadlyImportError("Invalid version, data format not compatible!"); } @@ -693,8 +698,10 @@ void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, I shortened = Read(stream) > 0; compressed = Read(stream) > 0; - if (shortened) + if (shortened) { + pIOHandler->Close(stream); throw DeadlyImportError("Shortened binaries are not supported!"); + } stream->Seek(256, aiOrigin_CUR); // original filename stream->Seek(128, aiOrigin_CUR); // options diff --git a/code/AssetLib/Assbin/AssbinLoader.h b/code/AssetLib/Assbin/AssbinLoader.h index f922b91fd..573e10799 100644 --- a/code/AssetLib/Assbin/AssbinLoader.h +++ b/code/AssetLib/Assbin/AssbinLoader.h @@ -1,9 +1,8 @@ - /* Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -61,7 +60,7 @@ struct aiCamera; #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------------- /** Importer class for 3D Studio r3 and r4 3DS files diff --git a/code/AssetLib/Assxml/AssxmlExporter.cpp b/code/AssetLib/Assxml/AssxmlExporter.cpp index 731916a25..873a89427 100644 --- a/code/AssetLib/Assxml/AssxmlExporter.cpp +++ b/code/AssetLib/Assxml/AssxmlExporter.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp { +namespace Assimp { void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { diff --git a/code/AssetLib/Assxml/AssxmlExporter.h b/code/AssetLib/Assxml/AssxmlExporter.h index 6fcdebfab..6b71c104d 100644 --- a/code/AssetLib/Assxml/AssxmlExporter.h +++ b/code/AssetLib/Assxml/AssxmlExporter.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.cpp b/code/AssetLib/Assxml/AssxmlFileWriter.cpp index 8f8e76bd2..c6842f5c6 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.cpp +++ b/code/AssetLib/Assxml/AssxmlFileWriter.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -36,7 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------- */ @@ -223,7 +221,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, const unsigned int majorVersion(aiGetVersionMajor()); const unsigned int minorVersion(aiGetVersionMinor()); const unsigned int rev(aiGetVersionRevision()); - const char *curtime(asctime(p)); + const char *curtime = asctime(p); ioprintf(io, header.c_str(), majorVersion, minorVersion, rev, pFile, c.c_str(), curtime, scene->mFlags, 0u); // write the node graph diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.h b/code/AssetLib/Assxml/AssxmlFileWriter.h index 0620c9db7..505cdb1e9 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.h +++ b/code/AssetLib/Assxml/AssxmlFileWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index 670f3de53..5ba041e5a 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER // internal headers -#include "AssetLib/B3D/B3DImporter.h" +#include "B3DImporter.h" #include "PostProcessing/ConvertToLHProcess.h" #include "PostProcessing/TextureTransform.h" diff --git a/code/AssetLib/B3D/B3DImporter.h b/code/AssetLib/B3D/B3DImporter.h index e47d9078b..05f63d75b 100644 --- a/code/AssetLib/B3D/B3DImporter.h +++ b/code/AssetLib/B3D/B3DImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index 4d2cfde15..df5c0746d 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -4,9 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -85,11 +83,9 @@ BVHLoader::BVHLoader() : mLine(), mAnimTickDuration(), mAnimNumFrames(), - noSkeletonMesh() {} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BVHLoader::~BVHLoader() = default; + noSkeletonMesh() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. diff --git a/code/AssetLib/BVH/BVHLoader.h b/code/AssetLib/BVH/BVHLoader.h index 56c32bd99..9c7361a8c 100644 --- a/code/AssetLib/BVH/BVHLoader.h +++ b/code/AssetLib/BVH/BVHLoader.h @@ -4,8 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -80,32 +79,27 @@ class BVHLoader : public BaseImporter { std::vector mChannels; std::vector mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames - Node() : - mNode(nullptr) {} - - explicit Node(const aiNode *pNode) : - mNode(pNode) {} + Node() : mNode(nullptr) {} + explicit Node(const aiNode *pNode) :mNode(pNode) {} }; public: BVHLoader(); - ~BVHLoader(); + ~BVHLoader() override = default; -public: /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ - bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const; + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const override; - void SetupProperties(const Importer *pImp); - const aiImporterDesc *GetInfo() const; + void SetupProperties(const Importer *pImp) override; + const aiImporterDesc *GetInfo() const override; protected: /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ - void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); + void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; -protected: /** Reads the file */ void ReadStructure(aiScene *pScene); diff --git a/code/AssetLib/Blender/BlenderBMesh.cpp b/code/AssetLib/Blender/BlenderBMesh.cpp index a82e7c678..c201edcbc 100644 --- a/code/AssetLib/Blender/BlenderBMesh.cpp +++ b/code/AssetLib/Blender/BlenderBMesh.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/Blender/BlenderBMesh.h b/code/AssetLib/Blender/BlenderBMesh.h index 7d2f71717..aade906d7 100644 --- a/code/AssetLib/Blender/BlenderBMesh.h +++ b/code/AssetLib/Blender/BlenderBMesh.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/Blender/BlenderDNA.cpp b/code/AssetLib/Blender/BlenderDNA.cpp index d22c4bfd7..8f5def96e 100644 --- a/code/AssetLib/Blender/BlenderDNA.cpp +++ b/code/AssetLib/Blender/BlenderDNA.cpp @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderDNA.h b/code/AssetLib/Blender/BlenderDNA.h index 494dc4b34..580b6d401 100644 --- a/code/AssetLib/Blender/BlenderDNA.h +++ b/code/AssetLib/Blender/BlenderDNA.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team - +Copyright (c) 2006-2025, assimp team All rights reserved. diff --git a/code/AssetLib/Blender/BlenderDNA.inl b/code/AssetLib/Blender/BlenderDNA.inl index 4f64987a5..83e07ccdf 100644 --- a/code/AssetLib/Blender/BlenderDNA.inl +++ b/code/AssetLib/Blender/BlenderDNA.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2025, assimp team All rights reserved. @@ -841,5 +841,7 @@ template