Compare commits

..

No commits in common. "master" and "kimkulling-issue_3760" have entirely different histories.

1785 changed files with 98382 additions and 209745 deletions

2
.coveralls.yml 100644
View File

@ -0,0 +1,2 @@
service_name: travis-pro
repo_token: GZXuNlublKFy7HAewHAZLk5ZwgipTFAOA

1
.github/FUNDING.yml vendored
View File

@ -1,2 +1 @@
open_collective: assimp
patreon: assimp

View File

@ -1,11 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "gitsubmodule"
directory: "/" # the .gitmodules file must be placed at the top-level directory of a git working tree
schedule:
interval: "weekly"
open-pull-requests-limit: 15 # Assimp has 15 dependencies

View File

@ -6,140 +6,12 @@ on:
pull_request:
branches: [ master ]
permissions:
contents: write # to fetch code (actions/checkout),and release
jobs:
build:
job:
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, ubuntu-latest-clang++]
# For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
include:
- name: windows-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') && 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" >> $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.
@ -170,23 +42,88 @@ jobs:
os: windows-latest
toolchain: ninja-vs-win64-cxx17
needs: [create-release]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- 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
- uses: actions/checkout@v2
- 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@v2
with:
repository: cpp-pm/polly
path: cmake/polly
- name: Remove contrib directory for Hunter builds
if: contains(matrix.name, 'hunter')
uses: JesseTG/rm@v1.0.2
with:
path: contrib
- name: Cache DX SDK
id: dxcache
if: contains(matrix.name, 'windows')
uses: actions/cache@v2
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"
- 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: '-- -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@v2
if: matrix.name == 'windows-msvc'
with:
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
path: build/bin

View File

@ -1,26 +0,0 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'assimp'
dry-run: false
language: c++
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'assimp'
fuzz-seconds: 300
dry-run: false
language: c++
- name: Upload Crash
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

View File

@ -1,51 +0,0 @@
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.2
with:
path: packaging/windows-innosetup/script_x64.iss
options: /O+

View File

@ -6,15 +6,12 @@ on:
pull_request:
branches: [ master ]
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
job1:
name: adress-sanitizer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- uses: lukka/get-cmake@latest
- uses: lukka/set-shell-env@v1
with:
@ -38,7 +35,7 @@ jobs:
name: undefined-behavior-sanitizer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- uses: lukka/get-cmake@latest
- uses: lukka/set-shell-env@v1
with:
@ -46,7 +43,7 @@ jobs:
CC: clang
- name: configure and build
uses: lukka/run-cmake@v3
uses: lukka/run-cmake@v2
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
@ -57,13 +54,3 @@ jobs:
- name: test
run: cd build/bin && ./unit
shell: bash
job3:
name: printf-sanitizer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: run scan_printf script
run: ./scripts/scan_printf.sh
shell: bash

5
.gitignore vendored
View File

@ -94,7 +94,6 @@ test/gtest/src/gtest-stamp/gtest-gitinfo.txt
test/gtest/src/gtest-stamp/gtest-gitclone-lastrun.txt
Assimp.opensdf
contrib/zlib/CTestTestfile.cmake
contrib/zlib/Debug/zlibstaticd.pdb
ipch/assimp_viewer-44bbbcd1/assimp_viewerd-ccc45335.ipch
bin64/assimp-vc140-mt.dll
bin64/assimp-vc140-mtd.dll
@ -120,7 +119,3 @@ tools/assimp_qt_viewer/ui_mainwindow.h
#Generated directory
generated/*
# 3rd party cloned repos/tarballs etc
# tinyusdz repo, automatically cloned via CMake
contrib/tinyusdz/autoclone

67
.travis.sh 100755
View File

@ -0,0 +1,67 @@
#---------------------------------------------------------------------------
#Open Asset Import Library (assimp)
#---------------------------------------------------------------------------
# Copyright (c) 2006-2020, assimp team
#
# License see LICENSE file
#
function generate() {
OPTIONS="-DASSIMP_WERROR=ON"
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
if [ "$DISABLE_EXPORTERS" = "YES" ] ; then
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES"
else
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
fi
if [ "$SHARED_BUILD" = "ON" ] ; then
OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=ON"
else
OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=OFF"
fi
if [ "$ENABLE_COVERALLS" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_COVERALLS=ON"
else
OPTIONS="$OPTIONS -DASSIMP_COVERALLS=OFF"
fi
if [ "$ASAN" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_ASAN=ON"
else
OPTIONS="$OPTIONS -DASSIMP_ASAN=OFF"
fi
if [ "$UBSAN" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_UBSAN=ON"
fi
cmake -G "Unix Makefiles" $OPTIONS
}
# build and run unittests, if not android
if [ $ANDROID ]; then
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
fi
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ $ANALYZE = "ON" ] ; then
if [ "$CC" = "clang" ]; then
scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_TESTS=OFF
scan-build --status-bugs make -j2
else
cppcheck --version
generate \
&& cppcheck --error-exitcode=1 -j2 -Iinclude -Icode code 2> cppcheck.txt
if [ -s cppcheck.txt ]; then
cat cppcheck.txt
exit 1
fi
fi
else
generate \
&& make -j4 \
&& sudo make install \
&& sudo ldconfig \
&& (cd test/unit; ../../bin/unit)
fi
fi

78
.travis.yml 100644
View File

@ -0,0 +1,78 @@
sudo: required
language: cpp
cache: ccache
before_install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake cppcheck && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
- 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then
if brew ls --versions cmake > /dev/null; then
echo cmake already installed.;
else
brew install cmake;
fi;
brew install python3;
brew install homebrew/x11/freeglut;
fi'
- echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
# install latest LCOV (1.9 was failing)
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz && tar xf lcov_1.11.orig.tar.gz && sudo make -C lcov-1.11/ install && gem install coveralls-lcov && lcov --version && g++ --version ; fi
os:
- linux
compiler:
- gcc
- clang
env:
global:
- secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
- PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
git:
depth: 1
matrix:
include:
- os: linux
compiler: clang
env: ASAN=ON
- os: linux
compiler: clang
env: UBSAN=ON
- os: linux
compiler: clang
env: SHARED_BUILD=ON
- os: linux
compiler: gcc
env: ANALYZE=ON
- os: linux
compiler: gcc
env: ENABLE_COVERALLS=ON
- os: linux
compiler: gcc
env: SHARED_BUILD=ON
install:
- if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
before_script:
cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES
script:
- export COVERALLS_SERVICE_NAME=travis-ci
- export COVERALLS_REPO_TOKEN=abc12345
- . ./.travis.sh
after_success:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi
addons:
coverity_scan:
project:
name: "assimp/assimp"
notification_email: kim.kulling@googlemail.com
build_command_prepend: "cmake ./"
build_command: "make -j4"
branch_pattern: coverity_scan

View File

@ -10,15 +10,16 @@
:: Also see: https://github.com/assimp/assimp/pull/2646
SET SOURCE_DIR=.
SET GENERATOR=Visual Studio 16 2019
SET BINARIES_DIR="./build/Win32"
cmake . -G "%GENERATOR%" -A Win32 -S %SOURCE_DIR% -B %BINARIES_DIR%
cmake --build %BINARIES_DIR% --config debug
:: For generators see "cmake --help"
SET GENERATOR=Visual Studio 15 2017
SET BINARIES_DIR="./BINARIES/Win32"
cmake CMakeLists.txt -G "%GENERATOR%" -S %SOURCE_DIR% -B %BINARIES_DIR%
cmake --build %BINARIES_DIR% --config release
SET BINARIES_DIR="./build/x64"
cmake . -G "%GENERATOR%" -A x64 -S %SOURCE_DIR% -B %BINARIES_DIR%
SET BINARIES_DIR="./BINARIES/x64"
cmake CMakeLists.txt -G "%GENERATOR% Win64" -S %SOURCE_DIR% -B %BINARIES_DIR%
cmake --build %BINARIES_DIR% --config debug
cmake --build %BINARIES_DIR% --config release

View File

@ -7,15 +7,14 @@ You can download and install assimp using the [vcpkg](https://github.com/Microso
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install assimp
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
sudo apt-get install assimp
```
## Install pyassimp
@ -27,7 +26,7 @@ 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
Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via
```bash
sudo apt-get install cmake
```
@ -43,16 +42,15 @@ cd assimp
cmake CMakeLists.txt
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/
First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
```bash
cmake CMakeLists.txt
```
This will generate the project files for the visual studio. All dependencies used to build Asset-Importer-Lib shall be part of the repo. If you want to use you own zlib installation this is possible as well. Check the options for it.
This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it.
### Build instructions for Windows with UWP
See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
@ -64,9 +62,9 @@ Open a terminal and got to your repository. You can generate the makefiles and b
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.
The option -j descripes the number of parallel processes for the build. In this case make will try to use 4 cores for the build.
If you want to use an IDE for linux you can try QTCreator for instance.
If you want to use a IDE for linux you can try QTCreator for instance.
### Build instructions for MinGW
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
@ -86,28 +84,23 @@ Besides the toolchain, compilation should be the same as for Linux / Unix.
### CMake build options
The cmake-build-environment provides options to configure the build. The following options can be used:
- **ASSIMP_HUNTER_ENABLED (default OFF)**: Enable Hunter package manager support.
- **BUILD_SHARED_LIBS (default ON)**: Generation of shared libs (dll for windows, so for Linux). Set this to OFF to get a static lib.
- **ASSIMP_BUILD_FRAMEWORK (default OFF, MacOnly)**: Build package as Mac OS X Framework bundle.
- **ASSIMP_DOUBLE_PRECISION (default OFF)**: All data will be stored as double values.
- **ASSIMP_OPT_BUILD_PACKAGES (default OFF)**: Set to ON to generate CPack configuration files and packaging targets.
- **ASSIMP_ANDROID_JNIIOSYSTEM (default OFF)**: Android JNI IOSystem support is active.
- **ASSIMP_NO_EXPORT (default OFF)**: Disable Assimp's export functionality.
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporters enabled.
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importers enabled.
- **ASSIMP_BUILD_ASSIMP_TOOLS (default OFF)**: If the supplementary tools for Assimp are built in addition to the library.
- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
- **ASSIMP_COVERALLS (default OFF)**: Enable this to measure test coverage.
- **ASSIMP_INSTALL (default ON)**: Install Assimp library. Disable this if you want to use Assimp as a submodule.
- **ASSIMP_WARNINGS_AS_ERRORS (default ON)**: Treat all warnings as errors.
- **ASSIMP_ASAN (default OFF)**: Enable AddressSanitizer.
- **ASSIMP_UBSAN (default OFF)**: Enable Undefined Behavior sanitizer.
- **ASSIMP_BUILD_DOCS (default OFF)**: Build documentation using Doxygen. OBSOLETE, see https://github.com/assimp/assimp-docs
- **ASSIMP_INJECT_DEBUG_POSTFIX (default ON)**: Inject debug postfix in .a/.so/.lib/.dll lib names
- **ASSIMP_IGNORE_GIT_HASH (default OFF)**: Don't call git to get the hash.
- **ASSIMP_INSTALL_PDB (default ON)**: Install MSVC debug files.
- **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).
- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib.
- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle
- **ASSIMP_DOUBLE_PRECISION( default OFF )**: All data will be stored as double values.
- **ASSIMP_OPT_BUILD_PACKAGES ( default OFF)**: Set to ON to generate CPack configuration files and packaging targets
- **ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF )**: Android JNI IOSystem support is active
- **ASSIMP_NO_EXPORT ( default OFF )**: Disable Assimp's export functionality
- **ASSIMP_BUILD_ZLIB ( default OFF )**: Build your own zlib
- **ASSIMP_BUILD_ASSIMP_TOOLS ( default ON )**: If the supplementary tools for Assimp are built in addition to the library.
- **ASSIMP_BUILD_SAMPLES ( default OFF )**: If the official samples are built as well (needs Glut).
- **ASSIMP_BUILD_TESTS ( default ON )**: If the test suite for Assimp is built in addition to the library.
- **ASSIMP_COVERALLS ( default OFF )**: Enable this to measure test coverage.
- **ASSIMP_ERROR_MAX( default OFF)**: Enable all warnings.
- **ASSIMP_WERROR( default OFF )**: Treat warnings as errors.
- **ASSIMP_ASAN ( default OFF )**: Enable AddressSanitizer.
- **ASSIMP_UBSAN ( default OFF )**: Enable Undefined Behavior sanitizer.
- **SYSTEM_IRRXML ( default OFF )**: Use system installed Irrlicht/IrrXML library.
- **BUILD_DOCS ( default OFF )**: Build documentation using Doxygen.
- **INJECT_DEBUG_POSTFIX( default ON )**: Inject debug postfix in .a/.so lib names
- **IGNORE_GIT_HASH ( default OFF )**: Don't call git to get the hash.
- **ASSIMP_INSTALL_PDB ( default ON )**: Install MSVC debug files.

View File

@ -1,6 +1,6 @@
# Open Asset Import Library (assimp)
# ----------------------------------------------------------------------
# Copyright (c) 2006-2024, assimp team
# Copyright (c) 2006-2021, assimp team
#
# All rights reserved.
#
@ -38,40 +38,22 @@ SET(CMAKE_POLICY_DEFAULT_CMP0012 NEW)
SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
# 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)
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 or later
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")
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.25.5.tar.gz"
SHA1 "a20151e4c0740ee7d0f9994476856d813cdead29"
URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz"
SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410"
)
add_definitions(-DASSIMP_USE_HUNTER)
ENDIF()
PROJECT(Assimp VERSION 5.4.3)
PROJECT( Assimp VERSION 5.0.1 )
# All supported options ###############################################
@ -99,9 +81,13 @@ OPTION( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality."
OFF
)
OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib"
OFF
)
OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library."
OFF
ON
)
OPTION ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)."
@ -119,9 +105,9 @@ OPTION( ASSIMP_INSTALL
"Disable this if you want to use assimp as a submodule."
ON
)
OPTION ( ASSIMP_WARNINGS_AS_ERRORS
"Treat all warnings as errors."
ON
OPTION ( ASSIMP_ERROR_MAX
"Enable all warnings."
OFF
)
OPTION ( ASSIMP_ASAN
"Enable AddressSanitizer."
@ -145,45 +131,22 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
OFF
)
IF (WIN32)
OPTION( ASSIMP_BUILD_ZLIB
"Build your zlib"
ON
)
ELSE()
OPTION( ASSIMP_BUILD_ZLIB
"Build your zlib"
OFF
)
ENDIF()
IF (WIN32)
# Use a subset of Windows.h
IF ( WIN32 )
# Use subset of Windows.h
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
"If the Assimp view tool is built. (requires DirectX)"
OFF )
IF(MSVC)
OPTION( ASSIMP_INSTALL_PDB
"Create MSVC debug symbol files and add to Install target."
"Install MSVC debug files."
ON )
IF(NOT (MSVC_VERSION LESS 1900))
# Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier)
# Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
ENDIF()
# 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 overridden by some Visual Studio generators, so we use an alternative
# global method here:
if (${USE_STATIC_CRT})
add_compile_options(
$<$<CONFIG:>:/MT>
$<$<CONFIG:Debug>:/MTd>
$<$<CONFIG:Release>:/MT>
)
endif()
ENDIF()
ENDIF()
@ -203,7 +166,6 @@ ENDIF()
IF(NOT BUILD_SHARED_LIBS)
MESSAGE(STATUS "Shared libraries disabled")
SET(LINK_SEARCH_START_STATIC TRUE)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} ${CMAKE_FIND_LIBRARY_SUFFIXES})
ELSE()
MESSAGE(STATUS "Shared libraries enabled")
ENDIF()
@ -216,9 +178,10 @@ SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VER
SET (ASSIMP_SOVERSION 5)
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 99)
if(NOT ASSIMP_HUNTER_ENABLED)
# Enable C++11 support globally
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
endif()
IF(NOT ASSIMP_IGNORE_GIT_HASH)
# Get the current working branch
@ -248,6 +211,16 @@ IF(ASSIMP_DOUBLE_PRECISION)
ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
ENDIF()
CONFIGURE_FILE(
${CMAKE_CURRENT_LIST_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h
)
CONFIGURE_FILE(
${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h
)
INCLUDE_DIRECTORIES( BEFORE
./
code/
@ -265,136 +238,107 @@ 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
IF(NOT ${OPERATING_SYSTEM} MATCHES "Android")
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit Linux
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
ENDIF()
ENDIF()
ENDIF()
# Grouped compiler settings ########################################
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF()
IF(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13)
MESSAGE(STATUS "GCC13 detected disabling \"-Wdangling-reference\" in Cpp files as it appears to be a false positive")
ADD_COMPILE_OPTIONS("$<$<COMPILE_LANGUAGE:CXX>:-Wno-dangling-reference>")
ENDIF()
# hide all not-exported symbols
IF(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64" )
SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++)
SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++)
ELSE()
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++)
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++)
ENDIF()
ELSEIF(MSVC)
# enable multi-core compilation with MSVC
IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
ADD_COMPILE_OPTIONS(/bigobj)
ADD_COMPILE_OPTIONS(/bigobj /W4 /WX )
ELSE() # msvc
ADD_COMPILE_OPTIONS(/MP /bigobj)
ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX)
ENDIF()
# disable "elements of array '' will be default initialized" warning on MSVC2013
IF(MSVC12)
ADD_COMPILE_OPTIONS(/wd4351)
ENDIF()
# 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")
# 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()
# Source code is encoded in UTF-8
ADD_COMPILE_OPTIONS(/source-charset:utf-8)
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 (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 11)
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}")
ELSEIF( MINGW )
ELSEIF( CMAKE_COMPILER_IS_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.")
ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3)
message(WARNING "MinGW is old, if you experience errors, update MinGW.")
ENDIF()
IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-std=gnu++17 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
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 -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}")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
ENDIF()
IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
ELSE()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
# Experimental for pdb generation
ENDIF()
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")
ENDIF()
IF (ASSIMP_ERROR_MAX)
MESSAGE(STATUS "Turning on all warnings")
IF (MSVC)
ADD_COMPILE_OPTIONS(/W4) # NB: there is a /Wall option, pedantic mode
ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
ENDIF()
ENDIF()
IF (ASSIMP_ASAN)
MESSAGE(STATUS "AddressSanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
ENDIF()
IF (ASSIMP_UBSAN)
MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
ENDIF()
INCLUDE (FindPkgMacros)
INCLUDE (PrecompiledHeader)
# Set Assimp project output directory variables.
# Will respect top-level CMAKE_*_OUTPUT_DIRECTORY variables if any are set.
IF(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
ELSE()
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} CACHE STRING "Path for runtime output files")
ENDIF()
IF(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
ELSE()
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} CACHE STRING "Path for runtime output files")
ENDIF()
IF(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for library output files")
ELSE()
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} CACHE STRING "Path for runtime output files")
ENDIF()
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files")
# Macro used to set the output directories of a target to the
# respective Assimp output directories.
@ -421,6 +365,13 @@ IF (NOT TARGET uninstall AND ASSIMP_INSTALL)
ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF()
# cmake configuration files
if(${BUILD_SHARED_LIBS})
set(BUILD_LIB_TYPE SHARED)
else()
set(BUILD_LIB_TYPE STATIC)
endif()
IF( UNIX )
# Use GNUInstallDirs for Unix predefined directories
INCLUDE(GNUInstallDirs)
@ -446,14 +397,14 @@ 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(CMAKE_CONFIG_TEMPLATE_FILE "cmake/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(CMAKE_CONFIG_TEMPLATE_FILE "cmake/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")
@ -475,20 +426,18 @@ configure_package_config_file(
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
)
if(ASSIMP_INSTALL)
install(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
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}
)
endif()
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT}
)
IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc)
@ -506,7 +455,7 @@ IF(ASSIMP_HUNTER_ENABLED)
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 AND ASSIMP_INSTALL)
IF( ZLIB_FOUND )
INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF()
@ -515,11 +464,7 @@ ELSE()
FIND_PACKAGE(ZLIB)
ENDIF()
IF ( NOT ZLIB_FOUND AND NOT ASSIMP_BUILD_ZLIB )
message( FATAL_ERROR
"Build configured with -DASSIMP_BUILD_ZLIB=OFF but unable to find zlib"
)
ELSEIF( NOT ZLIB_FOUND )
IF( NOT ZLIB_FOUND )
MESSAGE(STATUS "compiling zlib from sources")
INCLUDE(CheckIncludeFile)
INCLUDE(CheckTypeSize)
@ -588,15 +533,11 @@ SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
)
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
IF (WIN32)
# pick the correct prebuilt library
IF(MSVC143)
SET(C4D_LIB_POSTFIX "_2022")
ELSEIF(MSV142)
SET(C4D_LIB_POSTFIX "_2019")
ELSEIF(MSVC15)
IF(MSVC15)
SET(C4D_LIB_POSTFIX "_2017")
ELSEIF(MSVC14)
SET(C4D_LIB_POSTFIX "_2015")
@ -608,7 +549,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
SET(C4D_LIB_POSTFIX "_2010")
ELSE()
MESSAGE( FATAL_ERROR
"C4D for Windows is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3"
"C4D is currently only supported with MSVC 10, 11, 12, 14"
)
ENDIF()
@ -626,30 +567,15 @@ 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)
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"
)
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"
"C4D is currently only available on Windows 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")
@ -659,7 +585,7 @@ ELSE()
IF ( ASSIMP_BUILD_DRACO )
# Primarily for glTF v2
# Enable Draco glTF feature set
set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
set(DRACO_GLTF ON CACHE BOOL "" FORCE)
# Disable unnecessary or omitted components
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
set(DRACO_WASM OFF CACHE BOOL "" FORCE)
@ -685,29 +611,22 @@ ELSE()
"-Wno-sign-compare"
"-Wno-unused-local-typedefs"
)
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()
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang
list(APPEND DRACO_CXX_FLAGS
"-fvisibility=default"
)
ENDIF()
# Don't build or install all of Draco by default
ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
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()
if(BUILD_SHARED_LIBS)
set(draco_LIBRARIES "draco_shared")
else()
set(draco_LIBRARIES "draco_static")
endif()
endif()
@ -715,13 +634,13 @@ ELSE()
set_target_properties(draco_encoder draco_decoder PROPERTIES
EXCLUDE_FROM_ALL TRUE
EXCLUDE_FROM_DEFAULT_BUILD TRUE
)
)
# Do build the draco shared library
set_target_properties(${draco_LIBRARIES} PROPERTIES
EXCLUDE_FROM_ALL FALSE
EXCLUDE_FROM_DEFAULT_BUILD FALSE
)
)
TARGET_USE_COMMON_OUTPUT_DIRECTORY(${draco_LIBRARIES})
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder)
@ -730,34 +649,29 @@ ELSE()
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
# This is probably wrong
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()
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()
# Main assimp code
ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
# The viewer for windows only
IF (WIN32)
FIND_PACKAGE(DirectX)
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
IF ( WIN32 )
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF ()
ELSE()
MESSAGE("Building Assimp Viewer only supported on Windows.")
ENDIF ()
# The command line tool
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
@ -777,22 +691,12 @@ IF ( ASSIMP_BUILD_TESTS )
ADD_SUBDIRECTORY( test/ )
ENDIF ()
# Generate a pkg-config .pc, revision.h, and config.h for the Assimp library.
# Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
IF ( ASSIMP_INSTALL )
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
ENDIF()
CONFIGURE_FILE(
${CMAKE_CURRENT_LIST_DIR}/include/assimp/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/assimp/revision.h
)
CONFIGURE_FILE(
${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h
)
IF ( ASSIMP_INSTALL )
IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
# Packing information
@ -826,7 +730,7 @@ IF ( ASSIMP_INSTALL )
SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
SET(CPACK_DEBIAN_PACKAGE_SUGGESTS)
SET(CPACK_DEBIAN_PACKAGE_NAME "assimp")
SET(cPACK_DEBIAN_PACKAGE_NAME "assimp")
SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging)
SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
SET(CPACK_DEBIAN_CHANGELOG)
@ -855,7 +759,7 @@ if(WIN32)
IF(MSVC_TOOLSET_VERSION)
SET(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
SET(ASSIMP_MSVC_VERSION ${MSVC_PREFIX})
SET(ASSIMP_MSVC_VERSION ${MCVS_PREFIX})
ELSE()
IF(MSVC12)
SET(ASSIMP_MSVC_VERSION "vc120")
@ -863,10 +767,6 @@ if(WIN32)
SET(ASSIMP_MSVC_VERSION "vc140")
ELSEIF(MSVC15)
SET(ASSIMP_MSVC_VERSION "vc141")
ELSEIF(MSV142)
SET(ASSIMP_MSVC_VERSION "vc142")
ELSEIF(MSVC143)
SET(ASSIMP_MSVC_VERSION "vc143")
ENDIF()
ENDIF()

View File

@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@ -1,12 +1,16 @@
FROM ubuntu:22.04
FROM ubuntu:14.04
RUN apt-get update && apt-get install --no-install-recommends -y ninja-build \
RUN apt-get update && apt-get install -y \
git cmake build-essential software-properties-common
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update && apt-get install -y gcc-4.9 g++-4.9 && \
cd /usr/bin && \
rm gcc g++ cpp && \
ln -s gcc-4.9 gcc && \
ln -s g++-4.9 g++ && \
ln -s cpp-4.9 cpp
WORKDIR /opt
RUN apt install zlib1g-dev
# Build Assimp
RUN git clone https://github.com/assimp/assimp.git /opt/assimp
@ -15,8 +19,7 @@ WORKDIR /opt/assimp
RUN git checkout master \
&& mkdir build && cd build && \
cmake -G 'Ninja' \
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DASSIMP_BUILD_ASSIMP_TOOLS=ON \
.. && \
ninja -j4 && ninja install
make && make install

View File

@ -14,4 +14,4 @@ https://assimp-docs.readthedocs.io/en/latest/
Building Assimp
------------------------------
Just check the build-instructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md
Just check the build-instaructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md

1
README 100644
View File

@ -0,0 +1 @@
See Readme.md

View File

@ -1,41 +1,40 @@
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.
A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
### Current project status ###
[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp)
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
<a href="https://scan.coverity.com/projects/5607">
<img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a>
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
<br>
APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
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.
### Documentation ###
Read [our latest documentation](https://assimp-docs.readthedocs.io/en/latest/).
### Latest Doc's ###
Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/).
### Pre-built binaries ###
Download binaries from [our Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
### Get involved ###
This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
<br>
You find a bug in the docs? Use [Doc-Repo](https://github.com/assimp/assimp-docs).
<br>
Please check our Wiki as well: https://github.com/assimp/assimp/wiki
### Test data ###
Clone [our model database](https://github.com/assimp/assimp-mdb).
### Communities ###
- 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)
If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
#### Supported file formats ####
See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md).
You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
### Building ###
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.
Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
### Ports ###
* [Android](port/AndroidJNI/README.md)
@ -43,40 +42,43 @@ Start by reading [our build instructions](https://github.com/assimp/assimp/blob/
* [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/)
* [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))
* [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.
[Assimp-Viewer](https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
#### Repository structure ####
Open Asset Import Library is implemented in C++. The directory structure looks like this:
Open Asset Import Library is implemented in C++. The directory structure looks like:
/code Source code
/contrib Third-party libraries
/doc Documentation (doxysource 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
/scripts Scripts used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those.
/test Unit- and regression tests, test suite of models
/tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible use cases for Assimp
/samples A small number of samples to illustrate possible
use cases for Assimp
The source code is organized in the following way:
code/Common The base implementation for importers and the infrastructure
code/CApi Special implementations which are only used for the C-API
code/Geometry A collection of geometry tools
code/Material The material system
code/PBR An exporter for physical-based models
code/PostProcessing The post-processing steps
code/AssetLib/<FormatName> Implementation for import and export of the format
code/AssetLib/<FormatName> Implementation for import and export for the format
### Where to get help ###
For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
(CHMs for Windows are included in some release packages and should be located right here in the root folder).
If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
### Contributing ###
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
@ -113,4 +115,4 @@ and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you ma
For the legal details, see the `LICENSE` file.
### Why this name ###
Sorry, we're germans :-), no English native speakers ...
Sorry, we're germans :-), no english native speakers ...

View File

@ -1,16 +0,0 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 5.2.4 | :white_check_mark: |
## Reporting a Vulnerability
If you have found any security vulnerability you can contact us via
kim.kulling@googlemail.com

View File

@ -55,7 +55,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
endif(CMAKE_CL_64)
find_library(DirectX_LIBRARY NAMES d3d9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_DXERR_LIBRARY NAMES DxErr DxErr9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})

View File

@ -0,0 +1,17 @@
# Find IrrXMl from irrlicht project
#
# Find LibIrrXML headers and library
#
# IRRXML_FOUND - IrrXML found
# IRRXML_INCLUDE_DIR - Headers location
# IRRXML_LIBRARY - IrrXML main library
find_path(IRRXML_INCLUDE_DIR irrXML.h
PATH_SUFFIXES include/irrlicht include/irrxml)
find_library(IRRXML_LIBRARY IrrXML)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(IrrXML REQUIRED_VARS IRRXML_INCLUDE_DIR IRRXML_LIBRARY)
mark_as_advanced(IRRXML_INCLUDE_DIR IRRXML_LIBRARY)

View File

@ -54,7 +54,7 @@ macro(clear_if_changed TESTVAR)
set(${var} "NOTFOUND" CACHE STRING "x" FORCE)
endforeach(var)
endif ()
set(${TESTVAR}_INT_CHECK "${${TESTVAR}}" CACHE INTERNAL "x" FORCE)
set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE)
endmacro(clear_if_changed)
# Try to get some hints from pkg-config, if available

View File

@ -1,19 +0,0 @@
@PACKAGE_INIT@
find_package(RapidJSON CONFIG REQUIRED)
find_package(ZLIB CONFIG REQUIRED)
find_package(utf8cpp CONFIG REQUIRED)
find_package(minizip CONFIG REQUIRED)
find_package(openddlparser CONFIG REQUIRED)
find_package(poly2tri CONFIG REQUIRED)
find_package(polyclipping CONFIG REQUIRED)
find_package(zip CONFIG REQUIRED)
find_package(pugixml CONFIG REQUIRED)
find_package(stb CONFIG REQUIRED)
if(@ASSIMP_BUILD_DRACO@)
find_package(draco CONFIG REQUIRED)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")

View File

@ -22,9 +22,38 @@
# 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)

View File

@ -0,0 +1,19 @@
@PACKAGE_INIT@
find_package(RapidJSON CONFIG REQUIRED)
find_package(ZLIB CONFIG REQUIRED)
find_package(utf8cpp CONFIG REQUIRED)
find_package(minizip CONFIG REQUIRED)
find_package(openddlparser CONFIG REQUIRED)
find_package(poly2tri CONFIG REQUIRED)
find_package(polyclipping CONFIG REQUIRED)
find_package(zip CONFIG REQUIRED)
find_package(pugixml CONFIG REQUIRED)
find_package(stb CONFIG REQUIRED)
if(@ASSIMP_BUILD_DRACO@)
find_package(draco CONFIG REQUIRED)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -52,9 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cctype>
#include <memory>
namespace Assimp {
using namespace Assimp;
static constexpr unsigned int NotSet = 0xcdcdcdcd;
static const unsigned int NotSet = 0xcdcdcdcd;
// ------------------------------------------------------------------------------------------------
// Setup final material indices, generae a default material if necessary
@ -68,8 +68,8 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
unsigned int idx(NotSet);
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
std::string s = mScene->mMaterials[i].mName;
for (char &it : s) {
it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
*it = static_cast<char>(::tolower(static_cast<unsigned char>(*it)));
}
if (std::string::npos == s.find("default")) continue;
@ -79,7 +79,12 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
mScene->mMaterials[i].mDiffuse.r !=
mScene->mMaterials[i].mDiffuse.b) continue;
if (ContainsTextures(i)) {
if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexBump.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexShininess.mMapName.length() != 0) {
continue;
}
idx = i;
@ -262,7 +267,6 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
unsigned int iWire = 1;
mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
[[fallthrough]];
case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud;
@ -593,7 +597,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
// Cameras or lights define their transformation in their parent node and in the
// corresponding light or camera chunks. However, we read and process the latter
// to be able to return valid cameras/lights even if no scenegraph is given.
// to to be able to return valid cameras/lights even if no scenegraph is given.
for (unsigned int n = 0; n < pcSOut->mNumCameras; ++n) {
if (pcSOut->mCameras[n]->mName == pcOut->mName) {
pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f, 0.f, 1.f);
@ -643,17 +647,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
}
// Allocate storage for children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
pcOut->mNumChildren = size;
if (size == 0) {
return;
}
pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
// Recursively process all children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
for (unsigned int i = 0; i < size; ++i) {
pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut;
@ -715,7 +713,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
pcNode->mNumMeshes = 1;
// Build a name for the node
pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "3DSMesh_%u", i);
pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i);
}
// Build dummy nodes for all cameras
@ -811,6 +809,4 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
}
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -52,13 +52,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/Exceptional.h>
#include <assimp/IOSystem.hpp>
#include <memory>
using namespace Assimp;
namespace Assimp {
using namespace D3DS;
namespace {
@ -210,7 +209,9 @@ Discreet3DSExporter::Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, con
}
// ------------------------------------------------------------------------------------------------
Discreet3DSExporter::~Discreet3DSExporter() = default;
Discreet3DSExporter::~Discreet3DSExporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) {
@ -329,7 +330,6 @@ void Discreet3DSExporter::WriteMaterials() {
case aiShadingMode_Blinn:
case aiShadingMode_CookTorrance:
case aiShadingMode_Fresnel:
case aiShadingMode_PBR_BRDF: // Possibly should be Discreet3DS::Metal in some cases but this is undocumented
shading_mode_out = Discreet3DS::Phong;
break;
@ -356,10 +356,7 @@ void Discreet3DSExporter::WriteMaterials() {
writer.PutI2(1);
}
// Fallback to BASE_COLOR if no DIFFUSE
if (!WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE))
WriteTexture(mat, aiTextureType_BASE_COLOR, Discreet3DS::CHUNK_MAT_TEXTURE);
WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
@ -370,21 +367,20 @@ void Discreet3DSExporter::WriteMaterials() {
}
// ------------------------------------------------------------------------------------------------
// returns true if the texture existed
bool Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) {
void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) {
aiString path;
aiTextureMapMode map_mode[2] = {
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
};
ai_real blend = 1.0;
if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) {
return false;
return;
}
// TODO: handle embedded textures properly
if (path.data[0] == '*') {
ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str());
return false;
return;
}
ChunkWriter chunk(writer, chunk_flags);
@ -406,7 +402,6 @@ bool Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type
writer.PutU2(val);
}
// TODO: export texture transformation (i.e. UV offset, scale, rotation)
return true;
}
// ------------------------------------------------------------------------------------------------

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -56,7 +57,8 @@ struct aiNode;
struct aiMaterial;
struct aiMesh;
namespace Assimp {
namespace Assimp
{
// ------------------------------------------------------------------------------------------------
/**
@ -71,7 +73,7 @@ public:
private:
void WriteMeshes();
void WriteMaterials();
bool WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
void WriteFaceMaterialChunk(const aiMesh& mesh);
int WriteHierarchy(const aiNode& node, int level, int sibling_level);
void WriteString(const std::string& s);
@ -86,7 +88,7 @@ private:
std::map<const aiNode*, aiMatrix4x4> trafos;
using MeshesByNodeMap = std::multimap<const aiNode*, unsigned int>;
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
MeshesByNodeMap meshes;
};

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/light.h>
#include <assimp/material.h>
#include <assimp/qnan.h>
#include <cstdio> //sprintf
#include <stdio.h> //sprintf
namespace Assimp {
namespace D3DS {
@ -259,7 +259,7 @@ namespace Discreet3DS {
// Specifies the file name of a texture
CHUNK_MAPFILE = 0xA300,
// Specifies whether a material requires two-sided rendering
// Specifies whether a materail requires two-sided rendering
CHUNK_MAT_TWO_SIDE = 0xA081,
// ********************************************************************
@ -322,6 +322,7 @@ struct Texture {
//! Default constructor
Texture() AI_NO_EXCEPT
: mTextureBlend(0.0f),
mMapName(),
mOffsetU(0.0),
mOffsetV(0.0),
mScaleU(1.0),
@ -333,11 +334,51 @@ struct Texture {
mTextureBlend = get_qnan();
}
Texture(const Texture &other) = default;
Texture(const Texture &other) :
mTextureBlend(other.mTextureBlend),
mMapName(other.mMapName),
mOffsetU(other.mOffsetU),
mOffsetV(other.mOffsetV),
mScaleU(other.mScaleU),
mScaleV(other.mScaleV),
mRotation(other.mRotation),
mMapMode(other.mMapMode),
bPrivate(other.bPrivate),
iUVSrc(other.iUVSrc) {
// empty
}
Texture(Texture &&other) AI_NO_EXCEPT = default;
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
mMapName(std::move(other.mMapName)),
mOffsetU(other.mOffsetU),
mOffsetV(other.mOffsetV),
mScaleU(other.mScaleU),
mScaleV(other.mScaleV),
mRotation(other.mRotation),
mMapMode(other.mMapMode),
bPrivate(other.bPrivate),
iUVSrc(other.iUVSrc) {
// empty
}
Texture &operator=(Texture &&other) AI_NO_EXCEPT = default;
Texture &operator=(Texture &&other) AI_NO_EXCEPT {
if (this == &other) {
return *this;
}
mTextureBlend = other.mTextureBlend;
mMapName = std::move(other.mMapName);
mOffsetU = other.mOffsetU;
mOffsetV = other.mOffsetV;
mScaleU = other.mScaleU;
mScaleV = other.mScaleV;
mRotation = other.mRotation;
mMapMode = other.mMapMode;
bPrivate = other.bPrivate;
iUVSrc = other.iUVSrc;
return *this;
}
//! Specifies the blend factor for the texture
ai_real mTextureBlend;
@ -365,13 +406,14 @@ 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(0.6f, 0.6f, 0.6f),
mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
mSpecularExponent(ai_real(0.0)),
mShininessStrength(ai_real(1.0)),
mShading(Discreet3DS::Gouraud),
@ -384,7 +426,7 @@ struct Material {
//! Constructor with explicit name
explicit Material(const std::string &name) :
mName(name),
mDiffuse(0.6f, 0.6f, 0.6f),
mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
mSpecularExponent(ai_real(0.0)),
mShininessStrength(ai_real(1.0)),
mShading(Discreet3DS::Gouraud),
@ -394,9 +436,83 @@ struct Material {
// empty
}
Material(const Material &other) = default;
Material(const Material &other) :
mName(other.mName),
mDiffuse(other.mDiffuse),
mSpecularExponent(other.mSpecularExponent),
mShininessStrength(other.mShininessStrength),
mSpecular(other.mSpecular),
mAmbient(other.mAmbient),
mShading(other.mShading),
mTransparency(other.mTransparency),
sTexDiffuse(other.sTexDiffuse),
sTexOpacity(other.sTexOpacity),
sTexSpecular(other.sTexSpecular),
sTexReflective(other.sTexReflective),
sTexBump(other.sTexBump),
sTexEmissive(other.sTexEmissive),
sTexShininess(other.sTexShininess),
mBumpHeight(other.mBumpHeight),
mEmissive(other.mEmissive),
sTexAmbient(other.sTexAmbient),
mTwoSided(other.mTwoSided) {
// empty
}
virtual ~Material() = default;
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
mDiffuse(other.mDiffuse),
mSpecularExponent(other.mSpecularExponent),
mShininessStrength(other.mShininessStrength),
mSpecular(other.mSpecular),
mAmbient(other.mAmbient),
mShading(other.mShading),
mTransparency(other.mTransparency),
sTexDiffuse(std::move(other.sTexDiffuse)),
sTexOpacity(std::move(other.sTexOpacity)),
sTexSpecular(std::move(other.sTexSpecular)),
sTexReflective(std::move(other.sTexReflective)),
sTexBump(std::move(other.sTexBump)),
sTexEmissive(std::move(other.sTexEmissive)),
sTexShininess(std::move(other.sTexShininess)),
mBumpHeight(other.mBumpHeight),
mEmissive(other.mEmissive),
sTexAmbient(std::move(other.sTexAmbient)),
mTwoSided(other.mTwoSided) {
// empty
}
Material &operator=(Material &&other) AI_NO_EXCEPT {
if (this == &other) {
return *this;
}
mName = std::move(other.mName);
mDiffuse = other.mDiffuse;
mSpecularExponent = other.mSpecularExponent;
mShininessStrength = other.mShininessStrength,
mSpecular = other.mSpecular;
mAmbient = other.mAmbient;
mShading = other.mShading;
mTransparency = other.mTransparency;
sTexDiffuse = std::move(other.sTexDiffuse);
sTexOpacity = std::move(other.sTexOpacity);
sTexSpecular = std::move(other.sTexSpecular);
sTexReflective = std::move(other.sTexReflective);
sTexBump = std::move(other.sTexBump);
sTexEmissive = std::move(other.sTexEmissive);
sTexShininess = std::move(other.sTexShininess);
mBumpHeight = other.mBumpHeight;
mEmissive = other.mEmissive;
sTexAmbient = std::move(other.sTexAmbient);
mTwoSided = other.mTwoSided;
return *this;
}
virtual ~Material() {
// empty
}
//! Name of the material
std::string mName;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -54,9 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp>
namespace Assimp {
using namespace Assimp;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"Discreet 3DS Importer",
"",
"",
@ -103,11 +103,28 @@ Discreet3DSImporter::Discreet3DSImporter() :
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
Discreet3DSImporter::~Discreet3DSImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// 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 */ };
return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]);
bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
if (extension == "3ds" || extension == "prj") {
return true;
}
if (!extension.length() || checkSig) {
uint16_t token[3];
token[0] = 0x4d4d;
token[1] = 0x3dc2;
//token[2] = 0x3daa;
return CheckMagicToken(pIOHandler, pFile, token, 2, 0, 2);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@ -262,15 +279,8 @@ void Discreet3DSImporter::ParseMainChunk() {
};
ASSIMP_3DS_END_CHUNK();
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif
// recursively continue processing this hierarchy level
return ParseMainChunk();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
// ------------------------------------------------------------------------------------------------
@ -320,7 +330,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
case Discreet3DS::CHUNK_MAT_MATERIAL:
// Add a new material to the list
mScene->mMaterials.emplace_back(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size())));
mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size()))));
ParseMaterialChunk();
break;
@ -365,13 +375,13 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
// IMPLEMENTATION NOTE;
// Cameras or lights define their transformation in their parent node and in the
// corresponding light or camera chunks. However, we read and process the latter
// to be able to return valid cameras/lights even if no scenegraph is given.
// to to be able to return valid cameras/lights even if no scenegraph is given.
// get chunk type
switch (chunk.Flag) {
case Discreet3DS::CHUNK_TRIMESH: {
// this starts a new triangle mesh
mScene->mMeshes.emplace_back(std::string(name, num));
mScene->mMeshes.push_back(D3DS::Mesh(std::string(name, num)));
// Read mesh chunks
ParseMeshChunk();
@ -439,7 +449,7 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
// Read the lense angle
camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4());
if (camera->mHorizontalFOV < 0.001f) {
camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f));
camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f);
}
// Now check for further subchunks
@ -1000,7 +1010,7 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mFaces.reserve(num);
while (num-- > 0) {
// 3DS faces are ALWAYS triangles
mMesh.mFaces.emplace_back();
mMesh.mFaces.push_back(D3DS::Face());
D3DS::Face &sFace = mMesh.mFaces.back();
sFace.mIndices[0] = (uint16_t)stream->GetI2();
@ -1285,7 +1295,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_LINRGBF:
bGamma = true;
// fallthrough
case Discreet3DS::CHUNK_RGBF:
if (sizeof(float) * 3 > diff) {
*out = clrError;
@ -1298,7 +1308,6 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
case Discreet3DS::CHUNK_LINRGBB:
bGamma = true;
// fallthrough
case Discreet3DS::CHUNK_RGBB: {
if (sizeof(char) * 3 > diff) {
*out = clrError;
@ -1335,6 +1344,4 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
(void)bGamma;
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AI_3DSIMPORTER_H_INC
#define AI_3DSIMPORTER_H_INC
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
#include <assimp/BaseImporter.h>
#include <assimp/types.h>
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
#include "3DSHelper.h"
#include <assimp/StreamReader.h>
@ -59,6 +59,7 @@ struct aiNode;
namespace Assimp {
using namespace D3DS;
// ---------------------------------------------------------------------------------
@ -67,21 +68,21 @@ using namespace D3DS;
class Discreet3DSImporter : public BaseImporter {
public:
Discreet3DSImporter();
~Discreet3DSImporter() override = default;
~Discreet3DSImporter();
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
*/
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const override;
bool checkSig) const;
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp) override;
void SetupProperties(const Importer* pImp);
protected:
@ -89,14 +90,14 @@ protected:
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
*/
const aiImporterDesc* GetInfo () const override;
const aiImporterDesc* GetInfo () const;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler) override;
IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Converts a temporary material to the outer representation
@ -207,15 +208,6 @@ protected:
*/
void ReplaceDefaultMaterial();
bool ContainsTextures(unsigned int i) const {
return !mScene->mMaterials[i].sTexDiffuse.mMapName.empty() ||
!mScene->mMaterials[i].sTexBump.mMapName.empty() ||
!mScene->mMaterials[i].sTexOpacity.mMapName.empty() ||
!mScene->mMaterials[i].sTexEmissive.mMapName.empty() ||
!mScene->mMaterials[i].sTexSpecular.mMapName.empty() ||
!mScene->mMaterials[i].sTexShininess.mMapName.empty() ;
}
// -------------------------------------------------------------------
/** Convert the whole scene
*/

View File

@ -1,179 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#pragma once
#include <assimp/vector3.h>
#include <assimp/matrix4x4.h>
#include <assimp/ParsingUtils.h>
#include <vector>
#include <string>
struct aiMaterial;
struct aiMesh;
namespace Assimp {
namespace D3MF {
enum class ResourceType {
RT_Object,
RT_BaseMaterials,
RT_EmbeddedTexture2D,
RT_Texture2DGroup,
RT_ColorGroup,
RT_Unknown
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
class Resource {
public:
int mId;
Resource(int id) :
mId(id) {
// empty
}
virtual ~Resource() = default;
virtual ResourceType getType() const {
return ResourceType::RT_Unknown;
}
};
class EmbeddedTexture : public Resource {
public:
std::string mPath;
std::string mContentType;
std::string mTilestyleU;
std::string mTilestyleV;
std::vector<char> mBuffer;
EmbeddedTexture(int id) :
Resource(id),
mPath(),
mContentType(),
mTilestyleU(),
mTilestyleV() {
// empty
}
~EmbeddedTexture() override = default;
ResourceType getType() const override {
return ResourceType::RT_EmbeddedTexture2D;
}
};
class Texture2DGroup : public Resource {
public:
std::vector<aiVector2D> mTex2dCoords;
int mTexId;
Texture2DGroup(int id) :
Resource(id),
mTexId(-1) {
// empty
}
~Texture2DGroup() override = default;
ResourceType getType() const override {
return ResourceType::RT_Texture2DGroup;
}
};
class ColorGroup : public Resource {
public:
std::vector<aiColor4D> 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<unsigned int> mMaterialIndex;
BaseMaterials(int id) :
Resource(id),
mMaterialIndex() {
// empty
}
~BaseMaterials() override = default;
ResourceType getType() const override {
return ResourceType::RT_BaseMaterials;
}
};
struct Component {
int mObjectId;
aiMatrix4x4 mTransformation;
};
class Object : public Resource {
public:
std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents;
std::string mName;
Object(int id) :
Resource(id),
mName(std::string("Object_") + ai_to_string(id)) {
// empty
}
~Object() override = default;
ResourceType getType() const override {
return ResourceType::RT_Object;
}
};
} // namespace D3MF
} // namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -74,34 +74,19 @@ namespace XmlTag {
const char* const pid = "pid";
const char* const pindex = "pindex";
const char* const p1 = "p1";
const char *const p2 = "p2";
const char *const p3 = "p3";
const char* const name = "name";
const char* const type = "type";
const char* const build = "build";
const char* const item = "item";
const char* const objectid = "objectid";
const char* const transform = "transform";
const char *const path = "path";
// Material definitions
const char* const basematerials = "basematerials";
const char* const basematerials_id = "id";
const char* const basematerials_base = "base";
const char* const basematerials_name = "name";
const char* const basematerials_displaycolor = "displaycolor";
const char* const texture_2d = "m:texture2d";
const char *const texture_group = "m:texture2dgroup";
const char *const texture_content_type = "contenttype";
const char *const texture_tilestyleu = "tilestyleu";
const char *const texture_tilestylev = "tilestylev";
const char *const texture_2d_coord = "m:tex2coord";
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";
@ -118,7 +103,7 @@ namespace XmlTag {
const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
}
}
} // Namespace D3MF
} // Namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -83,7 +83,7 @@ void ExportScene3MF(const char *pFile, IOSystem *pIOSystem, const aiScene *pScen
namespace D3MF {
D3MFExporter::D3MFExporter(const char *pFile, const aiScene *pScene) :
mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene) {
mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene), mModelOutput(), mRelOutput(), mContentOutput(), mBuildItems(), mRelations() {
// empty
}
@ -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 {

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -40,9 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
#include <memory>
#include <sstream>
#include <vector>
@ -61,6 +58,8 @@ class IOStream;
namespace D3MF {
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
struct OpcPackageRelationship;
@ -101,11 +100,9 @@ private:
std::vector<OpcPackageRelationship*> mRelations;
};
#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT
} // Namespace D3MF
} // Namespace Assimp
#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "D3MFImporter.h"
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include "XmlSerializer.h"
#include <assimp/StringComparison.h>
#include <assimp/StringUtils.h>
@ -62,13 +61,517 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <string.h>
namespace Assimp {
namespace D3MF {
enum class ResourceType {
RT_Object,
RT_BaseMaterials,
RT_Unknown
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
class Resource {
public:
int mId;
Resource(int id) :
mId(id) {
// empty
}
virtual ~Resource() {
// empty
}
virtual ResourceType getType() const {
return ResourceType::RT_Unknown;
}
};
class BaseMaterials : public Resource {
public:
std::vector<aiMaterial *> mMaterials;
std::vector<unsigned int> mMaterialIndex;
BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {
// empty
}
~BaseMaterials() = default;
ResourceType getType() const override {
return ResourceType::RT_BaseMaterials;
}
};
struct Component {
int mObjectId;
aiMatrix4x4 mTransformation;
};
class Object : public Resource {
public:
std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents;
std::string mName;
Object(int id) :
Resource(id),
mName(std::string("Object_") + ai_to_string(id)) {
// empty
}
~Object() = default;
ResourceType getType() const override {
return ResourceType::RT_Object;
}
};
class XmlSerializer {
public:
XmlSerializer(XmlParser *xmlParser) :
mResourcesDictionnary(),
mMaterialCount(0),
mMeshCount(0),
mXmlParser(xmlParser) {
// empty
}
~XmlSerializer() {
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
delete it->second;
}
}
void ImportXml(aiScene *scene) {
if (nullptr == scene) {
return;
}
scene->mRootNode = new aiNode(XmlTag::RootTag);
XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
if (node.empty()) {
return;
}
XmlNode resNode = node.child(XmlTag::resources);
for (auto &currentNode : resNode.children()) {
const std::string currentNodeName = currentNode.name();
if (currentNodeName == XmlTag::object) {
ReadObject(currentNode);
} else if (currentNodeName == XmlTag::basematerials) {
ReadBaseMaterials(currentNode);
} else if (currentNodeName == XmlTag::meta) {
ReadMetadata(currentNode);
}
}
XmlNode buildNode = node.child(XmlTag::build);
for (auto &currentNode : buildNode.children()) {
const std::string currentNodeName = currentNode.name();
if (currentNodeName == XmlTag::item) {
int objectId = -1;
std::string transformationMatrixStr;
aiMatrix4x4 transformationMatrix;
getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
auto it = mResourcesDictionnary.find(objectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object *>(it->second);
if (hasTransform) {
transformationMatrix = parseTransformMatrix(transformationMatrixStr);
}
addObjectToNode(scene->mRootNode, obj, transformationMatrix);
}
}
}
// import the metadata
if (!mMetaData.empty()) {
const size_t numMeta = mMetaData.size();
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
for (size_t i = 0; i < numMeta; ++i) {
aiString val(mMetaData[i].value);
scene->mMetaData->Set(static_cast<unsigned int>(i), mMetaData[i].name, val);
}
}
// import the meshes
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
if (scene->mNumMeshes != 0) {
scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object *>(it->second);
ai_assert(nullptr != obj);
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
}
}
}
}
// import the materials
scene->mNumMaterials = mMaterialCount;
if (scene->mNumMaterials != 0) {
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
scene->mMaterials[baseMaterials->mMaterialIndex[i]] = baseMaterials->mMaterials[i];
}
}
}
}
}
private:
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
ai_assert(nullptr != obj);
aiNode *sceneNode = new aiNode(obj->mName);
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
sceneNode->mTransformation = nodeTransform;
if (nullptr != parent) {
parent->addChildren(1, &sceneNode);
}
for (size_t i = 0; i < obj->mComponents.size(); ++i) {
Component c = obj->mComponents[i];
auto it = mResourcesDictionnary.find(c.mObjectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
}
}
}
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
if (!objectAttribute.empty()) {
value = objectAttribute.as_string();
return true;
}
return false;
}
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
std::string strValue;
bool ret = getNodeAttribute(node, attribute, strValue);
if (ret) {
value = std::atoi(strValue.c_str());
return true;
}
return false;
}
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
// split the string
std::vector<float> numbers;
std::string currentNumber;
for (size_t i = 0; i < matrixStr.size(); ++i) {
const char c = matrixStr[i];
if (c == ' ') {
if (currentNumber.size() > 0) {
float f = std::stof(currentNumber);
numbers.push_back(f);
currentNumber.clear();
}
} else {
currentNumber.push_back(c);
}
}
if (currentNumber.size() > 0) {
const float f = std::stof(currentNumber);
numbers.push_back(f);
}
aiMatrix4x4 transformMatrix;
transformMatrix.a1 = numbers[0];
transformMatrix.b1 = numbers[1];
transformMatrix.c1 = numbers[2];
transformMatrix.d1 = 0;
transformMatrix.a2 = numbers[3];
transformMatrix.b2 = numbers[4];
transformMatrix.c2 = numbers[5];
transformMatrix.d2 = 0;
transformMatrix.a3 = numbers[6];
transformMatrix.b3 = numbers[7];
transformMatrix.c3 = numbers[8];
transformMatrix.d3 = 0;
transformMatrix.a4 = numbers[9];
transformMatrix.b4 = numbers[10];
transformMatrix.c4 = numbers[11];
transformMatrix.d4 = 1;
return transformMatrix;
}
void ReadObject(XmlNode &node) {
int id = -1, pid = -1, pindex = -1;
bool hasId = getNodeAttribute(node, XmlTag::id, id);
bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
if (!hasId) {
return;
}
Object *obj = new Object(id);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == D3MF::XmlTag::mesh) {
auto mesh = ReadMesh(currentNode);
mesh->mName.Set(ai_to_string(id));
if (hasPid) {
auto it = mResourcesDictionnary.find(pid);
if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
}
}
obj->mMeshes.push_back(mesh);
obj->mMeshIndex.push_back(mMeshCount);
mMeshCount++;
} else if (currentName == D3MF::XmlTag::components) {
for (XmlNode &currentSubNode : currentNode.children()) {
const std::string subNodeName = currentSubNode.name();
if (subNodeName == D3MF::XmlTag::component) {
int objectId = -1;
std::string componentTransformStr;
aiMatrix4x4 componentTransform;
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
componentTransform = parseTransformMatrix(componentTransformStr);
}
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
obj->mComponents.push_back({ objectId, componentTransform });
}
}
}
}
}
mResourcesDictionnary.insert(std::make_pair(id, obj));
}
aiMesh *ReadMesh(XmlNode &node) {
aiMesh *mesh = new aiMesh();
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::vertices) {
ImportVertices(currentNode, mesh);
} else if (currentName == XmlTag::triangles) {
ImportTriangles(currentNode, mesh);
}
}
return mesh;
}
void ReadMetadata(XmlNode &node) {
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
const std::string name = attribute.as_string();
const std::string value = node.value();
if (name.empty()) {
return;
}
MetaEntry entry;
entry.name = name;
entry.value = value;
mMetaData.push_back(entry);
}
void ImportVertices(XmlNode &node, aiMesh *mesh) {
std::vector<aiVector3D> vertices;
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::vertex) {
vertices.push_back(ReadVertex(currentNode));
}
}
mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
}
aiVector3D ReadVertex(XmlNode &node) {
aiVector3D vertex;
vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
return vertex;
}
void ImportTriangles(XmlNode &node, aiMesh *mesh) {
std::vector<aiFace> faces;
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::triangle) {
aiFace face = ReadTriangle(currentNode);
faces.push_back(face);
int pid = 0, p1 = 0;
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
if (hasPid && hasP1) {
auto it = mResourcesDictionnary.find(pid);
if (it != mResourcesDictionnary.end()) {
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
}
// TODO: manage the separation into several meshes if the triangles of the mesh do not all refer to the same material
}
}
}
}
mesh->mNumFaces = static_cast<unsigned int>(faces.size());
mesh->mFaces = new aiFace[mesh->mNumFaces];
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
std::copy(faces.begin(), faces.end(), mesh->mFaces);
}
aiFace ReadTriangle(XmlNode &node) {
aiFace face;
face.mNumIndices = 3;
face.mIndices = new unsigned int[face.mNumIndices];
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
return face;
}
void ReadBaseMaterials(XmlNode &node) {
int id = -1;
if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
BaseMaterials *baseMaterials = new BaseMaterials(id);
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::basematerials_base) {
baseMaterials->mMaterialIndex.push_back(mMaterialCount);
baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
++mMaterialCount;
}
}
mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
}
}
bool parseColor(const char *color, aiColor4D &diffuse) {
if (nullptr == color) {
return false;
}
//format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
const size_t len = strlen(color);
if (9 != len && 7 != len) {
return false;
}
const char *buf(color);
if ('#' != buf[0]) {
return false;
}
char r[3] = { buf[1], buf[2], '\0' };
diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
char g[3] = { buf[3], buf[4], '\0' };
diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
char b[3] = { buf[5], buf[6], '\0' };
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
if (7 == len)
return true;
char a[3] = { buf[7], buf[8], '\0' };
diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
return true;
}
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
aiColor4D diffuse;
if (parseColor(color, diffuse)) {
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
}
}
aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
aiMaterial *material = new aiMaterial();
material->mNumProperties = 0;
std::string name;
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
std::string stdMaterialName;
const std::string strId(ai_to_string(basematerialsId));
stdMaterialName += "id";
stdMaterialName += strId;
stdMaterialName += "_";
if (hasName) {
stdMaterialName += std::string(name);
} else {
stdMaterialName += "basemat_";
stdMaterialName += ai_to_string(mMaterialCount - basematerialsId);
}
aiString assimpMaterialName(stdMaterialName);
material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
assignDiffuseColor(node, material);
return material;
}
private:
struct MetaEntry {
std::string name;
std::string value;
};
std::vector<MetaEntry> mMetaData;
std::map<unsigned int, Resource *> mResourcesDictionnary;
unsigned int mMaterialCount, mMeshCount;
XmlParser *mXmlParser;
};
} //namespace D3MF
using namespace D3MF;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"3mf Importer",
"",
"",
@ -81,20 +584,34 @@ static constexpr aiImporterDesc desc = {
"3mf"
};
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool ) const {
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false;
}
static const char *const ModelRef = "3D/3dmodel.model";
ZipArchiveIOSystem archive(pIOHandler, filename);
if (!archive.Exists(ModelRef)) {
return false;
}
return true;
D3MFImporter::D3MFImporter() :
BaseImporter() {
// empty
}
void D3MFImporter::SetupProperties(const Importer*) {
D3MFImporter::~D3MFImporter() {
// empty
}
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension(GetExtension(filename));
if (extension == desc.mFileExtensions) {
return true;
} else if (!extension.length() || checkSig) {
if (nullptr == pIOHandler) {
return false;
}
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false;
}
D3MFOpcPackage opcPackage(pIOHandler, filename);
return opcPackage.validate();
}
return false;
}
void D3MFImporter::SetupProperties(const Importer * /*pImp*/) {
// empty
}
@ -109,15 +626,6 @@ void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene,
if (xmlParser.parse(opcPackage.RootStream())) {
XmlSerializer xmlSerializer(&xmlParser);
xmlSerializer.ImportXml(pScene);
const std::vector<aiTexture*> &tex = opcPackage.GetEmbeddedTextures();
if (!tex.empty()) {
pScene->mNumTextures = static_cast<unsigned int>(tex.size());
pScene->mTextures = new aiTexture *[pScene->mNumTextures];
for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
pScene->mTextures[i] = tex[i];
}
}
}
}

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -42,50 +43,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_D3MFLOADER_H_INCLUDED
#define AI_D3MFLOADER_H_INCLUDED
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
#include <assimp/BaseImporter.h>
namespace Assimp {
// ---------------------------------------------------------------------------
/// @brief The 3MF-importer class.
///
/// Implements the basic topology import and embedded textures.
// ---------------------------------------------------------------------------
class D3MFImporter : public BaseImporter {
public:
/// @brief The default class constructor.
D3MFImporter() = default;
/// @brief The class destructor.
~D3MFImporter() override = default;
/// @brief Performs the data format detection.
/// @param pFile The filename to check.
/// @param pIOHandler The used IO-System.
/// @param checkSig true for signature checking.
/// @return true for can be loaded, false for not.
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
/// @brief Not used
/// @param pImp Not used
void SetupProperties(const Importer *pImp) override;
/// @brief The importer description getter.
/// @return The info
const aiImporterDesc *GetInfo() const override;
D3MFImporter();
~D3MFImporter();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
void SetupProperties(const Importer *pImp);
const aiImporterDesc *GetInfo() const;
protected:
/// @brief Internal read function, performs the file parsing.
/// @param pFile The filename
/// @param pScene The scene to load in.
/// @param pIOHandler The io-system
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
};
} // Namespace Assimp
#endif // #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
#endif // AI_D3MFLOADER_H_INCLUDED

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -43,19 +43,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "D3MFOpcPackage.h"
#include <assimp/Exceptional.h>
#include <assimp/XmlParser.h>
#include <assimp/ZipArchiveIOSystem.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/texture.h>
#include "3MFXmlTags.h"
#include "3MFXmlTags.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <map>
#include <memory>
#include <vector>
namespace Assimp {
@ -63,12 +64,11 @@ namespace Assimp {
namespace D3MF {
// ------------------------------------------------------------------------------------------------
using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
class OpcPackageRelationshipReader {
public:
OpcPackageRelationshipReader(XmlParser &parser) :
mRelations() {
OpcPackageRelationshipReader(XmlParser &parser) {
XmlNode root = parser.getRootNode();
ParseRootNode(root);
}
@ -91,7 +91,6 @@ public:
if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) {
return false;
}
return true;
}
@ -101,39 +100,27 @@ public:
}
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
const std::string name = currentNode.name();
std::string name = currentNode.name();
if (name == "Relationship") {
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
if (validateRels(relPtr)) {
mRelations.push_back(relPtr);
m_relationShips.push_back(relPtr);
}
}
}
}
std::vector<OpcPackageRelationshipPtr> mRelations;
std::vector<OpcPackageRelationshipPtr> m_relationShips;
};
static bool IsEmbeddedTexture( const std::string &filename ) {
const std::string extension = BaseImporter::GetExtension(filename);
if (extension == "jpg" || extension == "png" || extension == "jpeg") {
std::string::size_type pos = filename.find("thumbnail");
if (pos != std::string::npos) {
return false;
}
return true;
}
return false;
}
// ------------------------------------------------------------------------------------------------
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
mRootStream(nullptr),
mZipArchive() {
mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
if (!mZipArchive->isOpen()) {
throw DeadlyImportError("Failed to open file ", rFile, ".");
}
@ -149,12 +136,12 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
IOStream *fileStream = mZipArchive->Open(file.c_str());
if (nullptr == fileStream) {
ASSIMP_LOG_ERROR("Filestream is nullptr.");
ai_assert(fileStream != nullptr);
continue;
}
std::string rootFile = ReadPackageRootRelationship(fileStream);
if (!rootFile.empty() && rootFile[0] == '/') {
if (rootFile.size() > 0 && rootFile[0] == '/') {
rootFile = rootFile.substr(1);
if (rootFile[0] == '/') {
// deal with zip-bug
@ -171,12 +158,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
if (nullptr == mRootStream) {
throw DeadlyImportError("Cannot open root-file in archive : " + rootFile);
}
} else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
} else if (IsEmbeddedTexture(file)) {
IOStream *fileStream = mZipArchive->Open(file.c_str());
LoadEmbeddedTextures(fileStream, file);
mZipArchive->Close(fileStream);
} else {
ASSIMP_LOG_WARN("Ignored file of unknown type: ", file);
}
@ -185,25 +169,20 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
D3MFOpcPackage::~D3MFOpcPackage() {
mZipArchive->Close(mRootStream);
delete mZipArchive;
}
IOStream *D3MFOpcPackage::RootStream() const {
return mRootStream;
}
const std::vector<aiTexture *> &D3MFOpcPackage::GetEmbeddedTextures() const {
return mEmbeddedTextures;
}
static const char *const ModelRef = "3D/3dmodel.model";
static const std::string ModelRef = "3D/3dmodel.model";
bool D3MFOpcPackage::validate() {
if (nullptr == mRootStream || nullptr == mZipArchive) {
return false;
}
return mZipArchive->Exists(ModelRef);
return mZipArchive->Exists(ModelRef.c_str());
}
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
@ -214,42 +193,17 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
OpcPackageRelationshipReader reader(xmlParser);
auto itr = std::find_if(reader.mRelations.begin(), reader.mRelations.end(), [](const OpcPackageRelationshipPtr &rel) {
auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
});
if (itr == reader.mRelations.end()) {
if (itr == reader.m_relationShips.end()) {
throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
}
return (*itr)->target;
}
void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename) {
if (nullptr == fileStream) {
return;
}
const size_t size = fileStream->FileSize();
if (0 == size) {
return;
}
unsigned char *data = new unsigned char[size];
fileStream->Read(data, 1, size);
aiTexture *texture = new aiTexture;
std::string embName = "*" + filename;
texture->mFilename.Set(embName.c_str());
texture->mWidth = static_cast<unsigned int>(size);
texture->mHeight = 0;
texture->achFormatHint[0] = 'p';
texture->achFormatHint[1] = 'n';
texture->achFormatHint[2] = 'g';
texture->achFormatHint[3] = '\0';
texture->pcData = (aiTexel*) data;
mEmbeddedTextures.emplace_back(texture);
}
} // Namespace D3MF
} // Namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -42,15 +42,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef D3MFOPCPACKAGE_H
#define D3MFOPCPACKAGE_H
#include <assimp/IOSystem.hpp>
#include <memory>
#include <string>
struct aiTexture;
#include <assimp/IOSystem.hpp>
namespace Assimp {
class ZipArchiveIOSystem;
class ZipArchiveIOSystem;
namespace D3MF {
@ -66,19 +63,16 @@ public:
~D3MFOpcPackage();
IOStream* RootStream() const;
bool validate();
const std::vector<aiTexture*> &GetEmbeddedTextures() const;
protected:
std::string ReadPackageRootRelationship(IOStream* stream);
void LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename);
private:
IOStream* mRootStream;
ZipArchiveIOSystem *mZipArchive;
std::vector<aiTexture *> mEmbeddedTextures;
std::unique_ptr<ZipArchiveIOSystem> mZipArchive;
};
} // namespace D3MF
} // namespace Assimp
} // Namespace D3MF
} // Namespace Assimp
#endif // D3MFOPCPACKAGE_H

View File

@ -1,724 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "XmlSerializer.h"
#include "D3MFOpcPackage.h"
#include "3MFXmlTags.h"
#include "3MFTypes.h"
#include <assimp/scene.h>
#include <utility>
namespace Assimp {
namespace D3MF {
static constexpr int IdNotSet = -1;
namespace {
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 std::string color) {
const size_t len = color.size();
if (ColRGBA_Len != len && ColRGB_Len != len) {
return false;
}
return true;
}
aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) {
aiFace face;
face.mNumIndices = 3;
face.mIndices = new unsigned int[face.mNumIndices];
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
texId0 = texId1 = texId2 = IdNotSet;
XmlParser::getIntAttribute(node, XmlTag::p1, texId0);
XmlParser::getIntAttribute(node, XmlTag::p2, texId1);
XmlParser::getIntAttribute(node, XmlTag::p3, texId2);
return face;
}
aiVector3D ReadVertex(XmlNode &node) {
aiVector3D vertex;
vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
return vertex;
}
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
if (!objectAttribute.empty()) {
value = objectAttribute.as_string();
return true;
}
return false;
}
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
std::string strValue;
const bool ret = getNodeAttribute(node, attribute, strValue);
if (ret) {
value = std::atoi(strValue.c_str());
return true;
}
return false;
}
aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
// split the string
std::vector<float> numbers;
std::string currentNumber;
for (char c : matrixStr) {
if (c == ' ') {
if (!currentNumber.empty()) {
float f = std::stof(currentNumber);
numbers.push_back(f);
currentNumber.clear();
}
} else {
currentNumber.push_back(c);
}
}
if (!currentNumber.empty()) {
const float f = std::stof(currentNumber);
numbers.push_back(f);
}
aiMatrix4x4 transformMatrix;
transformMatrix.a1 = numbers[0];
transformMatrix.b1 = numbers[1];
transformMatrix.c1 = numbers[2];
transformMatrix.d1 = 0;
transformMatrix.a2 = numbers[3];
transformMatrix.b2 = numbers[4];
transformMatrix.c2 = numbers[5];
transformMatrix.d2 = 0;
transformMatrix.a3 = numbers[6];
transformMatrix.b3 = numbers[7];
transformMatrix.c3 = numbers[8];
transformMatrix.d3 = 0;
transformMatrix.a4 = numbers[9];
transformMatrix.b4 = numbers[10];
transformMatrix.c4 = numbers[11];
transformMatrix.d4 = 1;
return transformMatrix;
}
bool parseColor(const std::string &color, aiColor4D &diffuse) {
if (color.empty()) {
return false;
}
if (!validateColorString(color)) {
return false;
}
if ('#' != color[0]) {
return false;
}
char r[3] = { color[1], color[2], '\0' };
diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
char g[3] = { color[3], color[4], '\0' };
diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
char b[3] = { color[5], color[6], '\0' };
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
const size_t len = color.size();
if (ColRGB_Len == len) {
return true;
}
char a[3] = { color[7], color[8], '\0' };
diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
return true;
}
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
aiColor4D diffuse;
if (parseColor(color, diffuse)) {
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
}
}
} // namespace
XmlSerializer::XmlSerializer(XmlParser *xmlParser) :
mResourcesDictionnary(),
mMeshCount(0),
mXmlParser(xmlParser) {
ai_assert(nullptr != xmlParser);
}
XmlSerializer::~XmlSerializer() {
for (auto &it : mResourcesDictionnary) {
delete it.second;
}
}
void XmlSerializer::ImportXml(aiScene *scene) {
if (nullptr == scene) {
return;
}
scene->mRootNode = new aiNode(XmlTag::RootTag);
XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
if (node.empty()) {
return;
}
XmlNode resNode = node.child(XmlTag::resources);
for (auto &currentNode : resNode.children()) {
const std::string currentNodeName = currentNode.name();
if (currentNodeName == XmlTag::texture_2d) {
ReadEmbeddecTexture(currentNode);
} else if (currentNodeName == XmlTag::texture_group) {
ReadTextureGroup(currentNode);
} else if (currentNodeName == XmlTag::object) {
ReadObject(currentNode);
} else if (currentNodeName == XmlTag::basematerials) {
ReadBaseMaterials(currentNode);
} else if (currentNodeName == XmlTag::meta) {
ReadMetadata(currentNode);
} else if (currentNodeName == XmlTag::colorgroup) {
ReadColorGroup(currentNode);
}
}
StoreMaterialsInScene(scene);
XmlNode buildNode = node.child(XmlTag::build);
if (buildNode.empty()) {
return;
}
for (auto &currentNode : buildNode.children()) {
const std::string currentNodeName = currentNode.name();
if (currentNodeName == XmlTag::item) {
int objectId = IdNotSet;
std::string transformationMatrixStr;
aiMatrix4x4 transformationMatrix;
getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
auto it = mResourcesDictionnary.find(objectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object *>(it->second);
if (hasTransform) {
transformationMatrix = parseTransformMatrix(transformationMatrixStr);
}
addObjectToNode(scene->mRootNode, obj, transformationMatrix);
}
}
}
// import the metadata
if (!mMetaData.empty()) {
const size_t numMeta = mMetaData.size();
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
for (size_t i = 0; i < numMeta; ++i) {
aiString val(mMetaData[i].value);
scene->mMetaData->Set(static_cast<unsigned int>(i), mMetaData[i].name, val);
}
}
// import the meshes, materials are already stored
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
if (scene->mNumMeshes != 0) {
scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
for (auto &it : mResourcesDictionnary) {
if (it.second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object *>(it.second);
ai_assert(nullptr != obj);
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
}
}
}
}
}
void XmlSerializer::addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
ai_assert(nullptr != obj);
aiNode *sceneNode = new aiNode(obj->mName);
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
sceneNode->mTransformation = nodeTransform;
if (nullptr != parent) {
parent->addChildren(1, &sceneNode);
}
for (Assimp::D3MF::Component c : obj->mComponents) {
auto it = mResourcesDictionnary.find(c.mObjectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
}
}
}
void XmlSerializer::ReadObject(XmlNode &node) {
int id = IdNotSet, pid = IdNotSet, pindex = IdNotSet;
bool hasId = getNodeAttribute(node, XmlTag::id, id);
if (!hasId) {
return;
}
bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
Object *obj = new Object(id);
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::mesh) {
auto mesh = ReadMesh(currentNode);
mesh->mName.Set(ai_to_string(id));
if (hasPid) {
auto it = mResourcesDictionnary.find(pid);
if (hasPindex && it != mResourcesDictionnary.end()) {
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
Texture2DGroup *group = static_cast<Texture2DGroup *>(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<unsigned int>(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<ColorGroup *>(it->second);
for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) {
mesh->mColors[0][vertex_idx] = group->mColors[pindex];
}
}
}
}
}
obj->mMeshes.push_back(mesh);
obj->mMeshIndex.push_back(mMeshCount);
mMeshCount++;
} else if (currentName == D3MF::XmlTag::components) {
for (XmlNode &currentSubNode : currentNode.children()) {
const std::string subNodeName = currentSubNode.name();
if (subNodeName == D3MF::XmlTag::component) {
int objectId = IdNotSet;
std::string componentTransformStr;
aiMatrix4x4 componentTransform;
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
componentTransform = parseTransformMatrix(componentTransformStr);
}
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
obj->mComponents.push_back({ objectId, componentTransform });
}
}
}
}
}
mResourcesDictionnary.insert(std::make_pair(id, obj));
}
aiMesh *XmlSerializer::ReadMesh(XmlNode &node) {
if (node.empty()) {
return nullptr;
}
aiMesh *mesh = new aiMesh();
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::vertices) {
ImportVertices(currentNode, mesh);
} else if (currentName == XmlTag::triangles) {
ImportTriangles(currentNode, mesh);
}
}
return mesh;
}
void XmlSerializer::ReadMetadata(XmlNode &node) {
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
const std::string name = attribute.as_string();
const std::string value = node.value();
if (name.empty()) {
return;
}
MetaEntry entry;
entry.name = name;
entry.value = value;
mMetaData.push_back(entry);
}
void XmlSerializer::ImportVertices(XmlNode &node, aiMesh *mesh) {
ai_assert(nullptr != mesh);
std::vector<aiVector3D> vertices;
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::vertex) {
vertices.push_back(ReadVertex(currentNode));
}
}
mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
}
void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
std::vector<aiFace> faces;
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::triangle) {
int pid = IdNotSet;
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
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<BaseMaterials *>(it->second);
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<Texture2DGroup *>(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;
}
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<unsigned int>(i);
}
}
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<ColorGroup *>(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);
}
}
}
faces.push_back(face);
}
}
mesh->mNumFaces = static_cast<unsigned int>(faces.size());
mesh->mFaces = new aiFace[mesh->mNumFaces];
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
std::copy(faces.begin(), faces.end(), mesh->mFaces);
}
void XmlSerializer::ReadBaseMaterials(XmlNode &node) {
int id = IdNotSet;
if (getNodeAttribute(node, D3MF::XmlTag::id, id)) {
BaseMaterials *baseMaterials = new BaseMaterials(id);
for (XmlNode &currentNode : node.children()) {
const std::string currentName = currentNode.name();
if (currentName == XmlTag::basematerials_base) {
baseMaterials->mMaterialIndex.push_back(static_cast<unsigned int>(mMaterials.size()));
mMaterials.push_back(readMaterialDef(currentNode, id));
}
}
mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
}
}
void XmlSerializer::ReadEmbeddecTexture(XmlNode &node) {
if (node.empty()) {
return;
}
std::string value;
EmbeddedTexture *tex2D = nullptr;
if (XmlParser::getStdStrAttribute(node, XmlTag::id, value)) {
tex2D = new EmbeddedTexture(atoi(value.c_str()));
}
if (nullptr == tex2D) {
return;
}
if (XmlParser::getStdStrAttribute(node, XmlTag::path, value)) {
tex2D->mPath = value;
}
if (XmlParser::getStdStrAttribute(node, XmlTag::texture_content_type, value)) {
tex2D->mContentType = value;
}
if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestyleu, value)) {
tex2D->mTilestyleU = value;
}
if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestylev, value)) {
tex2D->mTilestyleV = value;
}
mEmbeddedTextures.emplace_back(tex2D);
StoreEmbeddedTexture(tex2D);
}
void XmlSerializer::StoreEmbeddedTexture(EmbeddedTexture *tex) {
aiMaterial *mat = new aiMaterial;
aiString s;
s.Set(ai_to_string(tex->mId).c_str());
mat->AddProperty(&s, AI_MATKEY_NAME);
const std::string name = "*" + tex->mPath;
s.Set(name);
mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
aiColor3D col;
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_EMISSIVE);
mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_SPECULAR);
mMaterials.emplace_back(mat);
}
void XmlSerializer::ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup) {
if (node.empty() || nullptr == tex2DGroup) {
return;
}
int id = IdNotSet;
if (XmlParser::getIntAttribute(node, "texid", id)) {
tex2DGroup->mTexId = id;
}
double value = 0.0;
for (XmlNode currentNode : node.children()) {
const std::string currentName = currentNode.name();
aiVector2D texCoord;
if (currentName == XmlTag::texture_2d_coord) {
XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_u, value);
texCoord.x = (ai_real)value;
XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_v, value);
texCoord.y = (ai_real)value;
tex2DGroup->mTex2dCoords.push_back(texCoord);
}
}
}
void XmlSerializer::ReadTextureGroup(XmlNode &node) {
if (node.empty()) {
return;
}
int id = IdNotSet;
if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) {
return;
}
Texture2DGroup *group = new Texture2DGroup(id);
ReadTextureCoords2D(node, group);
mResourcesDictionnary.insert(std::make_pair(id, group));
}
aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
aiMaterial *material = new aiMaterial();
material->mNumProperties = 0;
std::string name;
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
std::string stdMaterialName;
const std::string strId(ai_to_string(basematerialsId));
stdMaterialName += "id";
stdMaterialName += strId;
stdMaterialName += "_";
if (hasName) {
stdMaterialName += name;
} else {
stdMaterialName += "basemat_";
stdMaterialName += ai_to_string(mMaterials.size());
}
aiString assimpMaterialName(stdMaterialName);
material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
assignDiffuseColor(node, material);
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;
}
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
if (scene->mNumMaterials == 0) {
return;
}
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (size_t i = 0; i < mMaterials.size(); ++i) {
scene->mMaterials[i] = mMaterials[i];
}
}
} // namespace D3MF
} // namespace Assimp

View File

@ -1,99 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#pragma once
#include <assimp/XmlParser.h>
#include <assimp/mesh.h>
#include <vector>
#include <map>
struct aiNode;
struct aiMesh;
struct aiMaterial;
namespace Assimp {
namespace D3MF {
class Resource;
class D3MFOpcPackage;
class Object;
class Texture2DGroup;
class EmbeddedTexture;
class ColorGroup;
class XmlSerializer {
public:
XmlSerializer(XmlParser *xmlParser);
~XmlSerializer();
void ImportXml(aiScene *scene);
private:
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform);
void ReadObject(XmlNode &node);
aiMesh *ReadMesh(XmlNode &node);
void ReadMetadata(XmlNode &node);
void ImportVertices(XmlNode &node, aiMesh *mesh);
void ImportTriangles(XmlNode &node, aiMesh *mesh);
void ReadBaseMaterials(XmlNode &node);
void ReadEmbeddecTexture(XmlNode &node);
void StoreEmbeddedTexture(EmbeddedTexture *tex);
void ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup);
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 {
std::string name;
std::string value;
};
std::vector<MetaEntry> mMetaData;
std::vector<EmbeddedTexture *> mEmbeddedTextures;
std::vector<aiMaterial *> mMaterials;
std::map<unsigned int, Resource *> mResourcesDictionnary;
unsigned int mMeshCount;
XmlParser *mXmlParser;
};
} // namespace D3MF
} // namespace Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp>
#include <memory>
namespace Assimp {
using namespace Assimp;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"AC3D Importer",
"",
"",
@ -77,8 +77,8 @@ static constexpr aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// skip to the next token
inline const char *AcSkipToNextToken(const char *buffer, const char *end) {
if (!SkipSpaces(&buffer, end)) {
inline const char *AcSkipToNextToken(const char *buffer) {
if (!SkipSpaces(&buffer)) {
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL");
}
return buffer;
@ -86,13 +86,13 @@ inline const char *AcSkipToNextToken(const char *buffer, const char *end) {
// ------------------------------------------------------------------------------------------------
// read a string (may be enclosed in double quotation marks). buffer must point to "
inline const char *AcGetString(const char *buffer, const char *end, std::string &out) {
inline const char *AcGetString(const char *buffer, std::string &out) {
if (*buffer == '\0') {
throw DeadlyImportError("AC3D: Unexpected EOF in string");
}
++buffer;
const char *sz = buffer;
while ('\"' != *buffer && buffer != end) {
while ('\"' != *buffer) {
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, const char *end, std::string
// ------------------------------------------------------------------------------------------------
// read 1 to n floats prefixed with an optional predefined identifier
template <class T>
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);
inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) {
buffer = AcSkipToNextToken(buffer);
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 *end,
buffer += name_length + 1;
}
for (unsigned int _i = 0; _i < num; ++_i) {
buffer = AcSkipToNextToken(buffer, end);
buffer = AcSkipToNextToken(buffer);
buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]);
}
@ -132,7 +132,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end,
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
AC3DImporter::AC3DImporter() :
mBuffer(),
buffer(),
configSplitBFCull(),
configEvalSubdivision(),
mNumMeshes(),
@ -146,13 +146,24 @@ AC3DImporter::AC3DImporter() :
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
AC3DImporter::~AC3DImporter() = default;
AC3DImporter::~AC3DImporter() {
// nothing to be done here
}
// ------------------------------------------------------------------------------------------------
// 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") };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
// fixme: are acc and ac3d *really* used? Some sources say they are
if (extension == "ac" || extension == "ac3d" || extension == "acc") {
return true;
}
if (!extension.length() || checkSig) {
uint32_t token = AI_MAKE_MAGIC("AC3D");
return CheckMagicToken(pIOHandler, pFile, &token, 1, 0);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@ -164,25 +175,25 @@ const aiImporterDesc *AC3DImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------
// Get a pointer to the next line from the file
bool AC3DImporter::GetNextLine() {
SkipLine(&mBuffer.data, mBuffer.end);
return SkipSpaces(&mBuffer.data, mBuffer.end);
SkipLine(&buffer);
return SkipSpaces(&buffer);
}
// ------------------------------------------------------------------------------------------------
// Parse an object section in an AC file
bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
if (!TokenMatch(mBuffer.data, "OBJECT", 6))
return false;
void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
if (!TokenMatch(buffer, "OBJECT", 6))
return;
SkipSpaces(&mBuffer.data, mBuffer.end);
SkipSpaces(&buffer);
++mNumMeshes;
objects.emplace_back();
objects.push_back(Object());
Object &obj = objects.back();
aiLight *light = nullptr;
if (!ASSIMP_strincmp(mBuffer.data, "light", 5)) {
if (!ASSIMP_strincmp(buffer, "light", 5)) {
// This is a light source. Add it to the list
mLights->push_back(light = new aiLight());
@ -193,71 +204,65 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
// 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, AI_MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(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(mBuffer.data, "group", 5)) {
} else if (!ASSIMP_strincmp(buffer, "group", 5)) {
obj.type = Object::Group;
} else if (!ASSIMP_strincmp(mBuffer.data, "world", 5)) {
} else if (!ASSIMP_strincmp(buffer, "world", 5)) {
obj.type = Object::World;
} else
obj.type = Object::Poly;
while (GetNextLine()) {
if (TokenMatch(mBuffer.data, "kids", 4)) {
SkipSpaces(&mBuffer.data, mBuffer.end);
unsigned int num = strtoul10(mBuffer.data, &mBuffer.data);
if (TokenMatch(buffer, "kids", 4)) {
SkipSpaces(&buffer);
unsigned int num = strtoul10(buffer, &buffer);
GetNextLine();
if (num) {
// load the children of this object recursively
obj.children.reserve(num);
for (unsigned int i = 0; i < num; ++i) {
if (!LoadObjectSection(obj.children)) {
ASSIMP_LOG_WARN("AC3D: wrong number of kids");
break;
}
}
for (unsigned int i = 0; i < num; ++i)
LoadObjectSection(obj.children);
}
return true;
} else if (TokenMatch(mBuffer.data, "name", 4)) {
SkipSpaces(&mBuffer.data, mBuffer.data);
mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, obj.name);
return;
} else if (TokenMatch(buffer, "name", 4)) {
SkipSpaces(&buffer);
buffer = AcGetString(buffer, 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(mBuffer.data, "texture", 7)) {
SkipSpaces(&mBuffer.data, mBuffer.end);
std::string texture;
mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, texture);
obj.textures.push_back(texture);
} else if (TokenMatch(mBuffer.data, "texrep", 6)) {
SkipSpaces(&mBuffer.data, mBuffer.end);
mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texRepeat);
} else if (TokenMatch(buffer, "texture", 7)) {
SkipSpaces(&buffer);
buffer = AcGetString(buffer, obj.texture);
} else if (TokenMatch(buffer, "texrep", 6)) {
SkipSpaces(&buffer);
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat);
if (!obj.texRepeat.x || !obj.texRepeat.y)
obj.texRepeat = aiVector2D(1.f, 1.f);
} 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);
} 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);
unsigned int t = strtoul10(mBuffer.data, &mBuffer.data);
unsigned int t = strtoul10(buffer, &buffer);
if (t >= AI_MAX_ALLOC(aiVector3D)) {
throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
}
@ -266,59 +271,59 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
if (!GetNextLine()) {
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet");
break;
} else if (!IsNumeric(*mBuffer.data)) {
} else if (!IsNumeric(*buffer)) {
ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet");
--mBuffer.data; // make sure the line is processed a second time
--buffer; // make sure the line is processed a second time
break;
}
obj.vertices.emplace_back();
obj.vertices.push_back(aiVector3D());
aiVector3D &v = obj.vertices.back();
mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &v.x);
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x);
}
} else if (TokenMatch(mBuffer.data, "numsurf", 7)) {
SkipSpaces(&mBuffer.data, mBuffer.end);
} else if (TokenMatch(buffer, "numsurf", 7)) {
SkipSpaces(&buffer);
bool Q3DWorkAround = false;
const unsigned int t = strtoul10(mBuffer.data, &mBuffer.data);
const unsigned int t = strtoul10(buffer, &buffer);
obj.surfaces.reserve(t);
for (unsigned int i = 0; i < t; ++i) {
GetNextLine();
if (!TokenMatch(mBuffer.data, "SURF", 4)) {
if (!TokenMatch(buffer, "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");
}
--mBuffer.data; // make sure the line is processed a second time
--buffer; // make sure the line is processed a second time
// break; --- see fix notes above
Q3DWorkAround = true;
}
SkipSpaces(&mBuffer.data, mBuffer.end);
obj.surfaces.emplace_back();
SkipSpaces(&buffer);
obj.surfaces.push_back(Surface());
Surface &surf = obj.surfaces.back();
surf.flags = strtoul_cppstyle(mBuffer.data);
surf.flags = strtoul_cppstyle(buffer);
while (true) {
while (1) {
if (!GetNextLine()) {
throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete");
}
if (TokenMatch(mBuffer.data, "mat", 3)) {
SkipSpaces(&mBuffer.data, mBuffer.end);
surf.mat = strtoul10(mBuffer.data);
} else if (TokenMatch(mBuffer.data, "refs", 4)) {
if (TokenMatch(buffer, "mat", 3)) {
SkipSpaces(&buffer);
surf.mat = strtoul10(buffer);
} else if (TokenMatch(buffer, "refs", 4)) {
// --- see fix notes above
if (Q3DWorkAround) {
if (!surf.entries.empty()) {
mBuffer.data -= 6;
buffer -= 6;
break;
}
}
SkipSpaces(&mBuffer.data, mBuffer.end);
const unsigned int m = strtoul10(mBuffer.data);
SkipSpaces(&buffer);
const unsigned int m = strtoul10(buffer);
surf.entries.reserve(m);
obj.numRefs += m;
@ -328,15 +333,15 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete");
break;
}
surf.entries.emplace_back();
surf.entries.push_back(Surface::SurfaceEntry());
Surface::SurfaceEntry &entry = surf.entries.back();
entry.first = strtoul10(mBuffer.data, &mBuffer.data);
SkipSpaces(&mBuffer.data, mBuffer.end);
mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &entry.second);
entry.first = strtoul10(buffer, &buffer);
SkipSpaces(&buffer);
buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second);
}
} else {
--mBuffer.data; // make sure the line is processed a second time
--buffer; // make sure the line is processed a second time
break;
}
}
@ -344,7 +349,6 @@ bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
}
}
ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected");
return false;
}
// ------------------------------------------------------------------------------------------------
@ -358,8 +362,8 @@ void AC3DImporter::ConvertMaterial(const Object &object,
s.Set(matSrc.name);
matDest.AddProperty(&s, AI_MATKEY_NAME);
}
if (!object.textures.empty()) {
s.Set(object.textures[0]);
if (object.texture.length()) {
s.Set(object.texture);
matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
// UV transformation
@ -450,7 +454,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
idx = 0;
}
if ((*it).entries.empty()) {
ASSIMP_LOG_WARN("AC3D: surface has zero vertex references");
ASSIMP_LOG_WARN("AC3D: surface her zero vertex references");
}
// validate all vertex indices to make sure we won't crash here
@ -468,15 +472,16 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
}
switch ((*it).GetType()) {
case Surface::ClosedLine: // closed line
needMat[idx].first += static_cast<unsigned int>((*it).entries.size());
needMat[idx].second += static_cast<unsigned int>((*it).entries.size() << 1u);
// closed line
case Surface::ClosedLine:
needMat[idx].first += (unsigned int)(*it).entries.size();
needMat[idx].second += (unsigned int)(*it).entries.size() << 1u;
break;
// unclosed line
case Surface::OpenLine:
needMat[idx].first += static_cast<unsigned int>((*it).entries.size() - 1);
needMat[idx].second += static_cast<unsigned int>(((*it).entries.size() - 1) << 1u);
needMat[idx].first += (unsigned int)(*it).entries.size() - 1;
needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u;
break;
// triangle strip
@ -538,7 +543,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
// allocate UV coordinates, but only if the texture name for the
// surface is not empty
aiVector3D *uv = nullptr;
if (!object.textures.empty()) {
if (object.texture.length()) {
uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
mesh->mNumUVComponents[0] = 2;
}
@ -578,6 +583,15 @@ 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];
@ -696,18 +710,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, AI_MAXLEN, "ACGroup_%i", mGroupsCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++);
break;
case Object::Poly:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACPoly_%i", mPolysCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++);
break;
case Object::Light:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACLight_%i", mLightsCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++);
break;
// there shouldn't be more than one world, but we don't care
case Object::World:
node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACWorld_%i", mWorldsCounter++);
node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++);
break;
}
}
@ -747,7 +761,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if (file == nullptr) {
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open AC3D file ", pFile, ".");
}
@ -755,18 +769,17 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
std::vector<char> mBuffer2;
TextFileToBuffer(file.get(), mBuffer2);
mBuffer.data = &mBuffer2[0];
mBuffer.end = &mBuffer2[0] + mBuffer2.size();
buffer = &mBuffer2[0];
mNumMeshes = 0;
mLightsCounter = mPolysCounter = mWorldsCounter = mGroupsCounter = 0;
if (::strncmp(mBuffer.data, "AC3D", 4)) {
if (::strncmp(buffer, "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(mBuffer.data[4]);
unsigned int version = HexDigitToDecimal(buffer[4]);
char msg[3];
ASSIMP_itoa10(msg, 3, version);
ASSIMP_LOG_INFO("AC3D file format version: ", msg);
@ -781,36 +794,35 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
mLights = &lights;
while (GetNextLine()) {
if (TokenMatch(mBuffer.data, "MATERIAL", 8)) {
materials.emplace_back();
if (TokenMatch(buffer, "MATERIAL", 8)) {
materials.push_back(Material());
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
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 = AcSkipToNextToken(buffer);
if ('\"' == *buffer) {
buffer = AcGetString(buffer, mat.name);
buffer = AcSkipToNextToken(buffer);
}
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);
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);
}
LoadObjectSection(rootObjects);
}
if (rootObjects.empty() || mNumMeshes == 0u) {
if (rootObjects.empty() || !mNumMeshes) {
throw DeadlyImportError("AC3D: No meshes have been loaded");
}
if (materials.empty()) {
ASSIMP_LOG_WARN("AC3D: No material has been found");
materials.emplace_back();
materials.push_back(Material());
}
mNumMeshes += (mNumMeshes >> 2u) + 1;
@ -821,7 +833,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 = nullptr;
Object *root;
if (1 == rootObjects.size())
root = &rootObjects[0];
else {
@ -834,7 +846,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
delete root;
}
if (::strncmp(pScene->mRootNode->mName.data, "Node", 4) == 0) {
if (!::strncmp(pScene->mRootNode->mName.data, "Node", 4)) {
pScene->mRootNode->mName.Set("<AC3DWorld>");
}
@ -853,12 +865,10 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
// copy lights
pScene->mNumLights = (unsigned int)lights.size();
if (!lights.empty()) {
if (lights.size()) {
pScene->mLights = new aiLight *[lights.size()];
::memcpy(pScene->mLights, &lights[0], lights.size() * sizeof(void *));
}
}
} // namespace Assimp
#endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -63,7 +63,7 @@ namespace Assimp {
class AC3DImporter : public BaseImporter {
public:
AC3DImporter();
~AC3DImporter() override;
~AC3DImporter();
// Represents an AC3D material
struct Material {
@ -125,6 +125,7 @@ public:
type(World),
name(),
children(),
texture(),
texRepeat(1.f, 1.f),
texOffset(0.0f, 0.0f),
rotation(),
@ -150,8 +151,7 @@ public:
std::vector<Object> children;
// texture to be assigned to all surfaces of the object
// the .acc format supports up to 4 textures
std::vector<std::string> textures;
std::string texture;
// texture repat factors (scaling for all coordinates)
aiVector2D texRepeat, texOffset;
@ -185,25 +185,25 @@ public:
* See BaseImporter::CanRead() for details.
*/
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override;
bool checkSig) const;
protected:
// -------------------------------------------------------------------
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details */
const aiImporterDesc *GetInfo() const override;
const aiImporterDesc *GetInfo() const;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details*/
void InternReadFile(const std::string &pFile, aiScene *pScene,
IOSystem *pIOHandler) override;
IOSystem *pIOHandler);
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.*/
void SetupProperties(const Importer *pImp) override;
void SetupProperties(const Importer *pImp);
private:
// -------------------------------------------------------------------
@ -216,7 +216,7 @@ private:
* load subobjects, the method returns after a 'kids 0' was
* encountered.
* @objects List of output objects*/
bool LoadObjectSection(std::vector<Object> &objects);
void LoadObjectSection(std::vector<Object> &objects);
// -------------------------------------------------------------------
/** Convert all objects into meshes and nodes.
@ -242,7 +242,7 @@ private:
private:
// points to the next data line
aiBuffer mBuffer;
const char *buffer;
// Configuration option: if enabled, up to two meshes
// are generated per material: those faces who have

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
static constexpr aiImporterDesc Description = {
const aiImporterDesc AMFImporter::Description = {
"Additive manufacturing file format(AMF) Importer",
"smalcom",
"",
@ -83,7 +83,11 @@ void AMFImporter::Clear() {
AMFImporter::AMFImporter() AI_NO_EXCEPT :
mNodeElement_Cur(nullptr),
mXmlParser(nullptr) {
mXmlParser(nullptr),
mUnit(),
mVersion(),
mMaterial_Converted(),
mTexture_Converted() {
// empty
}
@ -178,6 +182,28 @@ 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 == '/'));
}
@ -191,10 +217,7 @@ 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);
@ -238,7 +261,7 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if (file == nullptr) {
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open AMF file ", pFile, ".");
}
@ -384,17 +407,17 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "deltax") {
XmlParser::getValueAsReal(currentNode, als.Delta.x);
XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "deltay") {
XmlParser::getValueAsReal(currentNode, als.Delta.y);
XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "deltaz") {
XmlParser::getValueAsReal(currentNode, als.Delta.z);
XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} else if (currentName == "rx") {
XmlParser::getValueAsReal(currentNode, als.Delta.x);
XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "ry") {
XmlParser::getValueAsReal(currentNode, als.Delta.y);
XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "rz") {
XmlParser::getValueAsReal(currentNode, als.Delta.z);
XmlParser::getValueAsFloat(currentNode, als.Delta.z);
}
}
ParseHelper_Node_Exit();
@ -480,9 +503,19 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
}
bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*pCheckSig*/) const {
static const char *tokens[] = { "<amf" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "amf") {
return true;
}
if (extension.empty() || pCheckSig) {
const char *tokens[] = { "<amf" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
const aiImporterDesc *AMFImporter::GetInfo() const {

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -98,12 +98,8 @@ namespace Assimp {
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
///
class AMFImporter : public BaseImporter {
using AMFMetaDataArray = std::vector<AMFMetadata *>;
using MeshArray = std::vector<aiMesh *>;
using NodeArray = std::vector<aiNode *>;
public:
struct SPP_Material;
private:
struct SPP_Material; // forward declaration
/// Data type for post-processing step. More suitable container for part of material's composition.
struct SPP_Composite {
@ -111,6 +107,22 @@ public:
std::string Formula; ///< Formula for calculating ratio of \ref Material.
};
/// \struct SPP_Material
/// Data type for post-processing step. More suitable container for material.
struct SPP_Material {
std::string ID; ///< Material ID.
std::list<AMFMetadata *> Metadata; ///< Metadata of material.
AMFColor *Color; ///< Color of material.
std::list<SPP_Composite> Composition; ///< List of child materials if current material is composition of few another.
/// Return color calculated for specified coordinate.
/// \param [in] pX - "x" coordinate.
/// \param [in] pY - "y" coordinate.
/// \param [in] pZ - "z" coordinate.
/// \return calculated color.
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
};
/// Data type for post-processing step. More suitable container for texture.
struct SPP_Texture {
std::string ID;
@ -127,51 +139,10 @@ public:
const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
};
/// Data type for post-processing step. More suitable container for material.
struct SPP_Material {
std::string ID; ///< Material ID.
std::list<AMFMetadata *> Metadata; ///< Metadata of material.
AMFColor *Color; ///< Color of material.
std::list<SPP_Composite> Composition; ///< List of child materials if current material is composition of few another.
using AMFMetaDataArray = std::vector<AMFMetadata*>;
using MeshArray = std::vector<aiMesh*>;
using NodeArray = std::vector<aiNode*>;
/// Return color calculated for specified coordinate.
/// \param [in] pX - "x" coordinate.
/// \param [in] pY - "y" coordinate.
/// \param [in] pZ - "z" coordinate.
/// \return calculated color.
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
};
/// Default constructor.
AMFImporter() AI_NO_EXCEPT;
/// Default destructor.
~AMFImporter() override;
/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
/// Also exception can be thrown if trouble will found.
/// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override;
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
const aiImporterDesc *GetInfo() const override;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
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);
AMFImporter(const AMFImporter &pScene) = delete;
AMFImporter &operator=(const AMFImporter &pScene) = delete;
private:
/// Clear all temporary data.
void Clear();
@ -291,9 +262,40 @@ private:
/// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false);
public:
/// Default constructor.
AMFImporter() AI_NO_EXCEPT;
/// Default destructor.
~AMFImporter();
/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
/// Also exception can be thrown if trouble will found.
/// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
const aiImporterDesc *GetInfo() const;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
void Throw_CloseNotFound(const std::string &nodeName);
void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName);
void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName);
void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription);
void Throw_ID_NotFound(const std::string &pID) const;
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;
private:
static const aiImporterDesc Description;
AMFNodeElementBase *mNodeElement_Cur; ///< Current element.
std::list<AMFNodeElementBase *> mNodeElement_List; ///< All elements of scene graph.
XmlParser *mXmlParser;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, 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 &currentName = ai_tolower(currentNode.name());
if (currentName == "x") {
XmlParser::getValueAsReal(currentNode, als.Coordinate.x);
XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
} else if (currentName == "y") {
XmlParser::getValueAsReal(currentNode, als.Coordinate.y);
XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
} else if (currentName == "z") {
XmlParser::getValueAsReal(currentNode, als.Coordinate.z);
XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
}
}
ParseHelper_Node_Exit();

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -263,25 +263,26 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
const std::string &name = currentNode.name();
if (name == "utex1") {
read_flag[0] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[0].x);
XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
} else if (name == "utex2") {
read_flag[1] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[1].x);
XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
} else if (name == "utex3") {
read_flag[2] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[2].x);
XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
} else if (name == "vtex1") {
read_flag[3] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[0].y);
XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
} else if (name == "vtex2") {
read_flag[4] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[1].y);
XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
} else if (name == "vtex3") {
read_flag[5] = true;
XmlParser::getValueAsReal(node, als.TextureCoordinate[2].y);
XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
}
}
ParseHelper_Node_Exit();
} else {
for (pugi::xml_attribute &attr : node.attributes()) {
const std::string name = attr.name();

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -48,14 +48,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_AMF_IMPORTER_NODE_H
#define INCLUDED_AI_AMF_IMPORTER_NODE_H
// Header files, Assimp.
#include <assimp/scene.h>
#include <assimp/types.h>
// Header files, stdlib.
#include <list>
#include <string>
#include <vector>
// Header files, Assimp.
#include "assimp/scene.h"
#include "assimp/types.h"
/// \class CAMFImporter_NodeElement
/// Base class for elements of nodes.
class AMFNodeElementBase {
public:
@ -87,7 +89,9 @@ public:
std::list<AMFNodeElementBase *> Child; ///< Child elements.
public: /// Destructor, virtual..
virtual ~AMFNodeElementBase() = default;
virtual ~AMFNodeElementBase() {
// empty
}
/// Disabled copy constructor and co.
AMFNodeElementBase(const AMFNodeElementBase &pNodeElement) = delete;
@ -100,11 +104,12 @@ protected:
/// \param [in] pType - element type.
/// \param [in] pParent - parent element.
AMFNodeElementBase(const EType pType, AMFNodeElementBase *pParent) :
Type(pType), Parent(pParent) {
Type(pType), ID(), Parent(pParent), Child() {
// empty
}
}; // class IAMFImporter_NodeElement
/// \struct CAMFImporter_NodeElement_Constellation
/// A collection of objects or constellations with specific relative locations.
struct AMFConstellation : public AMFNodeElementBase {
/// Constructor.
@ -114,6 +119,7 @@ struct AMFConstellation : public AMFNodeElementBase {
}; // struct CAMFImporter_NodeElement_Constellation
/// \struct CAMFImporter_NodeElement_Instance
/// Part of constellation.
struct AMFInstance : public AMFNodeElementBase {
@ -132,6 +138,7 @@ struct AMFInstance : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Instance, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Metadata
/// Structure that define metadata node.
struct AMFMetadata : public AMFNodeElementBase {
@ -144,6 +151,7 @@ struct AMFMetadata : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Metadata, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Root
/// Structure that define root node.
struct AMFRoot : public AMFNodeElementBase {
@ -156,6 +164,7 @@ 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.
@ -166,11 +175,12 @@ struct AMFColor : public AMFNodeElementBase {
/// @brief Constructor.
/// @param [in] pParent - pointer to parent node.
AMFColor(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() {
AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color(), Profile() {
// empty
}
};
/// \struct CAMFImporter_NodeElement_Material
/// Structure that define material node.
struct AMFMaterial : public AMFNodeElementBase {
@ -180,6 +190,7 @@ struct AMFMaterial : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Material, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Object
/// Structure that define object node.
struct AMFObject : public AMFNodeElementBase {
@ -198,6 +209,7 @@ struct AMFMesh : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Mesh, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Vertex
/// Structure that define vertex node.
struct AMFVertex : public AMFNodeElementBase {
/// Constructor.
@ -206,6 +218,7 @@ struct AMFVertex : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Vertex, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Edge
/// Structure that define edge node.
struct AMFEdge : public AMFNodeElementBase {
/// Constructor.
@ -214,6 +227,7 @@ struct AMFEdge : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Edge, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Vertices
/// Structure that define vertices node.
struct AMFVertices : public AMFNodeElementBase {
/// Constructor.
@ -222,6 +236,7 @@ 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.
@ -233,6 +248,7 @@ struct AMFVolume : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Volume, pParent) {}
};
/// \struct CAMFImporter_NodeElement_Coordinates
/// Structure that define coordinates node.
struct AMFCoordinates : public AMFNodeElementBase {
aiVector3D Coordinate; ///< Coordinate.
@ -243,6 +259,7 @@ 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.
@ -254,11 +271,12 @@ struct AMFTexMap : public AMFNodeElementBase {
/// Constructor.
/// \param [in] pParent - pointer to parent node.
AMFTexMap(AMFNodeElementBase *pParent) :
AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} {
AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{}, TextureID_R(), TextureID_G(), TextureID_B(), TextureID_A() {
// empty
}
};
/// \struct CAMFImporter_NodeElement_Triangle
/// Structure that define triangle node.
struct AMFTriangle : public AMFNodeElementBase {
size_t V[3]; ///< Triangle vertices.

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -224,8 +224,7 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
}
// Create format hint.
constexpr char templateColor[] = "rgba0000";
memcpy(converted_texture.FormatHint, templateColor, 8);
strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string.
if (!r.empty()) converted_texture.FormatHint[4] = '8';
if (!g.empty()) converted_texture.FormatHint[5] = '8';
if (!b.empty()) converted_texture.FormatHint[6] = '8';
@ -691,7 +690,7 @@ void AMFImporter::Postprocess_BuildConstellation(AMFConstellation &pConstellatio
if (ne->Type == AMFNodeElementBase::ENET_Metadata) continue;
if (ne->Type != AMFNodeElementBase::ENET_Instance) throw DeadlyImportError("Only <instance> nodes can be in <constellation>.");
// create alias for convenience
// create alias for conveniance
AMFInstance &als = *((AMFInstance *)ne);
// find referenced object
if (!Find_ConvertedNode(als.ObjectID, nodeArray, &found_node)) Throw_ID_NotFound(als.ObjectID);
@ -816,7 +815,6 @@ nl_clean_loop:
for (; next_it != nodeArray.end(); ++next_it) {
if ((*next_it)->FindNode((*nl_it)->mName) != nullptr) {
// if current top node(nl_it) found in another top node then erase it from node_list and restart search loop.
// FIXME: this leaks memory on test models test8.amf and test9.amf
nodeArray.erase(nl_it);
goto nl_clean_loop;
@ -868,7 +866,7 @@ nl_clean_loop:
pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data;
// texture format description.
strncpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint, HINTMAXTEXTURELEN);
strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint);
idx++;
} // for(const SPP_Texture& tex_convd: mTexture_Converted)

View File

@ -3,7 +3,9 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -44,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers
@ -63,10 +66,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// utilities
#include <assimp/fast_atof.h>
namespace Assimp {
using namespace Assimp;
using namespace Assimp::ASE;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"ASE Importer",
"",
"",
@ -86,11 +89,27 @@ ASEImporter::ASEImporter() :
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ASEImporter::~ASEImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "*3dsmax_asciiexport" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
// check file extension
const std::string extension = GetExtension(pFile);
if (extension == "ase" || extension == "ask") {
return true;
}
if ((!extension.length() || cs) && pIOHandler) {
const char *tokens[] = { "*3dsmax_asciiexport" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@ -117,14 +136,14 @@ void ASEImporter::InternReadFile(const std::string &pFile,
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if (file == nullptr) {
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open ASE file ", pFile, ".");
}
// Allocate storage and copy the contents of the file to a memory buffer
std::vector<char> mBuffer2;
TextFileToBuffer(file.get(), mBuffer2);
const size_t fileSize = mBuffer2.size();
this->mBuffer = &mBuffer2[0];
this->pcScene = pScene;
@ -146,7 +165,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
};
// Construct an ASE parser and parse the file
ASE::Parser parser(mBuffer, fileSize, defaultFormat);
ASE::Parser parser(mBuffer, defaultFormat);
mParser = &parser;
mParser->Parse();
@ -258,7 +277,7 @@ void ASEImporter::GenerateDefaultMaterial() {
}
if (bHas || mParser->m_vMaterials.empty()) {
// add a simple material without submaterials to the parser's list
mParser->m_vMaterials.emplace_back(AI_DEFAULT_MATERIAL_NAME);
mParser->m_vMaterials.push_back(ASE::Material(AI_DEFAULT_MATERIAL_NAME));
ASE::Material &mat = mParser->m_vMaterials.back();
mat.mDiffuse = aiColor3D(0.6f, 0.6f, 0.6f);
@ -321,6 +340,21 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode *> &nodes) {
aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
nd->mNodeName.Set(me->mName + ".Target");
// If there is no input position channel we will need
// to supply the default position from the node's
// local transformation matrix.
/*TargetAnimationHelper helper;
if (me->mAnim.akeyPositions.empty())
{
aiMatrix4x4& mat = (*i)->mTransform;
helper.SetFixedMainAnimationChannel(aiVector3D(
mat.a4, mat.b4, mat.c4));
}
else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
helper.Process(&me->mTargetAnim.akeyPositions);*/
// Allocate the key array and fill it
nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size();
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
@ -446,9 +480,10 @@ void ASEImporter::BuildLights() {
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name) {
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
aiNode *pcParent, const char *szName) {
aiMatrix4x4 m;
AddNodes(nodes, pcParent, name, m);
AddNodes(nodes, pcParent, szName, m);
}
// ------------------------------------------------------------------------------------------------
@ -505,9 +540,10 @@ void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) {
// ------------------------------------------------------------------------------------------------
// Add child nodes to a given parent node
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name,
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
aiNode *pcParent, const char *szName,
const aiMatrix4x4 &mat) {
const size_t len = name.size();
const size_t len = szName ? ::strlen(szName) : 0;
ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
// Receives child nodes for the pcParent node
@ -517,18 +553,16 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParen
// which has *us* as parent.
for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
const BaseNode *snode = *it;
if (!name.empty()) {
if (len != snode->mParent.length() || name != snode->mParent.c_str()) {
if (szName) {
if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str()))
continue;
}
} else if (snode->mParent.length()) {
} else if (snode->mParent.length())
continue;
}
(*it)->mProcessed = true;
// Allocate a new node and add it to the output data structure
apcNodes.push_back(new aiNode);
apcNodes.push_back(new aiNode());
aiNode *node = apcNodes.back();
node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
@ -541,7 +575,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParen
// 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.C_Str(), snode->mTransform);
AddNodes(nodes, node, node->mName.data, snode->mTransform);
}
// Further processing depends on the type of the node
@ -619,8 +653,7 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
}
// add all nodes
static const std::string none = "";
AddNodes(nodes, ch, none);
AddNodes(nodes, ch, nullptr);
// now iterate through al nodes and find those that have not yet
// been added to the nodegraph (= their parent could not be recognized)
@ -650,7 +683,7 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
}
}
// Are there any orphaned nodes?
// Are there ane orphaned nodes?
if (!aiList.empty()) {
std::vector<aiNode *> apcNodes;
apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren);
@ -849,7 +882,6 @@ void ASEImporter::ConvertMaterial(ASE::Material &mat) {
unsigned int iWire = 1;
mat.pcInstance->AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
// fallthrough
case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud;
break;
@ -905,7 +937,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMes
ASSIMP_LOG_WARN("Material index is out of range");
}
// If the material the mesh is assigned to consists of submeshes, split it
// If the material the mesh is assigned to is consisting of submeshes, split it
if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) {
std::vector<ASE::Material> vSubMaterials = mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
@ -984,8 +1016,8 @@ void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMes
blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end(); ++blubb) {
// NOTE: illegal cases have already been filtered out
avOutputBones[(*blubb).first].emplace_back(
iBase, (*blubb).second);
avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
iBase, (*blubb).second));
}
}
}
@ -1263,8 +1295,6 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
return false;
}
}
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -62,37 +62,42 @@ namespace Assimp {
class ASEImporter : public BaseImporter {
public:
ASEImporter();
~ASEImporter() override = default;
~ASEImporter();
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details.
*/
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const override;
bool checkSig) const;
protected:
// -------------------------------------------------------------------
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details
*/
const aiImporterDesc* GetInfo () const override;
const aiImporterDesc* GetInfo () const;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler) override;
IOSystem* pIOHandler);
// -------------------------------------------------------------------
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.
*/
void SetupProperties(const Importer* pImp) override;
void SetupProperties(const Importer* pImp);
private:
// -------------------------------------------------------------------
/** Generate normal vectors basing on smoothing groups
* (in some cases the normal are already contained in the file)
@ -101,6 +106,7 @@ private:
*/
bool GenerateNormals(ASE::Mesh& mesh);
// -------------------------------------------------------------------
/** Create valid vertex/normal/UV/color/face lists.
* All elements are unique, faces have only one set of indices
@ -109,43 +115,51 @@ private:
*/
void BuildUniqueRepresentation(ASE::Mesh& mesh);
/** Create one-material-per-mesh meshes ;-)
* \param mesh Mesh to work with
* \param Receives the list of all created meshes
*/
void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
// -------------------------------------------------------------------
/** Convert a material to a aiMaterial object
* \param mat Input material
*/
void ConvertMaterial(ASE::Material& mat);
// -------------------------------------------------------------------
/** Setup the final material indices for each mesh
*/
void BuildMaterialIndices();
// -------------------------------------------------------------------
/** Build the node graph
*/
void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
// -------------------------------------------------------------------
/** Build output cameras
*/
void BuildCameras();
// -------------------------------------------------------------------
/** Build output lights
*/
void BuildLights();
// -------------------------------------------------------------------
/** Build output animations
*/
void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
// -------------------------------------------------------------------
/** Add sub nodes to a node
* \param pcParent parent node to be filled
@ -153,13 +167,13 @@ private:
* \param matrix Current transform
*/
void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent, const std::string &name);
aiNode* pcParent,const char* szName);
void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent, const std::string &name,
aiNode* pcParent,const char* szName,
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
@ -169,6 +183,7 @@ private:
void GenerateDefaultMaterial();
protected:
/** Parser instance */
ASE::Parser* mParser;
@ -188,4 +203,5 @@ protected:
} // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -115,7 +116,7 @@ struct Material : public D3DS::Material {
return *this;
}
~Material() = default;
~Material() {}
//! Contains all sub materials of this material
std::vector<Material> avSubMaterials;
@ -384,18 +385,20 @@ struct Dummy : public BaseNode {
/** \brief Class to parse ASE files
*/
class Parser {
public:
/// @brief No default constructor.
Parser() = delete;
private:
Parser() AI_NO_EXCEPT {
// empty
}
public:
// -------------------------------------------------------------------
//! Construct a parser from a given input file which is
//! guaranteed to be terminated with zero.
//! @param file The name of the input file.
//! @param szFile 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 *file, size_t fileLen, unsigned int fileFormatDefault);
Parser(const char *szFile, unsigned int fileFormatDefault);
// -------------------------------------------------------------------
//! Parses the file into the parsers internal representation
@ -553,15 +556,13 @@ private:
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats)
//! \param rIndexOut Output index
void ParseLV4MeshRealTriple(ai_real *apOut, unsigned int &rIndexOut);
void ParseLV4MeshFloatTriple(float *apOut, unsigned int &rIndexOut);
void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut);
// -------------------------------------------------------------------
//! Parse a *MESH_VERT block in a file
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats)
void ParseLV4MeshRealTriple(ai_real *apOut);
void ParseLV4MeshFloatTriple(float *apOut);
void ParseLV4MeshFloatTriple(ai_real *apOut);
// -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file
@ -579,8 +580,7 @@ private:
// -------------------------------------------------------------------
//! Parse a single float element
//! \param fOut Output float
void ParseLV4MeshReal(ai_real &fOut);
void ParseLV4MeshFloat(float &fOut);
void ParseLV4MeshFloat(ai_real &fOut);
// -------------------------------------------------------------------
//! Parse a single int element
@ -620,8 +620,8 @@ private:
bool ParseString(std::string &out, const char *szName);
public:
const char *mFilePtr; ////< Pointer to current data
const char *mEnd; ///< The end pointer of the file data
//! Pointer to current data
const char *filePtr;
//! background color to be passed to the viewer
//! QNAN if none was found

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -42,19 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file AssbinExporter.h
* ASSBIN Exporter Main Header
*/
#pragma once
#ifndef AI_ASSBINEXPORTER_H_INC
#define AI_ASSBINEXPORTER_H_INC
#include <assimp/defs.h>
#ifndef ASSIMP_BUILD_NO_EXPORT
// nothing really needed here - reserved for future use like properties
namespace Assimp {
void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/);
}
#endif
#endif // AI_ASSBINEXPORTER_H_INC

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -43,16 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "AssbinFileWriter.h"
#include "Common/assbin_chunks.h"
#include "PostProcessing/ProcessHelper.h"
#include <assimp/Exceptional.h>
#include <assimp/version.h>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include "zlib.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h>
#else
#include "../contrib/zlib/zlib.h"
#endif
#include <ctime>
#include <time.h>
#if _MSC_VER
#pragma warning(push)
@ -126,7 +132,7 @@ inline size_t Write<double>(IOStream *stream, const double &f) {
// Serialize a vec3
template <>
inline size_t Write<aiVector3D>(IOStream *stream, const aiVector3D &v) {
size_t t = Write<ai_real>(stream, v.x);
size_t t = Write<float>(stream, v.x);
t += Write<float>(stream, v.y);
t += Write<float>(stream, v.z);
@ -137,7 +143,7 @@ inline size_t Write<aiVector3D>(IOStream *stream, const aiVector3D &v) {
// Serialize a color value
template <>
inline size_t Write<aiColor3D>(IOStream *stream, const aiColor3D &v) {
size_t t = Write<ai_real>(stream, v.r);
size_t t = Write<float>(stream, v.r);
t += Write<float>(stream, v.g);
t += Write<float>(stream, v.b);
@ -148,7 +154,7 @@ inline size_t Write<aiColor3D>(IOStream *stream, const aiColor3D &v) {
// Serialize a color value
template <>
inline size_t Write<aiColor4D>(IOStream *stream, const aiColor4D &v) {
size_t t = Write<ai_real>(stream, v.r);
size_t t = Write<float>(stream, v.r);
t += Write<float>(stream, v.g);
t += Write<float>(stream, v.b);
t += Write<float>(stream, v.a);
@ -160,13 +166,13 @@ inline size_t Write<aiColor4D>(IOStream *stream, const aiColor4D &v) {
// Serialize a quaternion
template <>
inline size_t Write<aiQuaternion>(IOStream *stream, const aiQuaternion &v) {
size_t t = Write<ai_real>(stream, v.w);
size_t t = Write<float>(stream, v.w);
t += Write<float>(stream, v.x);
t += Write<float>(stream, v.y);
t += Write<float>(stream, v.z);
ai_assert(t == 16);
return t;
return 16;
}
// -----------------------------------------------------------------------------------
@ -178,19 +184,17 @@ inline size_t Write<aiVertexWeight>(IOStream *stream, const aiVertexWeight &v) {
return t + Write<float>(stream, v.mWeight);
}
constexpr size_t MatrixSize = 64;
// -----------------------------------------------------------------------------------
// Serialize a mat4x4
template <>
inline size_t Write<aiMatrix4x4>(IOStream *stream, const aiMatrix4x4 &m) {
for (unsigned int i = 0; i < 4; ++i) {
for (unsigned int i2 = 0; i2 < 4; ++i2) {
Write<ai_real>(stream, m[i][i2]);
Write<float>(stream, m[i][i2]);
}
}
return MatrixSize;
return 64;
}
// -----------------------------------------------------------------------------------
@ -273,7 +277,7 @@ public:
// empty
}
~AssbinChunkWriter() override {
virtual ~AssbinChunkWriter() {
if (container) {
container->Write(&magic, sizeof(uint32_t), 1);
container->Write(&cursor, sizeof(uint32_t), 1);
@ -284,27 +288,26 @@ public:
void *GetBufferPointer() { return buffer; }
size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override {
// -------------------------------------------------------------------
virtual size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
return 0;
}
aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override {
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
return aiReturn_FAILURE;
}
size_t Tell() const override {
virtual size_t Tell() const {
return cursor;
}
void Flush() override {
virtual void Flush() {
// not implemented
}
size_t FileSize() const override {
virtual size_t FileSize() const {
return cursor;
}
size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) override {
// -------------------------------------------------------------------
virtual size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) {
pSize *= pCount;
if (cursor + pSize > cur_size) {
Grow(cursor + pSize);
@ -638,10 +641,6 @@ protected:
Write<aiString>(&chunk, l->mName);
Write<unsigned int>(&chunk, l->mType);
Write<aiVector3D>(&chunk, l->mPosition);
Write<aiVector3D>(&chunk, l->mDirection);
Write<aiVector3D>(&chunk, l->mUp);
if (l->mType != aiLightSource_DIRECTIONAL) {
Write<float>(&chunk, l->mAttenuationConstant);
Write<float>(&chunk, l->mAttenuationLinear);

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"Assimp Binary Importer",
"Gargaj / Conspiracy",
"",
@ -406,7 +406,7 @@ void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) {
f.mIndices = new unsigned int[f.mNumIndices];
for (unsigned int a = 0; a < f.mNumIndices; ++a) {
// Check if unsigned short ( 16 bit ) are big enough for the indices
// Check if unsigned short ( 16 bit ) are big enought for the indices
if (fitsIntoUI16(mesh->mNumVertices)) {
f.mIndices[a] = Read<uint16_t>(stream);
} else {
@ -556,10 +556,6 @@ void AssbinImporter::ReadBinaryLight(IOStream *stream, aiLight *l) {
l->mName = Read<aiString>(stream);
l->mType = (aiLightSourceType)Read<unsigned int>(stream);
l->mPosition = Read<aiVector3D>(stream);
l->mDirection = Read<aiVector3D>(stream);
l->mUp = Read<aiVector3D>(stream);
if (l->mType != aiLightSource_DIRECTIONAL) {
l->mAttenuationConstant = Read<float>(stream);
l->mAttenuationLinear = Read<float>(stream);

View File

@ -3,7 +3,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -73,11 +74,17 @@ private:
bool compressed;
public:
bool CanRead(const std::string& pFile,
IOSystem* pIOHandler, bool checkSig) const override;
const aiImporterDesc* GetInfo() const override;
void InternReadFile(
const std::string& pFile,aiScene* pScene,IOSystem* pIOHandler) override;
virtual bool CanRead(
const std::string& pFile,
IOSystem* pIOHandler,
bool checkSig
) const;
virtual const aiImporterDesc* GetInfo() const;
virtual void InternReadFile(
const std::string& pFile,
aiScene* pScene,
IOSystem* pIOHandler
);
void ReadHeader();
void ReadBinaryScene( IOStream * stream, aiScene* pScene );
void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );

View File

@ -7,7 +7,7 @@ For details, see http://sourceforge.net/projects/libb64
#include "cencode.h" // changed from <B64/cencode.h>
static const int CHARS_PER_LINE = 72;
const int CHARS_PER_LINE = 72;
#ifdef _MSC_VER
#pragma warning(push)

View File

@ -10,7 +10,6 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
@ -24,15 +23,16 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information
#define CURRENT_FORMAT_VERSION 100
// grab scoped_ptr from assimp to avoid a dependency on boost.
//#include <assimp/../../code/BoostWorkaround/boost/scoped_ptr.hpp>
#include "mesh_splitter.h"
extern "C" {
# include "cencode.h"
#include "cencode.h"
}
namespace Assimp {
// Forward declarations
void ExportAssimp2Json(const char *, Assimp::IOSystem *, const aiScene *, const Assimp::ExportProperties *);
// small utility class to simplify serializing the aiScene to Json
@ -41,17 +41,12 @@ public:
enum {
Flag_DoNotIndent = 0x1,
Flag_WriteSpecialFloats = 0x2,
Flag_SkipWhitespaces = 0x4
};
JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
out(out), indent (""), newline("\n"), space(" "), buff (), first(false), flags(flags) {
out(out), first(), flags(flags) {
// make sure that all formatting happens using the standard, C locale and not the user's current locale
buff.imbue(std::locale("C"));
if (flags & Flag_SkipWhitespaces) {
newline = "";
space = "";
}
}
~JSONWriter() {
@ -75,7 +70,7 @@ public:
void Key(const std::string &name) {
AddIndentation();
Delimit();
buff << '\"' + name + "\":" << space;
buff << '\"' + name + "\": ";
}
template <typename Literal>
@ -83,12 +78,12 @@ public:
AddIndentation();
Delimit();
LiteralToString(buff, name) << newline;
LiteralToString(buff, name) << '\n';
}
template <typename Literal>
void SimpleValue(const Literal &s) {
LiteralToString(buff, s) << newline;
LiteralToString(buff, s) << '\n';
}
void SimpleValue(const void *buffer, size_t len) {
@ -107,7 +102,7 @@ public:
}
}
buff << '\"' << cur_out << "\"" << newline;
buff << '\"' << cur_out << "\"\n";
delete[] cur_out;
}
@ -120,7 +115,7 @@ public:
}
}
first = true;
buff << "{" << newline;
buff << "{\n";
PushIndent();
}
@ -128,7 +123,7 @@ public:
PopIndent();
AddIndentation();
first = false;
buff << "}" << newline;
buff << "}\n";
}
void StartArray(bool is_element = false) {
@ -140,19 +135,19 @@ public:
}
}
first = true;
buff << "[" << newline;
buff << "[\n";
PushIndent();
}
void EndArray() {
PopIndent();
AddIndentation();
buff << "]" << newline;
buff << "]\n";
first = false;
}
void AddIndentation() {
if (!(flags & Flag_DoNotIndent) && !(flags & Flag_SkipWhitespaces)) {
if (!(flags & Flag_DoNotIndent)) {
buff << indent;
}
}
@ -161,7 +156,7 @@ public:
if (!first) {
buff << ',';
} else {
buff << space;
buff << ' ';
first = false;
}
}
@ -179,6 +174,7 @@ private:
// escape backslashes and single quotes, both would render the JSON invalid if left as is
t.reserve(s.length);
for (size_t i = 0; i < s.length; ++i) {
if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') {
t.push_back('\\');
}
@ -231,16 +227,14 @@ private:
private:
Assimp::IOStream &out;
std::string indent;
std::string newline;
std::string space;
std::string indent, newline;
std::stringstream buff;
bool first;
unsigned int flags;
};
static void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
out.StartArray(is_elem);
out.Element(ai.x);
out.Element(ai.y);
@ -248,7 +242,7 @@ static void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
out.EndArray();
}
static void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
out.StartArray(is_elem);
out.Element(ai.w);
out.Element(ai.x);
@ -257,7 +251,7 @@ static void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true)
out.EndArray();
}
static void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
out.StartArray(is_elem);
out.Element(ai.r);
out.Element(ai.g);
@ -265,7 +259,7 @@ static void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
out.EndArray();
}
static void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
out.StartArray(is_elem);
for (unsigned int x = 0; x < 4; ++x) {
for (unsigned int y = 0; y < 4; ++y) {
@ -275,7 +269,7 @@ static void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
out.EndArray();
}
static void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -296,7 +290,7 @@ static void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
out.StartArray(is_elem);
for (unsigned int i = 0; i < ai.mNumIndices; ++i) {
out.Element(ai.mIndices[i]);
@ -304,7 +298,7 @@ static void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
out.EndArray();
}
static void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -415,7 +409,7 @@ static void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -445,7 +439,7 @@ static void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("properties");
@ -465,55 +459,41 @@ static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
out.Key("value");
switch (prop->mType) {
case aiPTI_Float:
if (prop->mDataLength / sizeof(float) > 1) {
out.StartArray();
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
out.Element(reinterpret_cast<float *>(prop->mData)[ii]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
case aiPTI_Float:
if (prop->mDataLength / sizeof(float) > 1) {
out.StartArray();
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
out.Element(reinterpret_cast<float *>(prop->mData)[ii]);
}
break;
case aiPTI_Double:
if (prop->mDataLength / sizeof(double) > 1) {
out.StartArray();
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(double); ++ii) {
out.Element(reinterpret_cast<double*>(prop->mData)[ii]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<double*>(prop->mData));
}
break;
case aiPTI_Integer:
if (prop->mDataLength / sizeof(int) > 1) {
out.StartArray();
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
out.Element(reinterpret_cast<int *>(prop->mData)[ii]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<int *>(prop->mData));
}
break;
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
}
break;
case aiPTI_String:
{
aiString s;
aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
out.SimpleValue(s);
case aiPTI_Integer:
if (prop->mDataLength / sizeof(int) > 1) {
out.StartArray();
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
out.Element(reinterpret_cast<int *>(prop->mData)[ii]);
}
break;
case aiPTI_Buffer:
{
// binary data is written as series of hex-encoded octets
out.SimpleValue(prop->mData, prop->mDataLength);
}
break;
default:
ai_assert(false);
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<int *>(prop->mData));
}
break;
case aiPTI_String: {
aiString s;
aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
out.SimpleValue(s);
} break;
case aiPTI_Buffer: {
// binary data is written as series of hex-encoded octets
out.SimpleValue(prop->mData, prop->mDataLength);
} break;
default:
assert(false);
}
out.EndObj();
@ -523,7 +503,7 @@ static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("width");
@ -559,7 +539,7 @@ static void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -607,7 +587,7 @@ static void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -660,7 +640,7 @@ static void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -681,7 +661,7 @@ static void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
@ -708,7 +688,7 @@ static void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
out.EndObj();
}
static void WriteFormatInfo(JSONWriter &out) {
void WriteFormatInfo(JSONWriter &out) {
out.StartObj();
out.Key("format");
out.SimpleValue("\"assimp2json\"");
@ -717,7 +697,7 @@ static void WriteFormatInfo(JSONWriter &out) {
out.EndObj();
}
static void Write(JSONWriter &out, const aiScene &ai) {
void Write(JSONWriter &out, const aiScene &ai) {
out.StartObj();
out.Key("__metadata__");
@ -785,7 +765,7 @@ static void Write(JSONWriter &out, const aiScene &ai) {
out.EndObj();
}
void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *pProperties) {
void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *) {
std::unique_ptr<Assimp::IOStream> str(io->Open(file, "wt"));
if (!str) {
throw DeadlyExportError("could not open output file");
@ -802,12 +782,7 @@ void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *sc
splitter.Execute(scenecopy_tmp);
// XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters
unsigned int flags = JSONWriter::Flag_WriteSpecialFloats;
if (pProperties->GetPropertyBool("JSON_SKIP_WHITESPACES", false)) {
flags |= JSONWriter::Flag_SkipWhitespaces;
}
JSONWriter s(*str, flags);
JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats);
Write(s, *scenecopy_tmp);
} catch (...) {

View File

@ -69,12 +69,13 @@ void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh
for (unsigned int i = 0, end = pcNode->mNumChildren; i < end;++i) {
UpdateNode ( pcNode->mChildren[i], source_mesh_map );
}
return;
}
static const unsigned int WAS_NOT_COPIED = 0xffffffff;
#define WAS_NOT_COPIED 0xffffffff
using PerVertexWeight = std::pair <unsigned int,float>;
using VertexWeightTable = std::vector <PerVertexWeight>;
typedef std::pair <unsigned int,float> PerVertexWeight;
typedef std::vector <PerVertexWeight> VertexWeightTable;
// ------------------------------------------------------------------------------------------------
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) {
@ -88,7 +89,7 @@ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) {
aiBone* bone = pMesh->mBones[i];
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
const aiVertexWeight& weight = bone->mWeights[a];
avPerVertexWeights[weight.mVertexId].emplace_back(i,weight.mWeight);
avPerVertexWeights[weight.mVertexId].push_back( std::make_pair(i,weight.mWeight) );
}
}
return avPerVertexWeights;
@ -99,7 +100,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
// TODO: should better use std::(multi)set for source_mesh_map.
if (in_mesh->mNumVertices <= LIMIT) {
source_mesh_map.emplace_back(in_mesh,a);
source_mesh_map.push_back(std::make_pair(in_mesh,a));
return;
}
@ -186,7 +187,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
break;
}
vFaces.emplace_back();
vFaces.push_back(aiFace());
aiFace& rFace = vFaces.back();
// setup face type and number of indices
@ -304,7 +305,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
}
// add the newly created mesh to the list
source_mesh_map.emplace_back(out_mesh,a);
source_mesh_map.push_back(std::make_pair(out_mesh,a));
if (base == in_mesh->mNumFaces) {
break;

View File

@ -24,29 +24,38 @@ struct aiNode;
/** Splits meshes of unique vertices into meshes with no more vertices than
* a given, configurable threshold value.
*/
class MeshSplitter {
class MeshSplitter
{
public:
unsigned int LIMIT;
void SetLimit(unsigned int l) {
LIMIT = l;
}
void SetLimit(unsigned int l) {
LIMIT = l;
}
unsigned int GetLimit() const {
return LIMIT;
}
unsigned int GetLimit() const {
return LIMIT;
}
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
public:
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute(aiScene *pScene);
void Execute( aiScene* pScene);
private:
void UpdateNode(aiNode *pcNode, const std::vector<std::pair<aiMesh *, unsigned int>> &source_mesh_map);
void SplitMesh(unsigned int index, aiMesh *mesh, std::vector<std::pair<aiMesh *, unsigned int>> &source_mesh_map);
void UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
void SplitMesh (unsigned int index, aiMesh* mesh, std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
public:
unsigned int LIMIT;
};
#endif // INCLUDED_MESH_SPLITTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file AssxmlExporter.h
* ASSXML Exporter Main Header
*/
#pragma once
#ifndef AI_ASSXMLEXPORTER_H_INC
#define AI_ASSXMLEXPORTER_H_INC

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -168,7 +168,7 @@ static void WriteNode(const aiNode *node, IOStream *io, unsigned int depth) {
}
// -----------------------------------------------------------------------------------
// Some chunks of text will need to be encoded for XML
// Some chuncks of text will need to be encoded for XML
// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
static std::string encodeXML(const std::string &data) {
std::string buffer;
@ -365,7 +365,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
ioprintf(io, "\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%u\"",
prop->mKey.data, sz,
::aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex);
::TextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex);
if (prop->mType == aiPTI_Float) {
ioprintf(io, " size=\"%i\">\n\t\t\t\t",
@ -601,7 +601,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" name=\"%s\" num_components=\"%u\"> \n",
mesh->mNumVertices,
a,
(mesh->HasTextureCoordsName(a) ? mesh->GetTextureCoordsName(a)->C_Str() : ""),
mesh->mTextureCoordsNames[a].C_Str(),
mesh->mNumUVComponents[a]);
if (!shortened) {
@ -652,7 +652,7 @@ void DumpSceneToAssxml(
const char *pFile, const char *cmd, IOSystem *pIOSystem,
const aiScene *pScene, bool shortened) {
std::unique_ptr<IOStream> file(pIOSystem->Open(pFile, "wt"));
if (!file) {
if (!file.get()) {
throw std::runtime_error("Unable to open output file " + std::string(pFile) + '\n');
}

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -42,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file AssxmlFileWriter.h
* @brief Declaration of Assxml file writer.
*/
#pragma once
#ifndef AI_ASSXMLFILEWRITER_H_INC
#define AI_ASSXMLFILEWRITER_H_INC

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -59,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
namespace Assimp {
using namespace Assimp;
using namespace std;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"BlitzBasic 3D Importer",
"",
"",
@ -79,7 +79,7 @@ static constexpr aiImporterDesc desc = {
#pragma warning(disable : 4018)
#endif
// #define DEBUG_B3D
//#define DEBUG_B3D
template <typename T>
void DeleteAllBarePointers(std::vector<T> &x) {
@ -88,10 +88,12 @@ void DeleteAllBarePointers(std::vector<T> &x) {
}
}
B3DImporter::~B3DImporter() = default;
B3DImporter::~B3DImporter() {
}
// ------------------------------------------------------------------------------------------------
bool B3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
size_t pos = pFile.find_last_of('.');
if (pos == string::npos) {
return false;
@ -116,7 +118,7 @@ void B3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
// Check whether we can read from the file
if (file == nullptr) {
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open B3D file ", pFile, ".");
}
@ -150,7 +152,7 @@ AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadByte() {
if (_pos >= _buf.size()) {
if (_pos > _buf.size()) {
Fail("EOF");
}
@ -253,7 +255,7 @@ size_t B3DImporter::ChunkSize() {
template <class T>
T *B3DImporter::to_array(const vector<T> &v) {
if (v.empty()) {
return nullptr;
return 0;
}
T *p = new T[v.size()];
for (size_t i = 0; i < v.size(); ++i) {
@ -266,7 +268,7 @@ T *B3DImporter::to_array(const vector<T> &v) {
template <class T>
T **unique_to_array(vector<std::unique_ptr<T>> &v) {
if (v.empty()) {
return nullptr;
return 0;
}
T **p = new T *[v.size()];
for (size_t i = 0; i < v.size(); ++i) {
@ -329,7 +331,7 @@ void B3DImporter::ReadBRUS() {
mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED);
}
// Textures
//Textures
for (int i = 0; i < n_texs; ++i) {
int texid = ReadInt();
if (texid < -1 || (texid >= 0 && texid >= static_cast<int>(_textures.size()))) {
@ -372,7 +374,7 @@ void B3DImporter::ReadVRTS() {
}
if (_vflags & 2) {
ReadQuat(); // skip v 4bytes...
ReadQuat(); //skip v 4bytes...
}
for (int j = 0; j < _tcsets; ++j) {
@ -418,6 +420,7 @@ void B3DImporter::ReadTRIS(int v0) {
ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
#endif
Fail("Bad triangle index");
continue;
}
face->mNumIndices = 3;
face->mIndices = new unsigned[3];
@ -476,13 +479,13 @@ void B3DImporter::ReadKEYS(aiNodeAnim *nodeAnim) {
while (ChunkSize()) {
int frame = ReadInt();
if (flags & 1) {
trans.emplace_back(frame, ReadVec3());
trans.push_back(aiVectorKey(frame, ReadVec3()));
}
if (flags & 2) {
scale.emplace_back(frame, ReadVec3());
scale.push_back(aiVectorKey(frame, ReadVec3()));
}
if (flags & 4) {
rot.emplace_back(frame, ReadQuat());
rot.push_back(aiQuatKey(frame, ReadQuat()));
}
}
@ -616,7 +619,7 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
} else if (chunk == "BRUS") {
ReadBRUS();
} else if (chunk == "NODE") {
ReadNODE(nullptr);
ReadNODE(0);
}
ExitChunk();
}
@ -641,7 +644,7 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
int n_tris = mesh->mNumFaces;
int n_verts = mesh->mNumVertices = n_tris * 3;
aiVector3D *mv = mesh->mVertices = new aiVector3D[n_verts], *mn = nullptr, *mc = nullptr;
aiVector3D *mv = mesh->mVertices = new aiVector3D[n_verts], *mn = 0, *mc = 0;
if (_vflags & 1) {
mn = mesh->mNormals = new aiVector3D[n_verts];
}
@ -670,7 +673,7 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
int bone = v.bones[k];
float weight = v.weights[k];
vweights[bone].emplace_back(vertIdx + faceIndex, weight);
vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight));
}
}
++face;
@ -704,22 +707,22 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
}
}
// nodes
//nodes
scene->mRootNode = _nodes[0];
_nodes.clear(); // node ownership now belongs to scene
// material
//material
if (!_materials.size()) {
_materials.emplace_back(std::unique_ptr<aiMaterial>(new aiMaterial));
}
scene->mNumMaterials = static_cast<unsigned int>(_materials.size());
scene->mMaterials = unique_to_array(_materials);
// meshes
//meshes
scene->mNumMeshes = static_cast<unsigned int>(_meshes.size());
scene->mMeshes = unique_to_array(_meshes);
// animations
//animations
if (_animations.size() == 1 && _nodeAnims.size()) {
aiAnimation *anim = _animations.back().get();
@ -738,6 +741,4 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
flip.Execute(scene);
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -39,10 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/**
* @file Definition of the .b3d importer class.
*/
#pragma once
/** @file Definition of the .b3d importer class. */
#ifndef AI_B3DIMPORTER_H_INC
#define AI_B3DIMPORTER_H_INC
@ -63,12 +62,14 @@ namespace Assimp{
class B3DImporter : public BaseImporter{
public:
B3DImporter() = default;
~B3DImporter() override;
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
virtual ~B3DImporter();
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected:
const aiImporterDesc* GetInfo () const override;
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
virtual const aiImporterDesc* GetInfo () const;
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
private:
@ -112,6 +113,7 @@ private:
void ReadBB3D( aiScene *scene );
size_t _pos;
// unsigned _size;
std::vector<unsigned char> _buf;
std::vector<size_t> _stack;

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
@ -55,11 +55,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include <memory>
namespace Assimp {
using namespace Assimp;
using namespace Assimp::Formatter;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"BVH Importer (MoCap)",
"",
"",
@ -74,8 +73,8 @@ static constexpr aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
template <typename... T>
AI_WONT_RETURN void BVHLoader::ThrowException(T &&...args) {
template<typename... T>
AI_WONT_RETURN void BVHLoader::ThrowException(T&&... args) {
throw DeadlyImportError(mFileName, ":", mLine, " - ", args...);
}
@ -89,13 +88,22 @@ BVHLoader::BVHLoader() :
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
BVHLoader::~BVHLoader() = default;
BVHLoader::~BVHLoader() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "HIERARCHY" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
// check file extension
const std::string extension = GetExtension(pFile);
if (extension == "bvh")
return true;
if ((!extension.length() || cs) && pIOHandler) {
const char *tokens[] = { "HIERARCHY" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@ -116,7 +124,7 @@ void BVHLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSyst
// read file into memory
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
if (file == nullptr) {
if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open file ", pFile, ".");
}
@ -170,7 +178,7 @@ void BVHLoader::ReadHierarchy(aiScene *pScene) {
}
// ------------------------------------------------------------------------------------------------
// Reads a node and recursively its children and returns the created node;
// Reads a node and recursively its childs and returns the created node;
aiNode *BVHLoader::ReadNode() {
// first token is name
std::string nodeName = GetNextToken();
@ -187,12 +195,12 @@ aiNode *BVHLoader::ReadNode() {
std::vector<aiNode *> childNodes;
// and create an bone entry for it
mNodes.emplace_back(node);
mNodes.push_back(Node(node));
Node &internNode = mNodes.back();
// now read the node's contents
std::string siteToken;
while (true) {
while (1) {
std::string token = GetNextToken();
// node offset to parent node
@ -248,7 +256,7 @@ aiNode *BVHLoader::ReadEndSite(const std::string &pParentName) {
// now read the node's contents. Only possible entry is "OFFSET"
std::string token;
while (true) {
while (1) {
token.clear();
token = GetNextToken();
@ -427,7 +435,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
nodeAnim->mNodeName.Set(nodeName);
std::map<BVHLoader::ChannelType, int> channelMap;
// Build map of channels
//Build map of channels
for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) {
channelMap[node.mChannels[channel]] = channel;
}
@ -442,7 +450,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
// Now compute all translations
for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) {
// Find channel in node
//Find channel in node
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
if (mapIter == channelMap.end())
@ -486,27 +494,30 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
aiMatrix4x4 temp;
aiMatrix3x3 rotMatrix;
for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++channelIdx) {
switch (node.mChannels[channelIdx]) {
case Channel_RotationX: {
for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) {
switch (node.mChannels[channelIdx]) {
case Channel_RotationX:
{
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationX(angle, temp);
rotMatrix *= aiMatrix3x3(temp);
} break;
case Channel_RotationY: {
aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp);
}
break;
case Channel_RotationY:
{
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationY(angle, temp);
rotMatrix *= aiMatrix3x3(temp);
} break;
case Channel_RotationZ: {
aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);
}
break;
case Channel_RotationZ:
{
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationZ(angle, temp);
rotMatrix *= aiMatrix3x3(temp);
} break;
aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp);
}
break;
default:
break;
}
}
}
}
rotkey->mTime = double(fr);
rotkey->mValue = aiQuaternion(rotMatrix);
++rotkey;
@ -523,6 +534,4 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
}
}
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -112,7 +112,7 @@ protected:
/** Reads the hierarchy */
void ReadHierarchy(aiScene *pScene);
/** Reads a node and recursively its children and returns the created node. */
/** Reads a node and recursively its childs and returns the created node. */
aiNode *ReadNode();
/** Reads an end node and returns the created node. */

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -52,7 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
template <>
const char *LogFunctions<BlenderBMeshConverter>::Prefix() {
return "BLEND_BMESH: ";
static auto prefix = "BLEND_BMESH: ";
return prefix;
}
} // namespace Assimp
@ -139,7 +140,7 @@ void BlenderBMeshConverter::ConvertPolyToFaces(const MPoly &poly) {
ThrowException("BMesh uv loop array has incorrect size");
}
const MLoopUV *loopUV = &BMesh->mloopuv[poly.loopstart];
AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : nullptr);
AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : 0);
}
} else if (poly.totloop > 4) {
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -80,7 +80,7 @@ namespace Assimp
void DestroyTriMesh( );
void ConvertPolyToFaces( const Blender::MPoly& poly );
void AddFace( int v1, int v2, int v3, int v4 = 0 );
void AddTFace(const float *uv1, const float *uv2, const float *uv3, const float *uv4 = nullptr);
void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
const Blender::Mesh* BMesh;
Blender::Mesh* triMesh;

View File

@ -96,8 +96,7 @@ struct CustomDataTypeDescription {
* other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
* use a special readfunction for that cases
*/
static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -72,7 +72,7 @@ struct Type {
// ------------------------------------------------------------------------------------------------
void DNAParser::Parse() {
StreamReaderAny &stream = *db.reader;
StreamReaderAny &stream = *db.reader.get();
DNA &dna = db.dna;
if (!match4(stream, "SDNA")) {
@ -325,10 +325,10 @@ void SectionParser ::Next() {
stream.SetCurrentPos(current.start + current.size);
const char tmp[] = {
(char)stream.GetI1(),
(char)stream.GetI1(),
(char)stream.GetI1(),
(char)stream.GetI1()
(const char)stream.GetI1(),
(const char)stream.GetI1(),
(const char)stream.GetI1(),
(const char)stream.GetI1()
};
current.id = std::string(tmp, tmp[3] ? 4 : tmp[2] ? 3 : tmp[1] ? 2 : 1);

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -106,7 +106,9 @@ struct ElemBase {
// empty
}
virtual ~ElemBase() = default;
virtual ~ElemBase() {
// empty
}
/** Type name of the element. The type
* string points is the `c_str` of the `name` attribute of the
@ -414,10 +416,10 @@ template <>
struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
template <typename T>
void operator()(T & /*out*/, const char *message = "") {
void operator()(T & /*out*/, const char * = "") {
// obviously, it is crucial that _DefaultInitializer is used
// only from within a catch clause.
throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error: ", message);
throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error");
}
};
@ -429,17 +431,6 @@ inline bool Structure ::ResolvePointer<std::shared_ptr, ElemBase>(std::shared_pt
const Field &f,
bool) const;
template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(
std::shared_ptr<ElemBase>& out, const Pointer & ptrval,
const FileDatabase& db, const Field&, bool) const;
template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const;
template<> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const;
template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const;
template <> inline void Structure::Convert<unsigned char>(unsigned char& dest, const FileDatabase& db) const;
template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const;
template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const;
template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const;
// -------------------------------------------------------------------------------
/** Represents the full data structure information for a single BLEND file.
* This data is extracted from the DNA1 chunk in the file.
@ -485,7 +476,7 @@ public:
* in BlenderScene.cpp and is machine-generated.
* Converters are used to quickly handle objects whose
* exact data type is a runtime-property and not yet
* known at compile time (consider Object::data).*/
* known at compile time (consier Object::data).*/
void RegisterConverters();
// --------------------------------------------------------

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -65,7 +65,8 @@ namespace Blender {
struct TempArray {
typedef TCLASS< T*,std::allocator<T*> > mywrap;
TempArray() = default;
TempArray() {
}
~TempArray () {
for(T* elem : arr) {

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -63,19 +63,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringComparison.h>
#include <cctype>
#include <memory>
#include <utility>
// zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
#include "Common/Compression.h"
# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
# else
# include "../contrib/zlib/zlib.h"
# endif
#endif
namespace Assimp {
template <>
const char *LogFunctions<BlenderImporter>::Prefix() {
return "BLEND: ";
static auto prefix = "BLEND: ";
return prefix;
}
} // namespace Assimp
@ -84,7 +87,7 @@ using namespace Assimp;
using namespace Assimp::Blender;
using namespace Assimp::Formatter;
static constexpr aiImporterDesc blenderDesc = {
static const aiImporterDesc blenderDesc = {
"Blender 3D Importer (http://www.blender3d.org)",
"",
"",
@ -110,12 +113,23 @@ BlenderImporter::~BlenderImporter() {
delete modifier_cache;
}
static const char Token[] = "BLENDER";
static const char *Tokens[] = { "BLENDER" };
static const char *TokensForSearch[] = { "blender" };
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
return ParseMagicToken(pFile, pIOHandler).error.empty();
bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string &extension = GetExtension(pFile);
if (extension == "blend") {
return true;
}
if ((!extension.length() || checkSig) && pIOHandler) {
// note: this won't catch compressed files
return SearchFileHeaderForToken(pIOHandler, pFile, TokensForSearch, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@ -134,25 +148,98 @@ void BlenderImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure.
void BlenderImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
std::vector<Bytef> uncompressed;
#endif
FileDatabase file;
StreamOrError streamOrError = ParseMagicToken(pFile, pIOHandler);
if (!streamOrError.error.empty()) {
ThrowException(streamOrError.error);
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
if (!stream) {
ThrowException("Could not open file for reading");
}
std::shared_ptr<IOStream> stream = std::move(streamOrError.stream);
char version[4] = { 0 };
file.i64bit = (stream->Read(version, 1, 1), version[0] == '-');
file.little = (stream->Read(version, 1, 1), version[0] == 'v');
char magic[8] = { 0 };
stream->Read(magic, 7, 1);
if (strcmp(magic, Tokens[0])) {
// Check for presence of the gzip header. If yes, assume it is a
// compressed blend file and try uncompressing it, else fail. This is to
// avoid uncompressing random files which our loader might end up with.
#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
#else
stream->Read(version, 3, 1);
version[3] = '\0';
if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
}
LogInfo("Blender version is ", version[0], ".", version + 1,
LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
if (magic[2] != 8) {
ThrowException("Unsupported GZIP compression method");
}
// http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
stream->Seek(0L, aiOrigin_SET);
std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
// build a zlib stream
z_stream zstream;
zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.data_type = Z_BINARY;
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
inflateInit2(&zstream, 16 + MAX_WBITS);
zstream.next_in = reinterpret_cast<Bytef *>(reader->GetPtr());
zstream.avail_in = (uInt)reader->GetRemainingSize();
size_t total = 0l;
// TODO: be smarter about this, decompress directly into heap buffer
// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
#define MYBLOCK 1024
Bytef block[MYBLOCK];
int ret;
do {
zstream.avail_out = MYBLOCK;
zstream.next_out = block;
ret = inflate(&zstream, Z_NO_FLUSH);
if (ret != Z_STREAM_END && ret != Z_OK) {
ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
}
const size_t have = MYBLOCK - zstream.avail_out;
total += have;
uncompressed.resize(total);
memcpy(uncompressed.data() + total - have, block, have);
} while (ret != Z_STREAM_END);
// terminate zlib
inflateEnd(&zstream);
// replace the input stream with a memory stream
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
// .. and retry
stream->Read(magic, 7, 1);
if (strcmp(magic, "BLENDER")) {
ThrowException("Found no BLENDER magic word in decompressed GZIP file");
}
#endif
}
file.i64bit = (stream->Read(magic, 1, 1), magic[0] == '-');
file.little = (stream->Read(magic, 1, 1), magic[0] == 'v');
stream->Read(magic, 3, 1);
magic[3] = '\0';
LogInfo("Blender version is ", magic[0], ".", magic + 1,
" (64bit: ", file.i64bit ? "true" : "false",
", little endian: ", file.little ? "true" : "false", ")");
ParseBlendFile(file, std::move(stream));
ParseBlendFile(file, stream);
Scene scene;
ExtractScene(scene, file);
@ -169,7 +256,7 @@ void BlenderImporter::ParseBlendFile(FileDatabase &out, std::shared_ptr<IOStream
out.entries.reserve(128);
{ // even small BLEND files tend to consist of many file blocks
SectionParser parser(*out.reader, out.i64bit);
SectionParser parser(*out.reader.get(), out.i64bit);
// first parse the file in search for the DNA and insert all other sections into the database
while ((parser.Next(), 1)) {
@ -231,81 +318,42 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) {
#endif
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::ParseSubCollection(const Blender::Scene &in, aiNode *root, const std::shared_ptr<Collection>& collection, ConversionData &conv_data) {
std::deque<Object *> root_objects;
// Count number of objects
for (std::shared_ptr<CollectionObject> cur = std::static_pointer_cast<CollectionObject>(collection->gobject.first); cur; cur = cur->next) {
if (cur->ob) {
root_objects.push_back(cur->ob);
}
}
std::deque<Collection *> root_children;
// Count number of child nodes
for (std::shared_ptr<CollectionChild> cur = std::static_pointer_cast<CollectionChild>(collection->children.first); cur; cur = cur->next) {
if (cur->collection) {
root_children.push_back(cur->collection.get());
}
}
root->mNumChildren = static_cast<unsigned int>(root_objects.size() + root_children.size());
root->mChildren = new aiNode *[root->mNumChildren]();
for (unsigned int i = 0; i < static_cast<unsigned int>(root_objects.size()); ++i) {
root->mChildren[i] = ConvertNode(in, root_objects[i], conv_data, aiMatrix4x4());
root->mChildren[i]->mParent = root;
}
// For each subcollection create a new node to represent it
unsigned int iterator = static_cast<unsigned int>(root_objects.size());
for (std::shared_ptr<CollectionChild> cur = std::static_pointer_cast<CollectionChild>(collection->children.first); cur; cur = cur->next) {
if (cur->collection) {
root->mChildren[iterator] = new aiNode(cur->collection->id.name + 2); // skip over the name prefix 'OB'
root->mChildren[iterator]->mParent = root;
ParseSubCollection(in, root->mChildren[iterator], cur->collection, conv_data);
}
iterator += 1;
}
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::ConvertBlendFile(aiScene *out, const Scene &in, const FileDatabase &file) {
ConversionData conv(file);
// FIXME it must be possible to take the hierarchy directly from
// the file. This is terrible. Here, we're first looking for
// all objects which don't have parent objects at all -
std::deque<const Object *> no_parents;
for (std::shared_ptr<Base> cur = std::static_pointer_cast<Base>(in.base.first); cur; cur = cur->next) {
if (cur->object) {
if (!cur->object->parent) {
no_parents.push_back(cur->object.get());
} else {
conv.objects.insert(cur->object.get());
}
}
}
for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
if (cur->object) {
if (cur->object->parent) {
conv.objects.insert(cur->object.get());
}
}
}
if (no_parents.empty()) {
ThrowException("Expected at least one object with no parent");
}
aiNode *root = out->mRootNode = new aiNode("<BlenderRoot>");
// Iterate over all objects directly under master_collection,
// If in.master_collection == null, then we're parsing something older.
if (in.master_collection) {
ParseSubCollection(in, root, in.master_collection, conv);
} else {
std::deque<const Object *> no_parents;
for (std::shared_ptr<Base> cur = std::static_pointer_cast<Base>(in.base.first); cur; cur = cur->next) {
if (cur->object) {
if (!cur->object->parent) {
no_parents.push_back(cur->object.get());
} else {
conv.objects.insert(cur->object.get());
}
}
}
for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
if (cur->object) {
if (cur->object->parent) {
conv.objects.insert(cur->object.get());
}
}
}
if (no_parents.empty()) {
ThrowException("Expected at least one object with no parent");
}
root->mNumChildren = static_cast<unsigned int>(no_parents.size());
root->mChildren = new aiNode *[root->mNumChildren]();
for (unsigned int i = 0; i < root->mNumChildren; ++i) {
root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4());
root->mChildren[i]->mParent = root;
}
root->mNumChildren = static_cast<unsigned int>(no_parents.size());
root->mChildren = new aiNode *[root->mNumChildren]();
for (unsigned int i = 0; i < root->mNumChildren; ++i) {
root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4());
root->mChildren[i]->mParent = root;
}
BuildMaterials(conv);
@ -359,7 +407,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
// check if the file contents are bundled with the BLEND file
if (img->packedfile) {
name.data[0] = '*';
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(AI_MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture());
aiTexture *curTex = conv_data.textures->back();
@ -433,7 +481,7 @@ void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, c
(void)conv_data;
aiString name;
name.length = ai_snprintf(name.data, AI_MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
GetTextureTypeDisplayString(tex->tex->type));
out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(
conv_data.next_texture[aiTextureType_DIFFUSE]++));
@ -937,7 +985,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
// key is material number, value is the TextureUVMapping for the material
typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
MaterialTextureUVMappings matTexUvMappings;
const uint32_t maxMat = static_cast<uint32_t>(mesh->mat.size());
const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
for (uint32_t m = 0; m < maxMat; ++m) {
// get material by index
const std::shared_ptr<Material> pMat = mesh->mat[m];
@ -1288,55 +1336,4 @@ aiNode *BlenderImporter::ConvertNode(const Scene &in, const Object *obj, Convers
return node.release();
}
BlenderImporter::StreamOrError BlenderImporter::ParseMagicToken(const std::string &pFile, IOSystem *pIOHandler) const {
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
if (stream == nullptr) {
return {{}, {}, "Could not open file for reading"};
}
char magic[8] = { 0 };
stream->Read(magic, 7, 1);
if (strcmp(magic, Token) == 0) {
return {stream, {}, {}};
}
// Check for presence of the gzip header. If yes, assume it is a
// compressed blend file and try uncompressing it, else fail. This is to
// avoid uncompressing random files which our loader might end up with.
#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
return {{}, {}, "BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?"};
#else
if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
return {{}, {}, "BLENDER magic bytes are missing, couldn't find GZIP header either"};
}
LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
if (magic[2] != 8) {
return {{}, {}, "Unsupported GZIP compression method"};
}
// http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
stream->Seek(0L, aiOrigin_SET);
std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
size_t total = 0;
Compression compression;
auto uncompressed = std::make_shared<std::vector<char>>();
if (compression.open(Compression::Format::Binary, Compression::FlushMode::NoFlush, 16 + Compression::MaxWBits)) {
total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), *uncompressed);
compression.close();
}
// replace the input stream with a memory stream
stream = std::make_shared<MemoryIOStream>(reinterpret_cast<uint8_t *>(uncompressed->data()), total);
// .. and retry
stream->Read(magic, 7, 1);
if (strcmp(magic, Token) == 0) {
return {stream, uncompressed, {}};
}
return {{}, {}, "Found no BLENDER magic word in decompressed GZIP file"};
#endif
}
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -42,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderLoader.h
* @brief Declaration of the Blender 3D (*.blend) importer class.
*/
#pragma once
#ifndef INCLUDED_AI_BLEND_LOADER_H
#define INCLUDED_AI_BLEND_LOADER_H
@ -56,154 +56,149 @@ struct aiLight;
struct aiCamera;
struct aiMaterial;
namespace Assimp {
namespace Assimp {
// TinyFormatter.h
namespace Formatter {
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
}
template <typename T, typename TR, typename A>
class basic_formatter;
// BlenderDNA.h
namespace Blender {
class FileDatabase;
struct ElemBase;
}
typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
// BlenderScene.h
namespace Blender {
struct Scene;
struct Object;
struct Mesh;
struct Camera;
struct Lamp;
struct MTex;
struct Image;
struct Material;
}
} // namespace Formatter
// BlenderIntermediate.h
namespace Blender {
struct ConversionData;
template <template <typename,typename> class TCLASS, typename T> struct TempArray;
}
// BlenderDNA.h
namespace Blender {
class FileDatabase;
struct ElemBase;
} // namespace Blender
// BlenderModifier.h
namespace Blender {
class BlenderModifierShowcase;
class BlenderModifier;
}
// BlenderScene.h
namespace Blender {
struct Scene;
struct Object;
struct Collection;
struct Mesh;
struct Camera;
struct Lamp;
struct MTex;
struct Image;
struct Material;
} // namespace Blender
// BlenderIntermediate.h
namespace Blender {
struct ConversionData;
template <template <typename, typename> class TCLASS, typename T>
struct TempArray;
} // namespace Blender
// BlenderModifier.h
namespace Blender {
class BlenderModifierShowcase;
class BlenderModifier;
} // namespace Blender
// -------------------------------------------------------------------------------------------
/** Load blenders official binary format. The actual file structure (the `DNA` how they
* call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
* conversion from intermediate format to aiScene. */
// -------------------------------------------------------------------------------------------
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter> {
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
{
public:
BlenderImporter();
~BlenderImporter() override;
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
~BlenderImporter();
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected:
const aiImporterDesc *GetInfo() const override;
void SetupProperties(const Importer *pImp) override;
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
void ParseBlendFile(Blender::FileDatabase &out, std::shared_ptr<IOStream> stream);
void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file);
void ParseSubCollection(const Blender::Scene &in, aiNode *root, const std::shared_ptr<Blender::Collection>& collection, Blender::ConversionData &conv_data);
void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file);
const aiImporterDesc* GetInfo () const;
void SetupProperties(const Importer* pImp);
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);
void ExtractScene(Blender::Scene& out, const Blender::FileDatabase& file);
void ConvertBlendFile(aiScene* out, const Blender::Scene& in, const Blender::FileDatabase& file);
private:
aiNode *ConvertNode(const Blender::Scene &in,
const Blender::Object *obj,
Blender::ConversionData &conv_info,
const aiMatrix4x4 &parentTransform);
aiNode* ConvertNode(const Blender::Scene& in,
const Blender::Object* obj,
Blender::ConversionData& conv_info,
const aiMatrix4x4& parentTransform
);
// --------------------
void ConvertMesh(const Blender::Scene &in,
const Blender::Object *obj,
const Blender::Mesh *mesh,
Blender::ConversionData &conv_data,
Blender::TempArray<std::vector, aiMesh> &temp);
void ConvertMesh(const Blender::Scene& in,
const Blender::Object* obj,
const Blender::Mesh* mesh,
Blender::ConversionData& conv_data,
Blender::TempArray<std::vector,aiMesh>& temp
);
// --------------------
aiLight *ConvertLight(const Blender::Scene &in,
const Blender::Object *obj,
const Blender::Lamp *mesh,
Blender::ConversionData &conv_data);
aiLight* ConvertLight(const Blender::Scene& in,
const Blender::Object* obj,
const Blender::Lamp* mesh,
Blender::ConversionData& conv_data
);
// --------------------
aiCamera *ConvertCamera(const Blender::Scene &in,
const Blender::Object *obj,
const Blender::Camera *mesh,
Blender::ConversionData &conv_data);
aiCamera* ConvertCamera(const Blender::Scene& in,
const Blender::Object* obj,
const Blender::Camera* mesh,
Blender::ConversionData& conv_data
);
// --------------------
void BuildDefaultMaterial(
Blender::ConversionData &conv_data);
Blender::ConversionData& conv_data
);
// --------------------
void AddBlendParams(
aiMaterial *result,
const Blender::Material *source);
aiMaterial* result,
const Blender::Material* source
);
// --------------------
void BuildMaterials(
Blender::ConversionData &conv_data);
Blender::ConversionData& conv_data
);
// --------------------
void ResolveTexture(
aiMaterial *out,
const Blender::Material *mat,
const Blender::MTex *tex,
Blender::ConversionData &conv_data);
aiMaterial* out,
const Blender::Material* mat,
const Blender::MTex* tex,
Blender::ConversionData& conv_data
);
// --------------------
void ResolveImage(
aiMaterial *out,
const Blender::Material *mat,
const Blender::MTex *tex,
const Blender::Image *img,
Blender::ConversionData &conv_data);
aiMaterial* out,
const Blender::Material* mat,
const Blender::MTex* tex,
const Blender::Image* img,
Blender::ConversionData& conv_data
);
// --------------------
void AddSentinelTexture(
aiMaterial *out,
const Blender::Material *mat,
const Blender::MTex *tex,
Blender::ConversionData &conv_data);
// TODO: Move to a std::variant, once c++17 is supported.
struct StreamOrError {
std::shared_ptr<IOStream> stream;
std::shared_ptr<std::vector<char>> input;
std::string error;
};
// Returns either a stream (and optional input data for the stream) or
// an error if it can't parse the magic token.
StreamOrError ParseMagicToken(
const std::string &pFile,
IOSystem *pIOHandler) const;
aiMaterial* out,
const Blender::Material* mat,
const Blender::MTex* tex,
Blender::ConversionData& conv_data
);
private: // static stuff, mostly logging and error reporting.
// --------------------
static void CheckActualType(const Blender::ElemBase *dt,
const char *check);
// --------------------
static void NotSupportedObjectType(const Blender::Object *obj,
const char *type);
static void CheckActualType(const Blender::ElemBase* dt,
const char* check
);
// --------------------
static void NotSupportedObjectType(const Blender::Object* obj,
const char* type
);
private:
Blender::BlenderModifierShowcase *modifier_cache;
Blender::BlenderModifierShowcase* modifier_cache;
}; // !class BlenderImporter

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -71,6 +71,10 @@ static const fpCreateModifier creators[] = {
nullptr // sentinel
};
// ------------------------------------------------------------------------------------------------
struct SharedModifierData : ElemBase {
ModifierData modifier;
};
// ------------------------------------------------------------------------------------------------
void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) {
@ -153,7 +157,6 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
const MirrorModifierData &mir = static_cast<const MirrorModifierData &>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
std::shared_ptr<Object> mirror_ob = mir.mirror_ob.lock();
conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
@ -168,8 +171,8 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
if (mirror_ob) {
const aiVector3D center(mirror_ob->obmat[3][0], mirror_ob->obmat[3][1], mirror_ob->obmat[3][2]);
if (mir.mirror_ob) {
const aiVector3D center(mir.mirror_ob->obmat[3][0], mir.mirror_ob->obmat[3][1], mir.mirror_ob->obmat[3][2]);
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
aiVector3D &v = mesh->mVertices[j];
@ -283,11 +286,6 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
if (conv_data.meshes->empty()) {
return;
}
const size_t meshIndex = conv_data.meshes->size() - out.mNumMeshes;
if (meshIndex >= conv_data.meshes->size()) {
ASSIMP_LOG_ERROR("Invalid index detected.");
return;
}
aiMesh **const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
std::unique_ptr<aiMesh *[]> tempmeshes(new aiMesh *[out.mNumMeshes]());

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -62,7 +62,9 @@ public:
/**
* The class destructor, virtual.
*/
virtual ~BlenderModifier() = default;
virtual ~BlenderModifier() {
// empty
}
// --------------------
/**

View File

@ -49,8 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
#include "BlenderSceneGen.h"
namespace Assimp {
namespace Blender {
using namespace Assimp;
using namespace Assimp::Blender;
//--------------------------------------------------------------------------------
template <>
@ -94,48 +94,6 @@ void Structure ::Convert<Group>(
db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
template <>
void Structure::Convert<CollectionObject>(
CollectionObject &dest,
const FileDatabase &db) const {
ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db);
{
std::shared_ptr<Object> ob;
ReadFieldPtr<ErrorPolicy_Igno>(ob, "*ob", db);
dest.ob = ob.get();
}
db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
template <>
void Structure::Convert<CollectionChild>(
CollectionChild &dest,
const FileDatabase &db) const {
ReadFieldPtr<ErrorPolicy_Fail>(dest.prev, "*prev", db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.collection, "*collection", db);
db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
template <>
void Structure::Convert<Collection>(
Collection &dest,
const FileDatabase &db) const {
ReadField<ErrorPolicy_Fail>(dest.id, "id", db);
ReadField<ErrorPolicy_Fail>(dest.gobject, "gobject", db);
ReadField<ErrorPolicy_Fail>(dest.children, "children", db);
db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
template <>
void Structure ::Convert<MTex>(
@ -297,7 +255,7 @@ void Structure ::Convert<Base>(
const FileDatabase &db) const {
// note: as per https://github.com/assimp/assimp/issues/128,
// reading the Object linked list recursively is prone to stack overflow.
// This structure converter is therefore a hand-written exception that
// This structure converter is therefore an hand-written exception that
// does it iteratively.
const int initial_pos = db.reader->GetCurrentPos();
@ -565,7 +523,7 @@ void Structure ::Convert<MVert>(
const FileDatabase &db) const {
ReadFieldArray<ErrorPolicy_Fail>(dest.co, "co", db);
ReadFieldArray<ErrorPolicy_Warn>(dest.no, "no", db);
ReadFieldArray<ErrorPolicy_Fail>(dest.no, "no", db);
ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
//ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.bweight, "bweight", db);
@ -620,9 +578,7 @@ void Structure ::Convert<ListBase>(
const FileDatabase &db) const {
ReadFieldPtr<ErrorPolicy_Igno>(dest.first, "*first", db);
std::shared_ptr<ElemBase> last;
ReadFieldPtr<ErrorPolicy_Igno>(last, "*last", db);
dest.last = last;
ReadFieldPtr<ErrorPolicy_Igno>(dest.last, "*last", db);
db.reader->IncPtr(size);
}
@ -646,9 +602,7 @@ void Structure ::Convert<ModifierData>(
const FileDatabase &db) const {
ReadFieldPtr<ErrorPolicy_Warn>(dest.next, "*next", db);
std::shared_ptr<ElemBase> prev;
ReadFieldPtr<ErrorPolicy_Warn>(prev, "*prev", db);
dest.prev = prev;
ReadFieldPtr<ErrorPolicy_Warn>(dest.prev, "*prev", db);
ReadField<ErrorPolicy_Igno>(dest.type, "type", db);
ReadField<ErrorPolicy_Igno>(dest.mode, "mode", db);
ReadFieldArray<ErrorPolicy_Igno>(dest.name, "name", db);
@ -706,7 +660,6 @@ void Structure ::Convert<Scene>(
ReadFieldPtr<ErrorPolicy_Warn>(dest.camera, "*camera", db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.world, "*world", db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.basact, "*basact", db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.master_collection, "*master_collection", db);
ReadField<ErrorPolicy_Igno>(dest.base, "base", db);
db.reader->IncPtr(size);
@ -772,9 +725,7 @@ void Structure ::Convert<MirrorModifierData>(
ReadField<ErrorPolicy_Igno>(dest.axis, "axis", db);
ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
ReadField<ErrorPolicy_Igno>(dest.tolerance, "tolerance", db);
std::shared_ptr<Object> mirror_ob;
ReadFieldPtr<ErrorPolicy_Igno>(mirror_ob, "*mirror_ob", db);
dest.mirror_ob = mirror_ob;
ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob, "*mirror_ob", db);
db.reader->IncPtr(size);
}
@ -835,9 +786,9 @@ void Structure::Convert<CustomDataLayer>(
ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
ReadField<ErrorPolicy_Warn>(dest.active_clone, "active_clone", db);
ReadField<ErrorPolicy_Warn>(dest.active_mask, "active_mask", db);
ReadField<ErrorPolicy_Warn>(dest.uid, "uid", db);
ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
@ -882,12 +833,6 @@ void DNA::RegisterConverters() {
converters["Image"] = DNA::FactoryPair(&Structure::Allocate<Image>, &Structure::Convert<Image>);
converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
converters["Collection"] = DNA::FactoryPair(&Structure::Allocate<Collection>, &Structure::Convert<Collection>);
converters["CollectionChild"] = DNA::FactoryPair(&Structure::Allocate<CollectionChild>, &Structure::Convert<CollectionChild>);
converters["CollectionObject"] = DNA::FactoryPair(&Structure::Allocate<CollectionObject>, &Structure::Convert<CollectionObject>);
}
} // namespace Blender
} //namespace Assimp
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -107,7 +107,6 @@ namespace Blender {
struct Object;
struct MTex;
struct Image;
struct Collection;
#include <memory>
@ -124,7 +123,7 @@ struct ID : ElemBase {
// -------------------------------------------------------------------------------
struct ListBase : ElemBase {
std::shared_ptr<ElemBase> first;
std::weak_ptr<ElemBase> last;
std::shared_ptr<ElemBase> last;
};
// -------------------------------------------------------------------------------
@ -148,26 +147,6 @@ struct Group : ElemBase {
std::shared_ptr<GroupObject> gobject;
};
// -------------------------------------------------------------------------------
struct CollectionObject : ElemBase {
//CollectionObject* prev;
std::shared_ptr<CollectionObject> next;
Object *ob;
};
// -------------------------------------------------------------------------------
struct CollectionChild : ElemBase {
std::shared_ptr<CollectionChild> next, prev;
std::shared_ptr<Collection> collection;
};
// -------------------------------------------------------------------------------
struct Collection : ElemBase {
ID id FAIL;
ListBase gobject; // CollectionObject
ListBase children; // CollectionChild
};
// -------------------------------------------------------------------------------
struct World : ElemBase {
ID id FAIL;
@ -182,7 +161,7 @@ struct MVert : ElemBase {
int bweight;
MVert() :
flag(0), mat_nr(0), bweight(0) {}
ElemBase(), flag(0), mat_nr(0), bweight(0) {}
};
// -------------------------------------------------------------------------------
@ -417,6 +396,7 @@ struct CustomDataLayer : ElemBase {
std::shared_ptr<ElemBase> data; // must be converted to real type according type member
CustomDataLayer() :
ElemBase(),
type(0),
offset(0),
flag(0),
@ -641,21 +621,14 @@ struct ModifierData : ElemBase {
};
std::shared_ptr<ElemBase> next WARN;
std::weak_ptr<ElemBase> prev WARN;
std::shared_ptr<ElemBase> prev WARN;
int type, mode;
char name[32];
};
// ------------------------------------------------------------------------------------------------
struct SharedModifierData : ElemBase {
ModifierData modifier;
};
// -------------------------------------------------------------------------------
struct SubsurfModifierData : SharedModifierData {
struct SubsurfModifierData : ElemBase {
enum Type {
@ -668,6 +641,7 @@ struct SubsurfModifierData : SharedModifierData {
FLAGS_SubsurfUV = 1 << 3
};
ModifierData modifier FAIL;
short subdivType WARN;
short levels FAIL;
short renderLevels;
@ -675,7 +649,7 @@ struct SubsurfModifierData : SharedModifierData {
};
// -------------------------------------------------------------------------------
struct MirrorModifierData : SharedModifierData {
struct MirrorModifierData : ElemBase {
enum Flags {
Flags_CLIPPING = 1 << 0,
@ -687,9 +661,11 @@ struct MirrorModifierData : SharedModifierData {
Flags_VGROUP = 1 << 6
};
ModifierData modifier FAIL;
short axis, flag;
float tolerance;
std::weak_ptr<Object> mirror_ob;
std::shared_ptr<Object> mirror_ob;
};
// -------------------------------------------------------------------------------
@ -728,7 +704,7 @@ struct Object : ElemBase {
ListBase modifiers;
Object() :
type(Type_EMPTY), parent(nullptr) {
ElemBase(), type(Type_EMPTY), parent(nullptr), track(), proxy(), proxy_from(), data() {
// empty
}
};
@ -740,7 +716,8 @@ struct Base : ElemBase {
std::shared_ptr<Object> object WARN;
Base() :
prev(nullptr) {
ElemBase(), prev(nullptr), next(), object() {
// empty
// empty
}
};
@ -752,11 +729,13 @@ struct Scene : ElemBase {
std::shared_ptr<Object> camera WARN;
std::shared_ptr<World> world WARN;
std::shared_ptr<Base> basact WARN;
std::shared_ptr<Collection> master_collection WARN;
ListBase base;
Scene() = default;
Scene() :
ElemBase(), camera(), world(), basact() {
// empty
}
};
// -------------------------------------------------------------------------------
@ -786,7 +765,10 @@ struct Image : ElemBase {
short gen_x, gen_y, gen_type;
Image() = default;
Image() :
ElemBase() {
// empty
}
};
// -------------------------------------------------------------------------------
@ -876,7 +858,7 @@ struct Tex : ElemBase {
//char use_nodes;
Tex() :
imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
ElemBase(), imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS), ima() {
// empty
}
};
@ -968,7 +950,10 @@ struct MTex : ElemBase {
//float shadowfac;
//float zenupfac, zendownfac, blendfac;
MTex() = default;
MTex() :
ElemBase() {
// empty
}
};
} // namespace Blender

View File

@ -62,12 +62,6 @@ template <> void Structure :: Convert<Group> (
) const
;
template <> void Structure::Convert<Collection>(
Collection& dest,
const FileDatabase& db
) const
;
template <> void Structure :: Convert<MTex> (
MTex& dest,
const FileDatabase& db

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -39,8 +40,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/// @file BlenderTessellator.cpp
/// @brief A simple tessellation wrapper
/** @file BlenderTessellator.cpp
* @brief A simple tessellation wrapper
*/
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
@ -59,7 +62,8 @@ namspace Assimp
{
template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
{
return "BLEND_TESS_GL: ";
static auto prefix = "BLEND_TESS_GL: ";
return prefix;
}
}
@ -77,7 +81,9 @@ BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
}
// ------------------------------------------------------------------------------------------------
BlenderTessellatorGL::~BlenderTessellatorGL() = default;
BlenderTessellatorGL::~BlenderTessellatorGL( )
{
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
@ -253,7 +259,8 @@ namespace Assimp
{
template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
{
return "BLEND_TESS_P2T: ";
static auto prefix = "BLEND_TESS_P2T: ";
return prefix;
}
}
@ -267,7 +274,9 @@ BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter )
}
// ------------------------------------------------------------------------------------------------
BlenderTessellatorP2T::~BlenderTessellatorP2T( )
{
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -143,7 +144,11 @@ namespace Assimp
#if ASSIMP_BLEND_WITH_POLY_2_TRI
#include "contrib/poly2tri/poly2tri/poly2tri.h"
#ifdef ASSIMP_USE_HUNTER
# include <poly2tri/poly2tri.h>
#else
# include "../contrib/poly2tri/poly2tri/poly2tri.h"
#endif
namespace Assimp
{
@ -181,7 +186,7 @@ namespace Assimp
{
public:
BlenderTessellatorP2T( BlenderBMeshConverter& converter );
~BlenderTessellatorP2T( ) = default;
~BlenderTessellatorP2T( );
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );

View File

@ -46,6 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// no #ifdefing here, Cinema4D support is carried out in a branch of assimp
// where it is turned on in the CMake settings.
#ifndef _MSC_VER
# error C4D support is currently MSVC only
#endif
#include "C4DImporter.h"
#include <memory>
#include <assimp/IOSystem.hpp>
@ -82,7 +86,8 @@ void GetWriterInfo(int &id, String &appname) {
namespace Assimp {
template<> const char* LogFunctions<C4DImporter>::Prefix() {
return "C4D: ";
static auto prefix = "C4D: ";
return prefix;
}
}
@ -100,12 +105,6 @@ static const aiImporterDesc desc = {
};
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter() = default;
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter() = default;
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile);
@ -301,7 +300,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
// based on Cineware sample code
while (object) {
const Int32 type = object->GetType();
const LONG type = object->GetType();
const Matrix& ml = object->GetMl();
aiNode* const nd = new aiNode();
@ -364,8 +363,8 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != nullptr);
const Int32 pointCount = polyObject->GetPointCount();
const Int32 polyCount = polyObject->GetPolygonCount();
const LONG pointCount = polyObject->GetPointCount();
const LONG polyCount = polyObject->GetPolygonCount();
if(!polyObject || !pointCount) {
LogWarn("ignoring mesh with zero vertices or faces");
return nullptr;
@ -387,7 +386,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
unsigned int vcount = 0;
// first count vertices
for (Int32 i = 0; i < polyCount; i++)
for (LONG i = 0; i < polyCount; i++)
{
vcount += 3;
@ -430,7 +429,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
}
// copy vertices and extra channels over and populate faces
for (Int32 i = 0; i < polyCount; ++i, ++face) {
for (LONG i = 0; i < polyCount; ++i, ++face) {
ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
const Vector& pointA = points[polys[i].a];
verts->x = pointA.x;
@ -507,7 +506,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
if (tangents_src) {
for(unsigned int k = 0; k < face->mNumIndices; ++k) {
Int32 l;
LONG l;
switch(k) {
case 0:
l = polys[i].a;

View File

@ -78,8 +78,6 @@ namespace Assimp {
// -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public:
C4DImporter();
~C4DImporter() override;
bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
protected:

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -61,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
namespace Assimp {
using namespace Assimp;
using namespace Assimp::COB;
using namespace Assimp::Formatter;
static constexpr float units[] = {
static const float units[] = {
1000.f,
100.f,
1.f,
@ -76,7 +76,7 @@ static constexpr float units[] = {
1.f / 1609.344f
};
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"TrueSpace Object Importer",
"",
"",
@ -89,11 +89,31 @@ static constexpr aiImporterDesc desc = {
"cob scn"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
COBImporter::COBImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
COBImporter::~COBImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "Caligary" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string &extension = GetExtension(pFile);
if (extension == "cob" || extension == "scn" || extension == "COB" || extension == "SCN") {
return true;
}
else if ((!extension.length() || checkSig) && pIOHandler) {
const char *tokens[] = { "Caligary" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
@ -150,7 +170,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// sort faces by material indices
for (std::shared_ptr<Node> &n : scene.nodes) {
if (n->type == Node::TYPE_MESH) {
Mesh &mesh = (Mesh &)(*n);
Mesh &mesh = (Mesh &)(*n.get());
for (Face &f : mesh.faces) {
mesh.temp_map[f.material].push_back(&f);
}
@ -160,7 +180,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// count meshes
for (std::shared_ptr<Node> &n : scene.nodes) {
if (n->type == Node::TYPE_MESH) {
Mesh &mesh = (Mesh &)(*n);
Mesh &mesh = (Mesh &)(*n.get());
if (mesh.vertex_positions.size() && mesh.texture_coords.size()) {
pScene->mNumMeshes += static_cast<unsigned int>(mesh.temp_map.size());
}
@ -203,7 +223,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
}
}
pScene->mRootNode = BuildNodes(*root, scene, pScene);
pScene->mRootNode = BuildNodes(*root.get(), scene, pScene);
//flip normals after import
FlipWindingOrderProcess flip;
flip.Execute(pScene);
@ -372,11 +392,9 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
}
// add children recursively
if (!root.temp_children.empty()) {
nd->mChildren = new aiNode *[root.temp_children.size()]();
for (const Node *n : root.temp_children) {
(nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
}
nd->mChildren = new aiNode *[root.temp_children.size()]();
for (const Node *n : root.temp_children) {
(nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
}
return nd;
@ -475,9 +493,8 @@ void COBImporter::ReadBasicNodeInfo_Ascii(Node &msh, LineSplitter &splitter, con
} else if (splitter.match_start("Transform")) {
for (unsigned int y = 0; y < 4 && ++splitter; ++y) {
const char *s = splitter->c_str();
const char *end = s + splitter->size();
for (unsigned int x = 0; x < 4; ++x) {
SkipSpaces(&s, end);
SkipSpaces(&s);
msh.transform[y][x] = fast_atof(&s);
}
}
@ -489,12 +506,12 @@ void COBImporter::ReadBasicNodeInfo_Ascii(Node &msh, LineSplitter &splitter, con
// ------------------------------------------------------------------------------------------------
template <typename T>
void COBImporter::ReadFloat3Tuple_Ascii(T &fill, const char **in, const char *end) {
void COBImporter::ReadFloat3Tuple_Ascii(T &fill, const char **in) {
const char *rgb = *in;
for (unsigned int i = 0; i < 3; ++i) {
SkipSpaces(&rgb, end);
SkipSpaces(&rgb);
if (*rgb == ',') ++rgb;
SkipSpaces(&rgb, end);
SkipSpaces(&rgb);
fill[i] = fast_atof(&rgb);
}
@ -513,7 +530,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
return;
}
out.materials.emplace_back();
out.materials.push_back(Material());
Material &mat = out.materials.back();
mat = nfo;
@ -541,7 +558,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
}
const char *rgb = splitter[1];
ReadFloat3Tuple_Ascii(mat.rgb, &rgb, splitter.getEnd());
ReadFloat3Tuple_Ascii(mat.rgb, &rgb);
++splitter;
if (!splitter.match_start("alpha ")) {
@ -569,7 +586,7 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
return;
}
// parent chunks preceede their children, so we should have the
// parent chunks preceede their childs, so we should have the
// corresponding chunk already.
for (std::shared_ptr<Node> &nd : out.nodes) {
if (nd->id == nfo.parent_id) {
@ -620,21 +637,20 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
}
const char *rgb = splitter[1];
const char *end = splitter.getEnd();
ReadFloat3Tuple_Ascii(msh.color, &rgb, end);
ReadFloat3Tuple_Ascii(msh.color, &rgb);
SkipSpaces(&rgb, end);
SkipSpaces(&rgb);
if (strncmp(rgb, "cone angle", 10) != 0) {
ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id);
}
SkipSpaces(rgb + 10, &rgb, end);
SkipSpaces(rgb + 10, &rgb);
msh.angle = fast_atof(&rgb);
SkipSpaces(&rgb, end);
SkipSpaces(&rgb);
if (strncmp(rgb, "inner angle", 11) != 0) {
ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
}
SkipSpaces(rgb + 11, &rgb, end);
SkipSpaces(rgb + 11, &rgb);
msh.inner_angle = fast_atof(&rgb);
// skip the rest for we can't handle this kind of physically-based lighting information.
@ -652,7 +668,7 @@ void COBImporter::ReadCame_Ascii(Scene &out, LineSplitter &splitter, const Chunk
ReadBasicNodeInfo_Ascii(msh, ++splitter, nfo);
// skip the next line, we don't know this differentiation between a
// skip the next line, we don't know this differenciation between a
// standard camera and a panoramic camera.
++splitter;
}
@ -707,14 +723,14 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
for (unsigned int cur = 0; cur < cnt && ++splitter; ++cur) {
const char *s = splitter->c_str();
const char *end = splitter.getEnd();
aiVector3D &v = msh.vertex_positions[cur];
SkipSpaces(&s, end);
SkipSpaces(&s);
v.x = fast_atof(&s);
SkipSpaces(&s, end);
SkipSpaces(&s);
v.y = fast_atof(&s);
SkipSpaces(&s, end);
SkipSpaces(&s);
v.z = fast_atof(&s);
}
} else if (splitter.match_start("Texture Vertices")) {
@ -723,13 +739,12 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
for (unsigned int cur = 0; cur < cnt && ++splitter; ++cur) {
const char *s = splitter->c_str();
const char *end = splitter.getEnd();
aiVector2D &v = msh.texture_coords[cur];
SkipSpaces(&s, end);
SkipSpaces(&s);
v.x = fast_atof(&s);
SkipSpaces(&s, end);
SkipSpaces(&s);
v.y = fast_atof(&s);
}
} else if (splitter.match_start("Faces")) {
@ -746,7 +761,7 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
ThrowException("Expected Face line");
}
msh.faces.emplace_back();
msh.faces.push_back(Face());
Face &face = msh.faces.back();
face.indices.resize(strtoul10(splitter[2]));
@ -754,9 +769,8 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
face.material = strtoul10(splitter[6]);
const char *s = (++splitter)->c_str();
const char *end = splitter.getEnd();
for (size_t i = 0; i < face.indices.size(); ++i) {
if (!SkipSpaces(&s, end)) {
if (!SkipSpaces(&s)) {
ThrowException("Expected EOL token in Face entry");
}
if ('<' != *s++) {
@ -866,7 +880,7 @@ void COBImporter::ReadBinaryFile(Scene &out, StreamReaderLE *reader) {
return;
}
while (true) {
while (1) {
std::string type;
type += reader->GetI1();
type += reader->GetI1();
@ -950,7 +964,7 @@ void COBImporter::ReadPolH_Binary(COB::Scene &out, StreamReaderLE &reader, const
ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id);
}
} else
msh.faces.emplace_back();
msh.faces.push_back(Face());
Face &f = msh.faces.back();
const size_t num = reader.GetI2();
@ -962,7 +976,7 @@ void COBImporter::ReadPolH_Binary(COB::Scene &out, StreamReaderLE &reader, const
}
for (size_t x = 0; x < num; ++x) {
f.indices.emplace_back();
f.indices.push_back(VertexIndex());
VertexIndex &v = f.indices.back();
v.pos_idx = reader.GetI4();
@ -1002,7 +1016,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
const chunk_guard cn(nfo, reader);
out.materials.emplace_back();
out.materials.push_back(Material());
Material &mat = out.materials.back();
mat = nfo;
@ -1052,7 +1066,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
id[0] = reader.GetI1(), id[1] = reader.GetI1();
if (id[0] == 'e' && id[1] == ':') {
mat.tex_env = std::make_shared<Texture>();
mat.tex_env.reset(new Texture());
reader.GetI1();
ReadString_Binary(mat.tex_env->path, reader);
@ -1062,7 +1076,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
}
if (id[0] == 't' && id[1] == ':') {
mat.tex_color = std::make_shared<Texture>();
mat.tex_color.reset(new Texture());
reader.GetI1();
ReadString_Binary(mat.tex_color->path, reader);
@ -1078,7 +1092,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
}
if (id[0] == 'b' && id[1] == ':') {
mat.tex_bump = std::make_shared<Texture>();
mat.tex_bump.reset(new Texture());
reader.GetI1();
ReadString_Binary(mat.tex_bump->path, reader);
@ -1155,7 +1169,7 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
const chunk_guard cn(nfo, reader);
// parent chunks preceede their children, so we should have the
// parent chunks preceede their childs, so we should have the
// corresponding chunk already.
for (std::shared_ptr<Node> &nd : out.nodes) {
if (nd->id == nfo.parent_id) {
@ -1170,6 +1184,4 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
}
}
#endif // ASSIMP_BUILD_NO_COB_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -51,100 +51,104 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiNode;
namespace Assimp {
class LineSplitter;
namespace Assimp {
class LineSplitter;
// TinyFormatter.h
namespace Formatter {
template <typename T, typename TR, typename A>
class basic_formatter;
typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
} // namespace Formatter
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
}
// COBScene.h
namespace COB {
struct ChunkInfo;
struct Node;
struct Scene;
} // namespace COB
// COBScene.h
namespace COB {
struct ChunkInfo;
struct Node;
struct Scene;
}
// -------------------------------------------------------------------------------------------
/** Importer class to load TrueSpace files (cob,scn) up to v6.
*
* Currently relatively limited, loads only ASCII files and needs more test coverage. */
// -------------------------------------------------------------------------------------------
class COBImporter : public BaseImporter {
class COBImporter : public BaseImporter
{
public:
COBImporter() = default;
~COBImporter() override = default;
COBImporter();
~COBImporter();
// --------------------
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override;
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
protected:
// --------------------
const aiImporterDesc *GetInfo() const override;
// --------------------
void SetupProperties(const Importer *pImp) override;
const aiImporterDesc* GetInfo () const;
// --------------------
void InternReadFile(const std::string &pFile, aiScene *pScene,
IOSystem *pIOHandler) override;
void SetupProperties(const Importer* pImp);
// --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
// -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX;
// -------------------------------------------------------------------
/** @brief Read from an ascii scene/object file
* @param out Receives output data.
* @param stream Stream to read from. */
void ReadAsciiFile(COB::Scene &out, StreamReaderLE *stream);
void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
// -------------------------------------------------------------------
/** @brief Read from a binary scene/object file
* @param out Receives output data.
* @param stream Stream to read from. */
void ReadBinaryFile(COB::Scene &out, StreamReaderLE *stream);
void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
// Conversion to Assimp output format
aiNode *BuildNodes(const COB::Node &root, const COB::Scene &scin, aiScene *fill);
aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
private:
// ASCII file support
void UnsupportedChunk_Ascii(LineSplitter &splitter, const COB::ChunkInfo &nfo, const char *name);
void ReadChunkInfo_Ascii(COB::ChunkInfo &out, const LineSplitter &splitter);
void ReadBasicNodeInfo_Ascii(COB::Node &msh, LineSplitter &splitter, const COB::ChunkInfo &nfo);
template <typename T>
void ReadFloat3Tuple_Ascii(T &fill, const char **in, const char *end);
void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter);
void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo);
template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in);
void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadPolH_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadBitM_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadMat1_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadGrou_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadBone_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadCame_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadLght_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadUnit_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
void ReadChan_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
// Binary file support
void UnsupportedChunk_Binary(StreamReaderLE &reader, const COB::ChunkInfo &nfo, const char *name);
void ReadString_Binary(std::string &out, StreamReaderLE &reader);
void ReadBasicNodeInfo_Binary(COB::Node &msh, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
void ReadString_Binary(std::string& out, StreamReaderLE& reader);
void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadPolH_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void ReadBitM_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void ReadCame_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void ReadLght_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void ReadGrou_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
void ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
}; // !class COBImporter

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -42,16 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file COBScene.h
* @brief Utilities for the COB importer.
*/
#pragma once
#ifndef INCLUDED_AI_COB_SCENE_H
#define INCLUDED_AI_COB_SCENE_H
#include <assimp/BaseImporter.h>
#include <assimp/material.h>
#include <memory>
#include <deque>
#include <map>
#include <assimp/BaseImporter.h>
#include <assimp/material.h>
namespace Assimp {
namespace COB {
@ -107,7 +108,7 @@ struct Node : public ChunkInfo
TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
};
virtual ~Node() = default;
virtual ~Node() {}
Node(Type type) : type(type), unit_scale(1.f){}
Type type;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
@ -44,6 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file CSMLoader.cpp
* Implementation of the CSM importer class.
*/
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
#include "CSMLoader.h"
@ -60,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"CharacterStudio Motion Importer (MoCap)",
"",
"",
@ -76,26 +79,43 @@ static constexpr aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
CSMImporter::CSMImporter() : noSkeletonMesh(){
// empty
}
CSMImporter::CSMImporter()
: noSkeletonMesh()
{}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
CSMImporter::~CSMImporter()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const {
static const char* tokens[] = {"$Filename"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens));
bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
// check file extension
const std::string extension = GetExtension(pFile);
if( extension == "csm")
return true;
if ((checkSig || !extension.length()) && pIOHandler) {
const char* tokens[] = {"$Filename"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
// Build a string of all file extensions supported
const aiImporterDesc* CSMImporter::GetInfo () const {
const aiImporterDesc* CSMImporter::GetInfo () const
{
return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void CSMImporter::SetupProperties(const Importer* pImp) {
void CSMImporter::SetupProperties(const Importer* pImp)
{
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
}
@ -107,7 +127,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file
if (file == nullptr) {
if( file.get() == nullptr) {
throw DeadlyImportError( "Failed to open CSM file ", pFile, ".");
}
@ -115,38 +135,38 @@ void CSMImporter::InternReadFile( const std::string& pFile,
std::vector<char> mBuffer2;
TextFileToBuffer(file.get(),mBuffer2);
const char* buffer = &mBuffer2[0];
const char *end = &mBuffer2[mBuffer2.size() - 1] + 1;
std::unique_ptr<aiAnimation> anim(new aiAnimation());
int first = 0, last = 0x00ffffff;
// now process the file and look out for '$' sections
while (true) {
SkipSpaces(&buffer, end);
while (1) {
SkipSpaces(&buffer);
if ('\0' == *buffer)
break;
if ('$' == *buffer) {
++buffer;
if (TokenMatchI(buffer,"firstframe",10)) {
SkipSpaces(&buffer, end);
SkipSpaces(&buffer);
first = strtol10(buffer,&buffer);
}
else if (TokenMatchI(buffer,"lastframe",9)) {
SkipSpaces(&buffer, end);
SkipSpaces(&buffer);
last = strtol10(buffer,&buffer);
}
else if (TokenMatchI(buffer,"rate",4)) {
SkipSpaces(&buffer, end);
float d = { 0.0f };
SkipSpaces(&buffer);
float d;
buffer = fast_atoreal_move<float>(buffer,d);
anim->mTicksPerSecond = d;
}
else if (TokenMatchI(buffer,"order",5)) {
std::vector< aiNodeAnim* > anims_temp;
anims_temp.reserve(30);
while (true) {
SkipSpaces(&buffer, end);
if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer, end) && *buffer == '$')
while (1) {
SkipSpaces(&buffer);
if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
break; // next section
// Construct a new node animation channel and setup its name
@ -154,43 +174,41 @@ void CSMImporter::InternReadFile( const std::string& pFile,
aiNodeAnim* nda = anims_temp.back();
char* ot = nda->mNodeName.data;
while (!IsSpaceOrNewLine(*buffer)) {
while (!IsSpaceOrNewLine(*buffer))
*ot++ = *buffer++;
}
*ot = '\0';
nda->mNodeName.length = static_cast<ai_uint32>(ot-nda->mNodeName.data);
}
anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());
if (!anim->mNumChannels) {
if (!anim->mNumChannels)
throw DeadlyImportError("CSM: Empty $order section");
}
// copy over to the output animation
anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
} else if (TokenMatchI(buffer,"points",6)) {
if (!anim->mNumChannels) {
}
else if (TokenMatchI(buffer,"points",6)) {
if (!anim->mNumChannels)
throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
}
// If we know how many frames we'll read, we can preallocate some storage
unsigned int alloc = 100;
if (last != 0x00ffffff) {
if (last != 0x00ffffff)
{
alloc = last-first;
alloc += alloc>>2u; // + 25%
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
for (unsigned int i = 0; i < anim->mNumChannels;++i)
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
}
}
unsigned int filled = 0;
// Now read all point data.
while (true) {
SkipSpaces(&buffer, end);
if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer, end) || *buffer == '$')) {
while (1) {
SkipSpaces(&buffer);
if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) {
break; // next section
}
@ -201,8 +219,8 @@ void CSMImporter::InternReadFile( const std::string& pFile,
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* s = anim->mChannels[i];
if (s->mNumPositionKeys == alloc) {
// need to reallocate?
if (s->mNumPositionKeys == alloc) { /* need to reallocate? */
aiVectorKey* old = s->mPositionKeys;
s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
@ -210,26 +228,24 @@ void CSMImporter::InternReadFile( const std::string& pFile,
}
// read x,y,z
if (!SkipSpacesAndLineEnd(&buffer, end)) {
if(!SkipSpacesAndLineEnd(&buffer))
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample x coord");
}
if (TokenMatchI(buffer, "DROPOUT", 7)) {
// seems this is invalid marker data; at least the doc says it's possible
ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)");
} else {
}
else {
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
sub->mTime = (double)frame;
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
if (!SkipSpacesAndLineEnd(&buffer, end)) {
if(!SkipSpacesAndLineEnd(&buffer))
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord");
}
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
if (!SkipSpacesAndLineEnd(&buffer, end)) {
if(!SkipSpacesAndLineEnd(&buffer))
throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord");
}
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
++s->mNumPositionKeys;
@ -237,22 +253,22 @@ void CSMImporter::InternReadFile( const std::string& pFile,
}
// update allocation granularity
if (filled == alloc) {
if (filled == alloc)
alloc *= 2;
}
++filled;
}
// all channels must be complete in order to continue safely.
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
if (!anim->mChannels[i]->mNumPositionKeys) {
if (!anim->mChannels[i]->mNumPositionKeys)
throw DeadlyImportError("CSM: Invalid marker track");
}
}
}
} else {
}
else {
// advance to the next line
SkipLine(&buffer, end);
SkipLine(&buffer);
}
}
@ -266,7 +282,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
pScene->mRootNode->mNumChildren = anim->mNumChannels;
pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* na = anim->mChannels[i];
aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();

View File

@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -47,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h>
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class to load MOCAPs in CharacterStudio Motion format.
@ -58,31 +59,35 @@ namespace Assimp {
* Link to file format specification:
* <max_8_dvd>\samples\Motion\Docs\CSM.rtf
*/
class CSMImporter : public BaseImporter {
class CSMImporter : public BaseImporter
{
public:
CSMImporter();
~CSMImporter() override = default;
~CSMImporter();
public:
// -------------------------------------------------------------------
bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override;
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
protected:
// -------------------------------------------------------------------
const aiImporterDesc *GetInfo() const override;
// -------------------------------------------------------------------
void SetupProperties(const Importer *pImp) override;
const aiImporterDesc* GetInfo () const;
// -------------------------------------------------------------------
void InternReadFile(const std::string &pFile, aiScene *pScene,
IOSystem *pIOHandler) override;
void SetupProperties(const Importer* pImp);
// -------------------------------------------------------------------
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
bool noSkeletonMesh;
};
} // namespace Assimp
}; // end of class CSMImporter
} // end of namespace Assimp
#endif // AI_AC3DIMPORTER_H_INC

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -91,7 +91,7 @@ void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *p
// Encodes a string into a valid XML ID using the xsd:ID schema qualifications.
static const std::string XMLIDEncode(const std::string &name) {
const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.";
const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char) - 1;
const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char);
if (name.length() == 0) {
return name;
@ -154,7 +154,8 @@ ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, con
// ------------------------------------------------------------------------------------------------
// Destructor
ColladaExporter::~ColladaExporter() = default;
ColladaExporter::~ColladaExporter() {
}
// ------------------------------------------------------------------------------------------------
// Starts writing the contents
@ -246,7 +247,7 @@ void ColladaExporter::WriteHeader() {
}
// Assimp root nodes can have meshes, Collada Scenes cannot
if (mScene->mRootNode->mNumChildren == 0 || mScene->mRootNode->mMeshes != nullptr) {
if (mScene->mRootNode->mNumChildren == 0 || mScene->mRootNode->mMeshes != 0) {
mAdd_root_node = true;
}
@ -448,7 +449,7 @@ void ColladaExporter::WriteLight(size_t pIndex) {
PushTag();
switch (light->mType) {
case aiLightSource_AMBIENT:
WriteAmbientLight(light);
WriteAmbienttLight(light);
break;
case aiLightSource_DIRECTIONAL:
WriteDirectionalLight(light);
@ -543,7 +544,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light) {
mOutput << startstr << "</spot>" << endstr;
}
void ColladaExporter::WriteAmbientLight(const aiLight *const light) {
void ColladaExporter::WriteAmbienttLight(const aiLight *const light) {
const aiColor3D &color = light->mColorAmbient;
mOutput << startstr << "<ambient>" << endstr;
@ -1329,9 +1330,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
std::vector<std::string> names;
for (size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
if (nodeAnim->mPreState == aiAnimBehaviour_DEFAULT || nodeAnim->mPreState == aiAnimBehaviour_LINEAR || nodeAnim->mPreState == aiAnimBehaviour_REPEAT) {
names.emplace_back("LINEAR");
names.push_back("LINEAR");
} else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) {
names.emplace_back("STEP");
names.push_back("STEP");
}
}

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -101,7 +101,7 @@ protected:
void WritePointLight(const aiLight *const light);
void WriteDirectionalLight(const aiLight *const light);
void WriteSpotLight(const aiLight *const light);
void WriteAmbientLight(const aiLight *const light);
void WriteAmbienttLight(const aiLight *const light);
/// Writes the controller library
void WriteControllerLibrary();
@ -233,7 +233,7 @@ public:
Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
Property shininess, transparency, index_refraction;
Material() = default;
Material() {}
};
std::map<unsigned int, std::string> textures;

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -621,11 +621,6 @@ struct Animation {
for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
Animation *anim = *it;
// Assign the first animation name to the parent if empty.
// This prevents the animation name from being lost when animations are combined
if (mName.empty()) {
mName = anim->mName;
}
CombineSingleChannelAnimationsRecursively(anim);
if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
@ -666,7 +661,7 @@ struct ChannelEntry {
const Collada::Accessor *mTimeAccessor; ///> Collada accessor to the time values
const Collada::Data *mTimeData; ///> Source data array for the time values
const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values
const Collada::Data *mValueData; ///> Source data array for the key value values
const Collada::Data *mValueData; ///> Source datat array for the key value values
ChannelEntry() :
mChannel(),

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2021, assimp team
All rights reserved.
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ColladaParser.h"
#include <assimp/ColladaMetaData.h>
#include <assimp/CreateAnimMesh.h>
#include <assimp/Defines.h>
#include <assimp/ParsingUtils.h>
#include <assimp/SkeletonMeshBuilder.h>
#include <assimp/ZipArchiveIOSystem.h>
@ -64,7 +65,7 @@ namespace Assimp {
using namespace Assimp::Formatter;
using namespace Assimp::Collada;
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = {
"Collada Importer",
"",
"",
@ -92,34 +93,66 @@ inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() :
mFileName(),
mMeshIndexByID(),
mMaterialIndexByName(),
mMeshes(),
newMats(),
mCameras(),
mLights(),
mTextures(),
mAnims(),
noSkeletonMesh(false),
removeEmptyBones(false),
ignoreUpDirection(false),
ignoreUnitSize(false),
useColladaName(false),
mNodeNameCounter(0) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ColladaLoader::~ColladaLoader() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
// Look for a DAE file inside, but don't extract it
ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
if (zip_archive.isOpen()) {
return !ColladaParser::ReadZaeManifest(zip_archive).empty();
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
// check file extension
const std::string extension = GetExtension(pFile);
const bool readSig = checkSig && (pIOHandler != nullptr);
if (!readSig) {
if (extension == "dae" || extension == "zae") {
return true;
}
} else {
// Look for a DAE file inside, but don't extract it
ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
if (zip_archive.isOpen()) {
return !ColladaParser::ReadZaeManifest(zip_archive).empty();
}
}
static const char *tokens[] = { "<collada" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
// XML - too generic, we need to open the file and search for typical keywords
if (extension == "xml" || !extension.length() || checkSig) {
/* If CanRead() is called in order to check whether we
* support a specific file extension in general pIOHandler
* might be nullptr and it's our duty to return true here.
*/
if (!pIOHandler) {
return true;
}
static const char *tokens[] = { "<collada" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
}
// ------------------------------------------------------------------------------------------------
void ColladaLoader::SetupProperties(const Importer *pImp) {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
removeEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true) != 0;
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0;
ignoreUnitSize = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UNIT_SIZE, 0) != 0;
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
}
@ -168,15 +201,12 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
// ... then fill the materials with the now adjusted settings
FillMaterials(parser, pScene);
if (!ignoreUnitSize) {
// Apply unit-size scale calculation
pScene->mRootNode->mTransformation *= aiMatrix4x4(
parser.mUnitSize, 0, 0, 0,
0, parser.mUnitSize, 0, 0,
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
}
// Apply unit-size scale calculation
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
0, parser.mUnitSize, 0, 0,
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
if (!ignoreUpDirection) {
// Convert to Y_UP, if different orientation
if (parser.mUpDirection == ColladaParser::UP_X) {
@ -247,9 +277,7 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
// add children. first the *real* ones
node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size() + instances.size());
if (node->mNumChildren != 0) {
node->mChildren = new aiNode * [node->mNumChildren];
}
node->mChildren = new aiNode *[node->mNumChildren];
for (size_t a = 0; a < pNode->mChildren.size(); ++a) {
node->mChildren[a] = BuildHierarchy(pParser, pNode->mChildren[a]);
@ -351,9 +379,9 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
out->mAngleInnerCone = AI_DEG_TO_RAD(srcLight->mFalloffAngle);
// ... some extension magic.
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - ai_epsilon)) {
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - 1e-6f)) {
// ... some deprecation magic.
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - ai_epsilon)) {
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET * (1 - 1e-6f)) {
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1
float f = 1.0f;
@ -545,7 +573,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// now place all mesh references we gathered in the target node
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
if (!newMeshRefs.empty()) {
if (newMeshRefs.size()) {
struct UIntTypeConverter {
unsigned int operator()(const size_t &v) const {
return static_cast<unsigned int>(v);
@ -625,14 +653,16 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
}
// same for texture coords, as many as we have
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
// empty slots are not allowed, need to pack and adjust UV indexes accordingly
for (size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
dstMesh->mTextureCoords[a] = new aiVector3D[numVertices];
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
for (size_t b = 0; b < numVertices; ++b) {
dstMesh->mTextureCoords[a][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
}
dstMesh->mNumUVComponents[a] = pSrcMesh->mNumUVComponents[a];
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
++real;
}
}
@ -790,10 +820,9 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
// count the number of bones which influence vertices of the current submesh
size_t numRemainingBones = 0;
for (const auto & dstBone : dstBones) {
if (dstBone.empty() && removeEmptyBones) {
continue;
if (!dstBone.empty()) {
++numRemainingBones;
}
++numRemainingBones;
}
// create bone array and copy bone weights one by one
@ -802,7 +831,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
size_t boneCount = 0;
for (size_t a = 0; a < numBones; ++a) {
// omit bones without weights
if (dstBones[a].empty() && removeEmptyBones) {
if (dstBones[a].empty()) {
continue;
}
@ -1058,7 +1087,7 @@ void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, floa
return;
}
for (unsigned int i = 0; i < values.size(); i++) {
if (std::abs(time - values[i].mTime) < ai_epsilon) {
if (std::abs(time - values[i].mTime) < 1e-6f) {
values[i].mKeys.push_back(k);
return;
} else if (time > values[i].mTime && time < values[i + 1].mTime) {
@ -1256,12 +1285,12 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// now for every unique point in time, find or interpolate the key values for that time
// and apply them to the transform chain. Then the node's present transformation can be calculated.
ai_real time = startTime;
while (true) {
while (1) {
for (ChannelEntry & e : entries) {
// find the keyframe behind the current point in time
size_t pos = 0;
ai_real postTime = 0.0;
while (true) {
while (1) {
if (pos >= e.mTimeAccessor->mCount) {
break;
}
@ -1657,7 +1686,7 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
// store the material
mMaterialIndexByName[matIt->first] = newMats.size();
newMats.emplace_back(&effect, mat);
newMats.push_back(std::pair<Effect *, aiMaterial *>(&effect, mat));
}
// ScenePreprocessor generates a default material automatically if none is there.
// All further code here in this loader works well without a valid material so
@ -1672,7 +1701,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// recurse through the param references until we end up at an image
std::string name = pName;
while (true) {
while (1) {
// the given string is a param entry. Find it
Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name);
// if not found, we're at the end of the recursion. The resulting string should be the image ID

Some files were not shown because too many files have changed in this diff Show More